]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Work around SWT 4.13 - 4.18 Win32 DnD bug 567422
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 16 Oct 2020 18:16:56 +0000 (21:16 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 16 Oct 2020 18:47:59 +0000 (21:47 +0300)
This is a temporary fix that can be reverted once we move
to a newer Eclipse RCP version than 4.18M1 which has the
fix for the nasty DnD bug can and will crash the JVM quite
often when dragging content to e.g. the internal workbench
web browser.

gitlab #623

Change-Id: If7985fb481e40c8a5c67990121e3dbeccfecc674

729 files changed:
bundles/org.eclipse.swt.win32.win32.x86_64/.api_description [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/.classpath [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/.project [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/about.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/about_files/IJG_README [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/about_files/mpl-v11.txt [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/build.properties [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/fragment.properties [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/build.bat [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/c.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/c.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/c_stats.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/c_stats.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/c_structs.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/c_structs.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/callback.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/callback.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/cancel.ico [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com_custom.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com_custom.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com_stats.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com_stats.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com_structs.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/com_structs.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/defines.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_custom.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_stats.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_stats.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_structs.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_structs.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/javaw.exe.manifest [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/make_common.mak [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/make_win32.mak [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os_custom.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os_custom.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os_stats.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os_stats.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os_structs.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/os_structs.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/search.ico [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.rc [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_awt.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_awt.rc [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_gdip.rc [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_webkit.rc [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_wgl.rc [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_custom.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_custom.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_stats.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_stats.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_structs.cpp [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_structs.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_stats.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_stats.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_structs.c [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_structs.h [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/pom.xml [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWTError.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWTException.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/ACC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextAttributeEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextExtendedAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextExtendedListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Relation.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/awt/SWT_AWT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/awt/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/AuthenticationEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/AuthenticationListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/Browser.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/BrowserFactory.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/BrowserFunction.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/CloseWindowListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/IE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/OpenWindowListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/StatusTextEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/StatusTextListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/TitleEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/TitleListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/VisibilityWindowAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/VisibilityWindowListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebBrowser.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebDownloadDelegate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebFrameLoadDelegate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebKit.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebPolicyDelegate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebResourceLoadDelegate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebSite.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebUIDelegate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WindowEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/AnimatedProgress.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BidiSegmentEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BidiSegmentListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/Bullet.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BusyIndicator.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CBanner.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CBannerLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CCombo.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CLabel.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CLayoutData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder2Adapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder2Listener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderRenderer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CaretEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CaretListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ControlEditor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/DefaultContent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ExtendedModifyEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ExtendedModifyListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineBackgroundEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineBackgroundListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineStyleEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineStyleListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MouseNavigator.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MovementEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MovementListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PaintObjectEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PaintObjectListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PopupList.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ST.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashForm.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashFormData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashFormLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ScrolledComposite.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ScrolledCompositeLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StackLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyleRange.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledText.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextContent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextLineSpacingProvider.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextPrintOptions.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextRenderer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TableCursor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TableEditor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangeListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangedEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangingEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TreeCursor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TreeEditor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/VerifyKeyListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ViewForm.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ViewFormLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ByteArrayTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/Clipboard.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DND.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DNDEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DNDListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSource.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTarget.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/FileTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/HTMLTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ImageTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/OleEnumFORMATETC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/RTFTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TableDragSourceEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TableDropTargetEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TextTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/Transfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TransferData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TreeDragSourceEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TreeDropTargetEffect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/URLTransfer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ArmEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ArmListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DisposeEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DisposeListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DragDetectEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DragDetectListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/GestureEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/GestureListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/HelpEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/HelpListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuDetectEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuDetectListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ModifyEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ModifyListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseMoveListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseTrackAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseTrackListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseWheelListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/PaintEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/PaintListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SegmentEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SegmentListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TouchEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TouchListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TraverseEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TraverseListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeAdapter.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TypedEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/VerifyEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/VerifyListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Color.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Cursor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Device.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/DeviceData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Drawable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Font.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/FontData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/FontMetrics.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GCData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GlyphMetrics.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Image.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageDataLoader.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageDataProvider.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageFileNameProvider.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoader.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoaderEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoaderListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/LineAttributes.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/PaletteData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Path.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/PathData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Pattern.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Point.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/RGB.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/RGBA.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Rectangle.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Region.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Resource.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/TextLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/TextStyle.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Transform.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/BidiUtil.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/C.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Callback.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Compatibility.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/DPIUtil.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/DefaultExceptionHandler.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ImageList.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/LONG.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Library.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Lock.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Platform.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/SWTEventListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/SWTMessages.properties [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/BitmapData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/ColorPalette.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/Gdip.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/GdiplusStartupInput.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/PointF.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/Rect.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/RectF.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/FileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/GIFFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGAppn.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGComment.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGDecoder.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGEndOfImage.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFrameHeader.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGHuffmanTable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGQuantizationTable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGRestartInterval.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGScanHeader.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGSegment.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGStartOfImage.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LEDataInputStream.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LEDataOutputStream.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LZWCodec.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LZWNode.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/OS2BMPFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PNGFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngChunk.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngChunkReader.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngDecodingDataStream.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngDeflater.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngFileReadState.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTables.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIdatChunk.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIendChunk.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIhdrChunk.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngInputStream.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngLzBlockReader.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngPlteChunk.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngTrnsChunk.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFDirectory.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFModifiedHuffmanCodec.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFRandomFileAccess.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/WinBMPFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/WinICOFileFormat.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/CAUUID.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/COM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/COMObject.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/CONTROLINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/DISPPARAMS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/EXCEPINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/FORMATETC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/FUNCDESC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/GUID.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IAccessible.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IClassFactory2.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IConnectionPoint.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IConnectionPointContainer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ICustomDestinationList.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDataObject.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDispatch.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDispatchEx.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnum.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumFORMATETC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumTfDisplayAttributeInfo.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumVARIANT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IFileDialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IMLangFontLink2.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IObjectArray.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IObjectCollection.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleCommandTarget.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleControl.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleDocument.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleDocumentView.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleInPlaceActiveObject.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleInPlaceObject.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleLink.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleObject.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleWindow.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersist.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistFile.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistStorage.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistStreamInit.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPropertyBag.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPropertyStore.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IProvideClassInfo.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IProvideClassInfo2.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IServiceProvider.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IShellItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IShellLink.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ISpecifyPropertyPages.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IStorage.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IStream.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITaskbarList3.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeInfo.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeProvider.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfInputProcessorProfiles.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITypeInfo.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IUnknown.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IViewObject2.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/LICINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/OLECMD.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/OLEINPLACEFRAMEINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/STGMEDIUM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/TYPEATTR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/VARDESC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/VARIANT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/LAYERPLANEDESCRIPTOR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/PIXELFORMATDESCRIPTOR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/WGL.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebCookieManager.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDataSource.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDocumentRepresentation.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDownload.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebError.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebErrorPrivate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebFrame.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebFramePrivate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebIBActions.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebMutableURLRequest.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebMutableURLRequestPrivate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebOpenPanelResultListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebPolicyDecisionListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebPreferences.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallenge.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallengeSender.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLCredential.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLProtectionSpace.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLRequest.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLResponse.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebView.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebViewPrivate.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/JSClassDefinition.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/WebKit_win32.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ACCEL.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ACTCTX.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BITMAP.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BITMAPINFOHEADER.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BLENDFUNCTION.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BP_PAINTPARAMS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BROWSEINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BUTTON_IMAGELIST.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CANDIDATEFORM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_CONTEXT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_INFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_NAME_BLOB.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_PUBLIC_KEY_INFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CHOOSECOLOR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CHOOSEFONT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CIDA.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/COMBOBOXINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/COMPOSITIONFORM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CREATESTRUCT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_ALGORITHM_IDENTIFIER.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_BIT_BLOB.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_INTEGER_BLOB.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_OBJID_BLOB.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DEVMODE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DIBSECTION.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DOCHOSTUIINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DOCINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DRAWITEMSTRUCT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DROPFILES.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DTTOPTS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EMR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EMREXTCREATEFONTINDIRECTW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EXTLOGFONTW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FILETIME.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FLICK_DATA.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FLICK_POINT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GCP_RESULTS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GESTURECONFIG.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GESTUREINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GRADIENT_RECT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GUITHREADINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDHITTESTINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDLAYOUT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HELPINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HIGHCONTRAST.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ICONINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/INITCOMMONCONTROLSEX.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/INPUT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/KEYBDINPUT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGBRUSH.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGFONT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGPEN.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LRESULT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVCOLUMN.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVHITTESTINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVINSERTMARK.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MARGINS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MCHITTESTINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MEASUREITEMSTRUCT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUBARINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUITEMINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MINMAXINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MONITORINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MOUSEINPUT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MSG.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMCUSTOMDRAW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMHDR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMHEADER.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLINK.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLISTVIEW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVCUSTOMDRAW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVDISPINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVFINDITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVODSTATECHANGE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMREBARCHEVRON.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMREBARCHILDSIZE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTBCUSTOMDRAW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTBHOTITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTOOLBAR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTREEVIEW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTTCUSTOMDRAW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTTDISPINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVCUSTOMDRAW.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVDISPINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVITEMCHANGE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMUPDOWN.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NONCLIENTMETRICS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NOTIFYICONDATA.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OFNOTIFY.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OPENFILENAME.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OUTLINETEXTMETRIC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PAINTSTRUCT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PANOSE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/POINT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PRINTDLG.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PROCESS_INFORMATION.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PROPERTYKEY.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/REBARBANDINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/RECT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SAFEARRAY.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SAFEARRAYBOUND.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_ANALYSIS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_CONTROL.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_DIGITSUBSTITUTE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_FONTPROPERTIES.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_ITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_LOGATTR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_PROPERTIES.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_STATE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCROLLBARINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCROLLINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHDRAGIMAGE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHELLEXECUTEINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHFILEINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SIZE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/STARTUPINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SYSTEMTIME.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TBBUTTON.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TBBUTTONINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCHAR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCHITTESTINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TEXTMETRIC.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TF_DA_COLOR.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TF_DISPLAYATTRIBUTE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TOOLINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TOUCHINPUT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TRACKMOUSEEVENT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TRIVERTEX.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVHITTESTINFO.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVINSERTSTRUCT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVITEM.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVITEMEX.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVSORTCB.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/UDACCEL.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WINDOWPLACEMENT.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WINDOWPOS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WNDCLASS.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FillData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FillLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormAttachment.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/GridData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/GridLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowLayout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OLE.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleAutomation.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleClientSite.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleControlSite.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEvent.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventSink.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventTable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleFrame.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleFunctionDescription.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleParameterDescription.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OlePropertyDescription.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/Variant.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/GLCanvas.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/GLData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/PrintDialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/Printer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/PrinterData.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/program/Program.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/program/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Button.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Canvas.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Caret.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ColorDialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Combo.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Control.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/CoolBar.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/CoolItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/DateTime.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Decorations.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Dialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/DirectoryDialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Display.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Event.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/EventTable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ExpandBar.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ExpandItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/FileDialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/FontDialog.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Group.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/IME.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Item.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Label.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Layout.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Link.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/List.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Listener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Menu.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/MenuItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/MessageBox.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Monitor.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ProgressBar.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/RunnableLock.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Sash.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Scale.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ScrollBar.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Scrollable.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Shell.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Slider.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Spinner.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Synchronizer.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TabFolder.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TabItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Table.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TableColumn.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TableItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskBar.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Text.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolBar.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolTip.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Touch.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TouchSource.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tracker.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tray.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TrayItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tree.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TreeColumn.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TreeItem.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TypedListener.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Widget.java [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/package.html [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/swt-awt-win32-4930r7.dll [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/swt-gdip-win32-4930r7.dll [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/swt-wgl-win32-4930r7.dll [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/swt-win32-4930r7.dll [new file with mode: 0644]
bundles/org.eclipse.swt.win32.win32.x86_64/version.txt [new file with mode: 0644]
bundles/pom.xml

diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/.api_description b/bundles/org.eclipse.swt.win32.win32.x86_64/.api_description
new file mode 100644 (file)
index 0000000..f9dcf8c
--- /dev/null
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component name="org.eclipse.swt.win32.win32.x86_64_3.113.0.v20191204-0601" version="1.2">
+    <plugin id="org.eclipse.swt.win32.win32.x86_64_3.113.0.v20191204-0601"/>
+    <package name="org.eclipse.swt.accessibility" visibility="1">
+        <type name="Accessible" restrictions="0">
+            <method name="internal_WM_GETOBJECT" restrictions="8" signature="(JJ)J"/>
+            <method name="internal_dispose_Accessible" restrictions="8" signature="()V"/>
+            <method name="internal_new_Accessible" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Control;)Lorg/eclipse/swt/accessibility/Accessible;"/>
+        </type>
+    </package>
+    <package name="org.eclipse.swt.browser" visibility="1">
+        <type name="Browser" restrictions="2"/>
+    </package>
+    <package name="org.eclipse.swt.custom" visibility="1">
+        <type name="CBanner" restrictions="2"/>
+        <type name="CTabFolder" restrictions="2"/>
+        <type name="CTabItem" restrictions="2"/>
+        <type name="StyledText" restrictions="2"/>
+        <type name="ViewForm" restrictions="2"/>
+    </package>
+    <package name="org.eclipse.swt.dnd" visibility="1">
+        <type name="Clipboard" restrictions="2"/>
+        <type name="DragSource" restrictions="2"/>
+        <type name="DropTarget" restrictions="2"/>
+        <type name="TransferData" restrictions="0">
+            <field name="formatetc" restrictions="8"/>
+            <field name="pIDataObject" restrictions="8"/>
+            <field name="result" restrictions="8"/>
+            <field name="stgmedium" restrictions="8"/>
+            <field name="type" restrictions="8"/>
+        </type>
+    </package>
+    <package name="org.eclipse.swt.graphics" visibility="1">
+        <type name="Color" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Device;I)Lorg/eclipse/swt/graphics/Color;"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Device;II)Lorg/eclipse/swt/graphics/Color;"/>
+        </type>
+        <type name="Cursor" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Device;I)Lorg/eclipse/swt/graphics/Cursor;"/>
+        </type>
+        <type name="Device" restrictions="0">
+            <method name="getDeviceZoom" restrictions="24" signature="()I"/>
+            <method name="internal_dispose_GC" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)V"/>
+            <method name="internal_new_GC" restrictions="8" signature="(Lorg/eclipse/swt/graphics/GCData;)J"/>
+        </type>
+        <type name="Drawable" restrictions="0">
+            <method name="internal_dispose_GC" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)V"/>
+            <method name="internal_new_GC" restrictions="8" signature="(Lorg/eclipse/swt/graphics/GCData;)J"/>
+            <method name="isAutoScalable" restrictions="8" signature="()Z"/>
+        </type>
+        <type name="Font" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Device;J)Lorg/eclipse/swt/graphics/Font;"/>
+        </type>
+        <type name="FontData" restrictions="0">
+            <field name="data" restrictions="8"/>
+            <field name="height" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/internal/win32/LOGFONT;F)Lorg/eclipse/swt/graphics/FontData;"/>
+        </type>
+        <type name="FontMetrics" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/internal/win32/TEXTMETRIC;)Lorg/eclipse/swt/graphics/FontMetrics;"/>
+        </type>
+        <type name="GC" restrictions="0">
+            <method name="getGCData" restrictions="8" signature="()Lorg/eclipse/swt/graphics/GCData;"/>
+            <field name="handle" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Drawable;Lorg/eclipse/swt/graphics/GCData;)Lorg/eclipse/swt/graphics/GC;"/>
+            <method name="win32_new" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)Lorg/eclipse/swt/graphics/GC;"/>
+        </type>
+        <type name="GCData" restrictions="8"/>
+        <type name="Image" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="internal_dispose_GC" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)V"/>
+            <method name="internal_new_GC" restrictions="8" signature="(Lorg/eclipse/swt/graphics/GCData;)J"/>
+            <field name="type" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Device;IJ)Lorg/eclipse/swt/graphics/Image;"/>
+        </type>
+        <type name="ImageData" restrictions="0">
+            <method name="internal_new" restrictions="8" signature="(IIILorg/eclipse/swt/graphics/PaletteData;I[BI[B[BIIIIIII)Lorg/eclipse/swt/graphics/ImageData;"/>
+        </type>
+        <type name="Path" restrictions="0">
+            <field name="handle" restrictions="8"/>
+        </type>
+        <type name="Pattern" restrictions="0">
+            <field name="handle" restrictions="8"/>
+        </type>
+        <type name="Region" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/graphics/Device;I)Lorg/eclipse/swt/graphics/Region;"/>
+        </type>
+        <type name="TextLayout" restrictions="0">
+            <method name="setDefaultTabWidth" restrictions="8" signature="(I)V"/>
+        </type>
+        <type name="Transform" restrictions="0">
+            <field name="handle" restrictions="8"/>
+        </type>
+    </package>
+    <package name="org.eclipse.swt.ole.win32" visibility="1">
+        <type name="OleClientSite" restrictions="0">
+            <method name="&lt;init&gt;" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Composite;ILjava/lang/String;Ljava/io/File;)V"/>
+        </type>
+        <type name="OleControlSite" restrictions="0">
+            <method name="&lt;init&gt;" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Composite;ILjava/lang/String;Ljava/io/File;)V"/>
+        </type>
+        <type name="Variant" restrictions="0">
+            <method name="win32_copy" restrictions="8" signature="(JLorg/eclipse/swt/ole/win32/Variant;)V"/>
+            <method name="win32_new" restrictions="8" signature="(J)Lorg/eclipse/swt/ole/win32/Variant;"/>
+        </type>
+    </package>
+    <package name="org.eclipse.swt.printing" visibility="1">
+        <type name="PrintDialog" restrictions="2"/>
+        <type name="Printer" restrictions="0">
+            <field name="handle" restrictions="8"/>
+            <method name="internal_dispose_GC" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)V"/>
+            <method name="internal_new_GC" restrictions="8" signature="(Lorg/eclipse/swt/graphics/GCData;)J"/>
+            <method name="isAutoScalable" restrictions="8" signature="()Z"/>
+        </type>
+    </package>
+    <package name="org.eclipse.swt.widgets" visibility="1">
+        <type name="Button" restrictions="2"/>
+        <type name="Caret" restrictions="2"/>
+        <type name="ColorDialog" restrictions="2"/>
+        <type name="Combo" restrictions="2"/>
+        <type name="Control" restrictions="2">
+            <field name="handle" restrictions="8"/>
+            <method name="internal_dispose_GC" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)V"/>
+            <method name="internal_new_GC" restrictions="8" signature="(Lorg/eclipse/swt/graphics/GCData;)J"/>
+        </type>
+        <type name="CoolBar" restrictions="2"/>
+        <type name="CoolItem" restrictions="2"/>
+        <type name="DateTime" restrictions="2"/>
+        <type name="Decorations" restrictions="2"/>
+        <type name="DirectoryDialog" restrictions="2"/>
+        <type name="Display" restrictions="2">
+            <method name="findWidget" restrictions="8" signature="(J)Lorg/eclipse/swt/widgets/Widget;"/>
+            <method name="findWidget" restrictions="8" signature="(JJ)Lorg/eclipse/swt/widgets/Widget;"/>
+            <method name="findWidget" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Widget;J)Lorg/eclipse/swt/widgets/Widget;"/>
+            <method name="internal_dispose_GC" restrictions="8" signature="(JLorg/eclipse/swt/graphics/GCData;)V"/>
+            <method name="internal_new_GC" restrictions="8" signature="(Lorg/eclipse/swt/graphics/GCData;)J"/>
+            <field name="msg" restrictions="8"/>
+            <method name="sendPostExternalEventDispatchEvent" restrictions="8" signature="()V"/>
+            <method name="sendPreExternalEventDispatchEvent" restrictions="8" signature="()V"/>
+        </type>
+        <type name="ExpandBar" restrictions="2"/>
+        <type name="ExpandItem" restrictions="2"/>
+        <type name="FileDialog" restrictions="2"/>
+        <type name="FontDialog" restrictions="2"/>
+        <type name="Group" restrictions="2"/>
+        <type name="IME" restrictions="2"/>
+        <type name="Label" restrictions="2"/>
+        <type name="Link" restrictions="2"/>
+        <type name="List" restrictions="2"/>
+        <type name="Menu" restrictions="2">
+            <field name="handle" restrictions="8"/>
+        </type>
+        <type name="MenuItem" restrictions="2"/>
+        <type name="MessageBox" restrictions="2"/>
+        <type name="ProgressBar" restrictions="2"/>
+        <type name="Sash" restrictions="2"/>
+        <type name="Scale" restrictions="2"/>
+        <type name="ScrollBar" restrictions="2"/>
+        <type name="Scrollable" restrictions="2"/>
+        <type name="Shell" restrictions="2">
+            <method name="internal_new" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Display;J)Lorg/eclipse/swt/widgets/Shell;"/>
+            <method name="win32_new" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Display;J)Lorg/eclipse/swt/widgets/Shell;"/>
+        </type>
+        <type name="Slider" restrictions="2"/>
+        <type name="Spinner" restrictions="2"/>
+        <type name="TabFolder" restrictions="2"/>
+        <type name="TabItem" restrictions="2"/>
+        <type name="Table" restrictions="2"/>
+        <type name="TableColumn" restrictions="2"/>
+        <type name="TableItem" restrictions="2"/>
+        <type name="TaskBar" restrictions="2"/>
+        <type name="TaskItem" restrictions="2"/>
+        <type name="Text" restrictions="2"/>
+        <type name="ToolBar" restrictions="2"/>
+        <type name="ToolItem" restrictions="2"/>
+        <type name="ToolTip" restrictions="2"/>
+        <type name="Tracker" restrictions="2"/>
+        <type name="Tray" restrictions="2"/>
+        <type name="TrayItem" restrictions="2"/>
+        <type name="Tree" restrictions="2"/>
+        <type name="TreeColumn" restrictions="2"/>
+        <type name="TreeItem" restrictions="2">
+            <field name="handle" restrictions="8"/>
+        </type>
+        <type name="TypedListener" restrictions="0">
+            <method name="&lt;init&gt;" restrictions="8" signature="(Lorg/eclipse/swt/internal/SWTEventListener;)V"/>
+            <method name="getEventListener" restrictions="8" signature="()Lorg/eclipse/swt/internal/SWTEventListener;"/>
+            <method name="handleEvent" restrictions="8" signature="(Lorg/eclipse/swt/widgets/Event;)V"/>
+        </type>
+        <type name="Widget" restrictions="0">
+            <method name="removeListener" restrictions="24" signature="(ILorg/eclipse/swt/internal/SWTEventListener;)V"/>
+        </type>
+    </package>
+</component>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/.classpath b/bundles/org.eclipse.swt.win32.win32.x86_64/.classpath
new file mode 100644 (file)
index 0000000..0a91e8e
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src/"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/.project b/bundles/org.eclipse.swt.win32.win32.x86_64/.project
new file mode 100644 (file)
index 0000000..19258d2
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.eclipse.swt.win32.win32.x86_64</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+               <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..8db2b22
--- /dev/null
@@ -0,0 +1,2483 @@
+Manifest-Version: 1.0
+Automatic-Module-Name: org.eclipse.swt.win32.win32.x86_64
+Bundle-SymbolicName: org.eclipse.swt.win32.win32.x86_64; singleton:=tr
+ ue
+Built-By: genie.releng
+SWT-WS: win32
+Bundle-ManifestVersion: 2
+Eclipse-PlatformFilter: (& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=
+ x86_64))
+Eclipse-SourceReferences: scm:git:git://git.eclipse.org/gitroot/platfo
+ rm/eclipse.platform.swt.binaries.git;path="bundles/org.eclipse.swt.wi
+ n32.win32.x86_64";tag="I20191204-0600";commitId=5f79b3dfcc116d035e911
+ 8b169fc1f1e841b4596
+Bundle-Vendor: %providerName
+Fragment-Host: org.eclipse.swt; bundle-version="[3.0.0,4.0.0)"
+Export-Package: org.eclipse.swt,org.eclipse.swt.accessibility,org.ecli
+ pse.swt.awt,org.eclipse.swt.browser,org.eclipse.swt.custom,org.eclips
+ e.swt.dnd,org.eclipse.swt.events,org.eclipse.swt.graphics,org.eclipse
+ .swt.layout,org.eclipse.swt.opengl,org.eclipse.swt.printing,org.eclip
+ se.swt.program,org.eclipse.swt.widgets,org.eclipse.swt.internal; x-fr
+ iends:="org.eclipse.ui",org.eclipse.swt.internal.image; x-internal:=t
+ rue,org.eclipse.swt.ole.win32,org.eclipse.swt.internal.gdip; x-intern
+ al:=true,org.eclipse.swt.internal.ole.win32; x-internal:=true,org.ecl
+ ipse.swt.internal.win32; x-internal:=true,org.eclipse.swt.internal.op
+ engl.win32; x-internal:=true
+Bundle-Name: %fragmentName
+Bundle-Version: 3.113.0.v20191204-0601
+Bundle-Localization: fragment
+SWT-Arch: x86_64
+Created-By: Apache Maven 3.5.4
+Build-Jdk: 11.0.4
+SWT-OS: win32
+
+Name: org/eclipse/swt/widgets/ProgressBar.class
+SHA-256-Digest: 3sUY49DCJ08Z11I8Y6nZMh1ithpFKfL/rchmL8rjnZc=
+
+Name: org/eclipse/swt/custom/ScrolledCompositeLayout.class
+SHA-256-Digest: UkfuveZibmjTvfQQnraqQkVU/ECvo0GPUxDrUw5e5KU=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_input_controller
+ .class
+SHA-256-Digest: K2gaa8bVg+HQqyZwQtreoMj/WEJkjS6TQuaJ1biiZbo=
+
+Name: org/eclipse/swt/internal/win32/TF_DISPLAYATTRIBUTE.class
+SHA-256-Digest: y4ooaXusa+otInhtOFK+gUBcXF5TXGab3J4NpsoRr0I=
+
+Name: org/eclipse/swt/internal/win32/COMPOSITIONFORM.class
+SHA-256-Digest: 0EvA1e4FKZnQ/in7V6jqVew4BuiI6wxgrpUqhAyu2bA=
+
+Name: org/eclipse/swt/internal/webkit/IWebViewPrivate.class
+SHA-256-Digest: vK0yv0usRfSKSbdT7xfqdYRRJpmuvDmlL7Wqj2jFWGI=
+
+Name: org/eclipse/swt/internal/win32/MENUBARINFO.class
+SHA-256-Digest: DhHfPGqFVpOxmoou31LNXrECwPEygAdqhsHf3117Cuo=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleDocument.class
+SHA-256-Digest: jm/WMk2aHHfWeudMlAkq+CyPvc2lnUdjYiQCbOAYQh4=
+
+Name: org/eclipse/swt/internal/ole/win32/IDispatch.class
+SHA-256-Digest: eDtXWwUv12SRgYCZGkN8aUmmhxHFSzgNHR4x4mjQRjU=
+
+Name: org/eclipse/swt/browser/WebKit$1.class
+SHA-256-Digest: 8nS/nopnibr919udrlYQztsv1FS7IfPPQL+eDjSWRJA=
+
+Name: org/eclipse/swt/internal/ImageList.class
+SHA-256-Digest: GaNv4WDBAWcjL4ERkhd8V6E9InFJYr6tX4OD5rec/ZQ=
+
+Name: org/eclipse/swt/internal/win32/OPENFILENAME.class
+SHA-256-Digest: +Funqyz32jogwCzBxaMDm0h6FavijJH/JfMM8efJ6gM=
+
+Name: org/eclipse/swt/internal/win32/LOGFONT.class
+SHA-256-Digest: IsKox5K+rlduABNKMC1wq/C9e2badWa9193o0Mg0bfI=
+
+Name: org/eclipse/swt/events/ModifyListener.class
+SHA-256-Digest: 63LdsfDP4OQ0ycNGE+rOxtIrk3ia5cEhjtBWx0P9rVo=
+
+Name: org/eclipse/swt/dnd/Clipboard.class
+SHA-256-Digest: Q4duWez/TlvLTnmXIhE+QU+8msZX0JgYnMb7x1SmKYs=
+
+Name: org/eclipse/swt/dnd/DNDEvent.class
+SHA-256-Digest: 8pxcn/BlSn261vWXcDXK1jMpdG7a+RdgP2iVqBFj9d8=
+
+Name: org/eclipse/swt/accessibility/AccessibleActionListener.class
+SHA-256-Digest: DJ3rjM7I1BxnAoxTSxyhC/bpYkhG5wMLNukw1aTa9Pg=
+
+Name: org/eclipse/swt/events/ShellListener$5.class
+SHA-256-Digest: b3CGi4SQJ6UJ2ClrNpissrGS7c7TmutP6BddpZ+qj9Q=
+
+Name: org/eclipse/swt/widgets/Slider.class
+SHA-256-Digest: B31vU4RNHpCmdqgHd0RVly4VImEpRSe0K598SKhGZkQ=
+
+Name: org/eclipse/swt/internal/DPIUtil$AutoScaleMethod.class
+SHA-256-Digest: FIlAHC906GUTnHhbE8f6eyR4qfEkk7rwHZNNXGEeeKo=
+
+Name: org/eclipse/swt/dnd/DragSourceListener.class
+SHA-256-Digest: /OznGcyEQqmrnGGO1Ca33tgwcq9e1KCTj9jKVUCPp0w=
+
+Name: org/eclipse/swt/widgets/CoolItem.class
+SHA-256-Digest: Cg39XwD4090rkt00Pa+ZoMIMin36BD7CNLljxLoelGg=
+
+Name: org/eclipse/swt/internal/ole/win32/OLEINPLACEFRAMEINFO.class
+SHA-256-Digest: uXMGzu9zh9NAtkCTGL3OsBIo+hoS86bILCMuzcpP4TU=
+
+Name: org/eclipse/swt/internal/image/PngHuffmanTable.class
+SHA-256-Digest: ZDRbCrRjrenUKr9K7sXkh9r5VaHUHgScpTrHMdgO5Rs=
+
+Name: org/eclipse/swt/internal/win32/NMLVFINDITEM.class
+SHA-256-Digest: ilxdgR6Xa881E459cIX7lGzZMgXgy8gvcjUtuQZvAjs=
+
+Name: org/eclipse/swt/events/MouseListener$3.class
+SHA-256-Digest: IQjuuAKXvk/1RX7C/uDR5y9Lj24tTbofmohDWAm6vB8=
+
+Name: org/eclipse/swt/accessibility/Relation$1.class
+SHA-256-Digest: o3SQtcWNWWER+6d3LfMiEUu6RtANSzTPj2V34LWC/so=
+
+Name: org/eclipse/swt/graphics/Point.class
+SHA-256-Digest: B2GV6vr1kBW+IyBagKVq2K/ecv3Msp5sEbIRlNOJOaQ=
+
+Name: org/eclipse/swt/internal/win32/SCROLLINFO.class
+SHA-256-Digest: a3h3yQlWsQB/KHKEw2SN3PVKQ1oSNOj60x5egqqMrQ8=
+
+Name: org/eclipse/swt/internal/webkit/IWebError.class
+SHA-256-Digest: wFWNYBvuAAtsnpV0yABhrWTfGiW7Nz668UheYZTku3I=
+
+Name: org/eclipse/swt/internal/image/LEDataInputStream.class
+SHA-256-Digest: EbQSlo+4HkSxa262JMVSO/QgwBas3fPL9Uot0SNZqCY=
+
+Name: org/eclipse/swt/custom/CCombo$4.class
+SHA-256-Digest: 8TcEkjhOEgcq4ECIDO/kkH+BxbtCdvyHU4AO2lZMnsE=
+
+Name: org/eclipse/swt/graphics/ImageLoader.class
+SHA-256-Digest: aMVjC0NkVmRPPNsn3imKifz8XC5CFihKFIMLY0DWg14=
+
+Name: org/eclipse/swt/events/MouseEvent.class
+SHA-256-Digest: dUD91ffo8srettr6uaEM61w3j+oCSBQ6WfC7APygfi0=
+
+Name: org/eclipse/swt/events/MenuDetectEvent.class
+SHA-256-Digest: Ryj0ODAlfUPck+su/M4pseIPTX48WYK3Dr+T6YutJT4=
+
+Name: org/eclipse/swt/internal/ole/win32/IPersistStorage.class
+SHA-256-Digest: XtcK+qGNtvOV3Jn0PIwbsbputotEi7Na/hCWwc2pjlI=
+
+Name: org/eclipse/swt/custom/StyledText$8.class
+SHA-256-Digest: bmDApABf4J31PbFcgXwQik6P4eCdmIv9GLeDeQatk1o=
+
+Name: org/eclipse/swt/internal/webkit/IWebFramePrivate.class
+SHA-256-Digest: HgfABlzHz2TNyRF+Iiw1ZcN+JNXtxqJYYHEa80C8dj8=
+
+Name: org/eclipse/swt/internal/image/JPEGHuffmanTable.class
+SHA-256-Digest: uDaYM0nLopg65zNnWDcWrQKmy9YnpsK0uzq9sEFP6JU=
+
+Name: org/eclipse/swt/internal/win32/EMREXTCREATEFONTINDIRECTW.class
+SHA-256-Digest: 7CrHFSCjk4kqkbHzkzG/a20BZ9Vw9mN7a4GczTRHVd8=
+
+Name: org/eclipse/swt/internal/win32/TVITEMEX.class
+SHA-256-Digest: mQl6NrgYKi0XtSJaYbJtYd6U97bxNzfzwZwjQWMBOZY=
+
+Name: org/eclipse/swt/opengl/GLData.class
+SHA-256-Digest: AJyuHO35bZznEH9MXLiYIG35xQt8Z6e/aI4WxxDCpCU=
+
+Name: org/eclipse/swt/internal/ole/win32/DISPPARAMS.class
+SHA-256-Digest: 3DHZf9XZaJKpsT8tHC6sB6dirf4wG2MMOJOG6bY4+L8=
+
+Name: org/eclipse/swt/internal/image/LZWCodec.class
+SHA-256-Digest: KNLWLByENgFx1E4fjtHO/CDEUybKpmi9DcjN+fuBz4c=
+
+Name: org/eclipse/swt/internal/webkit/IWebDownload.class
+SHA-256-Digest: kcU6exb7A7LYLkdjGr/XZcaCtQXmLj3HCVhXK0zwcaM=
+
+Name: org/eclipse/swt/accessibility/AccessibleTableAdapter.class
+SHA-256-Digest: 4IiUxaR55OW8NDBmGEHMWKlhvHVgzoRWihstOPy0Fa4=
+
+Name: org/eclipse/swt/internal/webkit/IWebPreferences.class
+SHA-256-Digest: Q709lxsniNNeuL50W+RKy8EzWOYu7NkB8aFbep+RwbU=
+
+Name: org/eclipse/swt/custom/StyledTextRenderer$LineInfo.class
+SHA-256-Digest: cT/kqi/rVgY5SX4W7tD9Ze99n3KysGebECi1C+0C9VM=
+
+Name: org/eclipse/swt/browser/ProgressListener$1.class
+SHA-256-Digest: CeRzgTGa1QlMS9NWiWfGPKZMh8H2QL76v6GQpopi7TM=
+
+Name: org/eclipse/swt/internal/win32/BITMAPINFOHEADER.class
+SHA-256-Digest: EGH+2NIQX9ZzVKJO71um6j9V1VoaeAlG0eIR4tXepgk=
+
+Name: org/eclipse/swt/widgets/TabItem.class
+SHA-256-Digest: I8TirkFHi5vV+Tn9y1gLjVpk2TcZVQiroGZiRph8kM0=
+
+Name: org/eclipse/swt/custom/PopupList.class
+SHA-256-Digest: Sx76y7RpPMaaeMrnhTlCjin8I94vs8RvJ7MxRUUFcm4=
+
+Name: org/eclipse/swt/ole/win32/OLE.class
+SHA-256-Digest: a2Q4llQOBkukGbxGlzfFT6382V2dsdxx4zPMFDn8NPo=
+
+Name: org/eclipse/swt/custom/TableEditor.class
+SHA-256-Digest: JqIkQRCiEuSSXG4+I0x9MudeDUA1Lxx4JWHzqpQ5snI=
+
+Name: org/eclipse/swt/internal/win32/BLENDFUNCTION.class
+SHA-256-Digest: TrF9k4aSklmt3Uq3sgHXS3aE/jSFCkOJFZDz3K5Jmmc=
+
+Name: org/eclipse/swt/internal/win32/CERT_NAME_BLOB.class
+SHA-256-Digest: pywth4UhB/qIfd8+WlXr1gwRROE1js2jkNUMcU/TQEk=
+
+Name: org/eclipse/swt/internal/webkit/IWebPolicyDecisionListener.class
+SHA-256-Digest: 3Wxw1I7oUgnmDQa1woaip0q0Wm9e2sMtf5rl1Q4wTBw=
+
+Name: org/eclipse/swt/internal/image/PngHuffmanTable$CodeLengthInfo.cl
+ ass
+SHA-256-Digest: BmRN6Wo427wOyl2F6omAo1Oo1QVB5mxa8+VMntPeJGY=
+
+Name: org/eclipse/swt/widgets/Display.class
+SHA-256-Digest: +cJqb19c+iwBykcZT5bR8BGWDVAQMcouNir5aR3f6io=
+
+Name: org/eclipse/swt/widgets/DateTime.class
+SHA-256-Digest: StdZtyjd70YR7XAp2gad9n0c1oy+sTmNMg1fanmpN/Q=
+
+Name: org/eclipse/swt/dnd/Clipboard$1.class
+SHA-256-Digest: fLRKno+mUwmKGHlI1k5SuNIBoPO9lfQKApVPNNpv2Ig=
+
+Name: org/eclipse/swt/internal/ole/win32/CONTROLINFO.class
+SHA-256-Digest: wJ+DbK5DbvNwiFckTPIVqrTVxNaggBiDtbaHF3CJUtg=
+
+Name: org/eclipse/swt/internal/image/TIFFModifiedHuffmanCodec.class
+SHA-256-Digest: OBCy4I/t7u+Y7/Nt2hMEsDOGf+StP/HQ27eK1enlx+M=
+
+Name: org/eclipse/swt/custom/CTabFolder$4.class
+SHA-256-Digest: BJPtAltqybgKoS1CwY2qk35ys0QQcv2iDR5CYSvNdB0=
+
+Name: org/eclipse/swt/events/ExpandAdapter.class
+SHA-256-Digest: bEL192q82rI602sxZfzu1xV8SVnUyz46yhCFgVfmwsk=
+
+Name: org/eclipse/swt/internal/win32/TOUCHINPUT.class
+SHA-256-Digest: bXY3O5Mesus7UJvzUXLk/WnYjd7r8kGpuEenA16SHRU=
+
+Name: org/eclipse/swt/internal/gdip/GdiplusStartupInput.class
+SHA-256-Digest: yrUVyHgvtCIURZ5Q9G1SyfCTVPuMBTpOAXZFVStxe0o=
+
+Name: org/eclipse/swt/internal/win32/CRYPT_OBJID_BLOB.class
+SHA-256-Digest: K5LyR6/3hDXXveaJPgq6kU9r0sQBYKlLNOTg1fVQfY4=
+
+Name: org/eclipse/swt/events/DisposeListener.class
+SHA-256-Digest: v14ULc/2VNzNmqNiQQIbT8WXQCSlMxy5shHtIzppSG4=
+
+Name: org/eclipse/swt/dnd/ByteArrayTransfer.class
+SHA-256-Digest: da9dW7idIAscx+zc1DARTcPl1GbvEuEdLFpA1ncUjQY=
+
+Name: org/eclipse/swt/events/MouseListener.class
+SHA-256-Digest: cU8Hm5pQ+XEV/90FZ6Hq4j3IEr28NArhEtUDIDDfSBs=
+
+Name: org/eclipse/swt/accessibility/AccessibleTextExtendedAdapter.clas
+ s
+SHA-256-Digest: xHRbvkk48Y/rXuf495rnFpn79EvMJh+3OSybu3pvI68=
+
+Name: org/eclipse/swt/internal/ole/win32/ITfInputProcessorProfiles.cla
+ ss
+SHA-256-Digest: zLxmGezoNalbW22MwZo+/siQm8+0qjEpOROoZ+H0hq8=
+
+Name: org/eclipse/swt/internal/win32/CHOOSECOLOR.class
+SHA-256-Digest: LcY45u9BidhQNuOosXqCbDypxd44Y+X5JnqxpqnoYOs=
+
+Name: org/eclipse/swt/browser/WebKit.class
+SHA-256-Digest: Mb4SmpKvoOogwM/Z21BArJAHUpgR87NCWOMRssnwehI=
+
+Name: org/eclipse/swt/internal/image/LEDataOutputStream.class
+SHA-256-Digest: +xp/0PZwhLb8h7OWV82AlVDnApAOmS8coJpS4+6YgFk=
+
+Name: org/eclipse/swt/custom/StyledText$RTFWriter.class
+SHA-256-Digest: SI5XUJnfAnQuX8UQodEkEz2IYBDOa/zD8+pGMRQ1Eh4=
+
+Name: org/eclipse/swt/internal/win32/TCHITTESTINFO.class
+SHA-256-Digest: 4jhIV/VAUTftHaSStHI+Si+LHidAFFw1XgyBUxKX8Pg=
+
+Name: org/eclipse/swt/widgets/Canvas.class
+SHA-256-Digest: CiyhpDZWb3qbUUWQPQ30XXXnCHDx2CEhvEfshp0KtUM=
+
+Name: org/eclipse/swt/ole/win32/OleEventSink$1.class
+SHA-256-Digest: 0v40QA+3iGt2t7eu99y+KIba5MEm92G7rjzWEamVS3s=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_component_info.c
+ lass
+SHA-256-Digest: pVbsFrJGhvG0rsigEOFKsck19Ysf3JajeMktB6kvNkQ=
+
+Name: org/eclipse/swt/internal/win32/BITMAP.class
+SHA-256-Digest: 3UuOqv4VTxNL5fD8yF5QTlQjoRTwUpIznBHfX5ofIkU=
+
+Name: org/eclipse/swt/custom/CTabFolder2Listener$1.class
+SHA-256-Digest: i09F4xgVX+j9rAYrtEgFdwhor/I41V3C0u6kAI6scyA=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$JQUANT_TBL.class
+SHA-256-Digest: KkoRjG6UYSdBkTd5ohpCumM9Rpdpj8/IBuuL3I5PlMc=
+
+Name: org/eclipse/swt/internal/win32/TVSORTCB.class
+SHA-256-Digest: //FDd9HlNreXXoGteJWdTio9hdBcSZm1Vmt1jMBJBpw=
+
+Name: org/eclipse/swt/internal/image/JPEGFrameHeader.class
+SHA-256-Digest: qipSKoF6fpMZcI18pbbw7Ile2VEtJwHH2bHrKsYwDzw=
+
+Name: org/eclipse/swt/accessibility/Accessible$5.class
+SHA-256-Digest: eH64pwQCBFwFi//mXEUysqdXEB7nXQMYalhNi5DnWfc=
+
+Name: org/eclipse/swt/widgets/Touch.class
+SHA-256-Digest: srAXHf8PLW8+Zp9/noVr9VA7NCeWvIiQOWFNtRKUeuI=
+
+Name: org/eclipse/swt/internal/webkit/IWebCookieManager.class
+SHA-256-Digest: kLLG9jR8wPN8pE09CVBcJl7I33CYt2FQ0mLlEbYbZGY=
+
+Name: org/eclipse/swt/graphics/Rectangle.class
+SHA-256-Digest: 3Z0oMyU81jj+wM1Min0Y6jpdC0UBb4N3DjhEh+40Kk0=
+
+Name: org/eclipse/swt/internal/win32/SCROLLBARINFO.class
+SHA-256-Digest: meeBZTdGzPjomv7q61ga3k8SvStLnZQq5KuHa1UA3Hw=
+
+Name: org/eclipse/swt/internal/opengl/win32/WGL.class
+SHA-256-Digest: RrLsgOEnEvFs0O/xZwBcTb2qeA+IGclLOPcJitNfLBA=
+
+Name: org/eclipse/swt/browser/CloseWindowListener.class
+SHA-256-Digest: dQhU7HMEqRIxsPisqIbCsx9dB/zAru5f+kMUSUCzwrA=
+
+Name: org/eclipse/swt/accessibility/AccessibleTextEvent.class
+SHA-256-Digest: FrderEegLNILO+TUCiW90wFR0jLB0cE5YdzKjtUW+sk=
+
+Name: org/eclipse/swt/accessibility/Accessible$6.class
+SHA-256-Digest: cvuU4EkOmLoqODWbX/1POb6/wbKL8kiZi4UNaY4P9bg=
+
+Name: org/eclipse/swt/widgets/ToolBar.class
+SHA-256-Digest: CmlnhIBmhfVI7xJtlPlhxxDjfIDEK96mUIjfndU5vwA=
+
+Name: org/eclipse/swt/internal/win32/NMHDR.class
+SHA-256-Digest: jFCUtVUZ3DHTZ6Ylub5XwI/kxxgd09nbBwGHsWIyflI=
+
+Name: org/eclipse/swt/internal/win32/LVHITTESTINFO.class
+SHA-256-Digest: OafthNPXjlo+PmXlLMv/25jBw4AvgSgNkkHbCzpGmY4=
+
+Name: org/eclipse/swt/program/Program.class
+SHA-256-Digest: XYcAmHWBE6xm4AquE8sAxFoO4nEJVE6H8DHKeaL+kkM=
+
+Name: org/eclipse/swt/widgets/Spinner.class
+SHA-256-Digest: KWdIMrSCEvtDLUcHma6wSakUpZ8+wUOpXM0jTLVfCxY=
+
+Name: org/eclipse/swt/events/MenuListener.class
+SHA-256-Digest: clu3ffe9o8hgh9HNR2y8vnWxIoLmW+RrqOUBm5Hz420=
+
+Name: org/eclipse/swt/custom/TableCursor$2.class
+SHA-256-Digest: /PvKN3oSbtqUQS+DEnYdcrPXPkdaL93goPvIyjNcVys=
+
+Name: org/eclipse/swt/events/TreeListener.class
+SHA-256-Digest: /F7wnrzFSN6tLA5qd31jAeRbj/BXfhjgxeOaD/F1cqg=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_ANALYSIS.class
+SHA-256-Digest: CtZh60HSToZX2pUeLLY5EXqPP05qMRwQNkqRc8w5eMk=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$bitread_perm_state.cl
+ ass
+SHA-256-Digest: uuj+rUIcgllnNf+4wD5bkRVxmLNzqis64RydJsSxR58=
+
+Name: org/eclipse/swt/internal/win32/MEASUREITEMSTRUCT.class
+SHA-256-Digest: coP0iMM/KbieF/mY34UWtyxe6D78wWqHSWf/UrXMwY0=
+
+Name: org/eclipse/swt/browser/Browser.class
+SHA-256-Digest: gxjyZr50Qllg8/z8LRHx8dz467bKKQ0eOqrmAxmvlO0=
+
+Name: org/eclipse/swt/events/TouchEvent.class
+SHA-256-Digest: mFSCKtrbSNbNHbPpNKVk03SJBIDt1S4hcfahZnyIxM0=
+
+Name: org/eclipse/swt/custom/LineStyleListener.class
+SHA-256-Digest: 2QsokpVELfKrWnvMMn2+3jDlaxp0J5LLG9IA2NMl+Ls=
+
+Name: org/eclipse/swt/internal/win32/HDLAYOUT.class
+SHA-256-Digest: KnXAv8a5julP4Bkw7RnQVX3ir5H7Tc3yHo4ICz+sfQU=
+
+Name: org/eclipse/swt/internal/image/PngDeflater$Match.class
+SHA-256-Digest: mVC8wQBh7BhlsOsV25DbWx0D7VQBJ0g4X9JwZ92h4W4=
+
+Name: org/eclipse/swt/widgets/Caret.class
+SHA-256-Digest: zEfmD7v5PD3DqDkOSmP3/rPBLP8gw0kv8tMS0tzpguo=
+
+Name: org/eclipse/swt/browser/WebDownloadDelegate.class
+SHA-256-Digest: HCT2mRlt1k3DUWucLIqXRbzira9+Ea9vuCJAOiD9qR0=
+
+Name: org/eclipse/swt/browser/WebUIDelegate$1.class
+SHA-256-Digest: 334luzIoHcEuMxyBEro8YX1q3qlqLmZ0cY3o976Qu4w=
+
+Name: org/eclipse/swt/internal/image/JPEGSegment.class
+SHA-256-Digest: D9rgGsuC+h6hs6hiIax99K/J6d9ulCmtvxG/NFYxELg=
+
+Name: fragment.properties
+SHA-256-Digest: axTKjveT9gk8k+GSRx0DSowgDF/95Y43zFp6/1WwxTg=
+
+Name: org/eclipse/swt/events/KeyListener.class
+SHA-256-Digest: kcVX0u+vNS2n+RGxqh+XcNCM77gQQDWagzgBecqsnjU=
+
+Name: org/eclipse/swt/internal/image/TIFFRandomFileAccess.class
+SHA-256-Digest: hq9X4ZT2YH5d3Eu7GVw+7XXogdEjMlQGZp62IuK2zMk=
+
+Name: org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallengeSe
+ nder.class
+SHA-256-Digest: xMJu/Jx+OxR1Oj0tN8+eK4UxJDypXQdax3ccCGknvz0=
+
+Name: org/eclipse/swt/events/ModifyEvent.class
+SHA-256-Digest: 12PAxXZSjxnemYQAh68N40hki3EUcZO+E/qijAypUmk=
+
+Name: org/eclipse/swt/widgets/Group.class
+SHA-256-Digest: UA2j7+6l/+iw7kgudz3PsR4TsD5cZ2Qs5oi/I2hxsxs=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$huff_entropy_decoder.
+ class
+SHA-256-Digest: A7MaalOqnK8sazYBgQgLIPxVHDFvFPTk09s1I6eky1s=
+
+Name: org/eclipse/swt/layout/RowLayout.class
+SHA-256-Digest: NfhHChAPS5GfJk4MlULV6eSN8UpZjyTo0kKUkBHbrcY=
+
+Name: org/eclipse/swt/events/MouseTrackListener$1.class
+SHA-256-Digest: eL4i6Q97O/YfmlQzBJgjRys6rrf9sqUD08u9fuywa2o=
+
+Name: org/eclipse/swt/internal/ole/win32/IProvideClassInfo.class
+SHA-256-Digest: D9FmqsQUMWK67N7WzuyKfwQpfluqGKXJoBhfdTztboI=
+
+Name: org/eclipse/swt/events/ExpandListener.class
+SHA-256-Digest: 0kpvEs3Kr0gEojdV3yqfokvt4F0T1qRVJwt0/XIWBFY=
+
+Name: org/eclipse/swt/internal/webkit/IWebErrorPrivate.class
+SHA-256-Digest: dnzcpmK76ztO+dBOANcIdrSLmoMdC5HHpwVUa7K9BXE=
+
+Name: org/eclipse/swt/browser/WindowEvent.class
+SHA-256-Digest: PMn0Gu9hpG0AFA0vxfyoKNFk1ps1NjlPpoijG1cxVMk=
+
+Name: org/eclipse/swt/custom/StyledText$Printing.class
+SHA-256-Digest: dqLSxWeZugt1fxzZYs0VXS5nwe4kfVtnoNRFMra1elQ=
+
+Name: org/eclipse/swt/browser/TitleEvent.class
+SHA-256-Digest: hldsbbNyrrZuU7ezBqvHaevqGHCrmwfD5e22zFeONEs=
+
+Name: org/eclipse/swt/custom/BidiSegmentEvent.class
+SHA-256-Digest: xPLLR0ShRvhwjBSx8UepUVZ4T8Fsv9tPcY3Be6F5orU=
+
+Name: org/eclipse/swt/internal/win32/FLICK_POINT.class
+SHA-256-Digest: FdIIMdLw36UxSEaDH/tbO5ocHiy9DGfsOFARXkPq6F4=
+
+Name: org/eclipse/swt/custom/LineBackgroundListener.class
+SHA-256-Digest: u6YltPzPv3y9oc1YpFYSYuIfmqxtQti77pNcKHH11gk=
+
+Name: org/eclipse/swt/internal/C.class
+SHA-256-Digest: pHTM+cCFhrJ/ApVe9qZsAISrjTtFzgB2ab0csPZN9KA=
+
+Name: org/eclipse/swt/browser/WebSite$5.class
+SHA-256-Digest: aWYfdJZvqWJcxiH2D20rEl8OSx985XfVMGSW2jpbYV0=
+
+Name: org/eclipse/swt/ole/win32/OleListener.class
+SHA-256-Digest: AKkvzRLNAonkPtTL1Krd6Uv4D90h0afWJkzPpK0U9Tw=
+
+Name: org/eclipse/swt/internal/webkit/WebKit_win32.class
+SHA-256-Digest: 82+//I1UARK6GscBhq4GGUmM9aGc47NPL6xAWIogw/Y=
+
+Name: org/eclipse/swt/browser/LocationListener.class
+SHA-256-Digest: IPdOQhy8HlCEaOK42cfRP54RwZ8+49tj0O/VwQgWwww=
+
+Name: org/eclipse/swt/custom/TreeCursor$1.class
+SHA-256-Digest: I1nWYyTVdZZDLQMBPuthHh2/CdE+LCrA/odlFmfBzak=
+
+Name: org/eclipse/swt/events/PaintEvent.class
+SHA-256-Digest: dgbDCN6qzW0v63O/J75qQsxoidDUgvQCOLjo7oRGaDk=
+
+Name: org/eclipse/swt/widgets/Tree.class
+SHA-256-Digest: An3BtP5LE5Lt3MqRzLVs3UILC3cRoim9cSKCjJQO5ds=
+
+Name: org/eclipse/swt/accessibility/AccessibleValueEvent.class
+SHA-256-Digest: Kg3xrU8r6Mdq9IZsZ04fpXIO6xvHs1VaggqfuaZUJ7U=
+
+Name: org/eclipse/swt/custom/CLabel$2.class
+SHA-256-Digest: rV0r5KKdJ4dzDfLtzGEiypqWCsmUaJNXlQPIIGZ5Beg=
+
+Name: org/eclipse/swt/events/PaintListener.class
+SHA-256-Digest: isR2hw7s4qxhEomos2briYlr3neW5WKY2hm6kU/H1cc=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleInPlaceObject.class
+SHA-256-Digest: hxe8efK5o4wF3hfswxmbUB81jxFgC+c0K8TUanUafmo=
+
+Name: org/eclipse/swt/custom/StyledTextDropTargetEffect.class
+SHA-256-Digest: 1vrZAnvw3MqGfOUXjtFBx5ORRUXsTdkNVaWbz/VBwmE=
+
+Name: org/eclipse/swt/accessibility/AccessibleActionAdapter.class
+SHA-256-Digest: cVh4OwICSV0MMH8pMLa1NStn9BjJ3NOSJzfaHeY0+Ng=
+
+Name: org/eclipse/swt/ole/win32/OlePropertyDescription.class
+SHA-256-Digest: m99Rg0gxhbL04h95kH/CkrUThAPhYp14nevvperJWO0=
+
+Name: org/eclipse/swt/internal/win32/TVHITTESTINFO.class
+SHA-256-Digest: ZzOOnQ+2HBRJ/JNVCZ6Sk0PbRcP0K0uuRFS7OYmbKAY=
+
+Name: org/eclipse/swt/events/TouchListener.class
+SHA-256-Digest: FVySObUfFNoPoeOzSERKOW3HTDll0TtOAn0+MPSCsD8=
+
+Name: org/eclipse/swt/custom/CTabFolderEvent.class
+SHA-256-Digest: CV3NrYPvscKYMAd6c2lTipVIFviBhHieZsybuP7BF4o=
+
+Name: org/eclipse/swt/internal/win32/SAFEARRAY.class
+SHA-256-Digest: w/1DFv9hSrX0q1eiAox2GAjuZV42ibaZPG4NwmhUXOE=
+
+Name: org/eclipse/swt/dnd/TextTransfer.class
+SHA-256-Digest: rtFNzuux8/wrQ4nkSHb48UmVrJx0HLRoXFsyRJr9ou4=
+
+Name: org/eclipse/swt/custom/CaretListener.class
+SHA-256-Digest: KXL0l98WA7SQOeStZeWUx0ActwEYckeH1rmUjcfxaGc=
+
+Name: org/eclipse/swt/custom/VerifyKeyListener.class
+SHA-256-Digest: +h5OWSnmKrQ5m3ZdZ7AS/Jj/pX9EtA22suO9PrcKaLg=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleLink.class
+SHA-256-Digest: J9RE9zhDWac0v3ZS2/PP4hn+ECIWmlyGDQV6SNMc8z0=
+
+Name: org/eclipse/swt/internal/image/PngInputStream.class
+SHA-256-Digest: SeY4pYBdSAWhaf6JfSLSo25a/YSuC0c/5ie5/Rbxvyw=
+
+Name: org/eclipse/swt/custom/CTabFolder2Listener$5.class
+SHA-256-Digest: NRzo3Xh4ygpXkYt97vcP82O4glJWqlrGmNpG+/wKc5c=
+
+Name: org/eclipse/swt/widgets/List.class
+SHA-256-Digest: bAW7oGgBdXEOsAO5EU4Q3hZHd5Ea3s21GSZQ69tT1LM=
+
+Name: org/eclipse/swt/dnd/DropTargetEffect.class
+SHA-256-Digest: 4chUmIrOw3tNM3X5E7mORh5u7JrNuPGTAKYUKxkTS6Q=
+
+Name: org/eclipse/swt/internal/win32/CREATESTRUCT.class
+SHA-256-Digest: QubU2mFEed7SinzJXuSUSCugK9cKipH4ui3Z+mbehZc=
+
+Name: org/eclipse/swt/internal/image/PngEncoder.class
+SHA-256-Digest: wPd+nnqGc3KUkNCwHN8HRsaLzrT1CCnQ/E+9m1rcCgQ=
+
+Name: org/eclipse/swt/custom/StyledTextPrintOptions.class
+SHA-256-Digest: gSmstx2jcNc/+VgbyXux2ihsEJsMim+L1Lb2JZq0xlI=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$JHUFF_TBL.class
+SHA-256-Digest: 1tvmEc6/jb3wEsO/d14Beedz2f2g/CEQkW/FlJ3m+AA=
+
+Name: org/eclipse/swt/dnd/ImageTransfer.class
+SHA-256-Digest: xwvXJfWcV0uEx2fZrIXmV7lYYhC6fkWP9ozd+piQXzA=
+
+Name: org/eclipse/swt/accessibility/AccessibleControlEvent.class
+SHA-256-Digest: 1o0xLprQ2jFMuhCiVbZbRcTEVe9w2m+K1c6UvywVrUU=
+
+Name: org/eclipse/swt/widgets/CoolBar.class
+SHA-256-Digest: IBKDM6VvbnrMEzhctQzLbX+TAZpSO2RvhD0Y7g6zn4c=
+
+Name: org/eclipse/swt/widgets/ColorDialog.class
+SHA-256-Digest: 1b8u4UNopSwVdpxZrJEPWiWB6jmUEIq57KqGloT+o8o=
+
+Name: org/eclipse/swt/widgets/TabFolder.class
+SHA-256-Digest: sTrSTr7fShOWD42b8sAXqcCMgKugWju4Ym4a1Hs3B1s=
+
+Name: org/eclipse/swt/internal/win32/NMREBARCHILDSIZE.class
+SHA-256-Digest: bwukbx4mi8qrNrY9w0ZuP5wdZSyE9OuQrZRdro1zMpg=
+
+Name: org/eclipse/swt/awt/SWT_AWT.class
+SHA-256-Digest: MT0+8NimQr8CHsGxa+5pnJKKFg0JDX+qQMnMAmy8bl8=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_d_post_controlle
+ r.class
+SHA-256-Digest: sdnS6/zty5J6fsQajimURHbEyxdaaIzCEjnpBjyLBnU=
+
+Name: org/eclipse/swt/internal/win32/OS.class
+SHA-256-Digest: h30Xv+nSFz3bdXFmrgDepBH6D64ok+AEQrNNfsCiKcY=
+
+Name: org/eclipse/swt/ole/win32/OleClientSite$1.class
+SHA-256-Digest: rFIk0r/Sq9A/yFvxde1yNxtVOQhXuQ+knSZ9s8akvy0=
+
+Name: org/eclipse/swt/internal/image/LZWNode.class
+SHA-256-Digest: T6NS47/Ex/EA3I/muPIwcW9q3Lavi+nWkmCd1DRPIhw=
+
+Name: org/eclipse/swt/custom/BidiSegmentListener.class
+SHA-256-Digest: cXHct7+MfWEAcyxNQzrbjV5gQtWM0p5h/Smhi6auzjI=
+
+Name: org/eclipse/swt/dnd/DropTargetEvent.class
+SHA-256-Digest: Zk11H38a6gRqXJPAfaZ2ZteelNAQpyrbbYHR/T2BBGI=
+
+Name: org/eclipse/swt/browser/WebSite$4.class
+SHA-256-Digest: EZapExFNvLYA6uLy4vRvApgMOCAIl+OgEc5W3Wl4xLo=
+
+Name: org/eclipse/swt/widgets/ExpandBar.class
+SHA-256-Digest: Qu0J3BEhC10mAX0U76yFG48WhvhNUDRfIdMXPmnqsaA=
+
+Name: org/eclipse/swt/accessibility/Accessible$1.class
+SHA-256-Digest: VzVvPiBNOL07YMZU8yBx9Jb3c0aCYAKXy/+mh2YPVmU=
+
+Name: org/eclipse/swt/dnd/DragSourceAdapter.class
+SHA-256-Digest: qEv1XTfIhE6aLzCdIk1d93ZX6mAF+7Xsl/7176KwvAI=
+
+Name: org/eclipse/swt/layout/FormAttachment.class
+SHA-256-Digest: GOPqijqGhFJcl+um7S3hOw7wxgfPGKQsIQRp9t3ppnE=
+
+Name: org/eclipse/swt/internal/webkit/IWebDocumentRepresentation.class
+SHA-256-Digest: 6SjzlenM2XsmW36qpad8kVVRPdVewpuQVOsYy/J/qhc=
+
+Name: org/eclipse/swt/internal/ole/win32/GUID.class
+SHA-256-Digest: vn6w5kPbl2Fm453eZK5aZyMMKjhTJWYJZBnLAfsrllo=
+
+Name: org/eclipse/swt/custom/TreeCursor$2.class
+SHA-256-Digest: qfcac5cHfBPUxd8GI9335v0/lIC5VSHK9suaPZAmmMg=
+
+Name: org/eclipse/swt/widgets/Monitor.class
+SHA-256-Digest: EFkobk8gqSvKFlz1MyaUy9MIXXnEOtxe/MAm11p+fSw=
+
+Name: org/eclipse/swt/browser/WebUIDelegate$6.class
+SHA-256-Digest: O3h8nsc9zavj/lN4C2NEIBvhpRsf7HUx+ObISHos6bs=
+
+Name: org/eclipse/swt/accessibility/Accessible$11.class
+SHA-256-Digest: 516sGVYBCOTrl6imk+ImZ1GHgXflXf0vW9u+dPvTB+s=
+
+Name: org/eclipse/swt/internal/BidiUtil.class
+SHA-256-Digest: wOHrTaayfBiBqraw4qTL2s0KqIznOYbEd+3az5dzPRw=
+
+Name: org/eclipse/swt/custom/BusyIndicator.class
+SHA-256-Digest: XPAEyUhok+LOlv/cv6C5yXEQywUMPgwDETe20Rwm/3U=
+
+Name: org/eclipse/swt/ole/win32/OleClientSite$2.class
+SHA-256-Digest: ETmuXmkLe2KCCTIrTfCzyzn9nArT4EvyyxOKk98j15g=
+
+Name: org/eclipse/swt/accessibility/AccessibleControlAdapter.class
+SHA-256-Digest: FGhjf5bIokuNUY5YFX0N2xYq0FXVt5wTPUuXADmoxFM=
+
+Name: org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeProvider.c
+ lass
+SHA-256-Digest: iQRpmGlUzabnlCR4Y8plfcdICyiuwyeGNNhBPPzLDeI=
+
+Name: org/eclipse/swt/events/FocusListener.class
+SHA-256-Digest: oJmYR4UUr9ok9sHaRNI1QeM+xUElWILQn+IXizhxjjg=
+
+Name: org/eclipse/swt/widgets/RunnableLock.class
+SHA-256-Digest: 8brlLjEnEYm+Z6wWWo1ai1wLQvidlXiRiQFFtoV7MNE=
+
+Name: org/eclipse/swt/internal/image/PngTrnsChunk.class
+SHA-256-Digest: mo2RtXfXDV/gHxziv7kCIlbbtoXllKJQ0uhIbdx2LCQ=
+
+Name: org/eclipse/swt/internal/win32/CERT_PUBLIC_KEY_INFO.class
+SHA-256-Digest: KVpHtRrYT2OwdqY2GKzjYe/+sRRo4WJSt9EbN9Etm9g=
+
+Name: org/eclipse/swt/accessibility/AccessibleAttributeListener.class
+SHA-256-Digest: qeeQXXkQ2YBwsC6dH1r1HprDgrF2XGKxHPlQeQPz5lc=
+
+Name: org/eclipse/swt/events/ShellAdapter.class
+SHA-256-Digest: Cg+S/HgeqsaGd+hYIUgIXFbFqN0sOQwYA/FnGxdCBK0=
+
+Name: org/eclipse/swt/accessibility/AccessibleEditableTextAdapter.clas
+ s
+SHA-256-Digest: +iD5pv0KPqWvpX9twsDazhOlaN6n1hFiWMYA3I5d2GM=
+
+Name: org/eclipse/swt/internal/ole/win32/IConnectionPoint.class
+SHA-256-Digest: SMXDZECGwSyMhuAFqEhfS2ACqH6f0GvYEf6aAkDd/C4=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_CONTROL.class
+SHA-256-Digest: /ncevCYRRBEaAfh7uPeaE4lNHPOw3gI6mju6aGxe3D8=
+
+Name: org/eclipse/swt/internal/webkit/IWebURLProtectionSpace.class
+SHA-256-Digest: brdOZWBLecxWwVkQgBJUIU5bnW30QJfYpZ/qyixvDkU=
+
+Name: org/eclipse/swt/internal/win32/TRIVERTEX.class
+SHA-256-Digest: 1APJXZQJTGXog4H7E1iqfbydpZE1dkhC8/95Nsfkz0I=
+
+Name: org/eclipse/swt/ole/win32/OleClientSite$3.class
+SHA-256-Digest: oLGHiYe4TuWzLFamek2zCzQbk24PIORHFKM/86POkG4=
+
+Name: org/eclipse/swt/internal/ole/win32/STGMEDIUM.class
+SHA-256-Digest: fyqGWgsCpqB0oa1v9bm5kubDEPDrZKH8L6soKWVRLY0=
+
+Name: org/eclipse/swt/accessibility/Accessible$12.class
+SHA-256-Digest: ut/80HGM6sM++/BlWEgmT8mvGCt6Sy3EqOVbMaVbWrI=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_LOGATTR.class
+SHA-256-Digest: zlOmZ57DcHsL+cNNL5SB2NAS3oaxD0cFVPTRfX9hagk=
+
+Name: org/eclipse/swt/internal/win32/WINDOWPOS.class
+SHA-256-Digest: tqsi1TgKI0KdOgHTfrv0Ck3yfAvFtiscqpk2UT14YzY=
+
+Name: org/eclipse/swt/internal/win32/TF_DA_COLOR.class
+SHA-256-Digest: D0kjE2Zb6m6Jlg4OrOraHzZaTJnhWoB44rkUBwniQMg=
+
+Name: org/eclipse/swt/browser/WebUIDelegate$5.class
+SHA-256-Digest: P05d4ir1bUvBiF8bSX6RoROdUC4Ge8F2eWTwxnWNjOw=
+
+Name: org/eclipse/swt/internal/win32/NMTVCUSTOMDRAW.class
+SHA-256-Digest: 5KNs97vWqWBs7oaQnM/V3ZqYa3FsVHoKk9KuoOxwl1I=
+
+Name: org/eclipse/swt/internal/ole/win32/IEnumVARIANT.class
+SHA-256-Digest: 97cIKd02ogzlbgusssYyVUr6IwdY5V6gQVUSVam1i8Y=
+
+Name: org/eclipse/swt/internal/win32/RECT.class
+SHA-256-Digest: qVgldU7mj3pxrNAQZZZyZwUAri2ms4wfDVmG/4cOtZE=
+
+Name: org/eclipse/swt/accessibility/AccessibleEditableTextListener.cla
+ ss
+SHA-256-Digest: EjPno3gJTxNasXdxoxRBy30EDU2bqH1WolltmQQXUJM=
+
+Name: org/eclipse/swt/custom/PopupList$2.class
+SHA-256-Digest: 9sjsQ2LWFvISYqIIGdjGbSvuF+6GN24Hs1exK+5mEzE=
+
+Name: org/eclipse/swt/internal/win32/PROCESS_INFORMATION.class
+SHA-256-Digest: gkaIpy2bGo0njs5WjTyWg3bhu8eQA5rWq+VvBYYkqvo=
+
+Name: org/eclipse/swt/internal/win32/WNDCLASS.class
+SHA-256-Digest: tCdW/Lxg+NkGlcMyR4udU8XifU4scNHLuQFLbx3t8rE=
+
+Name: org/eclipse/swt/internal/win32/LITEM.class
+SHA-256-Digest: /wJcy/gzaV/YfVA5zc/Jd0roxTucNmmo2d5RAG0LWZ4=
+
+Name: org/eclipse/swt/events/MenuEvent.class
+SHA-256-Digest: 5v8bvf7VkCOO/3mDFTkOTlS3lHrAnmh2pSHQscduQQs=
+
+Name: org/eclipse/swt/ole/win32/OleControlSite$2.class
+SHA-256-Digest: 4qGwM/EaAgi/tu6iTElUcRY3umQkWwcCXUD/7UJEWLs=
+
+Name: org/eclipse/swt/events/MouseMoveListener.class
+SHA-256-Digest: klWjDrtCDFgZoN6NqcOzrK1KPykkNKk/N4mn02pcTEc=
+
+Name: org/eclipse/swt/internal/win32/HELPINFO.class
+SHA-256-Digest: kbBjl3JIWnMNvinrThZy6kLGiRCt9HIKoDPs7IcGSdA=
+
+Name: org/eclipse/swt/internal/win32/TVITEM.class
+SHA-256-Digest: rfickpuAWXHVB5EMBM0poFx/SdpesEEhdTPETYCfPp4=
+
+Name: org/eclipse/swt/internal/win32/NMLVODSTATECHANGE.class
+SHA-256-Digest: 5D7jCIZmWw8ixNMeXhH8IhqA1ujMokMxlQ9zYTwfPPs=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_marker_reader.cl
+ ass
+SHA-256-Digest: Mas1IOtJXRUhq+vgIPd39RE2y6Cri+jVmmOtJ2t45yI=
+
+Name: org/eclipse/swt/layout/FormData.class
+SHA-256-Digest: ppYytholDqBpFYSh4fQyToJSkTSmygwdKXZfAJO+jyg=
+
+Name: org/eclipse/swt/graphics/ImageFileNameProvider.class
+SHA-256-Digest: NsDtc9VBut+MGPApR6sul+pepcs47tmw3CIkmzGFJ8E=
+
+Name: org/eclipse/swt/custom/StyledTextRenderer.class
+SHA-256-Digest: vnDpuElcVkWfFbPmLc0iw29ZdD19TtjtYnr8WRA6loI=
+
+Name: org/eclipse/swt/custom/StyledTextRenderer$StyleEntry.class
+SHA-256-Digest: nDSH8kB+dhYM3qsVDkAC3wmXwJM8mzuP9Yuvs+RFWU8=
+
+Name: org/eclipse/swt/internal/ole/win32/IStorage.class
+SHA-256-Digest: 6FcMbnKoQ81akQeMNtii5Z9cFM+nmskZoYW3/bADwq8=
+
+Name: org/eclipse/swt/internal/win32/NMLISTVIEW.class
+SHA-256-Digest: 0Px0vkV43fQkRf9urEtWN8SDw8PbdkBjZvsSKu7ak2E=
+
+Name: org/eclipse/swt/internal/win32/POINT.class
+SHA-256-Digest: 2PMoVHVuFyvqa/8uoB7CD8NKphexS0RCerIKzVEZ6gs=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$phuff_entropy_decoder
+ .class
+SHA-256-Digest: 8iErzpf8Zc3nKB1mci1H80w76Tg1OunhozNMOsiZHRg=
+
+Name: org/eclipse/swt/widgets/Widget.class
+SHA-256-Digest: v4dRx/DFapGbiMIDhCWBCBHYn2f+r0JPXtyk3rytGzo=
+
+Name: org/eclipse/swt/custom/CTabFolder$3.class
+SHA-256-Digest: cUFoAfv64/wN2V2L3kCUyPIiQ3gQFD+bh0lEsy+yWPY=
+
+Name: org/eclipse/swt/internal/win32/MENUITEMINFO.class
+SHA-256-Digest: L4jKVMC4JBHyBfYltLuBkAsp66u6jsPMT5c7dQWsyoo=
+
+Name: org/eclipse/swt/internal/ole/win32/IEnum.class
+SHA-256-Digest: O8qhhlUwNMBCDo2HYnIEK7lMc85r/urLFJs8gg2CRHY=
+
+Name: org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallenge.c
+ lass
+SHA-256-Digest: 5FpWSVhsdeR1pVOYKPQqwdUKMVNZxFrGHVBk9QIjpH4=
+
+Name: org/eclipse/swt/internal/gdip/ColorPalette.class
+SHA-256-Digest: OMDnUwq74RmF+f+zdYre+shyGQEQz/pbmzMUFuMcBhk=
+
+Name: org/eclipse/swt/browser/VisibilityWindowListener$1.class
+SHA-256-Digest: wxojriAUHZvlbZvVCx7CvTNboQtyphyp2NM4oCsWnOk=
+
+Name: org/eclipse/swt/browser/OpenWindowListener.class
+SHA-256-Digest: zTYIsQBn50YO/nRRnOoclp4vwWOuZhO4UMztx4IRVtc=
+
+Name: org/eclipse/swt/internal/ole/win32/IStream.class
+SHA-256-Digest: 8M4+D31w0MDIyHbxr4wUlGSrIokm7iZB3nYEkwBPMWE=
+
+Name: org/eclipse/swt/browser/ProgressListener$2.class
+SHA-256-Digest: AV2SzOXFMJRvL0qgtVLFzmPpf05op3Ai/BG3y2ZQrHo=
+
+Name: org/eclipse/swt/internal/win32/CRYPT_ALGORITHM_IDENTIFIER.class
+SHA-256-Digest: UrgYk9a9jMVefuXaifogQDxF2jlX5MetRpC4wntD1ls=
+
+Name: org/eclipse/swt/internal/win32/LVCOLUMN.class
+SHA-256-Digest: /XWCiYS7USGzsK/UQHHN0ek69N1fiY07+KJwBOelzy4=
+
+Name: org/eclipse/swt/dnd/TableDropTargetEffect.class
+SHA-256-Digest: KN6TR6gjeCobgpw6B6AvK9PGpWW0srVe6399tVfwq7U=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_FONTPROPERTIES.class
+SHA-256-Digest: KQCREd+rLzsdIaUeQq8z47AHFKwW9TAJuomp/KMGg9c=
+
+Name: org/eclipse/swt/accessibility/Accessible$2.class
+SHA-256-Digest: Zadsg0Ea5q8NccS83Wi6V3iWV3dXo4eUIXFYIER20uI=
+
+Name: org/eclipse/swt/internal/win32/DTTOPTS.class
+SHA-256-Digest: iwU00RZawqORSqhRg8TYJ1nyE0MbpTcHiDt4Mt37nLg=
+
+Name: org/eclipse/swt/events/MouseListener$2.class
+SHA-256-Digest: zarlvNP4pXuQ3pvLMiJPj0CNV674fgTVLryEPmivEt8=
+
+Name: org/eclipse/swt/internal/image/JPEGEndOfImage.class
+SHA-256-Digest: B1VG8eh2rg/jwkQPLwUqXvtjWlhEOWCvp0vjRqv+eAY=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$d_derived_tbl.class
+SHA-256-Digest: F18i+RWIKmq6yH8S7xCdVV2h0aDd9Kdx5zjwkUsMCNU=
+
+Name: org/eclipse/swt/internal/win32/CANDIDATEFORM.class
+SHA-256-Digest: ss+GOIhWVKgY8xM4lZlqxgfVtws45aBb9LNKMiTPM0g=
+
+Name: org/eclipse/swt/widgets/TreeItem.class
+SHA-256-Digest: zXIZsYldke970KM2AvWtN0LYOrAachcNS+NGGTW7GoE=
+
+Name: org/eclipse/swt/accessibility/Accessible$9.class
+SHA-256-Digest: QX82c4G6ub15+6SQ7WRhcmlw/FJ+lIYhNr3V8U1G7pM=
+
+Name: org/eclipse/swt/internal/win32/REBARBANDINFO.class
+SHA-256-Digest: vfcXxyG59vRpwCHapjLFQLwLf2ImjV8nBRfMGpv9Yhw=
+
+Name: org/eclipse/swt/graphics/RGBA.class
+SHA-256-Digest: 31WqwmUEaxtRTjTY3Ql4LCkD9pQ7c/v7nesw7VA59x8=
+
+Name: org/eclipse/swt/internal/image/PngChunk.class
+SHA-256-Digest: 5aMHCviB/PTq7IZOgdokpfBv/KSKbjPmwWgOZaNMupk=
+
+Name: org/eclipse/swt/dnd/TableDragSourceEffect.class
+SHA-256-Digest: nrirTmyG8qCAF2kOogbjNd0dfrPatAW90v7WQOlnKus=
+
+Name: org/eclipse/swt/browser/BrowserFunction.class
+SHA-256-Digest: rsegVqAZjiGI9YVi993DowvFfFZ+mbu+NGw3Jk18rvk=
+
+Name: org/eclipse/swt/custom/TreeEditor$2.class
+SHA-256-Digest: frwFAeIATDOn/TowR1N7e+AZN+tI8L/kPUpqNxcK6pU=
+
+Name: org/eclipse/swt/events/ExpandListener$2.class
+SHA-256-Digest: S4wjvRyJccz7SyiyghRYEF0pdMOcQk5+YtsAfxabeQg=
+
+Name: org/eclipse/swt/widgets/Table.class
+SHA-256-Digest: 7ZNAh8azDiiAPhr6ywx+tqRUn06Uc2oPbqRFwoKjuuU=
+
+Name: org/eclipse/swt/graphics/DeviceData.class
+SHA-256-Digest: 5GqXrg45uUIXtiZmycehV//iJGUlLellkLPP272t8MU=
+
+Name: org/eclipse/swt/browser/IE.class
+SHA-256-Digest: uJc/SjJXCvpJZw53j/6EI6WbSlEFKxSiCWPFLfhCdR0=
+
+Name: org/eclipse/swt/widgets/Decorations.class
+SHA-256-Digest: DzuUwPqtj4J3sRWko72n8VbDRaOdpl1rOTiw1fJCvvA=
+
+Name: org/eclipse/swt/internal/ole/win32/VARDESC.class
+SHA-256-Digest: 1c7nNrfO7hwbKD43mYTCx9vDixvgHNtAXS4Z5wvZB9E=
+
+Name: org/eclipse/swt/graphics/GCData.class
+SHA-256-Digest: EUPN9pF6rtjHAkuzG+6J4w87Lq+nVrxCAUpLkoednlc=
+
+Name: org/eclipse/swt/browser/VisibilityWindowAdapter.class
+SHA-256-Digest: 8AzzV9+zyW13Tuki+U4JRf0zZ0AT4eUFrzyoZt6rKUw=
+
+Name: org/eclipse/swt/accessibility/Accessible$7.class
+SHA-256-Digest: 3y+LBer2f6KYKMjktSmbIkdbXfw+PYdJOpl6lZQB0p4=
+
+Name: org/eclipse/swt/browser/LocationListener$1.class
+SHA-256-Digest: ybTz0o2GQfQaI50ZutFGZJLoFqntFQw9GwaVtJCmyko=
+
+Name: org/eclipse/swt/widgets/TaskBar.class
+SHA-256-Digest: rBApwz6QJiZoP5skz+FK9un93FPB2SinbTil508xAVo=
+
+Name: org/eclipse/swt/widgets/FontDialog.class
+SHA-256-Digest: MgMC3kOYh7i7wKhjpMdP2xfGu9MB96aB8gmrw0zAbfA=
+
+Name: org/eclipse/swt/internal/opengl/win32/LAYERPLANEDESCRIPTOR.class
+SHA-256-Digest: xlqDhlT7BWs+BRBPOoF05cYgd42y4CzvY6W9xnCLuJc=
+
+Name: org/eclipse/swt/accessibility/AccessibleTableCellEvent.class
+SHA-256-Digest: v2e7l9qZtEf5u8Z0d281IdRsmEacDv9ihbAwG+85wmg=
+
+Name: org/eclipse/swt/accessibility/Accessible$4.class
+SHA-256-Digest: avydBdF9YYAap7k9VDAZ6fc6A/JNd8l3HWfhvEJPwF4=
+
+Name: org/eclipse/swt/accessibility/AccessibleListener$1.class
+SHA-256-Digest: G5jGdazxH79WUMMGwgA1gYlAwJqyGAyAvX0KHmVX5aE=
+
+Name: org/eclipse/swt/custom/StyledTextEvent.class
+SHA-256-Digest: TLNoHNJxSIbqWMj7wDaFVL1ZbkuJFj+rpyqBqnpVFyM=
+
+Name: org/eclipse/swt/internal/webkit/IWebOpenPanelResultListener.clas
+ s
+SHA-256-Digest: AgI6TUmT69SMLzNI/oRjFDX8A+p/TnN/zgjV7yeQYOo=
+
+Name: org/eclipse/swt/dnd/TreeDropTargetEffect.class
+SHA-256-Digest: FIBZ/lP+pSatzqNoEdSRDqhbALdjUzEtR/AnG8NXLNA=
+
+Name: org/eclipse/swt/internal/ole/win32/CAUUID.class
+SHA-256-Digest: zK2A7WQSAgz0ngf+kO8qDDPIAhXqZAjjBx7KXV172o0=
+
+Name: org/eclipse/swt/accessibility/AccessibleListener$4.class
+SHA-256-Digest: QxL08f4QnB86rzu8KUO8nZr7fA7xUYR5dhuXmfAO/ko=
+
+Name: org/eclipse/swt/internal/SWTEventListener.class
+SHA-256-Digest: fsQE3UBCF0sLhnRfCTY5syYkdRg/kyedaqvkuKQijo8=
+
+Name: org/eclipse/swt/internal/DPIUtil$AutoScaleImageDataProvider.clas
+ s
+SHA-256-Digest: 51KwGELEVWgnGb/sRyXbeyF8Bxo7Xt8HQxVeyzWASt4=
+
+Name: org/eclipse/swt/internal/win32/SIZE.class
+SHA-256-Digest: /MMRMCnZFISWchZgFCEWEPuYenUR1bCIScYnciu9URk=
+
+Name: org/eclipse/swt/graphics/Image.class
+SHA-256-Digest: XCXOaElJyzih8c+rvKx2L1iUOw0LQTH3tcwcmtqfzSQ=
+
+Name: org/eclipse/swt/custom/TableCursor$1.class
+SHA-256-Digest: 53OszUGntVrUMOSOct7/RSuX3fSMcI3QzAdIb2dYJKE=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleCommandTarget.class
+SHA-256-Digest: QXEDEaHQmdxuX4eDnf2LrAkLBP1GvqNyjJluclHoVxA=
+
+Name: org/eclipse/swt/events/MenuListener$1.class
+SHA-256-Digest: hYZJi1ITFkkmNPLy4smPomrdKksGqKEH4Qf/XD+PhSo=
+
+Name: org/eclipse/swt/layout/GridData.class
+SHA-256-Digest: BZX9uJ6YZx/Qod+z7VQrsdwI/A0nY2PVkJoS6XM1KMc=
+
+Name: org/eclipse/swt/internal/image/PNGFileFormat.class
+SHA-256-Digest: 4M3BF/LcSkdQmivQaXovp5SSyAZi+Py4h7/JkKOzIxk=
+
+Name: org/eclipse/swt/graphics/ImageData.class
+SHA-256-Digest: Ecpny8NQ57E5voXRz5WdfQd/jZ2VSLjp6Ftnb3zAl8Y=
+
+Name: org/eclipse/swt/custom/CBanner.class
+SHA-256-Digest: nlLkCylwS8KYIYCRQf206AtbqnvRuMkEjlSmzi7T5yE=
+
+Name: org/eclipse/swt/browser/WebSite.class
+SHA-256-Digest: TTqcgdUGWTLMNTcmEyng5E2fbC+Q2a8S3rW08PWctXA=
+
+Name: org/eclipse/swt/internal/ole/win32/IDispatchEx.class
+SHA-256-Digest: S0tdnENwyFkrKED3vwDPC+KTyFZWwvrlWb5S8F1wHcw=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleWindow.class
+SHA-256-Digest: XDoy8hYC9eEYBHaRR/oY9uo9rjJUpE9CkVaI9YpJ8BQ=
+
+Name: org/eclipse/swt/custom/CTabFolder$1.class
+SHA-256-Digest: jnJfdDCorgADD9359Q8yXxrl5rb+AbL7zbjf7zNl1SM=
+
+Name: org/eclipse/swt/custom/CTabFolder.class
+SHA-256-Digest: D3XggYIPIaxvqdJCE6dToe7/Bbt88usSYMUgjCiKJ68=
+
+Name: org/eclipse/swt/internal/win32/PANOSE.class
+SHA-256-Digest: FfJRKUPoEXhnIvPKzv/ULzPhg556gyxN0l+rk8RwG+M=
+
+Name: org/eclipse/swt/browser/VisibilityWindowListener.class
+SHA-256-Digest: ABat5f+F0kYydGySLojarsW0OBdmuBHwomSQByWtb4Q=
+
+Name: org/eclipse/swt/internal/win32/INITCOMMONCONTROLSEX.class
+SHA-256-Digest: WaESmM8Zq3EsRtJKIX8l9lzXEzXEnsGox/BQ1fkTtHk=
+
+Name: org/eclipse/swt/widgets/TouchSource.class
+SHA-256-Digest: YC1ehOvy/hcE9uEkNLpwyAuiwx5ArrjFHfRukz57ypg=
+
+Name: org/eclipse/swt/widgets/Combo.class
+SHA-256-Digest: ehntYr3xOF9wUlhps7L5/u9YjyRSjw764d9SKm/cZPc=
+
+Name: org/eclipse/swt/internal/webkit/IWebFrame.class
+SHA-256-Digest: uHFWeHHHGyNilj6BKbwcCb9piTvFiOxIafeoUBbobho=
+
+Name: org/eclipse/swt/custom/DefaultContent.class
+SHA-256-Digest: 1tBQ61YcehvbHeUeG92hMbNmu/PTKrMG477FvjYmcc4=
+
+Name: org/eclipse/swt/internal/image/JPEGAppn.class
+SHA-256-Digest: 9shbWBX1mNDe7qwReAcGSswS9u0JYgX6mJwNZ+t5z/M=
+
+Name: org/eclipse/swt/accessibility/AccessibleListener$3.class
+SHA-256-Digest: jJR5X5VGfi3LFWCF8wbzXtHM1/hznnr4MUFg3BdOs8A=
+
+Name: org/eclipse/swt/custom/CCombo.class
+SHA-256-Digest: vmVbvnyBBxR/O3uIwDPCQI8/PzbayHmXF5BZ/DIN61M=
+
+Name: org/eclipse/swt/internal/win32/MCHITTESTINFO.class
+SHA-256-Digest: prXKgXa+imfFVJ7SvWPFqfyosVP0uyYlKISDyW4tHnc=
+
+Name: org/eclipse/swt/events/SegmentEvent.class
+SHA-256-Digest: z9bwRcbVnQTfhJ/U2SiOc3IRh0yE6J3SjXgyN8wos2w=
+
+Name: org/eclipse/swt/custom/MovementEvent.class
+SHA-256-Digest: M+V0ZvnlOMAVVd8ZRsst2fxIBq9FQLoqVe44hpZ6tjw=
+
+Name: org/eclipse/swt/internal/image/PngDeflater$Link.class
+SHA-256-Digest: wR42cMtcuc7u916GZ1R+3tCppJPg8F+In5oHjzNBlT0=
+
+Name: org/eclipse/swt/internal/win32/NMTBCUSTOMDRAW.class
+SHA-256-Digest: ABYMMlWmOGdvkZJClkDkWAyirukIuOqF0bnedpxVw9s=
+
+Name: org/eclipse/swt/internal/win32/GESTURECONFIG.class
+SHA-256-Digest: StuOS3AlxS22XEWHqHtBDnraulpN1I/ZPphpyFdRU1w=
+
+Name: org/eclipse/swt/events/FocusAdapter.class
+SHA-256-Digest: yccQH4/llJ+RC5zNn3AnarDe81Px2RXkWtIE4wtItIU=
+
+Name: org/eclipse/swt/custom/CTabFolder$6.class
+SHA-256-Digest: hrJj3x0Oi8fQykKFnaOpj/B0n79FxpiPKD6NTeG4nBQ=
+
+Name: org/eclipse/swt/accessibility/ACC.class
+SHA-256-Digest: +GCdn9dt/d/N6QAT6XcVNPuqiiuNFDWz6LD3ozvFC0k=
+
+Name: org/eclipse/swt/internal/win32/UDACCEL.class
+SHA-256-Digest: 22eBTSSaW7QyQvJpbx10mII7Mz32xyxwyBw4T9trSYA=
+
+Name: org/eclipse/swt/custom/CTabFolderAdapter.class
+SHA-256-Digest: GNv8iXTbCdIM4LfKMQMtjm2MGSsQdwfbxqBmO3CLpvk=
+
+Name: org/eclipse/swt/browser/TitleListener.class
+SHA-256-Digest: +VEWrrLOKNgKlX9fgfyA1pozAR63JVwfwB/IYyftNCs=
+
+Name: org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.c
+ lass
+SHA-256-Digest: eaEwE1GA2JdZrUSGtN0cRrwaOpd1EEr3843DuwnSjqM=
+
+Name: org/eclipse/swt/custom/CTabFolder2Listener.class
+SHA-256-Digest: bxR2NEbwgFNvHuDeIGGxnOcfcrvUFNs9NJtPMxywk/0=
+
+Name: org/eclipse/swt/accessibility/AccessibleTableEvent.class
+SHA-256-Digest: +PrTsVh8M+1otkRvGgJkwFj/pSKEw080As6R+hIxVhE=
+
+Name: org/eclipse/swt/internal/win32/TEXTMETRIC.class
+SHA-256-Digest: 6cwHsRicSQ1MqftRx0qQi3ZD9RBI1xzqBiPvPIKo5eY=
+
+Name: org/eclipse/swt/custom/TreeEditor.class
+SHA-256-Digest: vT+MKK5+P62stkrCQIbIuQn6UjdyUDS1KhC2KT3X5N8=
+
+Name: org/eclipse/swt/internal/ole/win32/LICINFO.class
+SHA-256-Digest: ktprSC/YBQkUyTTEFn6dsByhhqBFIXOZ3xW+r8ykZaM=
+
+Name: org/eclipse/swt/internal/win32/NMTTCUSTOMDRAW.class
+SHA-256-Digest: uc/BTohm5cUgIdXZWNK++V5q48gPVtPS6O5EoIHmOlQ=
+
+Name: org/eclipse/swt/accessibility/AccessibleTableCellAdapter.class
+SHA-256-Digest: 3RpTRicTU8vQlMVhvQ+53j7DXrOiZJzDrMPtlxFVsJI=
+
+Name: org/eclipse/swt/custom/ScrolledComposite.class
+SHA-256-Digest: mdtsNgExAqw3SSTnZtAPTOkz7FAsgiMWbdLh1JDrPP8=
+
+Name: org/eclipse/swt/widgets/Shell.class
+SHA-256-Digest: bjXya4Ib13TbuZQzKX3ww29xRwb/TtW8BgoPyaFDbvI=
+
+Name: org/eclipse/swt/internal/win32/CIDA.class
+SHA-256-Digest: bDCJbZVb+OBTEycDlhwhECtfGUK+Y2ZmXa1ZYGS/W9k=
+
+Name: org/eclipse/swt/custom/TextChangedEvent.class
+SHA-256-Digest: E1Hh58wDexqvhE3pa5miI7+xwnks7WD98JNahrieIw4=
+
+Name: org/eclipse/swt/layout/RowData.class
+SHA-256-Digest: ry2AoCsHBH753O1kzKLVdurP8TLv1AoIJ9megfID7S4=
+
+Name: org/eclipse/swt/graphics/TextLayout$1MetaFileEnumProc.class
+SHA-256-Digest: vd1Bdf6mvyVKlgGeR0sMMbdPfYvMHH8764dkOXq8/Lk=
+
+Name: org/eclipse/swt/SWTError.class
+SHA-256-Digest: p+hvuBcAssV8aJ0deVU0/9kborV2d/IdjXfvG7MvR5A=
+
+Name: org/eclipse/swt/internal/webkit/IWebMutableURLRequestPrivate.cla
+ ss
+SHA-256-Digest: glZLCHhLgIvIWrv+qfyhwTBYxWRuLEwUv8ENzmguQdc=
+
+Name: org/eclipse/swt/accessibility/AccessibleAdapter.class
+SHA-256-Digest: sCTJr8twrwfAu3Eq6u0m+B55IP1ODjEojT0UBVq6oIA=
+
+Name: org/eclipse/swt/accessibility/AccessibleHyperlinkAdapter.class
+SHA-256-Digest: gnGyZ+CshUTB4PaKV3NlFTJsajfg5AeZJK1m3OUbOtQ=
+
+Name: org/eclipse/swt/events/SelectionListener.class
+SHA-256-Digest: Gs+rkeatw4bdcjCOMvU3DzR4qZseK6BKD21Nb/x+s2I=
+
+Name: org/eclipse/swt/internal/ole/win32/IFileDialog.class
+SHA-256-Digest: ms6lrp2wYSR9oFbLwDUWwIuDMh2kFiM8bfx4MpMyHn0=
+
+Name: org/eclipse/swt/internal/win32/MARGINS.class
+SHA-256-Digest: nbXYMYy5oHuXZUWHMb/iyFZJiyaxAfRZJEapwZZjr48=
+
+Name: org/eclipse/swt/custom/ViewFormLayout.class
+SHA-256-Digest: XPpbvvHxDNy6kC1/HokWst/oaRuO8XHjNPmP8r0+ut8=
+
+Name: org/eclipse/swt/dnd/HTMLTransfer.class
+SHA-256-Digest: mYUFEDGHFncel2Pik0rIrToL1OUBJb8kPiSMSLUUBDY=
+
+Name: org/eclipse/swt/events/MouseWheelListener.class
+SHA-256-Digest: WlIIRAOvA/u3v3nEG9DU8inpufrVVbk1+a7KLUQzYt8=
+
+Name: org/eclipse/swt/widgets/ScrollBar.class
+SHA-256-Digest: nnaJ9LEQ+f15q7KdcBpqDwHPDSOZqD1P435J3OTbHns=
+
+Name: org/eclipse/swt/internal/image/JPEGRestartInterval.class
+SHA-256-Digest: 0c1cx7XILd40YbzaJszKLj1ct6biLJMHu60qwOB0Gr0=
+
+Name: org/eclipse/swt/custom/CTabFolder$5.class
+SHA-256-Digest: n+P2aSp01/AgLMTW2bXv4LDnFSmu5ZnK9BwMEZiT8yo=
+
+Name: org/eclipse/swt/custom/StyledTextContent.class
+SHA-256-Digest: T4CoXAfsLBGH6GuzkW9tSCacLuPzD+U0HZvXEnFcmos=
+
+Name: org/eclipse/swt/dnd/DropTarget.class
+SHA-256-Digest: XG/YMF3QfdBNM1dKorGXLsclH+Ov8cjzMUgAhThAM8s=
+
+Name: org/eclipse/swt/widgets/TypedListener.class
+SHA-256-Digest: UidgrwTePCWsqtCLOOq+dkh36AHCo1i07s0HjSMh8Nw=
+
+Name: org/eclipse/swt/internal/win32/NMLVCUSTOMDRAW.class
+SHA-256-Digest: QLqS0Q23fuoyKWwA2pEhVnXkZr0OnWy/i3vE1ujP+pY=
+
+Name: org/eclipse/swt/graphics/Cursor.class
+SHA-256-Digest: CIcdU7QXtXXGhnLqXQdTeRWA8yU5ns/N+Qfk0TW8LfQ=
+
+Name: org/eclipse/swt/widgets/Composite.class
+SHA-256-Digest: 6+uoiGeSKUTI35bp5RKnuyDfKQberbA49phEXW/eqPQ=
+
+Name: org/eclipse/swt/widgets/TableItem.class
+SHA-256-Digest: nEfxhm5M7watMMhUxkWrYTQ0Dip28ZB0WRjSNxMV+H8=
+
+Name: org/eclipse/swt/events/ShellEvent.class
+SHA-256-Digest: 4q2AoHrrfE5pteBg5ZPXFU+KfrHaZOHnKWZoOiNxBqk=
+
+Name: org/eclipse/swt/browser/WebFrameLoadDelegate.class
+SHA-256-Digest: eze+91d6em+kQkDp8His+FKQdpUfxo0hzH9QVZXvPaY=
+
+Name: org/eclipse/swt/browser/ProgressListener.class
+SHA-256-Digest: E5cSkqUhh9Yx/LdDfcaxwiUjAscnaCy5PCY3Jyojcts=
+
+Name: org/eclipse/swt/graphics/FontMetrics.class
+SHA-256-Digest: 1a12SvJUAvwJ6Ag06QOrJ8eDV3NetlSoKi+fcrVjA/c=
+
+Name: org/eclipse/swt/accessibility/AccessibleTableListener.class
+SHA-256-Digest: l2s8KACU2EYihi5XZsdBDRRewehm6wgDgDXERFjqKTc=
+
+Name: org/eclipse/swt/events/HelpListener.class
+SHA-256-Digest: PmL7rPM96MkeExVVwxbIa0OYvx0sftWg6bPZL2EpTF4=
+
+Name: org/eclipse/swt/browser/VisibilityWindowListener$2.class
+SHA-256-Digest: G9ZqgpS5c3/HpXsK1CXBp173OoC//cMOh6GFuUaXXs4=
+
+Name: org/eclipse/swt/internal/image/WinICOFileFormat.class
+SHA-256-Digest: XHRmLFNzU8FYi5332OpRxOol3yM9LYQ3tMYXvrrityc=
+
+Name: org/eclipse/swt/widgets/MenuItem$MenuItemToolTip.class
+SHA-256-Digest: EbCxDVmsqzZwiaE2pi13nAnMWGjVi4bVNDDizlcth6E=
+
+Name: org/eclipse/swt/ole/win32/OleClientSite.class
+SHA-256-Digest: Ia+s1leNUFarnzsd9HVx0NBHuNnyHCL/nYHE2bP5FHQ=
+
+Name: org/eclipse/swt/events/TraverseListener.class
+SHA-256-Digest: 05ohAND0Lk2jFRhvuh7A8EZArHLVHIy6n3oDQI28xCo=
+
+Name: org/eclipse/swt/internal/win32/MOUSEINPUT.class
+SHA-256-Digest: IgYZF55XQK2PgUFOIoak8MugXmz6V1SukgY+x+gOWLU=
+
+Name: org/eclipse/swt/internal/win32/DEVMODE.class
+SHA-256-Digest: 7142LIxE+6LI9XXN2gRjCEgftRcTdysPtjlegLz6k3A=
+
+Name: org/eclipse/swt/internal/ole/win32/IObjectArray.class
+SHA-256-Digest: ioeermoxkHJ+GDfVMuXvm/pj0fbfRxr7sZprKRAXH/s=
+
+Name: org/eclipse/swt/internal/image/PngDecodingDataStream.class
+SHA-256-Digest: hedSLEAoQgj+NCyCergI3OtdjWVPss6aOZNqqyhSC+k=
+
+Name: org/eclipse/swt/internal/win32/NMLVDISPINFO.class
+SHA-256-Digest: whPAZv/D8SbHeU+2J/Scj4ZfIE1pnk7NEx6C/zuIwQo=
+
+Name: org/eclipse/swt/dnd/RTFTransfer.class
+SHA-256-Digest: 9fmtFuq1t9OVAho8pyxnDM08e0LzG2td766tXuqmaaw=
+
+Name: org/eclipse/swt/layout/FillLayout.class
+SHA-256-Digest: xjps8VuQChDxTuHOnf9tJup2clbp4wgX0wlPH6qJ9tU=
+
+Name: org/eclipse/swt/internal/ole/win32/ITypeInfo.class
+SHA-256-Digest: F/P4g2YIB5Xs0qJdlX1QDX6R2VWyo4y8GFGiV1dV1KY=
+
+Name: org/eclipse/swt/accessibility/AccessibleControlListener.class
+SHA-256-Digest: WUawcS3daEFw85ri0XprBX2tvCeW9ilXTR01hordWr8=
+
+Name: org/eclipse/swt/dnd/TreeDragSourceEffect.class
+SHA-256-Digest: U4/9cX1R6SA0qrN0ruMGTUYUAD+uc2GI+CfXVtgtjHw=
+
+Name: org/eclipse/swt/internal/win32/CHOOSEFONT.class
+SHA-256-Digest: o8VrEjuePlMxt4yAfzXZj33nqvSD+sHyILhwX3eONvI=
+
+Name: swt-wgl-win32-4930r7.dll
+SHA-256-Digest: f+bW+8976WetgHFEKFr7iBn5LnPnGn1gX2iZ6qJ4pps=
+
+Name: org/eclipse/swt/internal/win32/WINDOWPLACEMENT.class
+SHA-256-Digest: WMyh+7cnajhVYqMDH7puY0zQHZjBTB3VSXduIfIP5lU=
+
+Name: org/eclipse/swt/internal/win32/LOGBRUSH.class
+SHA-256-Digest: Dd82XHZbnbMrkzgj/fe4p9WEPHmp0bAl3aTYoNWSumY=
+
+Name: org/eclipse/swt/internal/SWTMessages.properties
+SHA-256-Digest: Bz+05fSVJ43hw7/nBXoKjILAFZ510yBwelkQ0QqrTPU=
+
+Name: org/eclipse/swt/internal/win32/DROPFILES.class
+SHA-256-Digest: RJcZOdI6anX4ujHEFFIJGHXLtJ6aUPWqXUe3W9m2M/s=
+
+Name: org/eclipse/swt/events/FocusListener$1.class
+SHA-256-Digest: pyFF/uu7mDoGUKVEAjfCSZSkTgqViq/nXeVhcn7njhc=
+
+Name: org/eclipse/swt/events/FocusListener$2.class
+SHA-256-Digest: exmNmgM2pFfWCb+k856r7Z+NiBSnvjlXnFWJ65T/4oY=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleControl.class
+SHA-256-Digest: 9KUHYsT/8PD9WERCS+Kn5OzRiJiFrEp7JxVaO1VO4hI=
+
+Name: org/eclipse/swt/printing/PrintDialog.class
+SHA-256-Digest: p93Ie7rCxkuK1eHU8Q8qmvjYHuHXcDDZoO37lh5Sv2w=
+
+Name: org/eclipse/swt/internal/ole/win32/VARIANT.class
+SHA-256-Digest: 4MoMALTwOyTovryWhOsQR98c6LI/mTCmE9dvglnVVDw=
+
+Name: swt-awt-win32-4930r7.dll
+SHA-256-Digest: 74EO45dFRTaa3qPYsCmf5pFemrDiOMd3e7mleb6CcSA=
+
+Name: org/eclipse/swt/browser/WebResourceLoadDelegate.class
+SHA-256-Digest: dhUlALfJ6Mh92g04acW7C9MRIiTjWguAKYZ8mb/pS1Q=
+
+Name: org/eclipse/swt/graphics/Color.class
+SHA-256-Digest: T5AU3hbfHPJ9B7dpDGLwnJ7eERX4tmfZzpjsXab/Vq0=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_ITEM.class
+SHA-256-Digest: uckWukjK+4Forg8RVCTNQxGh95N1pdAXj7Toyhzn5vo=
+
+Name: org/eclipse/swt/internal/win32/STARTUPINFO.class
+SHA-256-Digest: pBEOailzahNaJI9H7OXkZYIju/4Ggsz6a3eCF28PcTM=
+
+Name: org/eclipse/swt/ole/win32/OleEventTable.class
+SHA-256-Digest: wUmjpcOVsQ2oNwPhIztDxD5G4eTEL7d4vPUqI/Nu4Fg=
+
+Name: org/eclipse/swt/internal/image/PngIdatChunk.class
+SHA-256-Digest: YtStTs1RQGXb1FbWKflBYsD5RpxNdPRk2tMr8PaNZqA=
+
+Name: org/eclipse/swt/custom/TableCursor.class
+SHA-256-Digest: BGxXgJW4QQB41KHSIfXAA+IOosloXTK2cj3XcNnEd0g=
+
+Name: org/eclipse/swt/internal/win32/PAINTSTRUCT.class
+SHA-256-Digest: 7mYqVK7S/dSj+FJZcLva5rj37gsQMh+m4CQsKjYMi7Y=
+
+Name: org/eclipse/swt/events/TypedEvent.class
+SHA-256-Digest: 3Sqtok4Ewr4j10dxueRiO8xfSnq/PRhXJTRsUoNMmlg=
+
+Name: org/eclipse/swt/internal/win32/DIBSECTION.class
+SHA-256-Digest: yJ0eG9x6nYqtMPXjG3h4IM6vAfMM/C+lFEV4LVDQ+wA=
+
+Name: org/eclipse/swt/internal/win32/BROWSEINFO.class
+SHA-256-Digest: i9EsWlQxPW0VR/SxDHIDoFudRsmB6DYvN4GoW0EUoGQ=
+
+Name: org/eclipse/swt/internal/win32/TVINSERTSTRUCT.class
+SHA-256-Digest: sikd+Dp3OFgYN+i2DsJAPx+Q7O1LvXMpVTk1km5xubw=
+
+Name: org/eclipse/swt/internal/webkit/IWebMutableURLRequest.class
+SHA-256-Digest: Up0aaDC8FAqM5AGiRwu6ahZ/4ntJaZSvCpTNMij1tVM=
+
+Name: org/eclipse/swt/events/SelectionEvent.class
+SHA-256-Digest: uksBlDyqoWLve1U4x47qMVHF+Ok2+aT7ZPEAZPC8wOY=
+
+Name: org/eclipse/swt/ole/win32/OleControlSite.class
+SHA-256-Digest: Q+cD1SM4BijetW7QZaJiRZQB4fURjz9wzAxzj1gHwGI=
+
+Name: org/eclipse/swt/browser/StatusTextListener.class
+SHA-256-Digest: 2TWwHR+90PCuXb0ZMIqcJc9zjnwV9MjkWzOT0BosDws=
+
+Name: org/eclipse/swt/internal/win32/COMBOBOXINFO.class
+SHA-256-Digest: FMCSfWMu8NgU4kNQpufO0SaOcr+SeQWRPIwyn3mSG+8=
+
+Name: org/eclipse/swt/custom/CTabFolderLayout.class
+SHA-256-Digest: dO06p7nA9g81YAUKqf0nFtzGWJCt3NfMMaN/VYWaCl8=
+
+Name: org/eclipse/swt/widgets/ToolItem.class
+SHA-256-Digest: 6xYzqyQyASjiAV84DwL4x6NuMOA/dOCegkIJBVIW+l8=
+
+Name: org/eclipse/swt/events/ExpandListener$1.class
+SHA-256-Digest: +3FxLcUo6qdsA98wwQC85worE5oE3CDmASBnUscky94=
+
+Name: org/eclipse/swt/internal/image/TIFFDirectory.class
+SHA-256-Digest: q28Z48Lh22ERCnl9wF+luSx1aJ4APhKXrM9NRuwOvdA=
+
+Name: org/eclipse/swt/internal/win32/GRADIENT_RECT.class
+SHA-256-Digest: kbZhlyzgJXmrJBRvcrd3o+Ag5tNR1SjLmZ0YEv7zySo=
+
+Name: org/eclipse/swt/browser/WebDownloadDelegate$1.class
+SHA-256-Digest: SPIfitfAae220hx7YJO6GY3CxV7cnHSYktQoGIkKqwE=
+
+Name: org/eclipse/swt/custom/MouseNavigator.class
+SHA-256-Digest: hpE1tm+WwitkLO8IL9Si7i64OzomP5g8MspoVR4TXvI=
+
+Name: org/eclipse/swt/internal/ole/win32/ITaskbarList3.class
+SHA-256-Digest: LId73KLAu/p4a2kkGpBjt4ZlNI8nIsLExa3pWBS5O3k=
+
+Name: org/eclipse/swt/internal/image/PngChunkReader.class
+SHA-256-Digest: yAQlD2NKx4vrPdxS351dS/VC4+jTelNV67GK3Ae6sAE=
+
+Name: org/eclipse/swt/graphics/GC.class
+SHA-256-Digest: Khv498pq8q6VJGjPV45ScT1tSbh5VE0vw4PoCcxF+A4=
+
+Name: org/eclipse/swt/events/MenuListener$2.class
+SHA-256-Digest: WiPx/eEHYuplzGKkCQS+er9+k26TVrui088u4OoyEqQ=
+
+Name: org/eclipse/swt/internal/win32/SHFILEINFO.class
+SHA-256-Digest: MXwTIBuCCtKf3pd1v3lP0OPSo+bSquZhdbJpJOn2HxE=
+
+Name: org/eclipse/swt/custom/CTabFolderRenderer.class
+SHA-256-Digest: O4YfXaR3RYcAm3/+NuKJ3pnxxsvOLrocbv/reSzuU4U=
+
+Name: org/eclipse/swt/internal/win32/TBBUTTON.class
+SHA-256-Digest: p/FB6/mRlP/G5rFx+I1bOIXz9M+a+UbJocxunxh29WE=
+
+Name: org/eclipse/swt/custom/CTabFolder2Listener$3.class
+SHA-256-Digest: Mb5O0+PNyZCJS65N1cw1vvaGuD1YM0W7ynR5lsrN0A8=
+
+Name: org/eclipse/swt/widgets/DirectoryDialog.class
+SHA-256-Digest: uwsx95zr4UXKWXqIx56prDZjMGSsK4a20M513X1vwGM=
+
+Name: org/eclipse/swt/widgets/MessageBox.class
+SHA-256-Digest: X4Wtmq6SIiuc3L/isHB5U8osGPSqmRpQuAFBqNB89UE=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleObject.class
+SHA-256-Digest: yDWvNeuwcmGkO5/ZEPg1nhtWOLpH2Zic0zDwRfya27A=
+
+Name: org/eclipse/swt/accessibility/Accessible$8.class
+SHA-256-Digest: cbWsqQ51oWfx9rEVCuiIv5pNiJJKgU/F5XfofJLLDWU=
+
+Name: org/eclipse/swt/custom/TreeEditor$1.class
+SHA-256-Digest: foeyMxuFzDxeiII0+ZnWtGGnckxdSAvIW4cTWZZ0020=
+
+Name: org/eclipse/swt/internal/image/PngLzBlockReader.class
+SHA-256-Digest: TIuKt6Pma0Zo8IundnGWpZ/+0QhJ3SCIQgM7mpyUNz0=
+
+Name: org/eclipse/swt/browser/AuthenticationListener.class
+SHA-256-Digest: xPpyNYVaDFu01YcoRM37w5Zz9mnproMffxCh/cwL4pI=
+
+Name: org/eclipse/swt/custom/TreeCursor.class
+SHA-256-Digest: oUGQCCZ6FDSdhU4ggONDoPhjKIOEQgudU4cTfrEOgTg=
+
+Name: org/eclipse/swt/internal/win32/HDITEM.class
+SHA-256-Digest: qIZAEkmvAdxUu4U4oBkMCFNDct1ZKp4ltRrLPXzM3PY=
+
+Name: org/eclipse/swt/events/KeyEvent.class
+SHA-256-Digest: uxjXSIqv1X5ULUABcsaGBRYfFGG0TD7HMKBLlLnJlEg=
+
+Name: org/eclipse/swt/events/ControlListener$1.class
+SHA-256-Digest: C4Go/0Xuzxek7AlqQ7ukTLPYJ10EwCHi5dRToZXlwxc=
+
+Name: org/eclipse/swt/internal/image/PngFileReadState.class
+SHA-256-Digest: N0HtKlKP6wuKqKgLUR9MwLBmrvpFHG8q61F0IyFmKO4=
+
+Name: org/eclipse/swt/internal/win32/SHDRAGIMAGE.class
+SHA-256-Digest: Ilgp2Rkbjc2PKyw8+qCz2hjdPIyi8T85N0L4iO40qDI=
+
+Name: org/eclipse/swt/internal/win32/DRAWITEMSTRUCT.class
+SHA-256-Digest: gxIV6KbmXf6tASYCUB4MXkr3y5ISsNhB/QK9Lj/ILcE=
+
+Name: org/eclipse/swt/custom/StyledText$1.class
+SHA-256-Digest: ZThuhsxDXPkfbGEVt0kZHOigGpiKaVMHj/PkwavoTa4=
+
+Name: org/eclipse/swt/widgets/ToolTip.class
+SHA-256-Digest: H2VQikm/XAyWBxavH2MvumEG2jHwX/qN05RK65rzVcs=
+
+Name: org/eclipse/swt/graphics/RGB.class
+SHA-256-Digest: 3/f6T4/I/E0m2hMsuifWuZuQSgXpuy7kN0vil2jokyc=
+
+Name: org/eclipse/swt/custom/TableEditor$1.class
+SHA-256-Digest: OXquAJf0KqVbkAAK0UFH9QH5gMaXhjv2HJ8a4bbG95U=
+
+Name: org/eclipse/swt/internal/image/TIFFFileFormat.class
+SHA-256-Digest: UJZIgwi+tV2E97OqZdTZZ85QnoKLM5+tzwmZSLEijnk=
+
+Name: org/eclipse/swt/accessibility/AccessibleTextListener.class
+SHA-256-Digest: I4kYjD9zcw81RqCtkd5nrYZpYuknAewdYWH03t5lJTM=
+
+Name: org/eclipse/swt/custom/Bullet.class
+SHA-256-Digest: PaXWGiiMqXVjdKw+Kw8URvMPb4t3yV3eMffVcbTUguY=
+
+Name: org/eclipse/swt/internal/ole/win32/IDataObject.class
+SHA-256-Digest: /zqM2A5dHpuRHaqzX3KvCB91b9k4hYOPQo5AS5DIpXI=
+
+Name: org/eclipse/swt/browser/WebFrameLoadDelegate$1.class
+SHA-256-Digest: am6hx8YTIzvFXCxVd7x8z+rhQgCtJ994JAAImvZZSQ8=
+
+Name: org/eclipse/swt/internal/Callback.class
+SHA-256-Digest: cQ3eQoG/+Ommve1FjsE2hJ/bjicqg3qusApcwPNZSNM=
+
+Name: org/eclipse/swt/internal/ole/win32/IProvideClassInfo2.class
+SHA-256-Digest: XZalENSLRopoMMf13DZ1stMUVPMWeDjfAVstTvAtK2A=
+
+Name: org/eclipse/swt/widgets/Text.class
+SHA-256-Digest: zqQcMdVqAQ4aHDrTguGKWXV7Ra8mwF9Us+Y7wL8JSOE=
+
+Name: org/eclipse/swt/ole/win32/OleEvent.class
+SHA-256-Digest: xFAMv5dx5Qcrk9aQebEIg/UpQ7RRMjKOMU912VPZOqU=
+
+Name: org/eclipse/swt/dnd/DragSourceEvent.class
+SHA-256-Digest: SqRgkuvhQh4eC9XT0EY0FwHNywF9ANMHZtQ3PUgS2mI=
+
+Name: org/eclipse/swt/custom/MovementListener.class
+SHA-256-Digest: UjSaaKtpqgvS4+eVUH1d11eBUwOIWuORdj4nyBNAN64=
+
+Name: org/eclipse/swt/ole/win32/OleControlSite$1.class
+SHA-256-Digest: xkbVwHTpq+lFohm69Fd3xqrHgfMLGVuHG3yODLzvQ1s=
+
+Name: org/eclipse/swt/events/SegmentListener.class
+SHA-256-Digest: 1MBLS7+Upo/zFlunQEgmGxiIiCEkXY19FI+ijHGRxE8=
+
+Name: org/eclipse/swt/events/MouseTrackListener$3.class
+SHA-256-Digest: sFnrA7NOXQ3lrI22DsZ9qoGS3M50DYTuNyG0Oy8meFM=
+
+Name: org/eclipse/swt/opengl/GLCanvas.class
+SHA-256-Digest: jrsWFFqEgvYdHJyTB5U3GsLqde1l9aVT0lLZjpfdxH0=
+
+Name: org/eclipse/swt/widgets/FileDialog.class
+SHA-256-Digest: snl+vFaKjMl9Ck2rcyW7MP3Tn7I4N+AqEHN5vksCzu4=
+
+Name: org/eclipse/swt/accessibility/Accessible$3.class
+SHA-256-Digest: qhbThaC7aYybc6kGdAxIQrcdlcTF0tekMTLkOwnQQJ4=
+
+Name: org/eclipse/swt/custom/ExtendedModifyListener.class
+SHA-256-Digest: JxdswEcWN8i/3TzXa5ug6fC/fmnTq8jN9kjQnGWEwQ0=
+
+Name: org/eclipse/swt/events/MouseTrackListener.class
+SHA-256-Digest: 8W2d+YwjP+biH0+yUfagEPrfCZP3JlE+Kyj4u7ylYKU=
+
+Name: org/eclipse/swt/accessibility/AccessibleListener.class
+SHA-256-Digest: UDIVffLxqFC1M6XEHOFm51Avvv6e5pKc+daPYroMdKE=
+
+Name: org/eclipse/swt/internal/win32/CRYPT_BIT_BLOB.class
+SHA-256-Digest: C/2GpIOdodPSjuPypHORvfYo+6E0HBlO3bXVFI3iNv0=
+
+Name: org/eclipse/swt/internal/win32/SAFEARRAYBOUND.class
+SHA-256-Digest: 2vyoMy3uA1dQ+GQXOuAZx+MeRnBhGh76H6uEKPI0VZE=
+
+Name: org/eclipse/swt/internal/win32/EMR.class
+SHA-256-Digest: CbtABbcdKBVqnuNxfXx6FBGVONRh+0CGS7gSphK85TQ=
+
+Name: org/eclipse/swt/graphics/TextStyle.class
+SHA-256-Digest: EUeYiFTF0sCmDJUrCqEBd+fY0mQrwa2Pzb9FAOhA3Ms=
+
+Name: org/eclipse/swt/browser/ProgressAdapter.class
+SHA-256-Digest: 7GKSEO/TS3w5ovW7Mee3Y1tSIw/onOKnahdWFEU6b48=
+
+Name: org/eclipse/swt/internal/win32/SHELLEXECUTEINFO.class
+SHA-256-Digest: d36tE/IYoY0vCiXK1yzo+MYIIMysjF1eIKR0txQK5SI=
+
+Name: org/eclipse/swt/graphics/ImageDataProvider.class
+SHA-256-Digest: XLqtg0I93Ycv1zomZOnPN0F5XaZ5UQHM6yYFt0QMNbs=
+
+Name: org/eclipse/swt/events/HelpEvent.class
+SHA-256-Digest: SjooLcq3VJroOPE4Fd2zJVvRJbC4jsi68tcYrCnzLNA=
+
+Name: org/eclipse/swt/widgets/IME.class
+SHA-256-Digest: +PFqe04ecDjD12k150pMn+jPH7H87MdTe0+djn8o7As=
+
+Name: org/eclipse/swt/internal/win32/DOCINFO.class
+SHA-256-Digest: ziZUT8Q4OwvgtZsORIGJuxZU9ghUwZGWspBi/A4h+GM=
+
+Name: org/eclipse/swt/widgets/Item.class
+SHA-256-Digest: B4fbiUd1nHeXuefcdTaDSda6Na6Td7z00wE8alZEQNE=
+
+Name: org/eclipse/swt/internal/win32/NMTREEVIEW.class
+SHA-256-Digest: j46zr3LPI4c77QQSZ5z/xaHQkIgMQfhgLRR1Kj2voFk=
+
+Name: org/eclipse/swt/widgets/Dialog.class
+SHA-256-Digest: NM65SH/2G32r6CIA/0NZDcj1TiW54YVjsl0zZ0fswW0=
+
+Name: org/eclipse/swt/events/KeyListener$2.class
+SHA-256-Digest: fiBFnkYIYDX9Q1PUQWo7Cs9UkqnYsBlX2OK+Pwm3dMs=
+
+Name: org/eclipse/swt/graphics/ImageLoaderListener.class
+SHA-256-Digest: utTjNLKOIZvA7Y5VFzC9I5l4feIevxT/h3aJJMsk86I=
+
+Name: org/eclipse/swt/events/KeyAdapter.class
+SHA-256-Digest: Z05g9AHnJ/hNJN3MixYXLgEKnAt64bEtHPaiD2tu0nw=
+
+Name: org/eclipse/swt/dnd/DND.class
+SHA-256-Digest: wEJjp1E0juX5l/JvolMwKkDGJu/LDEt6ft+4sY4j/gM=
+
+Name: org/eclipse/swt/widgets/Scale.class
+SHA-256-Digest: OY4v9cVe1IfodCgeASaG3FVUKL1fkomabmZaWSphIdY=
+
+Name: org/eclipse/swt/internal/ole/win32/ICustomDestinationList.class
+SHA-256-Digest: FTaZAtZ9FTSwHDIrrtifM6nxGOxoZEScgtT5gxJ/Ylk=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_entropy_decoder.
+ class
+SHA-256-Digest: HaIl7OK5mbk63ToICIE7+47prvPNzyYSm73WvOUwtSw=
+
+Name: org/eclipse/swt/events/MouseTrackAdapter.class
+SHA-256-Digest: m4QQBkb7vFqYHcX740udtTJFCZDGYD4RJNitqwV/KcQ=
+
+Name: org/eclipse/swt/internal/win32/LVITEM.class
+SHA-256-Digest: EiEXMRZBOVnM8iamwZZmaGSIVIwEAeUitO5RRXyIQ44=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$bitread_working_state
+ .class
+SHA-256-Digest: fB2GOD65MGInmRBJ0ayNPR9e0O4FvHGDskKBdvS/Sfc=
+
+Name: org/eclipse/swt/internal/ole/win32/IViewObject2.class
+SHA-256-Digest: wvb+0Bu/ihdtCVQnzyh6lfMZvXYHGL2kue6jcwtmTJE=
+
+Name: org/eclipse/swt/internal/win32/NMLINK.class
+SHA-256-Digest: oA/S3bO95uoHhyI8AGty0G1LKYMFeo/nDIVyfbI2BmY=
+
+Name: org/eclipse/swt/browser/WebSite$7.class
+SHA-256-Digest: RyqIse9A7rpxfwpbrCrQQrEM4b5f1C9j+yhcXusqzgU=
+
+Name: org/eclipse/swt/internal/ole/win32/OLECMD.class
+SHA-256-Digest: iE5Am18GlHMTeQ0NAzM0hiUQ76GKT7mVtph0AMRmCBk=
+
+Name: org/eclipse/swt/internal/image/PngDeflater$Code.class
+SHA-256-Digest: Oa8aMFcGHejnCjZxLqPMlFbFEk0z+O8BZzfD7GZZT94=
+
+Name: org/eclipse/swt/internal/image/PngHuffmanTables.class
+SHA-256-Digest: FPDlkR/46ROYN31jWaxCfzVE9jj/SvPZZcPlOYhRMnQ=
+
+Name: org/eclipse/swt/internal/win32/PRINTDLG.class
+SHA-256-Digest: uh5iehK2f02EkMB10V88qLGhsNZ7COdWM5v2mJQlXYw=
+
+Name: org/eclipse/swt/layout/FormLayout.class
+SHA-256-Digest: cFFiezAyJmmqac97xKp+AXRKhcyX7LqI7ax9cgB97/4=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_d_coef_controlle
+ r.class
+SHA-256-Digest: Bgh0bdrFw2GiyKsyjClNmVxn4jAH+55w22EJ1gNVe5Q=
+
+Name: org/eclipse/swt/awt/SWT_AWT$1.class
+SHA-256-Digest: MYDqoySAgVS0OJRdD8V4mcuOVF+uKE8Lz35Fts8lGcE=
+
+Name: org/eclipse/swt/custom/CTabFolder$2.class
+SHA-256-Digest: aqhMNo2PMXtsOStXl6TlRYiQeXrRWIH2Tib7LvOkyiA=
+
+Name: org/eclipse/swt/accessibility/AccessibleListener$2.class
+SHA-256-Digest: cgUXaU9WegsIpiyHR4Xpzwj49ZkPgdxeuoR2octp248=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_d_main_controlle
+ r.class
+SHA-256-Digest: xRmGQptfVY35YalyKo0NvfqZUCLAS7W+JJuuHuL4iT8=
+
+Name: org/eclipse/swt/internal/win32/TOOLINFO.class
+SHA-256-Digest: InvAjE8eZ+zxffuSA0w7vpo3s6IU+Ix/fWa8RPZtDG8=
+
+Name: org/eclipse/swt/graphics/GlyphMetrics.class
+SHA-256-Digest: 90tj5uUom9fNVL1I12ksVcC0k3c7QCU0RvKtBxJH/8A=
+
+Name: org/eclipse/swt/widgets/ExpandItem.class
+SHA-256-Digest: VSvF5Wl8IH41MEElxesLys/JAawYOMoyJeAuENQY4CE=
+
+Name: org/eclipse/swt/internal/ole/win32/FORMATETC.class
+SHA-256-Digest: K+gk+F4B4AzLc2pZ0iteYgeFlPHN2J41gA2u3bspYfc=
+
+Name: about_files/IJG_README
+SHA-256-Digest: TPnBkPGEAZthw2vMSdSiT/6yqDjG8WkNbE2xTPstBHg=
+
+Name: org/eclipse/swt/custom/CCombo$1.class
+SHA-256-Digest: 0Wla6Vs5RPwuCaxTJGnhZIKG33PigfEp2F0YG4OlI7o=
+
+Name: org/eclipse/swt/browser/LocationListener$2.class
+SHA-256-Digest: HoJPLSFrKE7s20KlRBcvzxv1laT6wbxloJQRwKhMUvE=
+
+Name: org/eclipse/swt/internal/win32/HDHITTESTINFO.class
+SHA-256-Digest: rrDRKeTV6SBO0B2WkbJBuGAQaO3QQL8Ogoi4840IMf4=
+
+Name: org/eclipse/swt/dnd/DragSource.class
+SHA-256-Digest: htGh0ftQt2JSvUbjs7WGA/zAzCOa6Fj4fYkjTKTg15M=
+
+Name: org/eclipse/swt/accessibility/AccessibleEditableTextEvent.class
+SHA-256-Digest: 8uf5GG4p52KKcucVO4FnRrTGU3ylQR25ZydNrBNGDtg=
+
+Name: org/eclipse/swt/internal/ole/win32/IConnectionPointContainer.cla
+ ss
+SHA-256-Digest: rPpEZtEJfGctPP+PJ7Bq/OqOEtblh5GgsnYEAqxrsP4=
+
+Name: org/eclipse/swt/internal/win32/ACCEL.class
+SHA-256-Digest: O9k69m7HAWyJfg/KzdUFPqvxIS+RYSt4d9aXDJmgjzE=
+
+Name: org/eclipse/swt/widgets/TaskItem.class
+SHA-256-Digest: tNvznvzupGvrJdFEhOFPSx9TeGG6hkvvGI3+xsV6lvY=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$savable_state.class
+SHA-256-Digest: hws0kFXAetlYTm6rTEs53IxgqsbUuVC+/RsjY/zWOMg=
+
+Name: org/eclipse/swt/layout/GridLayout.class
+SHA-256-Digest: +mGKnmG1iDr5bG7JE0nxrwbFgcgtYN151hhW3io1plU=
+
+Name: org/eclipse/swt/dnd/DragSource$1.class
+SHA-256-Digest: YZxHqqmb3w3Q1TUxi9fQrdifTzmhMGaDy0mEoCUORbE=
+
+Name: org/eclipse/swt/internal/image/JPEGQuantizationTable.class
+SHA-256-Digest: uCh4gSVEqHsMNXUCN+9ZufHzOExtYi0s7bIXcEGgvhg=
+
+Name: org/eclipse/swt/internal/image/JPEGComment.class
+SHA-256-Digest: 9r42qNAKpqnQhGo6moBsYlrLz34oZS8eDMcZI86sRAY=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_decomp_master.cl
+ ass
+SHA-256-Digest: CbLW3JItl+KJnDxpOk8tEsaezVyTyQY9fXDBHalgxA0=
+
+Name: org/eclipse/swt/custom/CCombo$2.class
+SHA-256-Digest: i3IOUPuXSMburZwf5JS/RlDxUzaxb/T1k8nv+I15PLY=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleDocumentView.class
+SHA-256-Digest: lAWLoeD/RjcTUwNKtob37io7UsPnleceMERhPTkvDBI=
+
+Name: org/eclipse/swt/graphics/TextLayout.class
+SHA-256-Digest: DVPc2zp0Fz+RfAH4RWWTBi/r/7LjhDE9YIBvBt87Mak=
+
+Name: org/eclipse/swt/dnd/DragSourceEffect.class
+SHA-256-Digest: mZlqIltWRo+lnh6SyFrpmm2ZCeFy3t3geWPbH/sX4ZQ=
+
+Name: org/eclipse/swt/ole/win32/OleParameterDescription.class
+SHA-256-Digest: UqEe1XYNFtshagCxbASFXG7ebLxRkKWa0p1nSpFWPt4=
+
+Name: org/eclipse/swt/widgets/TreeColumn.class
+SHA-256-Digest: kWg8GN+RXELBcYoF3DbpOqgPlovQ/jsNaEOzjV1m/94=
+
+Name: org/eclipse/swt/custom/LineStyleEvent.class
+SHA-256-Digest: IBwvbTnOAcxbIfou3nOW/bv1fh611nFhHNaqeQajAcM=
+
+Name: org/eclipse/swt/widgets/Link.class
+SHA-256-Digest: nl/Bh3RsXkej2l/iskqst4jwduZUsdRXKyj6CF0i0+o=
+
+Name: org/eclipse/swt/internal/ole/win32/IOleInPlaceActiveObject.class
+SHA-256-Digest: +bxUfKfLsdX6geIxTjt5WB0p4T+DAQjebYjr3WzfP7I=
+
+Name: org/eclipse/swt/dnd/DropTargetAdapter.class
+SHA-256-Digest: et+Lxn5dByGzXP8qF3ZpNmyqQjP/36c/iPpJDwV0f1I=
+
+Name: org/eclipse/swt/printing/PrinterData.class
+SHA-256-Digest: 0yvPxWiVjpYMgQ3S+/vQ/N7i0WesG25zoafy13+bXMg=
+
+Name: org/eclipse/swt/accessibility/AccessibleAttributeEvent.class
+SHA-256-Digest: j1z9Ttzs6dQ4I+T0s6WJBfzY0PIcpi2mZuGG+ETuqi8=
+
+Name: org/eclipse/swt/custom/CTabItem.class
+SHA-256-Digest: nWlgnDvD3MaN/Et07yiO3wPc4IIo4UuFZMKeRkmdzsY=
+
+Name: org/eclipse/swt/accessibility/Accessible$10.class
+SHA-256-Digest: TpJOc+9e6G4YQEye5XUrcET0Q/1PNh+Kf5dj8nTBtYY=
+
+Name: org/eclipse/swt/events/ShellListener$2.class
+SHA-256-Digest: NGADNnsztRq0xqf4ZekGpLmPkx9kmZo/kXM74UmqrEc=
+
+Name: org/eclipse/swt/internal/win32/DOCHOSTUIINFO.class
+SHA-256-Digest: kIZaArjTqmcvKy3vs46UIhwSKnG8hHL4uOf0zPWCh08=
+
+Name: org/eclipse/swt/events/DragDetectEvent.class
+SHA-256-Digest: lcd1b18q93dezD3G2+JxFoq8Yfwm+9N0o5KbcIJwZE8=
+
+Name: org/eclipse/swt/SWTException.class
+SHA-256-Digest: 7EH9xAtRnmgfg6RO8JQGz1emOdu3efiwtX6hrma23gA=
+
+Name: org/eclipse/swt/internal/webkit/IWebURLRequest.class
+SHA-256-Digest: WVapCt0uq+H0vV5/w16P2wA1UrYzEn7ODtZrREKacHQ=
+
+Name: org/eclipse/swt/events/SelectionAdapter.class
+SHA-256-Digest: s6VkdVdeGJ7NUO6De2n1t+1RLm13yBZhNCr+iCXj/a0=
+
+Name: org/eclipse/swt/events/KeyListener$1.class
+SHA-256-Digest: U6yjrpRsSqf1mO48Lx2NHzPd8bRKdUdljrbrqaXvaiM=
+
+Name: org/eclipse/swt/widgets/MenuItem.class
+SHA-256-Digest: z6MTnv/jfxRJ7iW4v5K7y/buhfnGhUu30YGvcLcQ+Vk=
+
+Name: org/eclipse/swt/ole/win32/OleClientSite$5.class
+SHA-256-Digest: t33Vexym7sFIL0vxyvjS+YTqZLn6VrElyMC04Y+55y8=
+
+Name: org/eclipse/swt/graphics/Path.class
+SHA-256-Digest: OrMmr5Ww+8lAJHluhoUqx1o3mkWHELL/EUCgOozTFFU=
+
+Name: org/eclipse/swt/browser/WebPolicyDelegate$1.class
+SHA-256-Digest: HmrtzRhX0zXFYjTXXsh8eCRKp69O8hYBo1g0E8MuSNI=
+
+Name: org/eclipse/swt/internal/win32/EXTLOGFONTW.class
+SHA-256-Digest: fAKTJip5EJ8y+IZqWKqHzyTi1ikWZw6hjkWpSrmtyQY=
+
+Name: org/eclipse/swt/custom/CBannerLayout.class
+SHA-256-Digest: UFISVM6bpAsRsyMpHBEv4TANHdpw0IoBerXr3odB1Zg=
+
+Name: org/eclipse/swt/internal/win32/NMREBARCHEVRON.class
+SHA-256-Digest: rJYTihpsb0wlIJarrDnx0jRXOl7Kujn/m+hTFdk4ynA=
+
+Name: org/eclipse/swt/accessibility/AccessibleTableCellListener.class
+SHA-256-Digest: MRnNjMhtOlTyCcyC/DARm0rK8ZyRPiEUHQn6AZZHyMA=
+
+Name: org/eclipse/swt/events/MenuAdapter.class
+SHA-256-Digest: v4NMkmo9/+JHlxehSPpYUk+itInXRphg8PF39XH8o6c=
+
+Name: org/eclipse/swt/internal/win32/ICONINFO.class
+SHA-256-Digest: eFt+t2bBVUDgh59v8p+5bTLcpzmo2lEn0apK0PT+7eA=
+
+Name: org/eclipse/swt/ole/win32/OleEventSink.class
+SHA-256-Digest: 0cmcR0Bsx7+s54iH3+Q0Xnkqn27Lj1OSrKrOIsu2w0Q=
+
+Name: org/eclipse/swt/internal/win32/MONITORINFO.class
+SHA-256-Digest: Akp47FiWhD6D6kqsswDL8moNbmJm1F+T7/CLHKOXkE8=
+
+Name: org/eclipse/swt/internal/ole/win32/IUnknown.class
+SHA-256-Digest: hrZPW4kyRijLnPgFky5Wqnf3w9egvOyMB/uTks1/wAg=
+
+Name: org/eclipse/swt/browser/ProgressEvent.class
+SHA-256-Digest: eiU5nUWbCTC6nVGIDGdkdlGVsiPMWiEsx6sY388zTRI=
+
+Name: org/eclipse/swt/browser/WebUIDelegate.class
+SHA-256-Digest: ZAVSJnyipvnLXxfCc10nBa10hRvwjDsOhLVYCKgViKg=
+
+Name: version.txt
+SHA-256-Digest: oQsISlhMGvCnD2sB/iFAv6yMykq7UZN2FBev+sFNS7Q=
+
+Name: org/eclipse/swt/events/MouseListener$1.class
+SHA-256-Digest: 6KvuPKaVcx3xR7IEfLI9GvwCxuiGs5Rks5tFGoKglf0=
+
+Name: org/eclipse/swt/browser/WebSite$6.class
+SHA-256-Digest: hNvI36zGpeqLQQ597/ZrA/e8+U/hqlFBAqXXq9j+Sec=
+
+Name: org/eclipse/swt/accessibility/AccessibleTextExtendedListener.cla
+ ss
+SHA-256-Digest: wDbIwyKbLRKSESbFHXN95XhHLj3c/OgNxpynnM/cN0k=
+
+Name: org/eclipse/swt/custom/SashForm.class
+SHA-256-Digest: 3m0U+KvE4OMyH/zQF9dGOJP6c3KFopbTBFFkTMZPreA=
+
+Name: org/eclipse/swt/internal/ole/win32/IPersist.class
+SHA-256-Digest: NjI5bcX84CnJzLhv64158CuwcNiDfvcvgQYHnJWRP4Q=
+
+Name: org/eclipse/swt/internal/gdip/Gdip.class
+SHA-256-Digest: qUxMKVxztFC4lDBmUZwerlasPAhEvspBuSHJ89lOYy8=
+
+Name: org/eclipse/swt/internal/DefaultExceptionHandler.class
+SHA-256-Digest: 2r8r6Xc02GivpufanfjLPQ3QSA10tcuu0QyknhNt8/g=
+
+Name: org/eclipse/swt/custom/CLabel$1.class
+SHA-256-Digest: 5rvdAZ/8qz947pYm4XKdLnxa/KsfLgVM0tzffAPPHQI=
+
+Name: org/eclipse/swt/graphics/LineAttributes.class
+SHA-256-Digest: sMqanpfVZrjSsr8QovHTVEd/tvuNH/Ko5fNv0vy6ajg=
+
+Name: org/eclipse/swt/browser/WebUIDelegate$2.class
+SHA-256-Digest: +fqRoy5obzl217bCPxKQ+XSPOHX1hhQXOmN9vuAotTw=
+
+Name: org/eclipse/swt/ole/win32/Variant.class
+SHA-256-Digest: kZRTvWg/cRJVsklK2QbqHLZpYkpRxX4TuG3F1Jx0c9U=
+
+Name: swt-gdip-win32-4930r7.dll
+SHA-256-Digest: UUwzcNP9BvvPkM+q5zqRdLuK6DWuSL2oBYEiwNNlnNQ=
+
+Name: org/eclipse/swt/dnd/DragSource$2.class
+SHA-256-Digest: ZB0BC6E/5TTQj8X0xYemj+zJtgprRWcIWweO9UYJypk=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_color_quantizer.
+ class
+SHA-256-Digest: ijkUA4ij/5TxeTTYrFI2QacxUcu7RGho1hEcqOB1x9s=
+
+Name: org/eclipse/swt/widgets/EventTable.class
+SHA-256-Digest: 5jjv1a/OpUJzEGMCfDOhjO02gGB8Q2+DyyB/v+ZiLRA=
+
+Name: org/eclipse/swt/internal/image/FileFormat.class
+SHA-256-Digest: B38XLaZGDwCp1mWjo6Aeny35/f+nZyMf4rFPl9EdDHU=
+
+Name: org/eclipse/swt/events/ShellListener$3.class
+SHA-256-Digest: S0kRmSaKZS7v4lVEhVtjCwoP+2nx0L+49vthLhKmv1o=
+
+Name: org/eclipse/swt/internal/win32/TCITEM.class
+SHA-256-Digest: /LYWsTG7SvuDDPV5Np93BfNiEk2m6TwYLZ9JXKGPkdA=
+
+Name: org/eclipse/swt/events/FocusEvent.class
+SHA-256-Digest: pLcLnAbkI47yCSntUq7hhdSIBt05vbtsUSMLiMk/WKg=
+
+Name: org/eclipse/swt/dnd/TransferData.class
+SHA-256-Digest: 2PCIpKa9E47UxE2i9qeUuMFdXdG57BQddNdyGn3jQAM=
+
+Name: org/eclipse/swt/custom/StyledTextRenderer$1.class
+SHA-256-Digest: DmU9eWqQC20G1idvGecsPSX6tWja/7aVpFZvHhzhOEo=
+
+Name: org/eclipse/swt/internal/opengl/win32/PIXELFORMATDESCRIPTOR.clas
+ s
+SHA-256-Digest: 6Pg41p0HGkDd7Wv7TeRyvebyFSXf9PpOvvoNiBZTfew=
+
+Name: org/eclipse/swt/internal/ole/win32/EXCEPINFO.class
+SHA-256-Digest: yF614TkYl+S0TlEBzSEcFl2PCgHUPph9iMf0sEREh9E=
+
+Name: org/eclipse/swt/graphics/PathData.class
+SHA-256-Digest: cGxY+GidqNMmZ+mvJXmzAvY/VKAxdBudj6ZgOgdRehY=
+
+Name: org/eclipse/swt/widgets/Tray.class
+SHA-256-Digest: 3IyF+UYBdGB82mOVDwApvLyw+Wg8qGbXlFvklI6Wqh4=
+
+Name: org/eclipse/swt/internal/ole/win32/IEnumFORMATETC.class
+SHA-256-Digest: a8LzVg3v5mE9mOjYa4rJAknlCv0926Dbyi2OdUasQFg=
+
+Name: org/eclipse/swt/browser/WebFrameLoadDelegate$2.class
+SHA-256-Digest: kw8lwp/jiZoWCrRw8JWkcoGEeGLGcjA0DvAPJ1UmdPs=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_upsampler.class
+SHA-256-Digest: 9FjYwwLC+76zlIv/+aFxngnQat14AhfRsSl4prY3wwE=
+
+Name: org/eclipse/swt/events/MouseTrackListener$2.class
+SHA-256-Digest: 5Mq0jK8K41vYHwIXMyUBYKqTEEgWXoxwIQC83hzGq64=
+
+Name: org/eclipse/swt/custom/CTabFolder2Adapter.class
+SHA-256-Digest: JvF6GhXFSYicS6QXN1EmXM7zJEbo4rs+5iSRlsrzszU=
+
+Name: org/eclipse/swt/internal/webkit/IWebDataSource.class
+SHA-256-Digest: HszeAcu7kuieeMnGX7boVVce5ANe2V9l4y/A6TvdgoQ=
+
+Name: org/eclipse/swt/internal/ole/win32/COMObject.class
+SHA-256-Digest: Gp4jMVA66MA+oWMKHVwYyxHA3ROEf0R5wRV84nne4qw=
+
+Name: org/eclipse/swt/ole/win32/OleClientSite$4.class
+SHA-256-Digest: jzypPU9Y/37j6KauFTc0kpF3BoDhYJLk8N0hlSYn45M=
+
+Name: org/eclipse/swt/dnd/OleEnumFORMATETC.class
+SHA-256-Digest: arDDVMt09NC6DEv+Gerl8AxiSPOsRYyBZI/Y7c9NzJw=
+
+Name: org/eclipse/swt/internal/ole/win32/IShellItem.class
+SHA-256-Digest: fhHjT/kSggfGN8GKJMOiaQX6kBf8q9vCgQkgvpDhrEY=
+
+Name: org/eclipse/swt/custom/PopupList$1.class
+SHA-256-Digest: qErOdUaXtPC9p5g6N8nueXOOcCI56zevRr6mQKa41M8=
+
+Name: org/eclipse/swt/browser/WebSite$1.class
+SHA-256-Digest: GZA+MhQThbBQbw368bUL1j55bVHanHfgSehMV89fYDw=
+
+Name: org/eclipse/swt/internal/gdip/PointF.class
+SHA-256-Digest: tNeEWjlBT7EQmZRgxgxA9iJRqT3I9lkuN1ThkHvFkhM=
+
+Name: org/eclipse/swt/browser/WebUIDelegate$3.class
+SHA-256-Digest: OgUTlpEW3Ph+ANPmRPstzu1Th50g2zuLG/e6y6Qjg/s=
+
+Name: org/eclipse/swt/internal/image/OS2BMPFileFormat.class
+SHA-256-Digest: 8X0FTDk3/mZ86Q7SeM1ysaXJypnlMcSzSxMJu07B+4c=
+
+Name: org/eclipse/swt/widgets/Synchronizer.class
+SHA-256-Digest: gprcrqFYobGKr79HzoB9+I4AZf/tVchnpdOPKjgpspE=
+
+Name: org/eclipse/swt/graphics/Resource.class
+SHA-256-Digest: gKmQlwxdBUu1uZGeuNQTNCxdPZj6o+/N3kbPZITiXh4=
+
+Name: org/eclipse/swt/custom/CCombo$6.class
+SHA-256-Digest: ruucAa0ty87RAbdhnXTkFaAW/u505sy8cZ/0jw0trwA=
+
+Name: org/eclipse/swt/internal/ole/win32/FUNCDESC.class
+SHA-256-Digest: bk6ZRz3HWo2e1VnowwboQd0AIlnm5xLUBwCQeAR/+mY=
+
+Name: org/eclipse/swt/widgets/Button.class
+SHA-256-Digest: q832vpYrYtV4ew3PgavtQWXiyOAHQLZwlgi77OFoyHw=
+
+Name: org/eclipse/swt/browser/WebBrowser.class
+SHA-256-Digest: RTxmX8exR0lJoSmzRLUcbcmxwVh4PJoHvos2skpumUA=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_PROPERTIES.class
+SHA-256-Digest: 2BSU48nRub1H+85j5gqXVHHcfRqCor1qv+e/e/o/7zE=
+
+Name: org/eclipse/swt/accessibility/AccessibleHyperlinkEvent.class
+SHA-256-Digest: tjE5S7iw+Yn5XuPHmJ061YsgIGGC7+y7SrifKPaHqLg=
+
+Name: org/eclipse/swt/internal/ole/win32/IClassFactory2.class
+SHA-256-Digest: 1wwk0VVLCD5j0niOhVv1HTQVfG6MXKBQiKAsipyazcE=
+
+Name: org/eclipse/swt/events/ControlListener.class
+SHA-256-Digest: LFlfD60GB7+KdiGjNTcTmOOjnTBacsQaCe0p01p3oHw=
+
+Name: org/eclipse/swt/internal/ole/win32/IEnumTfDisplayAttributeInfo.c
+ lass
+SHA-256-Digest: kecQIQ0dp+MHypeQq9sLeOBTagfBr2Cuuftp1T/xa7c=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_DIGITSUBSTITUTE.class
+SHA-256-Digest: snmzGILXvfLyPHAUuNokIfaXtCq69i3Fo9enIQhvCCE=
+
+Name: org/eclipse/swt/accessibility/AccessibleTextAttributeEvent.class
+SHA-256-Digest: R1dLWcH3QMXXN+MlD7KvX/zP/7VD4C07+0aumk/skxg=
+
+Name: org/eclipse/swt/SWT.class
+SHA-256-Digest: VTb6dngZu7Y8JBh5eGbUt8TeEdOIeXx34mLcrmmsmsE=
+
+Name: org/eclipse/swt/internal/LONG.class
+SHA-256-Digest: IkESLVa+lGHJOkABIIU3rnWFPHJUApB6lfrgtyqK/wQ=
+
+Name: org/eclipse/swt/internal/win32/CERT_CONTEXT.class
+SHA-256-Digest: l5YyQOeRoXcRzNRpaNziK9iD0DTVnf1Sb8BG3ONLYk0=
+
+Name: org/eclipse/swt/internal/ole/win32/IAccessible.class
+SHA-256-Digest: zsDlD0f7ID+zgzPM2TLP3BPZRK8zcK/kjhqTYzX6dM0=
+
+Name: org/eclipse/swt/events/ArmListener.class
+SHA-256-Digest: coYg1VoHS/6qD3WXYxbUDsi4UodXVUSgzcQvcpxInOo=
+
+Name: org/eclipse/swt/internal/win32/GUITHREADINFO.class
+SHA-256-Digest: 5VRPvzFc1M7vC++tc7J/mIpAFFF/6DL7nRu5v7yKUgQ=
+
+Name: org/eclipse/swt/widgets/Scrollable.class
+SHA-256-Digest: q9HpgyrLxiG3ye2c6NZ52L5grqGBHiWTEpWfr6oXmv8=
+
+Name: org/eclipse/swt/accessibility/Relation.class
+SHA-256-Digest: M1lBi8K5nr0luy5pOgmT0eaR/OKllxJIRkfqlsbjgh8=
+
+Name: org/eclipse/swt/internal/image/JPEGScanHeader.class
+SHA-256-Digest: eGIpUtSA2E6OGDoWU8QHGAc33PZabeQofvja0cbOPQw=
+
+Name: org/eclipse/swt/internal/win32/BUTTON_IMAGELIST.class
+SHA-256-Digest: Mnjt2cO99I6x8D8+ZimRDy7v4dAPxtC6bt0RJeFcyuA=
+
+Name: org/eclipse/swt/printing/Printer.class
+SHA-256-Digest: vH6YPkoF2IT1YIY10HqNOFrTOfSbm5odEynudg6KkbM=
+
+Name: org/eclipse/swt/widgets/Label.class
+SHA-256-Digest: RjPqcO1w2nKEoeoSnwaKOunmA8rkmJsw5edV/OanCw0=
+
+Name: org/eclipse/swt/events/ControlEvent.class
+SHA-256-Digest: Z1JCbxsW4FZlOabqeDWH+av/iIx5NFMHqkJNTFqw9P0=
+
+Name: org/eclipse/swt/dnd/URLTransfer.class
+SHA-256-Digest: 8BHTujur932HY31x9yFEn7/7hjEcJ4qtwHV1r9XTJME=
+
+Name: org/eclipse/swt/internal/win32/MENUINFO.class
+SHA-256-Digest: IYbQ0h+XXwISuXR1k5RrTdD9OkeVHN8uGgy1cDvFSyQ=
+
+Name: org/eclipse/swt/dnd/Transfer.class
+SHA-256-Digest: 399BQzwo4SkGMc5GWCUPJF7t1Al71gtA+cvizt21Lb8=
+
+Name: org/eclipse/swt/internal/win32/BP_PAINTPARAMS.class
+SHA-256-Digest: mPnxwIKN4x0RK/g0zYM/d51/Xd1SqR8ShFq4KkrdYvg=
+
+Name: org/eclipse/swt/internal/win32/LOGPEN.class
+SHA-256-Digest: AEMO0hYAC4EvWK5HFi6DSYXj4KmWyC4Qb8n2tvlaepo=
+
+Name: org/eclipse/swt/internal/ole/win32/IObjectCollection.class
+SHA-256-Digest: +iwfiwfITw5rHWBAxfEGcD5L1QKhlarRAlVV+/HeXX0=
+
+Name: org/eclipse/swt/browser/WebSite$2.class
+SHA-256-Digest: PLJNtELqf56K9fDEAYlPd5kFmQXEqoRZVVKZwaUntrU=
+
+Name: org/eclipse/swt/events/ExpandEvent.class
+SHA-256-Digest: qcwi7fVj9P1fq2JPVj6axcK2zMjygV5QnslKv0w17Xo=
+
+Name: org/eclipse/swt/events/MenuDetectListener.class
+SHA-256-Digest: eQFJ2ydz4GwGdD3nWTV6iQNfJAcbAZvovZAfZiO6vjo=
+
+Name: org/eclipse/swt/browser/WebUIDelegate$4.class
+SHA-256-Digest: oviYMkTTPh8+9pabACAitDhNOqJ7YdpJZWjYKqgRWqM=
+
+Name: org/eclipse/swt/graphics/Pattern.class
+SHA-256-Digest: O+rjb58o44OQ6FdrhJF4OrnhBxqbF5MS6IEMyc84LF0=
+
+Name: org/eclipse/swt/internal/win32/GCP_RESULTS.class
+SHA-256-Digest: S/Iiu4eMNDr/txUUw3GJ9KkccOixFFwDX6aaj8Pa+UQ=
+
+Name: org/eclipse/swt/internal/image/JPEGStartOfImage.class
+SHA-256-Digest: +23GXP50ilQTlQPkkSUja8hbKlZpU/B7vHcdjCg7jO8=
+
+Name: org/eclipse/swt/internal/win32/NMTTDISPINFO.class
+SHA-256-Digest: tYI7HNcBWQjCdHmfm9ju2Z4d/mfhOHPtzG/M2z6T4ac=
+
+Name: org/eclipse/swt/internal/webkit/IWebView.class
+SHA-256-Digest: VTn0PSoxD/lWPbF8lsToKUKNxKv79F1I49OQeSyEnl8=
+
+Name: org/eclipse/swt/layout/FillData.class
+SHA-256-Digest: U0cRfZd57XJGQ85C3A/xJXa8cLUqKeoQA0aES12ZRmU=
+
+Name: org/eclipse/swt/events/DragDetectListener.class
+SHA-256-Digest: DQC+rGI4udkHDW5Tl+6+2QM8Z9roZSk10ikEmr9ycPk=
+
+Name: org/eclipse/swt/internal/win32/SCRIPT_STATE.class
+SHA-256-Digest: jOUNLxHI4HaKJHYs/NiG4/hxFJjSpxpX1/gjjQyUS0o=
+
+Name: org/eclipse/swt/browser/WebSite$3.class
+SHA-256-Digest: oTLhVtxDewJGNyrGgsW8my3c5KM9rQfeb2dpFZD3ixQ=
+
+Name: org/eclipse/swt/internal/win32/ACTCTX.class
+SHA-256-Digest: EKunjYO5nQrOA6mS8fkjDLUpr0HncJOU6nBTiZjTV2w=
+
+Name: org/eclipse/swt/browser/WebResourceLoadDelegate$1.class
+SHA-256-Digest: Hj/f8ml/pJWO/8zvjiwHbDn7bkQSvWV/5mzsURywWTI=
+
+Name: org/eclipse/swt/events/ArmEvent.class
+SHA-256-Digest: 95HgyZphG0v12Oif14HBpgvOxvL0O+Js8f41qbZzdeY=
+
+Name: org/eclipse/swt/accessibility/AccessibleActionEvent.class
+SHA-256-Digest: 05i+bMeiyjfXvfRHmNSR7MDnUC/Q5+mVFs4dLIScCT0=
+
+Name: org/eclipse/swt/events/ControlListener$2.class
+SHA-256-Digest: XhlOAxUzsnBWOrQFc4tiuvCd3FLnPHcqZUktA4KkzFA=
+
+Name: org/eclipse/swt/internal/win32/NOTIFYICONDATA.class
+SHA-256-Digest: ROmYCayHA/vMSbX1MeQoW4XZllYL8hovWxcyXnL8+Y8=
+
+Name: org/eclipse/swt/internal/webkit/IWebURLResponse.class
+SHA-256-Digest: XR4oV/xuocro4AmDe21a6n0s3/c8+GfqGebupPV5NZ8=
+
+Name: org/eclipse/swt/custom/PaintObjectEvent.class
+SHA-256-Digest: p3H4JjRyCouTkl10PofI5Ym193NFZypdAX98UomsK1Q=
+
+Name: .api_description
+SHA-256-Digest: Ar0AqWqcBLBZpoZ5hEdO+ttg8rY75Ic6CzkJVcCfqaA=
+
+Name: org/eclipse/swt/custom/StyledTextRenderer$LineSizeInfo.class
+SHA-256-Digest: aQLkkRafLoL5OnMNX96uqFJXUWGWUhBLnrquD64RR58=
+
+Name: org/eclipse/swt/internal/win32/NMTOOLBAR.class
+SHA-256-Digest: 7y5xp/c4CA4EDchJ5ruEpE4c8n5yYwP7xoFy/mD6Cb8=
+
+Name: org/eclipse/swt/custom/StyledText$7.class
+SHA-256-Digest: lVydwK9fTSyaR0dc+CDDQ1XVyo2U+OzN/d+LrsBhUBo=
+
+Name: org/eclipse/swt/custom/SashFormLayout.class
+SHA-256-Digest: TTTmLz0ONZNqmPrabbW6V+84Do57FLi3A6ESgOv1KOY=
+
+Name: org/eclipse/swt/internal/gdip/BitmapData.class
+SHA-256-Digest: zSmdmdiT5GjksTDfsy3YSpLULepvc7lWjQDpx+iByb8=
+
+Name: org/eclipse/swt/internal/ole/win32/COM.class
+SHA-256-Digest: Xpo+0EWKHJU0vp0bysRA9VzGwgigSbmtDDCUMkwl4Wk=
+
+Name: org/eclipse/swt/internal/win32/KEYBDINPUT.class
+SHA-256-Digest: 1Da4iMww6qutTwnNGmAA0i4BQFGXZOfYKc8aQOmScjU=
+
+Name: org/eclipse/swt/browser/LocationAdapter.class
+SHA-256-Digest: 3nc/yTpg1dutJGGa/FeNhEXFIFnMzhT68HggYl1bnGQ=
+
+Name: org/eclipse/swt/events/VerifyEvent.class
+SHA-256-Digest: Txrwf359x04HfghGJQJTwi1hxNMeVOCv7A2tjm6ulwI=
+
+Name: org/eclipse/swt/internal/webkit/IWebURLCredential.class
+SHA-256-Digest: VJN27tqLo+W9oqa4nKA6rDl8hcVc4zMzBAMnUDwlAG4=
+
+Name: org/eclipse/swt/events/ShellListener$4.class
+SHA-256-Digest: lVPy+P1Viu2TkYzu1sPxdhrVfOo16rGxbeHbzr9g6XQ=
+
+Name: org/eclipse/swt/internal/win32/CERT_INFO.class
+SHA-256-Digest: i1c6rNIAJivzGV6z9FkdRhh8xh6Yi5791tEhppm/K08=
+
+Name: org/eclipse/swt/internal/ole/win32/IMLangFontLink2.class
+SHA-256-Digest: 6OF+6dVO+1VJ/3bTXyo63B0o8MaR9+IF5F6KGOZQWmk=
+
+Name: org/eclipse/swt/widgets/Listener.class
+SHA-256-Digest: qJi9ftlFttzc5t/buKmFQzR8kUFQMJt/etGDX9wWPnw=
+
+Name: org/eclipse/swt/custom/LineBackgroundEvent.class
+SHA-256-Digest: PFIV/QDD6VMH/wcXpdjWO4EpkNDVfakqNQqRGoMHuZo=
+
+Name: org/eclipse/swt/graphics/ImageDataLoader.class
+SHA-256-Digest: QACaFFm3LYNyXdqoHy4O34DMZ4G2fjY1erUv33FDqck=
+
+Name: org/eclipse/swt/custom/CTabFolder2Listener$4.class
+SHA-256-Digest: Mb9fk3ur8adnBfpV8W2YlFHss64w+UhqWBwpfDE/XkA=
+
+Name: org/eclipse/swt/dnd/DropTarget$1.class
+SHA-256-Digest: AG+e6lcK+WD1M1ztS8GpSOZd0xTpX3Wda1CrugEzDIs=
+
+Name: org/eclipse/swt/dnd/DNDListener.class
+SHA-256-Digest: 8XjEWf384Rq182A8Ds+IHiR/lBxI05+/chdCKS9YMpc=
+
+Name: org/eclipse/swt/graphics/PaletteData.class
+SHA-256-Digest: VwK3ah9sxC22rOPGa4OS72HAsgeHpPzu06TG/vjvbyE=
+
+Name: org/eclipse/swt/accessibility/AccessibleAttributeAdapter.class
+SHA-256-Digest: b/k4gxG6umf4y9Rs+UOzue4D9ck08AL+hlnuj8zo3Ng=
+
+Name: org/eclipse/swt/internal/win32/LVINSERTMARK.class
+SHA-256-Digest: C0AmOc+23HNn3IhFvkndViR/bviPs+MZKDmNMXTwicI=
+
+Name: org/eclipse/swt/custom/CCombo$5.class
+SHA-256-Digest: jBI8qjhGutN3V5tiEKnqO1HFops7XEw1uMl1DuhPVxs=
+
+Name: org/eclipse/swt/internal/Compatibility.class
+SHA-256-Digest: 4B+OmYc7jt1QqIr7oQkM4jHRy0vYBls51PahKiYIPHA=
+
+Name: org/eclipse/swt/internal/win32/INPUT.class
+SHA-256-Digest: J9oxYj7zklg1wKk+cz9AokDVVdGy6gScLH2ntkKa9cE=
+
+Name: org/eclipse/swt/custom/StyledText$TextWriter.class
+SHA-256-Digest: p/M4GKlY8WFOX9Y+QwuEZZr1nIPtU+SkNGp3UwFD9bg=
+
+Name: org/eclipse/swt/events/DisposeEvent.class
+SHA-256-Digest: Fy+FyJIQ2BcJLUcjmJM0bS9Dh29XO6NRjO9yegx8uMY=
+
+Name: org/eclipse/swt/internal/DPIUtil.class
+SHA-256-Digest: N44BkleMK6KS1JmiJclIF1YhGpK2/UDIaUD8sYo9IRY=
+
+Name: org/eclipse/swt/custom/StackLayout.class
+SHA-256-Digest: XaqCGiE2Fng9cq8KHDi9JnmEXYReaNANex3eKwmScqc=
+
+Name: org/eclipse/swt/internal/win32/NMCUSTOMDRAW.class
+SHA-256-Digest: ZnxwDQWdtwPiUOhAioh/lvdclxIDvHjrLi8aSKdhisA=
+
+Name: org/eclipse/swt/custom/CLabel.class
+SHA-256-Digest: rasSvy4z/xFCGeRxYqF9f4kZfo7axDq9cmlqZekPiK4=
+
+Name: org/eclipse/swt/custom/StyledText$2.class
+SHA-256-Digest: BppuZqpC0kde6Q0FiHiVSeES8j4XEmweY2KCBlyrsj8=
+
+Name: org/eclipse/swt/dnd/DropTargetListener.class
+SHA-256-Digest: WGis5tW/MB91qy+NiBV2LvrDExq3FZpqCc2UWRAEgxk=
+
+Name: org/eclipse/swt/widgets/Menu.class
+SHA-256-Digest: KCeTUVfohLsoEsuEctcliTvygqPI7eo7h/tJW6QwuPk=
+
+Name: org/eclipse/swt/graphics/ImageLoaderEvent.class
+SHA-256-Digest: /Ffo9azeutEmuIhhmuk+BaTxkpGJ8JUOScA0MNf70Fs=
+
+Name: org/eclipse/swt/internal/win32/PROPERTYKEY.class
+SHA-256-Digest: IC88Y2nZsLFMfX9IaF+sdKvPKShfGnabdwhCvK20IT0=
+
+Name: org/eclipse/swt/internal/win32/CRYPT_INTEGER_BLOB.class
+SHA-256-Digest: ChURe5/AZYAtMvn8qkVdA7uxQYoSzslOVSFWgXO2zSk=
+
+Name: org/eclipse/swt/internal/Platform.class
+SHA-256-Digest: 8R3+NMwLjc0zVogzSMR0MxXIiE7fGUYvDw0ONj9HLIk=
+
+Name: org/eclipse/swt/ole/win32/OleAutomation.class
+SHA-256-Digest: QP1/bm/uaYXl4W9lKhYD7S2mrBWksUL4DVeKV+tBXJk=
+
+Name: org/eclipse/swt/internal/image/PngDeflater.class
+SHA-256-Digest: L0/hj8kFwVPTb5nr1McoaxHT65Vh4ctUDGctdqKd1z8=
+
+Name: org/eclipse/swt/custom/StyledText$9.class
+SHA-256-Digest: WE4BC+PxZz12EFJABojR/YlLZJxvzWip/Z+dgxPlkV4=
+
+Name: org/eclipse/swt/custom/ExtendedModifyEvent.class
+SHA-256-Digest: 1lASTwjuRccSX1/9Z1k6EYTVca4iJqO8RvcxBeEVQXU=
+
+Name: org/eclipse/swt/custom/StyledText$10.class
+SHA-256-Digest: mc05Yog8bxuwznIDzUlC4314+c+edotJKz3KJmU+Ih0=
+
+Name: org/eclipse/swt/internal/win32/OUTLINETEXTMETRIC.class
+SHA-256-Digest: y8q0HAlXxJYxcxJiPtnUsDmaTOFksr0Mq0CdeNyGus8=
+
+Name: org/eclipse/swt/internal/win32/NMHEADER.class
+SHA-256-Digest: fyxoDZ6P4y7OTV5dELErBg4Tx/YAxJe3LCVw0zIAoqk=
+
+Name: org/eclipse/swt/custom/CCombo$3.class
+SHA-256-Digest: zHVqVT/wZ1sN4PXLR6h5AX0P5VU30LbqimHR8km91rs=
+
+Name: org/eclipse/swt/internal/win32/MINMAXINFO.class
+SHA-256-Digest: 3HR4IJkRYYv1YQXtCNNaggEdltvAjBgmJUiJQqTJ950=
+
+Name: org/eclipse/swt/internal/win32/SYSTEMTIME.class
+SHA-256-Digest: djpMx0OGZF5H8no8xn9VtuuPl69lMwFuSOZmZEaX9Mo=
+
+Name: org/eclipse/swt/internal/gdip/RectF.class
+SHA-256-Digest: oOGL2tb2fw+T+fVnKiPpqPrjGlq7adSB0TUFitpuTCE=
+
+Name: org/eclipse/swt/accessibility/AccessibleEvent.class
+SHA-256-Digest: 8JLcL/n1B+l3NZjRW+mZ1QFFZq5b4eOdhAUy3z0hU9c=
+
+Name: org/eclipse/swt/graphics/Font.class
+SHA-256-Digest: BnQE5Q/t53Bc0Nvv6CaD2cQZTxz3zgRWKo83ThpvLAw=
+
+Name: org/eclipse/swt/events/GestureEvent.class
+SHA-256-Digest: xshISuF+KOukCSR99Axj90bqSCscsIPMir3T0mZ53to=
+
+Name: org/eclipse/swt/ole/win32/OleFunctionDescription.class
+SHA-256-Digest: 0gYFOzhWfSe2UyHVlxX7GvhaDuf1SH4GiOfWzQ0TEVU=
+
+Name: org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeInfo.class
+SHA-256-Digest: KMj9DoZEkN1zjoGg9M+atzg9LP78PpFe88VDBcg7RCY=
+
+Name: org/eclipse/swt/internal/win32/HIGHCONTRAST.class
+SHA-256-Digest: h48FtpzZLhOHE1CmUXKdH3PZDmzJ0xHCeUp3QqWJjjg=
+
+Name: org/eclipse/swt/internal/image/WinBMPFileFormat.class
+SHA-256-Digest: 6mwqsEGugDxP0EUX/A3oBND2tZbcuDuRJcjdzyTDrcY=
+
+Name: org/eclipse/swt/internal/image/JPEGVariableSizeSegment.class
+SHA-256-Digest: x6CwNHoF7K9sLPeV5eNn0SGeO4LrFMc6gggYevBglZE=
+
+Name: org/eclipse/swt/events/ShellListener$1.class
+SHA-256-Digest: 0pBp9Qmwd2JE2x/klo682S6KgjVD9PskpxYbz3bAyoU=
+
+Name: org/eclipse/swt/events/TreeEvent.class
+SHA-256-Digest: iis5QfJgw9t4O7CcakI/5NrEUy13ZbsYZABcqpZMZpM=
+
+Name: org/eclipse/swt/accessibility/AccessibleHyperlinkListener.class
+SHA-256-Digest: b+EXgfMJu+pTJKZ/17mjXCIjebXNq/dgGGHj0A/Y7Dc=
+
+Name: org/eclipse/swt/internal/ole/win32/IShellLink.class
+SHA-256-Digest: Lwk3SE5sObvGgYX8LZ8Nletg2iNhcCtm3JPztmBVYu4=
+
+Name: org/eclipse/swt/ole/win32/OlePropertyChangeSink$1.class
+SHA-256-Digest: xLI3KHPyzc2BbrYONbWk0sR7JABqaN8grkubMAcOJhA=
+
+Name: org/eclipse/swt/internal/image/PngIhdrChunk.class
+SHA-256-Digest: 09c6eMGF2tWaj8BJfpQSCtX6i1l3D69mB6TW7bnl+Lg=
+
+Name: org/eclipse/swt/graphics/Drawable.class
+SHA-256-Digest: fxK/zaonEjKvbo337dTDNKFfqAA+/bDMpZAA8nc2n7w=
+
+Name: org/eclipse/swt/internal/win32/GESTUREINFO.class
+SHA-256-Digest: QutNOIFcDk0yr/eLWyva9esM5YoJVf2pBzjAdGi7br4=
+
+Name: org/eclipse/swt/graphics/FontData.class
+SHA-256-Digest: 1RESbMIHpCFFSuhOdCApuZwuehUDi7NESkdeXzk3hyE=
+
+Name: org/eclipse/swt/custom/CTabFolder2Listener$2.class
+SHA-256-Digest: /eKK6khIuUBJ9uid9Z4XyDfaZPQ6tYq8aBAyFTLPubY=
+
+Name: org/eclipse/swt/events/GestureListener.class
+SHA-256-Digest: bkAMtvmFXzw69qwYhzhFQGc7+LQ4Z/X2YJqscTqGpcI=
+
+Name: org/eclipse/swt/internal/image/JPEGFixedSizeSegment.class
+SHA-256-Digest: nS9/oXkWF/h2cNZLVRO4B8R390L6kIpPYtS9n9d9f3s=
+
+Name: org/eclipse/swt/custom/CaretEvent.class
+SHA-256-Digest: sDI5acDLwVjKX4tsNeEfe1bg/k9GQe+F4nAUB227L+A=
+
+Name: org/eclipse/swt/events/ShellListener.class
+SHA-256-Digest: 4dF+632EqlRJBk65MhjByK0OtnHioPQ3zDROJYA0q1I=
+
+Name: org/eclipse/swt/custom/ST.class
+SHA-256-Digest: v5FWU9uRxthFWLX9nk46lUv4FSehLiUSNild04hhrQE=
+
+Name: org/eclipse/swt/internal/win32/FILETIME.class
+SHA-256-Digest: Nz3K9NNo/Jyy/zuhKZN1qoPVmLG8p4IVfxQullbBZMU=
+
+Name: org/eclipse/swt/widgets/Tracker.class
+SHA-256-Digest: 27gsLJJX7jXzduEVquY8e9Qh37bKAYCKPtu8F247clE=
+
+Name: org/eclipse/swt/internal/win32/FLICK_DATA.class
+SHA-256-Digest: CWYO0GnyqpehnMAWf85i6nk7+GnuYwptHtrTlZkH6SM=
+
+Name: org/eclipse/swt/accessibility/AccessibleTextAdapter.class
+SHA-256-Digest: NaEWkpvhF6gku3odwnRxxM+qOD8f/j4NIsQJeMZYsiU=
+
+Name: org/eclipse/swt/accessibility/Accessible.class
+SHA-256-Digest: 6ZeQ5RxnkZzRvSHy2/YiRWkk8p+5hgndPFDa2kySi1U=
+
+Name: org/eclipse/swt/custom/StyledText.class
+SHA-256-Digest: xpfROSFJo6GeRPWDrw49nTjWpqtBk+gkT5jKD0Y8zyU=
+
+Name: about_files/mpl-v11.txt
+SHA-256-Digest: U2kqLtbGosbsmzLdC4IN+ukeCh/N9iXKntC9+HBfzE8=
+
+Name: org/eclipse/swt/custom/ControlEditor.class
+SHA-256-Digest: JI0epNI6Nx4qRgwYkVIao1G4hBodqzJ2FDnrSPNGj7c=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_color_deconverte
+ r.class
+SHA-256-Digest: 17j04EJx8F/10WCVaw01zflyExyQ3oOFDQO21CWyWG8=
+
+Name: org/eclipse/swt/internal/win32/TCHAR.class
+SHA-256-Digest: FJvBK+HU9jH0mjSCK0n5MzXMsG9d66PKXCg3Q6pMAJ0=
+
+Name: org/eclipse/swt/browser/BrowserFactory.class
+SHA-256-Digest: TUipkDAit64LoKgokUX5Uao6A22Ga4rAXQc4wKI3FCs=
+
+Name: org/eclipse/swt/events/SelectionListener$1.class
+SHA-256-Digest: MxM8TXMspT3nUzvPMPU5+7iats8KHr4iWRL0tLZcLWc=
+
+Name: org/eclipse/swt/internal/webkit/IWebIBActions.class
+SHA-256-Digest: Qu7TLzA5ySTLqRLrrRvCkSvkhXhXwTrQ1gd9B8+ce7Y=
+
+Name: org/eclipse/swt/custom/PaintObjectListener.class
+SHA-256-Digest: iofIzsfUuKR+rdK+TW9yufTEmeKA6UIuW77cBUaGOMQ=
+
+Name: org/eclipse/swt/graphics/Device.class
+SHA-256-Digest: +7az8WwFYCwbi5QwEpgHnoDq07VMpLvPWY9Ullu+Wsw=
+
+Name: org/eclipse/swt/widgets/Sash.class
+SHA-256-Digest: aEdN4RGzwF5j+zjYFfu3jsgA7wTS6NELyX0V4k4xSw4=
+
+Name: org/eclipse/swt/custom/CLayoutData.class
+SHA-256-Digest: PY3i0a3Si98hKiI9m6P1L/ekYCHPMAfXtSuobGsoeoI=
+
+Name: org/eclipse/swt/browser/WebPolicyDelegate.class
+SHA-256-Digest: r7YlT9PXWlvBh+NCTHnWh4cG+hp2Mk/Di4ckBKZWQYs=
+
+Name: org/eclipse/swt/ole/win32/OleFrame.class
+SHA-256-Digest: jhewslKdC/YTUKvipvdTD0EVKpc7eWUfbeqpr2vVjyE=
+
+Name: org/eclipse/swt/events/TreeListener$2.class
+SHA-256-Digest: yD2saroOqKlkA+x6D1b0LAdDKsrkotlavZHUOv+XOnk=
+
+Name: org/eclipse/swt/internal/win32/NMTVDISPINFO.class
+SHA-256-Digest: PfB9SYobu2AzjrpRVB+zhoqXdG5W4DlanXiG4EZjzOI=
+
+Name: org/eclipse/swt/internal/win32/OFNOTIFY.class
+SHA-256-Digest: 9yDBvjIBcYQ6hdQygVOaVGlxV+xAUPpWV+akb7Ad9DM=
+
+Name: org/eclipse/swt/graphics/TextLayout$StyleItem.class
+SHA-256-Digest: sXwnljWrCzUCWBjmLtlIw7m1Z+e5NLX/+Cj4vLvCu8s=
+
+Name: org/eclipse/swt/internal/ole/win32/IPersistFile.class
+SHA-256-Digest: efnllopRpu2LbYm7nPraH5USuVBdvY0Q18FWhtfDzNQ=
+
+Name: org/eclipse/swt/internal/image/JPEGFileFormat.class
+SHA-256-Digest: i7uzwienWneVuHCqeyOHxUpPCuTTLc6xqEL75X7TcQk=
+
+Name: org/eclipse/swt/custom/TextChangeListener.class
+SHA-256-Digest: GY9HbSyno35eTmMJZZx6dwChGHdjRxZ9f9wVABFKE70=
+
+Name: org/eclipse/swt/ole/win32/OlePropertyChangeSink.class
+SHA-256-Digest: X0NYuocFv3TsU72hJJOAfDLw5nW7r6KmVOTFFNuAQGg=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_inverse_dct.clas
+ s
+SHA-256-Digest: 8WNACP/QTMp5k4q2bvYzdSz3wwLu47fBHntXnTgIJKg=
+
+Name: org/eclipse/swt/internal/webkit/JSClassDefinition.class
+SHA-256-Digest: T3zwOyiybe7S4dh1yQwx1NBScnd6ED5prXmyPWVDHT8=
+
+Name: org/eclipse/swt/graphics/Transform.class
+SHA-256-Digest: ANGIRdcILu/vOFeco3uLg/xkSsPXQ9jzNgtg+yVGF40=
+
+Name: org/eclipse/swt/custom/CTabFolderListener.class
+SHA-256-Digest: N5ckLAMtYaSJdneJpT2RidjosRn/WC0a2ka37Qt9J+A=
+
+Name: org/eclipse/swt/internal/gdip/Rect.class
+SHA-256-Digest: drYxQRyfQDYEmaswrMApzX2y8DAvTTewKTnafWfn3S4=
+
+Name: org/eclipse/swt/internal/win32/NMUPDOWN.class
+SHA-256-Digest: 3ccWB9sihdo0e5oZ9+rKEk/L7Bx4/4FL/IIH4P24D80=
+
+Name: org/eclipse/swt/internal/win32/NMTBHOTITEM.class
+SHA-256-Digest: lwuvVItD82KxfzKhZiYe5yVguuFNnaebs8dGSEYdhvI=
+
+Name: org/eclipse/swt/events/TreeListener$1.class
+SHA-256-Digest: /vG5cJWZ3sc6c8TIeIncuqDXi9dB+AUjQWbNxoeBImI=
+
+Name: org/eclipse/swt/dnd/FileTransfer.class
+SHA-256-Digest: 0amk2T03p0Gn3l+10tnNTaZ8e9NWlOs3C1VzwE+Xgoo=
+
+Name: org/eclipse/swt/internal/win32/TBBUTTONINFO.class
+SHA-256-Digest: bFY1cSQW/Tawz8uP7pwEq84a54cOIuDIDSNlL7FQrEk=
+
+Name: org/eclipse/swt/browser/StatusTextEvent.class
+SHA-256-Digest: pRVBfO3EI7cYCWlPeJrFaWCfLlTFgI4H7vmy/ekfxfE=
+
+Name: org/eclipse/swt/custom/StyledTextLineSpacingProvider.class
+SHA-256-Digest: VGvuEEjJy2Ln6oowf7wvQrAPwqoUnxKvwtxUDbntE18=
+
+Name: org/eclipse/swt/internal/ole/win32/IServiceProvider.class
+SHA-256-Digest: SV/vUp5MgaV0rdewcWr4aV1X7kUQv5FQOCBcfHcVuC8=
+
+Name: org/eclipse/swt/graphics/Region.class
+SHA-256-Digest: Vz2q6GKTsd+gCbDyRXlbD28V0uzOmj6aQE3JtO67ZAw=
+
+Name: org/eclipse/swt/custom/StyledTextListener.class
+SHA-256-Digest: wxhLBPUq1plVbX84mmrZDZpO0j9XkyLMk9zT7DNDqgw=
+
+Name: org/eclipse/swt/custom/StyleRange.class
+SHA-256-Digest: aTRhCbKu4E0del9Z6anO9h+wORhAGeWh2sYXx0BNXS8=
+
+Name: org/eclipse/swt/internal/win32/NMTVITEMCHANGE.class
+SHA-256-Digest: bqFJflOq/vsMiK+/LMSFbxTial9sYIlaKcbrOStQ9Is=
+
+Name: org/eclipse/swt/internal/ole/win32/IPropertyBag.class
+SHA-256-Digest: SHQmacA6+5lOHSNimrgPw5pvF6CKCjMXX0EpuxlBOMc=
+
+Name: org/eclipse/swt/custom/SashFormData.class
+SHA-256-Digest: Hh8sGnplrLPShtfdKWcO+Ebc/dmbDgOYMKh/jx297Sw=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder$jpeg_decompress_struc
+ t.class
+SHA-256-Digest: 6PafCN0sXWWjTtIWcoH8KsZxhWXxU1E5MgFMJuXXhMQ=
+
+Name: org/eclipse/swt/browser/WebDownloadDelegate$2.class
+SHA-256-Digest: 8kj/6LZYU3mnF9TsroBYSYwXhcV3BKa1Unpmcakdlss=
+
+Name: org/eclipse/swt/widgets/TaskItem$1.class
+SHA-256-Digest: 7YvIej6EFJ4ZSIEDyqWypJgrfCOQZ1DCFb8/U59l8QU=
+
+Name: org/eclipse/swt/internal/image/GIFFileFormat.class
+SHA-256-Digest: FL0ki1XEplmtqdO8e+EtH47gKrtxXw1/m6ptHv4yjB8=
+
+Name: org/eclipse/swt/events/VerifyListener.class
+SHA-256-Digest: zLMtoyG/cbb82mZbtOiX8Bvbi5nRHT7agq9ppMI8Ce0=
+
+Name: org/eclipse/swt/custom/StyledText$6.class
+SHA-256-Digest: a1grIG7AsijwcXODRm4zHZwn4oBJXfVuh7VbLt4TJvs=
+
+Name: org/eclipse/swt/custom/StyledText$3.class
+SHA-256-Digest: 1J5Xv77LR7JmauiV7Dcg8gPbdosQArKdCa6lTLVPF54=
+
+Name: org/eclipse/swt/internal/image/PngIendChunk.class
+SHA-256-Digest: kiXNuUKj3WsohIUc/9/pkfkV/dnJekSYhUk0ujzwqjE=
+
+Name: org/eclipse/swt/events/TraverseEvent.class
+SHA-256-Digest: TTktNwUFDuZYr+Igo5a4PQ4bwSEvl2fSRDnuAS5dVvw=
+
+Name: org/eclipse/swt/accessibility/AccessibleValueAdapter.class
+SHA-256-Digest: hP/29i0p0RkduY0JexEbz6aTkDolRL/fjPEf4Q+Q06s=
+
+Name: org/eclipse/swt/widgets/Event.class
+SHA-256-Digest: NrOEnPjFxOevpbPFeUgQQHnirqb4MpJ8vr8sGHc6Qyo=
+
+Name: org/eclipse/swt/events/SelectionListener$2.class
+SHA-256-Digest: M2E03CoKfKhcz7aWjjvhC4VXCW35ArGlNIEXPJWkdxI=
+
+Name: org/eclipse/swt/browser/AuthenticationEvent.class
+SHA-256-Digest: SY79N1zm+huQFVLkaZEXVuDNrwq08eLscUvjAi0rKqE=
+
+Name: org/eclipse/swt/dnd/OleEnumFORMATETC$1.class
+SHA-256-Digest: CGT62osQ3CDMY4Yj6IslpqkY2m3y8LfcFNhUIXsedEQ=
+
+Name: org/eclipse/swt/browser/WebBrowser$EvaluateFunction.class
+SHA-256-Digest: rUW5qI/Nq744mt8X6VUtrgWa7tkdSQjLJ0ZdgTdG3kg=
+
+Name: org/eclipse/swt/custom/StyledText$4.class
+SHA-256-Digest: 2GEDlwwEMnUPnNOQcoIeV7vPQIuK67BqJyE5TK0+W9o=
+
+Name: org/eclipse/swt/internal/win32/TRACKMOUSEEVENT.class
+SHA-256-Digest: jd2zQikReCWVRyBfHzVdnPAkYMXmzem3g1r3pZWp1V8=
+
+Name: swt-win32-4930r7.dll
+SHA-256-Digest: UVWU8vAwQrRytLnFlCbeIVw4DzhaWaUF56zGz1kM4CI=
+
+Name: org/eclipse/swt/accessibility/AccessibleValueListener.class
+SHA-256-Digest: 0O0qiyEboJ7neqIgr3ntOpjlxpNcQNkf0ZsnI8N0sXs=
+
+Name: org/eclipse/swt/custom/ViewForm.class
+SHA-256-Digest: /ETkdYOVOFPrZbHEVcG+FsU8u3RZDnksRlxMEvcGV94=
+
+Name: org/eclipse/swt/events/MouseAdapter.class
+SHA-256-Digest: v8rUNKsMdb4k1arnE3rDcMTMboPkblO8bZ9vqXiSff4=
+
+Name: org/eclipse/swt/widgets/Layout.class
+SHA-256-Digest: 9aGdKN09Cg5gd23muU8FGdaSY8QfVEMFPd4SIPXeHEE=
+
+Name: org/eclipse/swt/events/ControlAdapter.class
+SHA-256-Digest: C2PAERYmnLMNJbvwp4rATogF1pyJhZWa3sUDNoaxue0=
+
+Name: org/eclipse/swt/internal/ole/win32/ISpecifyPropertyPages.class
+SHA-256-Digest: td/8mAhoNbpD5CVSw4+jEScP07k7Ww8l95Fc/1AGjNw=
+
+Name: org/eclipse/swt/internal/Library.class
+SHA-256-Digest: mG44gHI2OdksNkDHK83yW4jt6Z9oIe4x3PsuHao1uiY=
+
+Name: org/eclipse/swt/internal/ole/win32/IPersistStreamInit.class
+SHA-256-Digest: QYD+W4/lxDoc2RnaFL1v5ZYnQU+J5mARcFnIHNTXoNQ=
+
+Name: org/eclipse/swt/widgets/TrayItem.class
+SHA-256-Digest: yzNkN3UF9UmOqbIjRL2RoDq4b2OnKTFSvxFGjoTYuSI=
+
+Name: org/eclipse/swt/internal/ole/win32/IPropertyStore.class
+SHA-256-Digest: uBE5Tz0kMZd2A9w9MJiHmTzuYiOw3e6xHFsMT6S7dLc=
+
+Name: org/eclipse/swt/custom/AnimatedProgress.class
+SHA-256-Digest: cuWsGUaIImw048qCyG7jBuNHLqs+jYtIfR8pQEsz9zs=
+
+Name: about.html
+SHA-256-Digest: jbGODuQ6e5s3Q+z5nvnwy+EI/Ju14vrc1MNoFe40fLk=
+
+Name: org/eclipse/swt/internal/Lock.class
+SHA-256-Digest: FzqRQLRB8YYeRrtO2388uhSMfY1RsFs6MIwXjHNeV9Q=
+
+Name: org/eclipse/swt/widgets/Control.class
+SHA-256-Digest: cYfWn0dchKNYwvzoUxP4p6fyX+JeSGqxBCwHOtWbP/g=
+
+Name: org/eclipse/swt/browser/LocationEvent.class
+SHA-256-Digest: J4wPVFd3mZ3UpNY70AZKbr97opXkJa0MYEdZzrdvw0Y=
+
+Name: org/eclipse/swt/custom/TextChangingEvent.class
+SHA-256-Digest: 0UOHDDdvOlOgYfN/y+1ukpGgmeRNyn1kaeDONCJ1Q98=
+
+Name: org/eclipse/swt/custom/StyledText$5.class
+SHA-256-Digest: hH7vbovtIqEz/6HHbPHT0j8axdL9n40YZfomYNC5kok=
+
+Name: org/eclipse/swt/events/TreeAdapter.class
+SHA-256-Digest: AkY2aX/nBDv/ePbgo2jo9+bUDhJskeG9YCw30EwATUc=
+
+Name: org/eclipse/swt/internal/image/PngPlteChunk.class
+SHA-256-Digest: g3c7iPrTcl8rFcWJDXXEnWopNgOR59000KoByUXpbSo=
+
+Name: org/eclipse/swt/internal/win32/LRESULT.class
+SHA-256-Digest: cXMUr2xtHsW1NIyjUC/NLJvOWs4tPQg9EyyLCMAekTo=
+
+Name: org/eclipse/swt/internal/win32/NONCLIENTMETRICS.class
+SHA-256-Digest: GwiboMNGc4aABKXEtN7mt6m/PGbgGaPCEwqDVx1s6I0=
+
+Name: org/eclipse/swt/internal/image/JPEGDecoder.class
+SHA-256-Digest: +GVuNEGsDnPLxNgeECaehyTxn3rHSqWBFSGwevm6LLY=
+
+Name: org/eclipse/swt/widgets/TableColumn.class
+SHA-256-Digest: VsNeX9/wdwq7ktgU9K+3OadFDzMX41LuHqoASV8y/bQ=
+
+Name: org/eclipse/swt/internal/ole/win32/TYPEATTR.class
+SHA-256-Digest: 1VWT3BGT/lW8cvXkrEhn+3NKjxS0ezQW/hz7psL7I9Q=
+
+Name: org/eclipse/swt/ole/win32/OleFrame$1.class
+SHA-256-Digest: Dg4Dvr8qiWEEWJnMdxJnlT1d1YSa4wgHTTxLSlCefYE=
+
+Name: org/eclipse/swt/internal/win32/MSG.class
+SHA-256-Digest: UnL2irXq2DnmQd0WILDflPIGXnx9puodb24B76KN+kU=
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/about.html b/bundles/org.eclipse.swt.win32.win32.x86_64/about.html
new file mode 100644 (file)
index 0000000..0973f70
--- /dev/null
@@ -0,0 +1,152 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+<p>August 17, 2006</p> 
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+<h3>Third Party Content</h3>
+
+<p>The Content includes items that have been sourced from third parties as set out below. If you 
+did not receive this Content directly from the Eclipse Foundation, the following is provided 
+for informational purposes only, and you should look to the Redistributor&rsquo;s license for 
+terms and conditions of use.</p>
+
+<h4>Independent JPEG Group's JPEG software release 6b</h4>
+
+<p>This software is based in part on the work of the Independent JPEG Group's JPEG software release 6b (&quot;LIBJPEG&quot;).
+LIBJPEG was used to implement the decoding of JPEG format files in Java (TM).  The Content does NOT include any portion of the LIBJPEG file ansi2knr.c.</p>
+
+<p>Your use of LIBJPEG is subject to the terms and conditions located in the <a href="about_files/IJG_README">about_files/IJG_README</a> file which is included
+with the Content.</p>
+
+<p>The IJG's website is located at <a href="http://ijg.org/" target="_blank">http://ijg.org</a>.</p>
+
+<p>The class org.eclipse.swt.internal.image.JPEGFileFormat is based on following files from LIBJPEG:</p>
+
+<ul>
+    <li>cderror.h</li>
+    <li>cdjpeg.h</li>
+    <li>jchuff.h</li>
+    <li>jdcolor.c</li>
+    <li>jdct.h</li>
+    <li>jdhuff.h</li>
+    <li>jerror.h</li>
+    <li>jidctint.c</li>
+    <li>jinclude.h</li>
+    <li>jmemsys.h</li>
+    <li>jmorecfg.h</li>
+    <li>jpegint.h</li>
+    <li>jpeglib.h</li>
+    <li>jversion.h</li>
+    <li>transupp.h</li>
+</ul>
+
+<p>The class org.eclipse.swt.internal.image.JPEGDecoder is based on the following files from LIBJPEG:</p>
+
+<ul>
+       <li>jcapimin.c</li>
+       <li>jcapistd.c</li>
+       <li>jccoefct.c</li>
+       <li>jccolor.c</li>
+       <li>jcdctmgr.c</li>
+       <li>jchuff.c</li>
+       <li>jcinit.c</li>
+       <li>jcmainct.c</li>
+       <li>jcmarker.c</li>
+       <li>jcmaster.c</li>
+       <li>jcomapi.c</li>
+       <li>jcparam.c</li>
+       <li>jcphuff.c</li>
+       <li>jcprepct.c</li>
+       <li>jcsample.c</li>
+       <li>jctrans.c</li>
+       <li>jdapimin.c</li>
+       <li>jdapistd.c</li>
+       <li>jdatadst.c</li>
+       <li>jdatasrc.c</li>
+       <li>jdcoefct.c</li>
+       <li>jdcolor.c</li>
+       <li>jddctmgr.c</li>
+       <li>jdhuff.c</li>
+       <li>jdinput.c</li>
+       <li>jdmainct.c</li>
+       <li>jdmarker.c</li>
+       <li>jdmaster.c</li>
+       <li>jdmerge.c</li>
+       <li>jdphuff.c</li>
+       <li>jdpostct.c</li>
+       <li>jdsample.c</li>
+       <li>jdtrans.c</li>
+       <li>jerror.c</li>
+       <li>jfdctflt.c</li>
+       <li>jfdctfst.c</li>
+       <li>jfdctint.c</li>
+       <li>jidctflt.c</li>
+       <li>jidctfst.c</li>
+       <li>jidctint.c</li>
+       <li>jidctred.c</li>
+       <li>jpegtran.c</li>
+       <li>jquant1.c</li>
+       <li>jquant2.c</li>
+       <li>jutils.c</li>
+       <li>cderror.h</li>
+       <li>cdjpeg.h</li>
+       <li>jchuff.h</li>
+       <li>jconfig.h</li>
+       <li>jdct.h</li>
+       <li>jdhuff.h</li>
+       <li>jerror.h</li>
+       <li>jinclude.h</li>
+       <li>jmorecfg.h</li>
+       <li>jpegint.h</li>
+       <li>jpeglib.h</li>
+       <li>jversion.h</li>
+       <li>transupp.h</li>
+</ul>
+       
+<p>The following changes were made to the LIBJPEG code in the Content:</p>
+
+<ol>
+       <li>In Java, pointer math is not allowed so indexing was used instead.</li>
+       <li>Function pointers were replaced with switch statements.</li>
+       <li>The virtual memory, tracing and progress monitoring were removed.</li>
+       <li>The error handling was simplified and now uses Java exceptions.</li>
+</ol>
+
+<h4>PuTTY 0.58 (derivative work)</h4>
+
+<p>Portions of the SWT class org/eclipse/swt/internal/image/PngDeflater are based on PuTTY's sshzlib.c. PuTTY is made available by Mozilla.org.  Use of PuTTY is governed by the terms and
+conditions of the the following MIT-style license:  </p>
+<blockquote>
+  <p><em>PuTTY is copyright 1997-2007 Simon Tatham.</em> </p>
+  <p><em>Portions copyright Robert de Bath, Joris van Rantwijk, Delian  Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,  Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus Kuhn,  and CORE SDI S.A.</em> </p>
+  <p><em>Permission is hereby granted, free of charge, to any person  obtaining a copy of this software and associated documentation files  (the &quot;Software&quot;), to deal in the Software without restriction,  including without limitation the rights to use, copy, modify, merge,  publish, distribute, sublicense, and/or sell copies of the Software,  and to permit persons to whom the Software is furnished to do so,  subject to the following conditions:</em> </p>
+  <p><em>The above copyright notice and this permission notice shall be  included in all copies or substantial portions of the Software.</em> </p>
+  <p><em>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  NONINFRINGEMENT.  IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR ANY  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</em> </p>
+</blockquote>
+<p>A copy of the license is also available at <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/licence.html" target="_blank">http://www.chiark.greenend.org.uk/~sgtatham/putty/licence.html</a>.</p>
+
+<p><small>Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.</small></p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/about_files/IJG_README b/bundles/org.eclipse.swt.win32.win32.x86_64/about_files/IJG_README
new file mode 100644 (file)
index 0000000..86cc206
--- /dev/null
@@ -0,0 +1,385 @@
+The Independent JPEG Group's JPEG software
+==========================================
+
+README for release 6b of 27-Mar-1998
+====================================
+
+This distribution contains the sixth public release of the Independent JPEG
+Group's free JPEG software.  You are welcome to redistribute this software and
+to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+Serious users of this software (particularly those incorporating it into
+larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
+our electronic mailing list.  Mailing list members are notified of updates
+and have a chance to participate in technical discussions, etc.
+
+This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
+Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
+Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
+Group.
+
+IJG is not affiliated with the official ISO JPEG standards committee.
+
+
+DOCUMENTATION ROADMAP
+=====================
+
+This file contains the following sections:
+
+OVERVIEW            General description of JPEG and the IJG software.
+LEGAL ISSUES        Copyright, lack of warranty, terms of distribution.
+REFERENCES          Where to learn more about JPEG.
+ARCHIVE LOCATIONS   Where to find newer versions of this software.
+RELATED SOFTWARE    Other stuff you should get.
+FILE FORMAT WARS    Software *not* to get.
+TO DO               Plans for future IJG releases.
+
+Other documentation files in the distribution are:
+
+User documentation:
+  install.doc       How to configure and install the IJG software.
+  usage.doc         Usage instructions for cjpeg, djpeg, jpegtran,
+                    rdjpgcom, and wrjpgcom.
+  *.1               Unix-style man pages for programs (same info as usage.doc).
+  wizard.doc        Advanced usage instructions for JPEG wizards only.
+  change.log        Version-to-version change highlights.
+Programmer and internal documentation:
+  libjpeg.doc       How to use the JPEG library in your own programs.
+  example.c         Sample code for calling the JPEG library.
+  structure.doc     Overview of the JPEG library's internal structure.
+  filelist.doc      Road map of IJG files.
+  coderules.doc     Coding style rules --- please read if you contribute code.
+
+Please read at least the files install.doc and usage.doc.  Useful information
+can also be found in the JPEG FAQ (Frequently Asked Questions) article.  See
+ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
+
+If you want to understand how the JPEG code works, we suggest reading one or
+more of the REFERENCES, then looking at the documentation files (in roughly
+the order listed) before diving into the code.
+
+
+OVERVIEW
+========
+
+This package contains C software to implement JPEG image compression and
+decompression.  JPEG (pronounced "jay-peg") is a standardized compression
+method for full-color and gray-scale images.  JPEG is intended for compressing
+"real-world" scenes; line drawings, cartoons and other non-realistic images
+are not its strong suit.  JPEG is lossy, meaning that the output image is not
+exactly identical to the input image.  Hence you must not use JPEG if you
+have to have identical output bits.  However, on typical photographic images,
+very good compression levels can be obtained with no visible change, and
+remarkably high compression levels are possible if you can tolerate a
+low-quality image.  For more details, see the references, or just experiment
+with various compression settings.
+
+This software implements JPEG baseline, extended-sequential, and progressive
+compression processes.  Provision is made for supporting all variants of these
+processes, although some uncommon parameter settings aren't implemented yet.
+For legal reasons, we are not distributing code for the arithmetic-coding
+variants of JPEG; see LEGAL ISSUES.  We have made no provision for supporting
+the hierarchical or lossless processes defined in the standard.
+
+We provide a set of library routines for reading and writing JPEG image files,
+plus two sample applications "cjpeg" and "djpeg", which use the library to
+perform conversion between JPEG and some other popular image file formats.
+The library is intended to be reused in other applications.
+
+In order to support file conversion and viewing software, we have included
+considerable functionality beyond the bare JPEG coding/decoding capability;
+for example, the color quantization modules are not strictly part of JPEG
+decoding, but they are essential for output to colormapped file formats or
+colormapped displays.  These extra functions can be compiled out of the
+library if not required for a particular application.  We have also included
+"jpegtran", a utility for lossless transcoding between different JPEG
+processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
+inserting and extracting textual comments in JFIF files.
+
+The emphasis in designing this software has been on achieving portability and
+flexibility, while also making it fast enough to be useful.  In particular,
+the software is not intended to be read as a tutorial on JPEG.  (See the
+REFERENCES section for introductory material.)  Rather, it is intended to
+be reliable, portable, industrial-strength code.  We do not claim to have
+achieved that goal in every aspect of the software, but we strive for it.
+
+We welcome the use of this software as a component of commercial products.
+No royalty is required, but we do ask for an acknowledgement in product
+documentation, as described under LEGAL ISSUES.
+
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it.  (See the file
+ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltconfig, ltmain.sh).  Another support script, install-sh, is copyright
+by M.I.T. but is also freely distributable.
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents owned by IBM, AT&T, and Mitsubishi.  Hence arithmetic coding cannot
+legally be used without obtaining one or more licenses.  For this reason,
+support for arithmetic coding has been removed from the free JPEG software.
+(Since arithmetic coding provides only a marginal gain over the unpatented
+Huffman mode, it is unlikely that very many implementations will support it.)
+So far as we are aware, there are no patent restrictions on the remaining
+code.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs".  This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+    "The Graphics Interchange Format(c) is the Copyright property of
+    CompuServe Incorporated.  GIF(sm) is a Service Mark property of
+    CompuServe Incorporated."
+
+
+REFERENCES
+==========
+
+We highly recommend reading one or more of these references before trying to
+understand the innards of the JPEG software.
+
+The best short technical introduction to the JPEG compression algorithm is
+       Wallace, Gregory K.  "The JPEG Still Picture Compression Standard",
+       Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+(Adjacent articles in that issue discuss MPEG motion picture compression,
+applications of JPEG, and related topics.)  If you don't have the CACM issue
+handy, a PostScript file containing a revised version of Wallace's article is
+available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz.  The file (actually
+a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
+omits the sample images that appeared in CACM, but it includes corrections
+and some added material.  Note: the Wallace article is copyright ACM and IEEE,
+and it may not be used for commercial purposes.
+
+A somewhat less technical, more leisurely introduction to JPEG can be found in
+"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
+M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1.  This book provides
+good explanations and example C code for a multitude of compression methods
+including JPEG.  It is an excellent source if you are comfortable reading C
+code but don't know much about data compression in general.  The book's JPEG
+sample code is far from industrial-strength, but when you are ready to look
+at a full implementation, you've got one here...
+
+The best full description of JPEG is the textbook "JPEG Still Image Data
+Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
+by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.  Price US$59.95, 638 pp.
+The book includes the complete text of the ISO JPEG standards (DIS 10918-1
+and draft DIS 10918-2).  This is by far the most complete exposition of JPEG
+in existence, and we highly recommend it.
+
+The JPEG standard itself is not available electronically; you must order a
+paper copy through ISO or ITU.  (Unless you feel a need to own a certified
+official copy, we recommend buying the Pennebaker and Mitchell book instead;
+it's much cheaper and includes a great deal of useful explanatory material.)
+In the USA, copies of the standard may be ordered from ANSI Sales at (212)
+642-4900, or from Global Engineering Documents at (800) 854-7179.  (ANSI
+doesn't take credit card orders, but Global does.)  It's not cheap: as of
+1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
+shipping/handling.  The standard is divided into two parts, Part 1 being the
+actual specification, while Part 2 covers compliance testing methods.  Part 1
+is titled "Digital Compression and Coding of Continuous-tone Still Images,
+Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
+10918-1, ITU-T T.81.  Part 2 is titled "Digital Compression and Coding of
+Continuous-tone Still Images, Part 2: Compliance testing" and has document
+numbers ISO/IEC IS 10918-2, ITU-T T.83.
+
+Some extensions to the original JPEG standard are defined in JPEG Part 3,
+a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84.  IJG
+currently does not support any Part 3 extensions.
+
+The JPEG standard does not specify all details of an interchangeable file
+format.  For the omitted details we follow the "JFIF" conventions, revision
+1.02.  A copy of the JFIF spec is available from:
+       Literature Department
+       C-Cube Microsystems, Inc.
+       1778 McCarthy Blvd.
+       Milpitas, CA 95035
+       phone (408) 944-6300,  fax (408) 944-6314
+A PostScript version of this document is available by FTP at
+ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz.  There is also a plain text
+version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
+the figures.
+
+The TIFF 6.0 file format specification can be obtained by FTP from
+ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation scheme
+found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
+IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
+Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
+(Compression tag 7).  Copies of this Note can be obtained from ftp.sgi.com or
+from ftp://ftp.uu.net/graphics/jpeg/.  It is expected that the next revision
+of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
+Although IJG's own code does not support TIFF/JPEG, the free libtiff library
+uses our library to implement TIFF/JPEG per the Note.  libtiff is available
+from ftp://ftp.sgi.com/graphics/tiff/.
+
+
+ARCHIVE LOCATIONS
+=================
+
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9).  The most recent released version can always be found
+there in directory graphics/jpeg.  This particular version will be archived
+as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz.  If you don't have
+direct Internet access, UUNET's archives are also available via UUCP; contact
+help@uunet.uu.net for information on retrieving files that way.
+
+Numerous Internet sites maintain copies of the UUNET files.  However, only
+ftp.uu.net is guaranteed to have the latest official version.
+
+You can also obtain this software in DOS-compatible "zip" archive format from
+the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
+on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
+"JPEG Tools".  Again, these versions may sometimes lag behind the ftp.uu.net
+release.
+
+The JPEG FAQ (Frequently Asked Questions) article is a useful source of
+general information about JPEG.  It is updated constantly and therefore is
+not included in this distribution.  The FAQ is posted every two weeks to
+Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
+It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
+and other news.answers archive sites, including the official news.answers
+archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
+If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
+with body
+       send usenet/news.answers/jpeg-faq/part1
+       send usenet/news.answers/jpeg-faq/part2
+
+
+RELATED SOFTWARE
+================
+
+Numerous viewing and image manipulation programs now support JPEG.  (Quite a
+few of them use this library to do so.)  The JPEG FAQ described above lists
+some of the more popular free and shareware viewers, and tells where to
+obtain them on Internet.
+
+If you are on a Unix machine, we highly recommend Jef Poskanzer's free
+PBMPLUS software, which provides many useful operations on PPM-format image
+files.  In particular, it can convert PPM images to and from a wide range of
+other formats, thus making cjpeg/djpeg considerably more useful.  The latest
+version is distributed by the NetPBM group, and is available from numerous
+sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
+Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
+you are likely to have difficulty making it work on any non-Unix machine.
+
+A different free JPEG implementation, written by the PVRG group at Stanford,
+is available from ftp://havefun.stanford.edu/pub/jpeg/.  This program
+is designed for research and experimentation rather than production use;
+it is slower, harder to use, and less portable than the IJG code, but it
+is easier to read and modify.  Also, the PVRG code supports lossless JPEG,
+which we do not.  (On the other hand, it doesn't do progressive JPEG.)
+
+
+FILE FORMAT WARS
+================
+
+Some JPEG programs produce files that are not compatible with our library.
+The root of the problem is that the ISO JPEG committee failed to specify a
+concrete file format.  Some vendors "filled in the blanks" on their own,
+creating proprietary formats that no one else could read.  (For example, none
+of the early commercial JPEG implementations for the Macintosh were able to
+exchange compressed files.)
+
+The file format we have adopted is called JFIF (see REFERENCES).  This format
+has been agreed to by a number of major commercial JPEG vendors, and it has
+become the de facto standard.  JFIF is a minimal or "low end" representation.
+We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
+Technical Note #2) for "high end" applications that need to record a lot of
+additional data about an image.  TIFF/JPEG is fairly new and not yet widely
+supported, unfortunately.
+
+The upcoming JPEG Part 3 standard defines a file format called SPIFF.
+SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
+be able to read the most common variant of SPIFF.  SPIFF has some technical
+advantages over JFIF, but its major claim to fame is simply that it is an
+official standard rather than an informal one.  At this point it is unclear
+whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
+standard.  IJG intends to support SPIFF once the standard is frozen, but we
+have not decided whether it should become our default output format or not.
+(In any case, our decoder will remain capable of reading JFIF indefinitely.)
+
+Various proprietary file formats incorporating JPEG compression also exist.
+We have little or no sympathy for the existence of these formats.  Indeed,
+one of the original reasons for developing this free software was to help
+force convergence on common, open format standards for JPEG files.  Don't
+use a proprietary file format!
+
+
+TO DO
+=====
+
+The major thrust for v7 will probably be improvement of visual quality.
+The current method for scaling the quantization tables is known not to be
+very good at low Q values.  We also intend to investigate block boundary
+smoothing, "poor man's variable quantization", and other means of improving
+quality-vs-file-size performance without sacrificing compatibility.
+
+In future versions, we are considering supporting some of the upcoming JPEG
+Part 3 extensions --- principally, variable quantization and the SPIFF file
+format.
+
+As always, speeding things up is of great interest.
+
+Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/about_files/mpl-v11.txt b/bundles/org.eclipse.swt.win32.win32.x86_64/about_files/mpl-v11.txt
new file mode 100644 (file)
index 0000000..7714141
--- /dev/null
@@ -0,0 +1,470 @@
+                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
+
+                              ---------------
+
+1. Definitions.
+
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
+
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
+
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
+
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
+
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation,  method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your")  means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code;  or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of  Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d)    Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2)  separate from the Contributor Version;
+          3)  for infringements caused by: i) third party modifications of
+          Contributor Version or ii)  the combination of Modifications made
+          by that Contributor with other software  (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+               (c)    Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code.  If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice.  If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A.  You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code.  You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+     8.1.  This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2.  If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant")  alleging that:
+
+     (a)  such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant.  If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b)  any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3.  If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+     ``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 Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the  "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above.  If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting  the provisions above and replace  them with the notice and
+     other provisions required by the [___] License.  If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/build.properties b/bundles/org.eclipse.swt.win32.win32.x86_64/build.properties
new file mode 100644 (file)
index 0000000..37e75d6
--- /dev/null
@@ -0,0 +1,12 @@
+source.. = src/\r
+bin.includes = META-INF/,\\r
+               swt-win32-4930r7.dll,\\r
+               .api_description,\\r
+               about_files/,\\r
+               .,\\r
+               swt-wgl-win32-4930r7.dll,\\r
+               about.html,\\r
+               swt-awt-win32-4930r7.dll,\\r
+               version.txt,\\r
+               swt-gdip-win32-4930r7.dll,\\r
+               fragment.properties\r
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/fragment.properties b/bundles/org.eclipse.swt.win32.win32.x86_64/fragment.properties
new file mode 100644 (file)
index 0000000..2bc7b6b
--- /dev/null
@@ -0,0 +1,12 @@
+###############################################################################
+# 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
+###############################################################################
+fragmentName = Standard Widget Toolkit for Windows
+providerName = Eclipse.org
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/build.bat b/bundles/org.eclipse.swt.win32.win32.x86_64/library/build.bat
new file mode 100644 (file)
index 0000000..7931672
--- /dev/null
@@ -0,0 +1,88 @@
+@rem ***************************************************************************
+@rem Copyright (c) 2000, 2018 IBM Corporation and others.
+@rem
+@rem This program and the accompanying materials
+@rem are made available under the terms of the Eclipse Public License 2.0
+@rem which accompanies this distribution, and is available at
+@rem https://www.eclipse.org/legal/epl-2.0/
+@rem
+@rem SPDX-License-Identifier: EPL-2.0
+@rem
+@rem Contributors:
+@rem      IBM Corporation - initial API and implementation
+@rem ***************************************************************************
+
+@rem The original build.bat source is located in /org.eclipse.swt/Eclipse SWT PI/win32/library/build.bat. It is copied during various build(s).
+@rem Typically it's not ran directly, instead it is reached by build.xml's build_libraries target found in eclipse.platform.swt.binaries\bundles\org.eclipse.swt.win32.win32.x86*
+
+@echo off
+echo
+echo INFO Starting build of binaries. Detailed system setup instructions can be found in /Readme.Win32.md
+
+@rem builddir used for 32 bit building with webkit. Not needed on 64 bit builds.
+IF "x.%SWT_BUILDDIR%"=="x." set "SWT_BUILDDIR=W:"
+echo SWT build dir: %SWT_BUILDDIR%
+IF "x.%MSSDK%"=="x." set "MSSDK=%ProgramFiles(x86)%\Windows Kits\10"
+echo Microsoft Windows10 SDK dir: %MSSDK%
+IF "x.%WEBKIT_DIR%"=="x." set "WEBKIT_DIR=%SWT_BUILDDIR%\WebKit\r72896"
+echo Webkit dir: %WEBKIT_DIR%
+IF "x.%WEBKIT_SUPPORT_DIR%"=="x." set "WEBKIT_SUPPORT_DIR=%SWT_BUILDDIR%\WebKit\SupportLibrary"
+echo Webkit SupportLibrary dir: %WEBKIT_SUPPORT_DIR%
+
+
+IF "x.%MSVC_HOME%"=="x." set "MSVC_HOME=%SWT_BUILDDIR%\Microsoft\Visual Studio\2017\"
+IF NOT EXIST "%MSVC_HOME%" set "MSVC_HOME=%ProgramFiles(x86)%\Microsoft Visual Studio\2017"
+IF EXIST "%MSVC_HOME%" (
+       echo "Microsoft Visual Studio 2017 dir: %MSVC_HOME%"
+) ELSE (
+       echo "WARNING: Microsoft Visual Studio 2017 was not found."
+)
+
+IF "x.%1"=="x.x86" GOTO X86
+IF "x.%1"=="x.x86_64" GOTO X86_64
+
+:X86
+IF "x.%OUTPUT_DIR%"=="x." set OUTPUT_DIR=..\..\..\org.eclipse.swt.win32.win32.x86
+IF "x.%SWT_JAVA_HOME%"=="x." set "SWT_JAVA_HOME=%SWT_BUILDDIR%\Java\Oracle\jdk1.8.0-latest\x86"
+IF "x.%SWT_JAVA_HOME%"=="x." (
+    echo "WARNING: x86 Java JDK not found. Please set SWT_JAVA_HOME to your JDK directory."
+) ELSE (
+    echo "SWT_JAVA_HOME x86: %SWT_JAVA_HOME%"
+)
+call "%MSVC_HOME%\Community\VC\Auxiliary\Build\vcvarsall.bat" x86
+IF x.%1==x.x86 shift
+GOTO MAKE
+
+:X86_64
+set PROCESSOR_ARCHITECTURE=AMD64
+IF "x.%OUTPUT_DIR%"=="x." set OUTPUT_DIR=..\..\..\org.eclipse.swt.win32.win32.x86_64
+
+IF "x.%SWT_JAVA_HOME%"=="x." (
+    IF exist "%SWT_BUILDDIR%\Java\Oracle\jdk1.8.0-latest\x64" (
+        set "SWT_JAVA_HOME=%SWT_BUILDDIR%\Java\Oracle\jdk1.8.0-latest\x64"
+    ) ELSE (
+        IF exist "C:\Program Files\Java\jdk*" (
+            echo "Found Java in C:\Program Files\Java\jdk, automatically setting SWT_JAVA_HOME to latest java"
+            for /d %%i in ("\Program Files\Java\jdk*") do set SWT_JAVA_HOME=%%i
+        )
+    )
+)
+IF "x.%SWT_JAVA_HOME%"=="x." (
+    echo "WARNING: x64 Java JDK not found. Please set SWT_JAVA_HOME to your JDK directory."
+) ELSE (
+    echo "SWT_JAVA_HOME x64: %SWT_JAVA_HOME%"
+)
+
+set CFLAGS=-DJNI64
+call "%MSVC_HOME%\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+shift
+GOTO MAKE
+
+:MAKE
+@rem if call to vcvarsall.bat (which sets up environment) silently fails, then provide advice to user.
+WHERE cl
+if %ERRORLEVEL% NEQ 0 (
+    echo "WARNING: cl (Microsoft C compiler) not found on path. Please install Microsoft Visual Studio."
+    echo "     If already installed, try launching eclipse from the 'Developer Command Prompt for VS' "
+)
+nmake -f make_win32.mak %1 %2 %3 %4 %5 %6 %7 %8 %9
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/c.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/c.c
new file mode 100644 (file)
index 0000000..b626890
--- /dev/null
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "c_structs.h"
+#include "c_stats.h"
+
+#ifndef C_NATIVE
+#define C_NATIVE(func) Java_org_eclipse_swt_internal_C_##func
+#endif
+
+#ifndef NO_PTR_1sizeof
+JNIEXPORT jint JNICALL C_NATIVE(PTR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       C_NATIVE_ENTER(env, that, PTR_1sizeof_FUNC);
+       rc = (jint)PTR_sizeof();
+       C_NATIVE_EXIT(env, that, PTR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_free
+JNIEXPORT void JNICALL C_NATIVE(free)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       C_NATIVE_ENTER(env, that, free_FUNC);
+       free((void *)arg0);
+       C_NATIVE_EXIT(env, that, free_FUNC);
+}
+#endif
+
+#ifndef NO_getenv
+JNIEXPORT jlong JNICALL C_NATIVE(getenv)
+       (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+       jbyte *lparg0=NULL;
+       jlong rc = 0;
+       C_NATIVE_ENTER(env, that, getenv_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)getenv((const char *)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, getenv_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_malloc
+JNIEXPORT jlong JNICALL C_NATIVE(malloc)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       C_NATIVE_ENTER(env, that, malloc_FUNC);
+       rc = (jlong)malloc(arg0);
+       C_NATIVE_EXIT(env, that, malloc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_memmove__JJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__JJJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       C_NATIVE_ENTER(env, that, memmove__JJJ_FUNC);
+       memmove((void *)arg0, (const void *)arg1, (size_t)arg2);
+       C_NATIVE_EXIT(env, that, memmove__JJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3BJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3BJ)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jlong arg2)
+{
+       jbyte *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3BJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3BJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3CJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3CJ)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2)
+{
+       jchar *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3CJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3CJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3DJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3DJ)
+       (JNIEnv *env, jclass that, jlong arg0, jdoubleArray arg1, jlong arg2)
+{
+       jdouble *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3DJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3DJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3FJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3FJ)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jlong arg2)
+{
+       jfloat *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3FJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3FJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3IJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3IJ)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jlong arg2)
+{
+       jint *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3IJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3IJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3JJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3JJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1, jlong arg2)
+{
+       jlong *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3JJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3JJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove__J_3SJ
+JNIEXPORT void JNICALL C_NATIVE(memmove__J_3SJ)
+       (JNIEnv *env, jclass that, jlong arg0, jshortArray arg1, jlong arg2)
+{
+       jshort *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove__J_3SJ_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       C_NATIVE_EXIT(env, that, memmove__J_3SJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3BJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3BJJ)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jlong arg1, jlong arg2)
+{
+       jbyte *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3BJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3BJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3B_3CJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3B_3CJ)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jcharArray arg1, jlong arg2)
+{
+       jbyte *lparg0=NULL;
+       jchar *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3B_3CJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3B_3CJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3CJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3CJJ)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlong arg1, jlong arg2)
+{
+       jchar *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3CJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3CJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3DJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3DJJ)
+       (JNIEnv *env, jclass that, jdoubleArray arg0, jlong arg1, jlong arg2)
+{
+       jdouble *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3DJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3DJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3FJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3FJJ)
+       (JNIEnv *env, jclass that, jfloatArray arg0, jlong arg1, jlong arg2)
+{
+       jfloat *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3FJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3FJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3IJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3IJJ)
+       (JNIEnv *env, jclass that, jintArray arg0, jlong arg1, jlong arg2)
+{
+       jint *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3IJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3IJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3I_3BJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3I_3BJ)
+       (JNIEnv *env, jclass that, jintArray arg0, jbyteArray arg1, jlong arg2)
+{
+       jint *lparg0=NULL;
+       jbyte *lparg1=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3I_3BJ_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)lparg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+       C_NATIVE_EXIT(env, that, memmove___3I_3BJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3JJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3JJJ)
+       (JNIEnv *env, jclass that, jlongArray arg0, jlong arg1, jlong arg2)
+{
+       jlong *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3JJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3JJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memmove___3SJJ
+JNIEXPORT void JNICALL C_NATIVE(memmove___3SJJ)
+       (JNIEnv *env, jclass that, jshortArray arg0, jlong arg1, jlong arg2)
+{
+       jshort *lparg0=NULL;
+       C_NATIVE_ENTER(env, that, memmove___3SJJ_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       memmove((void *)lparg0, (const void *)arg1, (size_t)arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, memmove___3SJJ_FUNC);
+}
+#endif
+
+#ifndef NO_memset
+JNIEXPORT jlong JNICALL C_NATIVE(memset)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2)
+{
+       jlong rc = 0;
+       C_NATIVE_ENTER(env, that, memset_FUNC);
+       rc = (jlong)memset((void *)arg0, arg1, (size_t)arg2);
+       C_NATIVE_EXIT(env, that, memset_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_setenv
+JNIEXPORT jint JNICALL C_NATIVE(setenv)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jbyteArray arg1, jint arg2)
+{
+       jbyte *lparg0=NULL;
+       jbyte *lparg1=NULL;
+       jint rc = 0;
+       C_NATIVE_ENTER(env, that, setenv_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)setenv((const char *)lparg0, (const char *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+       C_NATIVE_EXIT(env, that, setenv_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_strlen
+JNIEXPORT jint JNICALL C_NATIVE(strlen)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       C_NATIVE_ENTER(env, that, strlen_FUNC);
+       rc = (jint)strlen((char *)arg0);
+       C_NATIVE_EXIT(env, that, strlen_FUNC);
+       return rc;
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/c.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/c.h
new file mode 100644 (file)
index 0000000..486ea4e
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#ifndef INC_c_H
+#define INC_c_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#define PTR_sizeof() sizeof(void *)
+
+/* Functions excludes */
+#ifdef _WIN32_WCE
+#define NO_getenv
+#endif /* _WIN32_WCE */
+
+#ifdef _WIN32
+#define NO_setenv
+#endif /* _WIN32 */
+
+#endif /* INC_c_H */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_stats.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_stats.c
new file mode 100644 (file)
index 0000000..ed4d3f9
--- /dev/null
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "c_stats.h"
+
+#ifdef NATIVE_STATS
+
+char * C_nativeFunctionNames[] = {
+       "PTR_1sizeof",
+       "free",
+       "getenv",
+       "malloc",
+       "memmove__JJJ",
+       "memmove__J_3BJ",
+       "memmove__J_3CJ",
+       "memmove__J_3DJ",
+       "memmove__J_3FJ",
+       "memmove__J_3IJ",
+       "memmove__J_3JJ",
+       "memmove__J_3SJ",
+       "memmove___3BJJ",
+       "memmove___3B_3CJ",
+       "memmove___3CJJ",
+       "memmove___3DJJ",
+       "memmove___3FJJ",
+       "memmove___3IJJ",
+       "memmove___3I_3BJ",
+       "memmove___3JJJ",
+       "memmove___3SJJ",
+       "memset",
+       "setenv",
+       "strlen",
+};
+#define NATIVE_FUNCTION_COUNT sizeof(C_nativeFunctionNames) / sizeof(char*)
+int C_nativeFunctionCount = NATIVE_FUNCTION_COUNT;
+int C_nativeFunctionCallCount[NATIVE_FUNCTION_COUNT];
+
+#define STATS_NATIVE(func) Java_org_eclipse_swt_tools_internal_NativeStats_##func
+
+JNIEXPORT jint JNICALL STATS_NATIVE(C_1GetFunctionCount)
+       (JNIEnv *env, jclass that)
+{
+       return C_nativeFunctionCount;
+}
+
+JNIEXPORT jstring JNICALL STATS_NATIVE(C_1GetFunctionName)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return (*env)->NewStringUTF(env, C_nativeFunctionNames[index]);
+}
+
+JNIEXPORT jint JNICALL STATS_NATIVE(C_1GetFunctionCallCount)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return C_nativeFunctionCallCount[index];
+}
+
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_stats.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_stats.h
new file mode 100644 (file)
index 0000000..311a251
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#ifdef NATIVE_STATS
+extern int C_nativeFunctionCount;
+extern int C_nativeFunctionCallCount[];
+extern char* C_nativeFunctionNames[];
+#define C_NATIVE_ENTER(env, that, func) C_nativeFunctionCallCount[func]++;
+#define C_NATIVE_EXIT(env, that, func) 
+#else
+#ifndef C_NATIVE_ENTER
+#define C_NATIVE_ENTER(env, that, func) 
+#endif
+#ifndef C_NATIVE_EXIT
+#define C_NATIVE_EXIT(env, that, func) 
+#endif
+#endif
+
+typedef enum {
+       PTR_1sizeof_FUNC,
+       free_FUNC,
+       getenv_FUNC,
+       malloc_FUNC,
+       memmove__JJJ_FUNC,
+       memmove__J_3BJ_FUNC,
+       memmove__J_3CJ_FUNC,
+       memmove__J_3DJ_FUNC,
+       memmove__J_3FJ_FUNC,
+       memmove__J_3IJ_FUNC,
+       memmove__J_3JJ_FUNC,
+       memmove__J_3SJ_FUNC,
+       memmove___3BJJ_FUNC,
+       memmove___3B_3CJ_FUNC,
+       memmove___3CJJ_FUNC,
+       memmove___3DJJ_FUNC,
+       memmove___3FJJ_FUNC,
+       memmove___3IJJ_FUNC,
+       memmove___3I_3BJ_FUNC,
+       memmove___3JJJ_FUNC,
+       memmove___3SJJ_FUNC,
+       memset_FUNC,
+       setenv_FUNC,
+       strlen_FUNC,
+} C_FUNCS;
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_structs.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_structs.c
new file mode 100644 (file)
index 0000000..e38d782
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "c_structs.h"
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_structs.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/c_structs.h
new file mode 100644 (file)
index 0000000..eba1f55
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "c.h"
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/callback.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/callback.c
new file mode 100644 (file)
index 0000000..87b46e9
--- /dev/null
@@ -0,0 +1,1280 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/**
+ * Callback implementation.
+ */
+#include "callback.h"
+#include <string.h>
+
+#ifndef CALLBACK_NATIVE
+#define CALLBACK_NATIVE(func) Java_org_eclipse_swt_internal_Callback_##func
+#endif
+
+/* define this to print out debug statements */
+/* #define DEBUG_CALL_PRINTS */
+
+/* --------------- callback globals ----------------- */
+
+static JavaVM *jvm = NULL;
+static CALLBACK_DATA callbackData[MAX_CALLBACKS];
+static int callbackEnabled = 1;
+static int callbackEntryCount = 0;
+static int initialized = 0;
+static jint JNI_VERSION = 0;
+
+#ifdef DEBUG_CALL_PRINTS
+static int counter = 0;
+#endif
+
+#ifdef ATOMIC
+#include <libkern/OSAtomic.h>
+#define ATOMIC_INC(value) OSAtomicIncrement32(&value);
+#define ATOMIC_DEC(value) OSAtomicDecrement32(&value);
+#else
+#define ATOMIC_INC(value) value++;
+#define ATOMIC_DEC(value) value--;
+#endif
+
+jintLong callback(int index, ...);
+
+#ifdef USE_ASSEMBLER
+
+#if !(defined (_WIN32) || defined (_WIN32_WCE))
+#include <sys/mman.h>
+#endif
+
+static unsigned char *callbackCode = NULL;
+#define CALLBACK_THUNK_SIZE 64
+
+#else
+
+/* --------------- callback functions --------------- */
+
+
+/* Function name from index and number of arguments */
+#define FN(index, args) fn##index##_##args
+
+/**
+ * Functions templates
+ *
+ * NOTE: If the maximum number of arguments changes (MAX_ARGS), the number
+ *       of function templates has to change accordingly.
+ */
+
+/* Function template with no arguments */
+#define FN_0(index) RETURN_TYPE FN(index, 0)() { return RETURN_CAST callback(index); }
+
+/* Function template with 1 argument */
+#define FN_1(index) RETURN_TYPE FN(index, 1)(jintLong p1) { return RETURN_CAST callback(index, p1); }
+
+/* Function template with 2 arguments */
+#define FN_2(index) RETURN_TYPE FN(index, 2)(jintLong p1, jintLong p2) { return RETURN_CAST callback(index, p1, p2); }
+
+/* Function template with 3 arguments */
+#define FN_3(index) RETURN_TYPE FN(index, 3)(jintLong p1, jintLong p2, jintLong p3) { return RETURN_CAST callback(index, p1, p2, p3); }
+
+/* Function template with 4 arguments */
+#define FN_4(index) RETURN_TYPE FN(index, 4)(jintLong p1, jintLong p2, jintLong p3, jintLong p4) { return RETURN_CAST callback(index, p1, p2, p3, p4); }
+
+/* Function template with 5 arguments */
+#define FN_5(index) RETURN_TYPE FN(index, 5)(jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5); }
+
+/* Function template with 6 arguments */
+#define FN_6(index) RETURN_TYPE FN(index, 6)(jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6); }
+
+/* Function template with 7 arguments */
+#define FN_7(index) RETURN_TYPE FN(index, 7)(jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6, jintLong p7) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7); }
+
+/* Function template with 8 arguments */
+#define FN_8(index) RETURN_TYPE FN(index, 8)(jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6, jintLong p7, jintLong p8) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8); }
+
+/* Function template with 9 arguments */
+#define FN_9(index) RETURN_TYPE FN(index, 9)(jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6, jintLong p7, jintLong p8, jintLong p9) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9); }
+
+/* Function template with 10 arguments */
+#define FN_10(index) RETURN_TYPE FN(index, 10) (jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6, jintLong p7, jintLong p8, jintLong p9, jintLong p10) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
+
+/* Function template with 11 arguments */
+#define FN_11(index) RETURN_TYPE FN(index, 11) (jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6, jintLong p7, jintLong p8, jintLong p9, jintLong p10, jintLong p11) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
+
+/* Function template with 12 arguments */
+#define FN_12(index) RETURN_TYPE FN(index, 12) (jintLong p1, jintLong p2, jintLong p3, jintLong p4, jintLong p5, jintLong p6, jintLong p7, jintLong p8, jintLong p9, jintLong p10, jintLong p11, jintLong p12) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
+
+/**
+ * Define all functions with the specified number of arguments.
+ *
+ * NOTE: If the maximum number of callbacks changes (MAX_CALLBACKS),
+ *       this macro has to be updated. 
+ */
+#if MAX_CALLBACKS == 16
+#define FN_BLOCK(args) \
+       FN_##args(0) \
+       FN_##args(1) \
+       FN_##args(2) \
+       FN_##args(3) \
+       FN_##args(4) \
+       FN_##args(5) \
+       FN_##args(6) \
+       FN_##args(7) \
+       FN_##args(8) \
+       FN_##args(9) \
+       FN_##args(10) \
+       FN_##args(11) \
+       FN_##args(12) \
+       FN_##args(13) \
+       FN_##args(14) \
+       FN_##args(15)
+#elif MAX_CALLBACKS == 128
+#define FN_BLOCK(args) \
+       FN_##args(0) \
+       FN_##args(1) \
+       FN_##args(2) \
+       FN_##args(3) \
+       FN_##args(4) \
+       FN_##args(5) \
+       FN_##args(6) \
+       FN_##args(7) \
+       FN_##args(8) \
+       FN_##args(9) \
+       FN_##args(10) \
+       FN_##args(11) \
+       FN_##args(12) \
+       FN_##args(13) \
+       FN_##args(14) \
+       FN_##args(15) \
+       FN_##args(16) \
+       FN_##args(17) \
+       FN_##args(18) \
+       FN_##args(19) \
+       FN_##args(20) \
+       FN_##args(21) \
+       FN_##args(22) \
+       FN_##args(23) \
+       FN_##args(24) \
+       FN_##args(25) \
+       FN_##args(26) \
+       FN_##args(27) \
+       FN_##args(28) \
+       FN_##args(29) \
+       FN_##args(30) \
+       FN_##args(31) \
+       FN_##args(32) \
+       FN_##args(33) \
+       FN_##args(34) \
+       FN_##args(35) \
+       FN_##args(36) \
+       FN_##args(37) \
+       FN_##args(38) \
+       FN_##args(39) \
+       FN_##args(40) \
+       FN_##args(41) \
+       FN_##args(42) \
+       FN_##args(43) \
+       FN_##args(44) \
+       FN_##args(45) \
+       FN_##args(46) \
+       FN_##args(47) \
+       FN_##args(48) \
+       FN_##args(49) \
+       FN_##args(50) \
+       FN_##args(51) \
+       FN_##args(52) \
+       FN_##args(53) \
+       FN_##args(54) \
+       FN_##args(55) \
+       FN_##args(56) \
+       FN_##args(57) \
+       FN_##args(58) \
+       FN_##args(59) \
+       FN_##args(60) \
+       FN_##args(61) \
+       FN_##args(62) \
+       FN_##args(63) \
+       FN_##args(64) \
+       FN_##args(65) \
+       FN_##args(66) \
+       FN_##args(67) \
+       FN_##args(68) \
+       FN_##args(69) \
+       FN_##args(70) \
+       FN_##args(71) \
+       FN_##args(72) \
+       FN_##args(73) \
+       FN_##args(74) \
+       FN_##args(75) \
+       FN_##args(76) \
+       FN_##args(77) \
+       FN_##args(78) \
+       FN_##args(79) \
+       FN_##args(80) \
+       FN_##args(81) \
+       FN_##args(82) \
+       FN_##args(83) \
+       FN_##args(84) \
+       FN_##args(85) \
+       FN_##args(86) \
+       FN_##args(87) \
+       FN_##args(88) \
+       FN_##args(89) \
+       FN_##args(90) \
+       FN_##args(91) \
+       FN_##args(92) \
+       FN_##args(93) \
+       FN_##args(94) \
+       FN_##args(95) \
+       FN_##args(96) \
+       FN_##args(97) \
+       FN_##args(98) \
+       FN_##args(99) \
+       FN_##args(100) \
+       FN_##args(101) \
+       FN_##args(102) \
+       FN_##args(103) \
+       FN_##args(104) \
+       FN_##args(105) \
+       FN_##args(106) \
+       FN_##args(107) \
+       FN_##args(108) \
+       FN_##args(109) \
+       FN_##args(110) \
+       FN_##args(111) \
+       FN_##args(112) \
+       FN_##args(113) \
+       FN_##args(114) \
+       FN_##args(115) \
+       FN_##args(116) \
+       FN_##args(117) \
+       FN_##args(118) \
+       FN_##args(119) \
+       FN_##args(120) \
+       FN_##args(121) \
+       FN_##args(122) \
+       FN_##args(123) \
+       FN_##args(124) \
+       FN_##args(125) \
+       FN_##args(126) \
+       FN_##args(127)
+#elif MAX_CALLBACKS == 256
+#define FN_BLOCK(args) \
+       FN_##args(0) \
+       FN_##args(1) \
+       FN_##args(2) \
+       FN_##args(3) \
+       FN_##args(4) \
+       FN_##args(5) \
+       FN_##args(6) \
+       FN_##args(7) \
+       FN_##args(8) \
+       FN_##args(9) \
+       FN_##args(10) \
+       FN_##args(11) \
+       FN_##args(12) \
+       FN_##args(13) \
+       FN_##args(14) \
+       FN_##args(15) \
+       FN_##args(16) \
+       FN_##args(17) \
+       FN_##args(18) \
+       FN_##args(19) \
+       FN_##args(20) \
+       FN_##args(21) \
+       FN_##args(22) \
+       FN_##args(23) \
+       FN_##args(24) \
+       FN_##args(25) \
+       FN_##args(26) \
+       FN_##args(27) \
+       FN_##args(28) \
+       FN_##args(29) \
+       FN_##args(30) \
+       FN_##args(31) \
+       FN_##args(32) \
+       FN_##args(33) \
+       FN_##args(34) \
+       FN_##args(35) \
+       FN_##args(36) \
+       FN_##args(37) \
+       FN_##args(38) \
+       FN_##args(39) \
+       FN_##args(40) \
+       FN_##args(41) \
+       FN_##args(42) \
+       FN_##args(43) \
+       FN_##args(44) \
+       FN_##args(45) \
+       FN_##args(46) \
+       FN_##args(47) \
+       FN_##args(48) \
+       FN_##args(49) \
+       FN_##args(50) \
+       FN_##args(51) \
+       FN_##args(52) \
+       FN_##args(53) \
+       FN_##args(54) \
+       FN_##args(55) \
+       FN_##args(56) \
+       FN_##args(57) \
+       FN_##args(58) \
+       FN_##args(59) \
+       FN_##args(60) \
+       FN_##args(61) \
+       FN_##args(62) \
+       FN_##args(63) \
+       FN_##args(64) \
+       FN_##args(65) \
+       FN_##args(66) \
+       FN_##args(67) \
+       FN_##args(68) \
+       FN_##args(69) \
+       FN_##args(70) \
+       FN_##args(71) \
+       FN_##args(72) \
+       FN_##args(73) \
+       FN_##args(74) \
+       FN_##args(75) \
+       FN_##args(76) \
+       FN_##args(77) \
+       FN_##args(78) \
+       FN_##args(79) \
+       FN_##args(80) \
+       FN_##args(81) \
+       FN_##args(82) \
+       FN_##args(83) \
+       FN_##args(84) \
+       FN_##args(85) \
+       FN_##args(86) \
+       FN_##args(87) \
+       FN_##args(88) \
+       FN_##args(89) \
+       FN_##args(90) \
+       FN_##args(91) \
+       FN_##args(92) \
+       FN_##args(93) \
+       FN_##args(94) \
+       FN_##args(95) \
+       FN_##args(96) \
+       FN_##args(97) \
+       FN_##args(98) \
+       FN_##args(99) \
+       FN_##args(100) \
+       FN_##args(101) \
+       FN_##args(102) \
+       FN_##args(103) \
+       FN_##args(104) \
+       FN_##args(105) \
+       FN_##args(106) \
+       FN_##args(107) \
+       FN_##args(108) \
+       FN_##args(109) \
+       FN_##args(110) \
+       FN_##args(111) \
+       FN_##args(112) \
+       FN_##args(113) \
+       FN_##args(114) \
+       FN_##args(115) \
+       FN_##args(116) \
+       FN_##args(117) \
+       FN_##args(118) \
+       FN_##args(119) \
+       FN_##args(120) \
+       FN_##args(121) \
+       FN_##args(122) \
+       FN_##args(123) \
+       FN_##args(124) \
+       FN_##args(125) \
+       FN_##args(126) \
+       FN_##args(127) \
+       FN_##args(128) \
+       FN_##args(129) \
+       FN_##args(130) \
+       FN_##args(131) \
+       FN_##args(132) \
+       FN_##args(133) \
+       FN_##args(134) \
+       FN_##args(135) \
+       FN_##args(136) \
+       FN_##args(137) \
+       FN_##args(138) \
+       FN_##args(139) \
+       FN_##args(140) \
+       FN_##args(141) \
+       FN_##args(142) \
+       FN_##args(143) \
+       FN_##args(144) \
+       FN_##args(145) \
+       FN_##args(146) \
+       FN_##args(147) \
+       FN_##args(148) \
+       FN_##args(149) \
+       FN_##args(150) \
+       FN_##args(151) \
+       FN_##args(152) \
+       FN_##args(153) \
+       FN_##args(154) \
+       FN_##args(155) \
+       FN_##args(156) \
+       FN_##args(157) \
+       FN_##args(158) \
+       FN_##args(159) \
+       FN_##args(160) \
+       FN_##args(161) \
+       FN_##args(162) \
+       FN_##args(163) \
+       FN_##args(164) \
+       FN_##args(165) \
+       FN_##args(166) \
+       FN_##args(167) \
+       FN_##args(168) \
+       FN_##args(169) \
+       FN_##args(170) \
+       FN_##args(171) \
+       FN_##args(172) \
+       FN_##args(173) \
+       FN_##args(174) \
+       FN_##args(175) \
+       FN_##args(176) \
+       FN_##args(177) \
+       FN_##args(178) \
+       FN_##args(179) \
+       FN_##args(180) \
+       FN_##args(181) \
+       FN_##args(182) \
+       FN_##args(183) \
+       FN_##args(184) \
+       FN_##args(185) \
+       FN_##args(186) \
+       FN_##args(187) \
+       FN_##args(188) \
+       FN_##args(189) \
+       FN_##args(190) \
+       FN_##args(191) \
+       FN_##args(192) \
+       FN_##args(193) \
+       FN_##args(194) \
+       FN_##args(195) \
+       FN_##args(196) \
+       FN_##args(197) \
+       FN_##args(198) \
+       FN_##args(199) \
+       FN_##args(200) \
+       FN_##args(201) \
+       FN_##args(202) \
+       FN_##args(203) \
+       FN_##args(204) \
+       FN_##args(205) \
+       FN_##args(206) \
+       FN_##args(207) \
+       FN_##args(208) \
+       FN_##args(209) \
+       FN_##args(210) \
+       FN_##args(211) \
+       FN_##args(212) \
+       FN_##args(213) \
+       FN_##args(214) \
+       FN_##args(215) \
+       FN_##args(216) \
+       FN_##args(217) \
+       FN_##args(218) \
+       FN_##args(219) \
+       FN_##args(220) \
+       FN_##args(221) \
+       FN_##args(222) \
+       FN_##args(223) \
+       FN_##args(224) \
+       FN_##args(225) \
+       FN_##args(226) \
+       FN_##args(227) \
+       FN_##args(228) \
+       FN_##args(229) \
+       FN_##args(230) \
+       FN_##args(231) \
+       FN_##args(232) \
+       FN_##args(233) \
+       FN_##args(234) \
+       FN_##args(235) \
+       FN_##args(236) \
+       FN_##args(237) \
+       FN_##args(238) \
+       FN_##args(239) \
+       FN_##args(240) \
+       FN_##args(241) \
+       FN_##args(242) \
+       FN_##args(243) \
+       FN_##args(244) \
+       FN_##args(245) \
+       FN_##args(246) \
+       FN_##args(247) \
+       FN_##args(248) \
+       FN_##args(249) \
+       FN_##args(250) \
+       FN_##args(251) \
+       FN_##args(252) \
+       FN_##args(253) \
+       FN_##args(254) \
+       FN_##args(255)
+#else
+#error Invalid MAX_CALLBACKS
+#endif /* MAX_CALLBACKS == 16 */
+
+/**
+ * Define all callback functions.
+ *
+ * NOTE: If the maximum number of arguments changes (MAX_ARGS), the following
+ *       has to change accordinglly.
+ */
+FN_BLOCK(0)
+FN_BLOCK(1)
+FN_BLOCK(2)
+FN_BLOCK(3)
+FN_BLOCK(4)
+FN_BLOCK(5)
+FN_BLOCK(6)
+FN_BLOCK(7)
+FN_BLOCK(8)
+FN_BLOCK(9)
+FN_BLOCK(10)
+FN_BLOCK(11)
+FN_BLOCK(12)
+
+/**
+ * Initialize the function pointers for the callback routines.
+ *
+ * NOTE: If MAX_ARGS or MAX_CALLBACKS changes, the following has to be updated.
+ */
+#if MAX_CALLBACKS == 16
+#define FN_A_BLOCK(args) { \
+       (jintLong)FN(0, args), \
+       (jintLong)FN(1, args), \
+       (jintLong)FN(2, args), \
+       (jintLong)FN(3, args), \
+       (jintLong)FN(4, args), \
+       (jintLong)FN(5, args), \
+       (jintLong)FN(6, args), \
+       (jintLong)FN(7, args), \
+       (jintLong)FN(8, args), \
+       (jintLong)FN(9, args), \
+       (jintLong)FN(10, args), \
+       (jintLong)FN(11, args), \
+       (jintLong)FN(12, args), \
+       (jintLong)FN(13, args), \
+       (jintLong)FN(14, args), \
+       (jintLong)FN(15, args), \
+},
+#elif MAX_CALLBACKS == 128
+#define FN_A_BLOCK(args) { \
+       (jintLong)FN(0, args), \
+       (jintLong)FN(1, args), \
+       (jintLong)FN(2, args), \
+       (jintLong)FN(3, args), \
+       (jintLong)FN(4, args), \
+       (jintLong)FN(5, args), \
+       (jintLong)FN(6, args), \
+       (jintLong)FN(7, args), \
+       (jintLong)FN(8, args), \
+       (jintLong)FN(9, args), \
+       (jintLong)FN(10, args), \
+       (jintLong)FN(11, args), \
+       (jintLong)FN(12, args), \
+       (jintLong)FN(13, args), \
+       (jintLong)FN(14, args), \
+       (jintLong)FN(15, args), \
+       (jintLong)FN(16, args), \
+       (jintLong)FN(17, args), \
+       (jintLong)FN(18, args), \
+       (jintLong)FN(19, args), \
+       (jintLong)FN(20, args), \
+       (jintLong)FN(21, args), \
+       (jintLong)FN(22, args), \
+       (jintLong)FN(23, args), \
+       (jintLong)FN(24, args), \
+       (jintLong)FN(25, args), \
+       (jintLong)FN(26, args), \
+       (jintLong)FN(27, args), \
+       (jintLong)FN(28, args), \
+       (jintLong)FN(29, args), \
+       (jintLong)FN(30, args), \
+       (jintLong)FN(31, args), \
+       (jintLong)FN(32, args), \
+       (jintLong)FN(33, args), \
+       (jintLong)FN(34, args), \
+       (jintLong)FN(35, args), \
+       (jintLong)FN(36, args), \
+       (jintLong)FN(37, args), \
+       (jintLong)FN(38, args), \
+       (jintLong)FN(39, args), \
+       (jintLong)FN(40, args), \
+       (jintLong)FN(41, args), \
+       (jintLong)FN(42, args), \
+       (jintLong)FN(43, args), \
+       (jintLong)FN(44, args), \
+       (jintLong)FN(45, args), \
+       (jintLong)FN(46, args), \
+       (jintLong)FN(47, args), \
+       (jintLong)FN(48, args), \
+       (jintLong)FN(49, args), \
+       (jintLong)FN(50, args), \
+       (jintLong)FN(51, args), \
+       (jintLong)FN(52, args), \
+       (jintLong)FN(53, args), \
+       (jintLong)FN(54, args), \
+       (jintLong)FN(55, args), \
+       (jintLong)FN(56, args), \
+       (jintLong)FN(57, args), \
+       (jintLong)FN(58, args), \
+       (jintLong)FN(59, args), \
+       (jintLong)FN(60, args), \
+       (jintLong)FN(61, args), \
+       (jintLong)FN(62, args), \
+       (jintLong)FN(63, args), \
+       (jintLong)FN(64, args), \
+       (jintLong)FN(65, args), \
+       (jintLong)FN(66, args), \
+       (jintLong)FN(67, args), \
+       (jintLong)FN(68, args), \
+       (jintLong)FN(69, args), \
+       (jintLong)FN(70, args), \
+       (jintLong)FN(71, args), \
+       (jintLong)FN(72, args), \
+       (jintLong)FN(73, args), \
+       (jintLong)FN(74, args), \
+       (jintLong)FN(75, args), \
+       (jintLong)FN(76, args), \
+       (jintLong)FN(77, args), \
+       (jintLong)FN(78, args), \
+       (jintLong)FN(79, args), \
+       (jintLong)FN(80, args), \
+       (jintLong)FN(81, args), \
+       (jintLong)FN(82, args), \
+       (jintLong)FN(83, args), \
+       (jintLong)FN(84, args), \
+       (jintLong)FN(85, args), \
+       (jintLong)FN(86, args), \
+       (jintLong)FN(87, args), \
+       (jintLong)FN(88, args), \
+       (jintLong)FN(89, args), \
+       (jintLong)FN(90, args), \
+       (jintLong)FN(91, args), \
+       (jintLong)FN(92, args), \
+       (jintLong)FN(93, args), \
+       (jintLong)FN(94, args), \
+       (jintLong)FN(95, args), \
+       (jintLong)FN(96, args), \
+       (jintLong)FN(97, args), \
+       (jintLong)FN(98, args), \
+       (jintLong)FN(99, args), \
+       (jintLong)FN(100, args), \
+       (jintLong)FN(101, args), \
+       (jintLong)FN(102, args), \
+       (jintLong)FN(103, args), \
+       (jintLong)FN(104, args), \
+       (jintLong)FN(105, args), \
+       (jintLong)FN(106, args), \
+       (jintLong)FN(107, args), \
+       (jintLong)FN(108, args), \
+       (jintLong)FN(109, args), \
+       (jintLong)FN(110, args), \
+       (jintLong)FN(111, args), \
+       (jintLong)FN(112, args), \
+       (jintLong)FN(113, args), \
+       (jintLong)FN(114, args), \
+       (jintLong)FN(115, args), \
+       (jintLong)FN(116, args), \
+       (jintLong)FN(117, args), \
+       (jintLong)FN(118, args), \
+       (jintLong)FN(119, args), \
+       (jintLong)FN(120, args), \
+       (jintLong)FN(121, args), \
+       (jintLong)FN(122, args), \
+       (jintLong)FN(123, args), \
+       (jintLong)FN(124, args), \
+       (jintLong)FN(125, args), \
+       (jintLong)FN(126, args), \
+       (jintLong)FN(127, args), \
+},
+#elif MAX_CALLBACKS == 256
+#define FN_A_BLOCK(args) { \
+       (jintLong)FN(0, args), \
+       (jintLong)FN(1, args), \
+       (jintLong)FN(2, args), \
+       (jintLong)FN(3, args), \
+       (jintLong)FN(4, args), \
+       (jintLong)FN(5, args), \
+       (jintLong)FN(6, args), \
+       (jintLong)FN(7, args), \
+       (jintLong)FN(8, args), \
+       (jintLong)FN(9, args), \
+       (jintLong)FN(10, args), \
+       (jintLong)FN(11, args), \
+       (jintLong)FN(12, args), \
+       (jintLong)FN(13, args), \
+       (jintLong)FN(14, args), \
+       (jintLong)FN(15, args), \
+       (jintLong)FN(16, args), \
+       (jintLong)FN(17, args), \
+       (jintLong)FN(18, args), \
+       (jintLong)FN(19, args), \
+       (jintLong)FN(20, args), \
+       (jintLong)FN(21, args), \
+       (jintLong)FN(22, args), \
+       (jintLong)FN(23, args), \
+       (jintLong)FN(24, args), \
+       (jintLong)FN(25, args), \
+       (jintLong)FN(26, args), \
+       (jintLong)FN(27, args), \
+       (jintLong)FN(28, args), \
+       (jintLong)FN(29, args), \
+       (jintLong)FN(30, args), \
+       (jintLong)FN(31, args), \
+       (jintLong)FN(32, args), \
+       (jintLong)FN(33, args), \
+       (jintLong)FN(34, args), \
+       (jintLong)FN(35, args), \
+       (jintLong)FN(36, args), \
+       (jintLong)FN(37, args), \
+       (jintLong)FN(38, args), \
+       (jintLong)FN(39, args), \
+       (jintLong)FN(40, args), \
+       (jintLong)FN(41, args), \
+       (jintLong)FN(42, args), \
+       (jintLong)FN(43, args), \
+       (jintLong)FN(44, args), \
+       (jintLong)FN(45, args), \
+       (jintLong)FN(46, args), \
+       (jintLong)FN(47, args), \
+       (jintLong)FN(48, args), \
+       (jintLong)FN(49, args), \
+       (jintLong)FN(50, args), \
+       (jintLong)FN(51, args), \
+       (jintLong)FN(52, args), \
+       (jintLong)FN(53, args), \
+       (jintLong)FN(54, args), \
+       (jintLong)FN(55, args), \
+       (jintLong)FN(56, args), \
+       (jintLong)FN(57, args), \
+       (jintLong)FN(58, args), \
+       (jintLong)FN(59, args), \
+       (jintLong)FN(60, args), \
+       (jintLong)FN(61, args), \
+       (jintLong)FN(62, args), \
+       (jintLong)FN(63, args), \
+       (jintLong)FN(64, args), \
+       (jintLong)FN(65, args), \
+       (jintLong)FN(66, args), \
+       (jintLong)FN(67, args), \
+       (jintLong)FN(68, args), \
+       (jintLong)FN(69, args), \
+       (jintLong)FN(70, args), \
+       (jintLong)FN(71, args), \
+       (jintLong)FN(72, args), \
+       (jintLong)FN(73, args), \
+       (jintLong)FN(74, args), \
+       (jintLong)FN(75, args), \
+       (jintLong)FN(76, args), \
+       (jintLong)FN(77, args), \
+       (jintLong)FN(78, args), \
+       (jintLong)FN(79, args), \
+       (jintLong)FN(80, args), \
+       (jintLong)FN(81, args), \
+       (jintLong)FN(82, args), \
+       (jintLong)FN(83, args), \
+       (jintLong)FN(84, args), \
+       (jintLong)FN(85, args), \
+       (jintLong)FN(86, args), \
+       (jintLong)FN(87, args), \
+       (jintLong)FN(88, args), \
+       (jintLong)FN(89, args), \
+       (jintLong)FN(90, args), \
+       (jintLong)FN(91, args), \
+       (jintLong)FN(92, args), \
+       (jintLong)FN(93, args), \
+       (jintLong)FN(94, args), \
+       (jintLong)FN(95, args), \
+       (jintLong)FN(96, args), \
+       (jintLong)FN(97, args), \
+       (jintLong)FN(98, args), \
+       (jintLong)FN(99, args), \
+       (jintLong)FN(100, args), \
+       (jintLong)FN(101, args), \
+       (jintLong)FN(102, args), \
+       (jintLong)FN(103, args), \
+       (jintLong)FN(104, args), \
+       (jintLong)FN(105, args), \
+       (jintLong)FN(106, args), \
+       (jintLong)FN(107, args), \
+       (jintLong)FN(108, args), \
+       (jintLong)FN(109, args), \
+       (jintLong)FN(110, args), \
+       (jintLong)FN(111, args), \
+       (jintLong)FN(112, args), \
+       (jintLong)FN(113, args), \
+       (jintLong)FN(114, args), \
+       (jintLong)FN(115, args), \
+       (jintLong)FN(116, args), \
+       (jintLong)FN(117, args), \
+       (jintLong)FN(118, args), \
+       (jintLong)FN(119, args), \
+       (jintLong)FN(120, args), \
+       (jintLong)FN(121, args), \
+       (jintLong)FN(122, args), \
+       (jintLong)FN(123, args), \
+       (jintLong)FN(124, args), \
+       (jintLong)FN(125, args), \
+       (jintLong)FN(126, args), \
+       (jintLong)FN(127, args), \
+       (jintLong)FN(128, args), \
+       (jintLong)FN(129, args), \
+       (jintLong)FN(130, args), \
+       (jintLong)FN(131, args), \
+       (jintLong)FN(132, args), \
+       (jintLong)FN(133, args), \
+       (jintLong)FN(134, args), \
+       (jintLong)FN(135, args), \
+       (jintLong)FN(136, args), \
+       (jintLong)FN(137, args), \
+       (jintLong)FN(138, args), \
+       (jintLong)FN(139, args), \
+       (jintLong)FN(140, args), \
+       (jintLong)FN(141, args), \
+       (jintLong)FN(142, args), \
+       (jintLong)FN(143, args), \
+       (jintLong)FN(144, args), \
+       (jintLong)FN(145, args), \
+       (jintLong)FN(146, args), \
+       (jintLong)FN(147, args), \
+       (jintLong)FN(148, args), \
+       (jintLong)FN(149, args), \
+       (jintLong)FN(150, args), \
+       (jintLong)FN(151, args), \
+       (jintLong)FN(152, args), \
+       (jintLong)FN(153, args), \
+       (jintLong)FN(154, args), \
+       (jintLong)FN(155, args), \
+       (jintLong)FN(156, args), \
+       (jintLong)FN(157, args), \
+       (jintLong)FN(158, args), \
+       (jintLong)FN(159, args), \
+       (jintLong)FN(160, args), \
+       (jintLong)FN(161, args), \
+       (jintLong)FN(162, args), \
+       (jintLong)FN(163, args), \
+       (jintLong)FN(164, args), \
+       (jintLong)FN(165, args), \
+       (jintLong)FN(166, args), \
+       (jintLong)FN(167, args), \
+       (jintLong)FN(168, args), \
+       (jintLong)FN(169, args), \
+       (jintLong)FN(170, args), \
+       (jintLong)FN(171, args), \
+       (jintLong)FN(172, args), \
+       (jintLong)FN(173, args), \
+       (jintLong)FN(174, args), \
+       (jintLong)FN(175, args), \
+       (jintLong)FN(176, args), \
+       (jintLong)FN(177, args), \
+       (jintLong)FN(178, args), \
+       (jintLong)FN(179, args), \
+       (jintLong)FN(180, args), \
+       (jintLong)FN(181, args), \
+       (jintLong)FN(182, args), \
+       (jintLong)FN(183, args), \
+       (jintLong)FN(184, args), \
+       (jintLong)FN(185, args), \
+       (jintLong)FN(186, args), \
+       (jintLong)FN(187, args), \
+       (jintLong)FN(188, args), \
+       (jintLong)FN(189, args), \
+       (jintLong)FN(190, args), \
+       (jintLong)FN(191, args), \
+       (jintLong)FN(192, args), \
+       (jintLong)FN(193, args), \
+       (jintLong)FN(194, args), \
+       (jintLong)FN(195, args), \
+       (jintLong)FN(196, args), \
+       (jintLong)FN(197, args), \
+       (jintLong)FN(198, args), \
+       (jintLong)FN(199, args), \
+       (jintLong)FN(200, args), \
+       (jintLong)FN(201, args), \
+       (jintLong)FN(202, args), \
+       (jintLong)FN(203, args), \
+       (jintLong)FN(204, args), \
+       (jintLong)FN(205, args), \
+       (jintLong)FN(206, args), \
+       (jintLong)FN(207, args), \
+       (jintLong)FN(208, args), \
+       (jintLong)FN(209, args), \
+       (jintLong)FN(210, args), \
+       (jintLong)FN(211, args), \
+       (jintLong)FN(212, args), \
+       (jintLong)FN(213, args), \
+       (jintLong)FN(214, args), \
+       (jintLong)FN(215, args), \
+       (jintLong)FN(216, args), \
+       (jintLong)FN(217, args), \
+       (jintLong)FN(218, args), \
+       (jintLong)FN(219, args), \
+       (jintLong)FN(220, args), \
+       (jintLong)FN(221, args), \
+       (jintLong)FN(222, args), \
+       (jintLong)FN(223, args), \
+       (jintLong)FN(224, args), \
+       (jintLong)FN(225, args), \
+       (jintLong)FN(226, args), \
+       (jintLong)FN(227, args), \
+       (jintLong)FN(228, args), \
+       (jintLong)FN(229, args), \
+       (jintLong)FN(230, args), \
+       (jintLong)FN(231, args), \
+       (jintLong)FN(232, args), \
+       (jintLong)FN(233, args), \
+       (jintLong)FN(234, args), \
+       (jintLong)FN(235, args), \
+       (jintLong)FN(236, args), \
+       (jintLong)FN(237, args), \
+       (jintLong)FN(238, args), \
+       (jintLong)FN(239, args), \
+       (jintLong)FN(240, args), \
+       (jintLong)FN(241, args), \
+       (jintLong)FN(242, args), \
+       (jintLong)FN(243, args), \
+       (jintLong)FN(244, args), \
+       (jintLong)FN(245, args), \
+       (jintLong)FN(246, args), \
+       (jintLong)FN(247, args), \
+       (jintLong)FN(248, args), \
+       (jintLong)FN(249, args), \
+       (jintLong)FN(250, args), \
+       (jintLong)FN(251, args), \
+       (jintLong)FN(252, args), \
+       (jintLong)FN(253, args), \
+       (jintLong)FN(254, args), \
+       (jintLong)FN(255, args), \
+},
+#else
+#error Invalid MAX_CALLBACKS
+#endif /* MAX_CALLBACKS == 16 */
+
+jintLong fnx_array[MAX_ARGS+1][MAX_CALLBACKS] = { 
+       FN_A_BLOCK(0)    
+       FN_A_BLOCK(1)    
+       FN_A_BLOCK(2)    
+       FN_A_BLOCK(3)    
+       FN_A_BLOCK(4)    
+       FN_A_BLOCK(5)    
+       FN_A_BLOCK(6)    
+       FN_A_BLOCK(7)    
+       FN_A_BLOCK(8)    
+       FN_A_BLOCK(9)    
+       FN_A_BLOCK(10)    
+       FN_A_BLOCK(11)    
+       FN_A_BLOCK(12)    
+};
+
+#endif /* USE_ASSEMBLER */
+
+/* --------------- callback class calls --------------- */
+
+JNIEXPORT jintLong JNICALL CALLBACK_NATIVE(bind)
+  (JNIEnv *env, jclass that, jobject callbackObject, jobject object, jstring method, jstring signature, jint argCount, jboolean isStatic, jboolean isArrayBased, jintLong errorResult)
+{
+       int i;
+       jmethodID mid = NULL;
+       jclass javaClass = that;
+       const char *methodString = NULL, *sigString = NULL;
+       if (jvm == NULL) (*env)->GetJavaVM(env, &jvm);
+       if (JNI_VERSION == 0) JNI_VERSION = (*env)->GetVersion(env);
+       if (!initialized) {
+               memset(&callbackData, 0, sizeof(callbackData));
+               initialized = 1;
+       }
+       if (method) methodString = (const char *) (*env)->GetStringUTFChars(env, method, NULL);
+       if (signature) sigString = (const char *) (*env)->GetStringUTFChars(env, signature, NULL);
+       if (object && methodString && sigString) {
+               if (isStatic) {
+                       mid = (*env)->GetStaticMethodID(env, object, methodString, sigString);
+               } else {
+                       javaClass = (*env)->GetObjectClass(env, object);    
+                       mid = (*env)->GetMethodID(env, javaClass, methodString, sigString);
+               }
+       }
+       if (method && methodString) (*env)->ReleaseStringUTFChars(env, method, methodString);
+       if (signature && sigString) (*env)->ReleaseStringUTFChars(env, signature, sigString);
+       if (mid == 0) goto fail;
+       for (i=0; i<MAX_CALLBACKS; i++) {
+               if (!callbackData[i].callback) {
+                       if ((callbackData[i].callback = (*env)->NewGlobalRef(env, callbackObject)) == NULL) goto fail;
+                       if ((callbackData[i].object = (*env)->NewGlobalRef(env, object)) == NULL) goto fail;
+                       callbackData[i].isStatic = isStatic;
+                       callbackData[i].isArrayBased = isArrayBased;
+                       callbackData[i].argCount = argCount;
+                       callbackData[i].errorResult = errorResult;
+                       callbackData[i].methodID = mid;
+#ifndef USE_ASSEMBLER
+                       return (jintLong) fnx_array[argCount][i];
+#else
+                       {
+                       int j = 0, k;
+                       unsigned char* code;
+#ifdef __APPLE__
+                       int pad = 0;
+#endif
+                       if (callbackCode == NULL) {
+#if defined (_WIN32) || defined (_WIN32_WCE)
+                               callbackCode = VirtualAlloc(NULL, CALLBACK_THUNK_SIZE * MAX_CALLBACKS, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+                               if (callbackCode == NULL) return 0;
+#else 
+                               callbackCode = mmap(NULL, CALLBACK_THUNK_SIZE * MAX_CALLBACKS, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+                               if (callbackCode == MAP_FAILED) return 0;
+#endif
+                       }
+                       code = (unsigned char *)(callbackCode + (i * CALLBACK_THUNK_SIZE));
+
+                       //PUSH EBP - 1 byte
+                       code[j++] = 0x55;
+
+                       //MOV EBP,ESP - 2 bytes
+                       code[j++] = 0x8b;
+                       code[j++] = 0xec;
+
+#ifdef __APPLE__
+                       /* darwin calling conventions require that the stack be aligned on a 16-byte boundary. */
+                       k = (argCount+3)*sizeof(jintLong);
+                       pad = ((k + 15) & ~15) - k;
+                       if (pad > 0) {
+                               //SUB ESP,pad - 3 bytes
+                               code[j++] = 0x83;
+                               code[j++] = 0xec;
+                               code[j++] = pad;
+                       }
+#endif
+
+                       // 3*argCount bytes
+                       for (k=(argCount + 1) * sizeof(jintLong); k >= sizeof(jintLong)*2; k -= sizeof(jintLong)) {
+                               //PUSH SS:[EBP+k]
+                               code[j++] = 0xff;
+                               code[j++] = 0x75;
+                               code[j++] = k;
+                       }
+
+                       if (i > 127) {
+                               //PUSH i - 5 bytes
+                               code[j++] = 0x68;
+                               code[j++] = ((i >> 0) & 0xFF);
+                               code[j++] = ((i >> 8) & 0xFF);
+                               code[j++] = ((i >> 16) & 0xFF);
+                               code[j++] = ((i >> 24) & 0xFF);
+                       } else {
+                               //PUSH i - 2 bytes
+                               code[j++] = 0x6a;
+                               code[j++] = i;
+                       }
+
+                       //MOV EAX callback - 1 + sizeof(jintLong) bytes
+                       code[j++] = 0xb8;
+                       ((jintLong *)&code[j])[0] = (jintLong)&callback;
+                       j += sizeof(jintLong);
+
+                       //CALL EAX - 2 bytes
+                       code[j++] = 0xff;
+                       code[j++] = 0xd0;
+
+                       //ADD ESP,(argCount + 1) * sizeof(jintLong) - 3 bytes
+                       code[j++] = 0x83;
+                       code[j++] = 0xc4;
+#ifdef __APPLE__
+                       code[j++] = (unsigned char)(pad + ((argCount + 1) * sizeof(jintLong)));
+#else
+                       code[j++] = (unsigned char)((argCount + 1) * sizeof(jintLong));
+#endif
+
+                       //POP EBP - 1 byte
+                       code[j++] = 0x5d;
+
+#if defined (_WIN32) || defined (_WIN32_WCE)
+                       //RETN argCount * sizeof(jintLong) - 3 bytes
+                       code[j++] = 0xc2;
+                       code[j++] = (unsigned char)(argCount * sizeof(jintLong));
+                       code[j++] = 0x00;
+#else
+                       //RETN - 1 byte
+                       code[j++] = 0xc3;
+#endif
+
+                       if (j > CALLBACK_THUNK_SIZE) {
+                               jclass errorClass = (*env)->FindClass(env, "java/lang/Error");
+                               (*env)->ThrowNew(env, errorClass, "Callback thunk overflow");
+                       }
+
+                       return (jintLong)code;
+                       }
+#endif /* USE_ASSEMBLER */
+               }
+       }
+fail:
+    return 0;
+}
+
+JNIEXPORT void JNICALL CALLBACK_NATIVE(unbind)
+  (JNIEnv *env, jclass that, jobject callback)
+{
+       int i;
+    for (i=0; i<MAX_CALLBACKS; i++) {
+        if (callbackData[i].callback != NULL && (*env)->IsSameObject(env, callback, callbackData[i].callback)) {
+            if (callbackData[i].callback != NULL) (*env)->DeleteGlobalRef(env, callbackData[i].callback);
+            if (callbackData[i].object != NULL) (*env)->DeleteGlobalRef(env, callbackData[i].object);
+            memset(&callbackData[i], 0, sizeof(CALLBACK_DATA));
+        }
+    }
+}
+
+JNIEXPORT jboolean JNICALL CALLBACK_NATIVE(getEnabled)
+  (JNIEnv *env, jclass that)
+{
+       return (jboolean)callbackEnabled;
+}
+
+JNIEXPORT jint JNICALL CALLBACK_NATIVE(getEntryCount)
+  (JNIEnv *env, jclass that)
+{
+       return (jint)callbackEntryCount;
+}
+
+JNIEXPORT void JNICALL CALLBACK_NATIVE(setEnabled)
+  (JNIEnv *env, jclass that, jboolean enable)
+{
+       callbackEnabled = enable;
+}
+
+JNIEXPORT void JNICALL CALLBACK_NATIVE(reset)
+  (JNIEnv *env, jclass that)
+{
+    memset((void *)&callbackData, 0, sizeof(callbackData));
+}
+
+jintLong callback(int index, ...)
+{
+       if (!callbackEnabled) return 0;
+
+       {
+       JNIEnv *env = NULL;
+       jmethodID mid = callbackData[index].methodID;
+       jobject object = callbackData[index].object;
+       jboolean isStatic = callbackData[index].isStatic;
+       jboolean isArrayBased = callbackData[index].isArrayBased;
+       jint argCount = callbackData[index].argCount;
+       jintLong result = callbackData[index].errorResult;
+       jthrowable ex;
+       int detach = 0;
+       va_list vl;
+
+#ifdef DEBUG_CALL_PRINTS
+       fprintf(stderr, "* callback starting %d\n", counter++);
+#endif
+
+#ifdef JNI_VERSION_1_2
+       if (IS_JNI_1_2) {
+               (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2);
+       }
+#endif
+       
+#ifdef JNI_VERSION_1_4
+       if (env == NULL) {
+               if (JNI_VERSION >= JNI_VERSION_1_4) {
+                       (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&env, NULL);
+               }
+       }
+#endif
+       
+       if (env == NULL) {
+               (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
+               if (IS_JNI_1_2) detach = 1;
+       }
+       
+       /* If the current thread is not attached to the VM, it is not possible to call into the VM */
+       if (env == NULL) {
+#ifdef DEBUG_CALL_PRINTS
+               fprintf(stderr, "* could not get env\n");
+#endif
+               goto noEnv;
+       }
+
+       /* If an exception has occurred in previous callbacks do not call into the VM. */
+       if ((ex = (*env)->ExceptionOccurred(env))) {
+               (*env)->DeleteLocalRef(env, ex);
+               goto done;
+       }
+
+       /* Call into the VM. */
+       ATOMIC_INC(callbackEntryCount);
+       va_start(vl, index);
+       if (isArrayBased) {
+               int i;
+               jintLongArray argsArray = (*env)->NewIntLongArray(env, argCount);
+               if (argsArray != NULL) {
+                       jintLong *elements = (*env)->GetIntLongArrayElements(env, argsArray, NULL);
+                       if (elements != NULL) {
+                               for (i=0; i<argCount; i++) {
+                                       elements[i] = va_arg(vl, jintLong); 
+                               }
+                               (*env)->ReleaseIntLongArrayElements(env, argsArray, elements, 0);
+                               if (isStatic) {
+                                       result = (*env)->CallStaticIntLongMethod(env, object, mid, argsArray);
+                               } else {
+                                       result = (*env)->CallIntLongMethod(env, object, mid, argsArray);
+                               }
+                       }
+                       /*
+                       * This function may be called many times before returning to Java,
+                       * explicitly delete local references to avoid GP's in certain VMs.
+                       */
+                       (*env)->DeleteLocalRef(env, argsArray);
+               }
+       } else {
+               if (isStatic) {
+                       result = (*env)->CallStaticIntLongMethodV(env, object, mid, vl);
+               } else {
+                       result = (*env)->CallIntLongMethodV(env, object, mid, vl);
+               }
+       }
+       va_end(vl);
+       ATOMIC_DEC(callbackEntryCount);
+
+done:
+       /* If an exception has occurred in Java, return the error result. */
+       if ((ex = (*env)->ExceptionOccurred(env))) {
+               (*env)->DeleteLocalRef(env, ex);
+#ifdef DEBUG_CALL_PRINTS
+               fprintf(stderr, "* java exception occurred\n");
+               (*env)->ExceptionDescribe(env);
+#endif
+               result = callbackData[index].errorResult;
+       }
+
+       if (detach) {
+               (*jvm)->DetachCurrentThread(jvm);
+               env = NULL;
+       }
+
+noEnv:
+
+#ifdef DEBUG_CALL_PRINTS
+       fprintf(stderr, "* callback exiting %d\n", --counter);
+#endif
+
+       return result;
+       }
+}
+
+/* ------------- callback class calls end --------------- */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/callback.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/callback.h
new file mode 100644 (file)
index 0000000..a9bc844
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/**
+ * Callback implementation.
+ */
+#ifndef INC_callback_H
+#define INC_callback_H
+
+#include "swt.h"
+
+#if defined (_WIN32) || defined (_WIN32_WCE)
+#include "windows.h"
+#define RETURN_TYPE LRESULT CALLBACK
+#define RETURN_CAST (LRESULT)
+#endif
+
+#if defined COCOA
+#import <Foundation/Foundation.h>
+#endif
+
+#ifndef RETURN_TYPE
+#define RETURN_TYPE jintLong
+#endif
+
+#ifndef RETURN_CAST
+#define RETURN_CAST
+#endif
+
+/*
+* Note that only x86 assembler is supported
+*/
+#if !(defined(__i386__) || defined(_M_IX86) || defined(_X86_))
+#undef USE_ASSEMBLER
+#endif
+
+#ifdef REDUCED_CALLBACKS
+#define MAX_CALLBACKS 16
+#else
+#if (defined(USE_ASSEMBLER) || defined(GTK))
+#define MAX_CALLBACKS 256
+#else
+#define MAX_CALLBACKS 128
+#endif
+#endif /* REDUCED_CALLBACKS */
+
+#define MAX_ARGS 12
+
+typedef struct CALLBACK_DATA {
+    jobject callback;
+    jmethodID methodID;
+       jobject object;
+       jboolean isStatic;
+       jboolean isArrayBased; 
+       jint argCount;
+       jintLong errorResult;
+} CALLBACK_DATA;
+
+#endif /* ifndef INC_callback_H */
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/cancel.ico b/bundles/org.eclipse.swt.win32.win32.x86_64/library/cancel.ico
new file mode 100644 (file)
index 0000000..d113216
Binary files /dev/null and b/bundles/org.eclipse.swt.win32.win32.x86_64/library/cancel.ico differ
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com.c
new file mode 100644 (file)
index 0000000..152c33c
--- /dev/null
@@ -0,0 +1,2193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "com_structs.h"
+#include "com_stats.h"
+
+#ifndef COM_NATIVE
+#define COM_NATIVE(func) Java_org_eclipse_swt_internal_ole_win32_COM_##func
+#endif
+
+#ifndef NO_AccessibleChildren
+JNIEXPORT jint JNICALL COM_NATIVE(AccessibleChildren)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jlong arg3, jintArray arg4)
+{
+       jint *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, AccessibleChildren_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)AccessibleChildren((IAccessible *)arg0, (LONG)arg1, (LONG)arg2, (VARIANT *)arg3, (LONG *)lparg4);
+*/
+       {
+               COM_LOAD_FUNCTION(fp, AccessibleChildren)
+               if (fp) {
+                       rc = (jint)((jint (CALLING_CONVENTION*)(IAccessible *, LONG, LONG, VARIANT *, LONG *))fp)((IAccessible *)arg0, (LONG)arg1, (LONG)arg2, (VARIANT *)arg3, (LONG *)lparg4);
+               }
+       }
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       COM_NATIVE_EXIT(env, that, AccessibleChildren_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AccessibleObjectFromWindow
+JNIEXPORT jint JNICALL COM_NATIVE(AccessibleObjectFromWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2, jlongArray arg3)
+{
+       GUID _arg2, *lparg2=NULL;
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, AccessibleObjectFromWindow_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)AccessibleObjectFromWindow((HWND)arg0, (DWORD)arg1, lparg2, (LPVOID *)lparg3);
+*/
+       {
+               COM_LOAD_FUNCTION(fp, AccessibleObjectFromWindow)
+               if (fp) {
+                       rc = (jint)((jint (CALLING_CONVENTION*)(HWND, DWORD, GUID *, LPVOID *))fp)((HWND)arg0, (DWORD)arg1, lparg2, (LPVOID *)lparg3);
+               }
+       }
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, AccessibleObjectFromWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CAUUID_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(CAUUID_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CAUUID_1sizeof_FUNC);
+       rc = (jint)CAUUID_sizeof();
+       COM_NATIVE_EXIT(env, that, CAUUID_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CLSIDFromProgID
+JNIEXPORT jint JNICALL COM_NATIVE(CLSIDFromProgID)
+       (JNIEnv *env, jclass that, jcharArray arg0, jobject arg1)
+{
+       jchar *lparg0=NULL;
+       GUID _arg1, *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CLSIDFromProgID_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)CLSIDFromProgID((LPCOLESTR)lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, CLSIDFromProgID_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CLSIDFromString
+JNIEXPORT jint JNICALL COM_NATIVE(CLSIDFromString)
+       (JNIEnv *env, jclass that, jcharArray arg0, jobject arg1)
+{
+       jchar *lparg0=NULL;
+       GUID _arg1, *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CLSIDFromString_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)CLSIDFromString((LPOLESTR)lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, CLSIDFromString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CONTROLINFO_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(CONTROLINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CONTROLINFO_1sizeof_FUNC);
+       rc = (jint)CONTROLINFO_sizeof();
+       COM_NATIVE_EXIT(env, that, CONTROLINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoCreateInstance
+JNIEXPORT jint JNICALL COM_NATIVE(CoCreateInstance)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2, jobject arg3, jlongArray arg4)
+{
+       GUID _arg0, *lparg0=NULL;
+       GUID _arg3, *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CoCreateInstance_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)CoCreateInstance(lparg0, (LPUNKNOWN)arg1, arg2, lparg3, (LPVOID *)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, CoCreateInstance_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoFreeUnusedLibraries
+JNIEXPORT void JNICALL COM_NATIVE(CoFreeUnusedLibraries)
+       (JNIEnv *env, jclass that)
+{
+       COM_NATIVE_ENTER(env, that, CoFreeUnusedLibraries_FUNC);
+       CoFreeUnusedLibraries();
+       COM_NATIVE_EXIT(env, that, CoFreeUnusedLibraries_FUNC);
+}
+#endif
+
+#ifndef NO_CoGetClassObject
+JNIEXPORT jint JNICALL COM_NATIVE(CoGetClassObject)
+       (JNIEnv *env, jclass that, jobject arg0, jint arg1, jlong arg2, jobject arg3, jlongArray arg4)
+{
+       GUID _arg0, *lparg0=NULL;
+       GUID _arg3, *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CoGetClassObject_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)CoGetClassObject(lparg0, arg1, (COSERVERINFO *)arg2, lparg3, (LPVOID *)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, CoGetClassObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoLockObjectExternal
+JNIEXPORT jint JNICALL COM_NATIVE(CoLockObjectExternal)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1, jboolean arg2)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CoLockObjectExternal_FUNC);
+       rc = (jint)CoLockObjectExternal((IUnknown *)arg0, (BOOL)arg1, (BOOL)arg2);
+       COM_NATIVE_EXIT(env, that, CoLockObjectExternal_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateStdAccessibleObject
+JNIEXPORT jint JNICALL COM_NATIVE(CreateStdAccessibleObject)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2, jlongArray arg3)
+{
+       GUID _arg2, *lparg2=NULL;
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, CreateStdAccessibleObject_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)CreateStdAccessibleObject((HWND)arg0, arg1, lparg2, (LPVOID *)lparg3);
+*/
+       {
+               COM_LOAD_FUNCTION(fp, CreateStdAccessibleObject)
+               if (fp) {
+                       rc = (jint)((jint (CALLING_CONVENTION*)(HWND, jint, GUID *, LPVOID *))fp)((HWND)arg0, arg1, lparg2, (LPVOID *)lparg3);
+               }
+       }
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, CreateStdAccessibleObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DISPPARAMS_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(DISPPARAMS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, DISPPARAMS_1sizeof_FUNC);
+       rc = (jint)DISPPARAMS_sizeof();
+       COM_NATIVE_EXIT(env, that, DISPPARAMS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DoDragDrop
+JNIEXPORT jint JNICALL COM_NATIVE(DoDragDrop)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jintArray arg3)
+{
+       jint *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, DoDragDrop_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)DoDragDrop((IDataObject *)arg0, (IDropSource *)arg1, arg2, (LPDWORD)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, DoDragDrop_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ELEMDESC_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(ELEMDESC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, ELEMDESC_1sizeof_FUNC);
+       rc = (jint)ELEMDESC_sizeof();
+       COM_NATIVE_EXIT(env, that, ELEMDESC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EXCEPINFO_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(EXCEPINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, EXCEPINFO_1sizeof_FUNC);
+       rc = (jint)EXCEPINFO_sizeof();
+       COM_NATIVE_EXIT(env, that, EXCEPINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FORMATETC_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(FORMATETC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, FORMATETC_1sizeof_FUNC);
+       rc = (jint)FORMATETC_sizeof();
+       COM_NATIVE_EXIT(env, that, FORMATETC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FUNCDESC_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(FUNCDESC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, FUNCDESC_1sizeof_FUNC);
+       rc = (jint)FUNCDESC_sizeof();
+       COM_NATIVE_EXIT(env, that, FUNCDESC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GUID_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(GUID_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, GUID_1sizeof_FUNC);
+       rc = (jint)GUID_sizeof();
+       COM_NATIVE_EXIT(env, that, GUID_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClassFile
+JNIEXPORT jint JNICALL COM_NATIVE(GetClassFile)
+       (JNIEnv *env, jclass that, jcharArray arg0, jobject arg1)
+{
+       jchar *lparg0=NULL;
+       GUID _arg1, *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, GetClassFile_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)GetClassFile((LPCWSTR)lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, GetClassFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IIDFromString
+JNIEXPORT jint JNICALL COM_NATIVE(IIDFromString)
+       (JNIEnv *env, jclass that, jcharArray arg0, jobject arg1)
+{
+       jchar *lparg0=NULL;
+       GUID _arg1, *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, IIDFromString_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)IIDFromString((LPOLESTR)lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, IIDFromString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsEqualGUID
+JNIEXPORT jboolean JNICALL COM_NATIVE(IsEqualGUID)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1)
+{
+       GUID _arg0, *lparg0=NULL;
+       GUID _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       COM_NATIVE_ENTER(env, that, IsEqualGUID_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)IsEqualGUID(lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, IsEqualGUID_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LICINFO_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(LICINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, LICINFO_1sizeof_FUNC);
+       rc = (jint)LICINFO_sizeof();
+       COM_NATIVE_EXIT(env, that, LICINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LresultFromObject
+JNIEXPORT jlong JNICALL COM_NATIVE(LresultFromObject)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jlong arg2)
+{
+       GUID _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       COM_NATIVE_ENTER(env, that, LresultFromObject_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+/*
+       rc = (jlong)LresultFromObject(lparg0, arg1, (LPUNKNOWN)arg2);
+*/
+       {
+               COM_LOAD_FUNCTION(fp, LresultFromObject)
+               if (fp) {
+                       rc = (jlong)((jlong (CALLING_CONVENTION*)(GUID *, jlong, LPUNKNOWN))fp)(lparg0, arg1, (LPUNKNOWN)arg2);
+               }
+       }
+fail:
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, LresultFromObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_ole_win32_FORMATETC_2I
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_ole_win32_FORMATETC_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       FORMATETC _arg1, *lparg1=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_ole_win32_FORMATETC_2I_FUNC);
+       if (arg1) if ((lparg1 = getFORMATETCFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       COM_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_ole_win32_FORMATETC_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_ole_win32_OLEINPLACEFRAMEINFO_2I
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_ole_win32_OLEINPLACEFRAMEINFO_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       OLEINPLACEFRAMEINFO _arg1, *lparg1=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_ole_win32_OLEINPLACEFRAMEINFO_2I_FUNC);
+       if (arg1) if ((lparg1 = getOLEINPLACEFRAMEINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       COM_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_ole_win32_OLEINPLACEFRAMEINFO_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2I
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       STGMEDIUM _arg1, *lparg1=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2I_FUNC);
+       if (arg1) if ((lparg1 = getSTGMEDIUMFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       COM_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       DISPPARAMS _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setDISPPARAMSFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FORMATETC_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FORMATETC_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       FORMATETC _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FORMATETC_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setFORMATETCFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FORMATETC_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FUNCDESC_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FUNCDESC_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       FUNCDESC _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FUNCDESC_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setFUNCDESCFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FUNCDESC_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_GUID_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_GUID_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       GUID _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_GUID_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_GUID_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       STGMEDIUM _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setSTGMEDIUMFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_TYPEATTR_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_TYPEATTR_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       TYPEATTR _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_TYPEATTR_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setTYPEATTRFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_TYPEATTR_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARDESC_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARDESC_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       VARDESC _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARDESC_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setVARDESCFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARDESC_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARIANT_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARIANT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       VARIANT _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARIANT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setVARIANTFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARIANT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_RECT_2JI
+JNIEXPORT void JNICALL COM_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_RECT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       RECT _arg0, *lparg0=NULL;
+       COM_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_RECT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setRECTFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_RECT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_OLECMD_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(OLECMD_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OLECMD_1sizeof_FUNC);
+       rc = (jint)OLECMD_sizeof();
+       COM_NATIVE_EXIT(env, that, OLECMD_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OLEINPLACEFRAMEINFO_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(OLEINPLACEFRAMEINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OLEINPLACEFRAMEINFO_1sizeof_FUNC);
+       rc = (jint)OLEINPLACEFRAMEINFO_sizeof();
+       COM_NATIVE_EXIT(env, that, OLEINPLACEFRAMEINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleCreate
+JNIEXPORT jint JNICALL COM_NATIVE(OleCreate)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1, jint arg2, jobject arg3, jlong arg4, jlong arg5, jlongArray arg6)
+{
+       GUID _arg0, *lparg0=NULL;
+       GUID _arg1, *lparg1=NULL;
+       FORMATETC _arg3, *lparg3=NULL;
+       jlong *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleCreate_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getFORMATETCFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetLongArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)OleCreate(lparg0, lparg1, arg2, lparg3, (IOleClientSite *)arg4, (IStorage *)arg5, (void **)lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseLongArrayElements(env, arg6, lparg6, 0);
+       if (arg3 && lparg3) setFORMATETCFields(env, arg3, lparg3);
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, OleCreate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleCreateFromFile
+JNIEXPORT jint JNICALL COM_NATIVE(OleCreateFromFile)
+       (JNIEnv *env, jclass that, jobject arg0, jcharArray arg1, jobject arg2, jint arg3, jobject arg4, jlong arg5, jlong arg6, jlongArray arg7)
+{
+       GUID _arg0, *lparg0=NULL;
+       jchar *lparg1=NULL;
+       GUID _arg2, *lparg2=NULL;
+       FORMATETC _arg4, *lparg4=NULL;
+       jlong *lparg7=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleCreateFromFile_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getFORMATETCFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = (*env)->GetLongArrayElements(env, arg7, NULL)) == NULL) goto fail;
+       rc = (jint)OleCreateFromFile(lparg0, (LPCOLESTR)lparg1, lparg2, arg3, lparg4, (LPOLECLIENTSITE)arg5, (LPSTORAGE)arg6, (LPVOID *)lparg7);
+fail:
+       if (arg7 && lparg7) (*env)->ReleaseLongArrayElements(env, arg7, lparg7, 0);
+       if (arg4 && lparg4) setFORMATETCFields(env, arg4, lparg4);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, OleCreateFromFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleCreatePropertyFrame
+JNIEXPORT jint JNICALL COM_NATIVE(OleCreatePropertyFrame)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jcharArray arg3, jint arg4, jlongArray arg5, jint arg6, jlong arg7, jint arg8, jint arg9, jlong arg10)
+{
+       jchar *lparg3=NULL;
+       jlong *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleCreatePropertyFrame_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)OleCreatePropertyFrame((HWND)arg0, arg1, arg2, (LPCOLESTR)lparg3, arg4, (LPUNKNOWN FAR*)lparg5, arg6, (LPCLSID)arg7, (LCID)arg8, arg9, (LPVOID)arg10);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0);
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, OleCreatePropertyFrame_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleDraw
+JNIEXPORT jint JNICALL COM_NATIVE(OleDraw)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleDraw_FUNC);
+       rc = (jint)OleDraw((LPUNKNOWN)arg0, (DWORD)arg1, (HDC)arg2, (LPRECT)arg3);
+       COM_NATIVE_EXIT(env, that, OleDraw_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleFlushClipboard
+JNIEXPORT jint JNICALL COM_NATIVE(OleFlushClipboard)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleFlushClipboard_FUNC);
+       rc = (jint)OleFlushClipboard();
+       COM_NATIVE_EXIT(env, that, OleFlushClipboard_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleGetClipboard
+JNIEXPORT jint JNICALL COM_NATIVE(OleGetClipboard)
+       (JNIEnv *env, jclass that, jlongArray arg0)
+{
+       jlong *lparg0=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleGetClipboard_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetLongArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)OleGetClipboard((IDataObject **)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseLongArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, OleGetClipboard_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleIsCurrentClipboard
+JNIEXPORT jint JNICALL COM_NATIVE(OleIsCurrentClipboard)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleIsCurrentClipboard_FUNC);
+       rc = (jint)OleIsCurrentClipboard((IDataObject *)arg0);
+       COM_NATIVE_EXIT(env, that, OleIsCurrentClipboard_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleIsRunning
+JNIEXPORT jboolean JNICALL COM_NATIVE(OleIsRunning)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       COM_NATIVE_ENTER(env, that, OleIsRunning_FUNC);
+       rc = (jboolean)OleIsRunning((LPOLEOBJECT)arg0);
+       COM_NATIVE_EXIT(env, that, OleIsRunning_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleRun
+JNIEXPORT jint JNICALL COM_NATIVE(OleRun)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleRun_FUNC);
+       rc = (jint)OleRun((LPUNKNOWN)arg0);
+       COM_NATIVE_EXIT(env, that, OleRun_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleSave
+JNIEXPORT jint JNICALL COM_NATIVE(OleSave)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleSave_FUNC);
+       rc = (jint)OleSave((IPersistStorage *)arg0, (IStorage *)arg1, arg2);
+       COM_NATIVE_EXIT(env, that, OleSave_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleSetClipboard
+JNIEXPORT jint JNICALL COM_NATIVE(OleSetClipboard)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleSetClipboard_FUNC);
+       rc = (jint)OleSetClipboard((IDataObject *)arg0);
+       COM_NATIVE_EXIT(env, that, OleSetClipboard_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleSetContainedObject
+JNIEXPORT jint JNICALL COM_NATIVE(OleSetContainedObject)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleSetContainedObject_FUNC);
+       rc = (jint)OleSetContainedObject((LPUNKNOWN)arg0, arg1);
+       COM_NATIVE_EXIT(env, that, OleSetContainedObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleSetMenuDescriptor
+JNIEXPORT jint JNICALL COM_NATIVE(OleSetMenuDescriptor)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER_TRY(env, that, OleSetMenuDescriptor_FUNC);
+       rc = (jint)OleSetMenuDescriptor((HOLEMENU)arg0, (HWND)arg1, (HWND)arg2, (LPOLEINPLACEFRAME)arg3, (LPOLEINPLACEACTIVEOBJECT)arg4);
+       COM_NATIVE_EXIT_CATCH(env, that, OleSetMenuDescriptor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleTranslateColor
+JNIEXPORT jint JNICALL COM_NATIVE(OleTranslateColor)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jintArray arg2)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, OleTranslateColor_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)OleTranslateColor((OLE_COLOR)arg0, (HPALETTE)arg1, (COLORREF *)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, OleTranslateColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathToPIDL
+JNIEXPORT jint JNICALL COM_NATIVE(PathToPIDL)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlongArray arg1)
+{
+       jchar *lparg0=NULL;
+       jlong *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, PathToPIDL_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)PathToPIDL((PCWSTR)lparg0, (PIDLIST_ABSOLUTE)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, PathToPIDL_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ProgIDFromCLSID
+JNIEXPORT jint JNICALL COM_NATIVE(ProgIDFromCLSID)
+       (JNIEnv *env, jclass that, jobject arg0, jlongArray arg1)
+{
+       GUID _arg0, *lparg0=NULL;
+       jlong *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, ProgIDFromCLSID_FUNC);
+       if (arg0) if ((lparg0 = getGUIDFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)ProgIDFromCLSID(lparg0, (LPOLESTR *)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) setGUIDFields(env, arg0, lparg0);
+       COM_NATIVE_EXIT(env, that, ProgIDFromCLSID_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegisterDragDrop
+JNIEXPORT jint JNICALL COM_NATIVE(RegisterDragDrop)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, RegisterDragDrop_FUNC);
+       rc = (jint)RegisterDragDrop((HWND)arg0, (IDropTarget *)arg1);
+       COM_NATIVE_EXIT(env, that, RegisterDragDrop_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ReleaseStgMedium
+JNIEXPORT void JNICALL COM_NATIVE(ReleaseStgMedium)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       COM_NATIVE_ENTER(env, that, ReleaseStgMedium_FUNC);
+       ReleaseStgMedium((STGMEDIUM *)arg0);
+       COM_NATIVE_EXIT(env, that, ReleaseStgMedium_FUNC);
+}
+#endif
+
+#ifndef NO_RevokeDragDrop
+JNIEXPORT jint JNICALL COM_NATIVE(RevokeDragDrop)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, RevokeDragDrop_FUNC);
+       rc = (jint)RevokeDragDrop((HWND)arg0);
+       COM_NATIVE_EXIT(env, that, RevokeDragDrop_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHCreateItemFromParsingName
+JNIEXPORT jint JNICALL COM_NATIVE(SHCreateItemFromParsingName)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlong arg1, jobject arg2, jlongArray arg3)
+{
+       jchar *lparg0=NULL;
+       GUID _arg2, *lparg2=NULL;
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, SHCreateItemFromParsingName_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)SHCreateItemFromParsingName((PCWSTR)lparg0, (IBindCtx *)arg1, (REFIID)lparg2, (void **)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, SHCreateItemFromParsingName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_STGMEDIUM_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(STGMEDIUM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, STGMEDIUM_1sizeof_FUNC);
+       rc = (jint)STGMEDIUM_sizeof();
+       COM_NATIVE_EXIT(env, that, STGMEDIUM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StgCreateDocfile
+JNIEXPORT jint JNICALL COM_NATIVE(StgCreateDocfile)
+       (JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jint arg2, jlongArray arg3)
+{
+       jchar *lparg0=NULL;
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, StgCreateDocfile_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)StgCreateDocfile(lparg0, arg1, arg2, (IStorage **)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, StgCreateDocfile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StgIsStorageFile
+JNIEXPORT jint JNICALL COM_NATIVE(StgIsStorageFile)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, StgIsStorageFile_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)StgIsStorageFile((const WCHAR *)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, StgIsStorageFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StgOpenStorage
+JNIEXPORT jint JNICALL COM_NATIVE(StgOpenStorage)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlong arg1, jint arg2, jlong arg3, jint arg4, jlongArray arg5)
+{
+       jchar *lparg0=NULL;
+       jlong *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, StgOpenStorage_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)StgOpenStorage((const WCHAR *)lparg0, (IStorage *)arg1, arg2, (SNB)arg3, arg4, (IStorage **)lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, StgOpenStorage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SysAllocString
+JNIEXPORT jlong JNICALL COM_NATIVE(SysAllocString)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jlong rc = 0;
+       COM_NATIVE_ENTER(env, that, SysAllocString_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)SysAllocString((OLECHAR *)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       COM_NATIVE_EXIT(env, that, SysAllocString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SysFreeString
+JNIEXPORT void JNICALL COM_NATIVE(SysFreeString)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       COM_NATIVE_ENTER(env, that, SysFreeString_FUNC);
+       SysFreeString((BSTR)arg0);
+       COM_NATIVE_EXIT(env, that, SysFreeString_FUNC);
+}
+#endif
+
+#ifndef NO_SysStringByteLen
+JNIEXPORT jint JNICALL COM_NATIVE(SysStringByteLen)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, SysStringByteLen_FUNC);
+       rc = (jint)SysStringByteLen((BSTR)arg0);
+       COM_NATIVE_EXIT(env, that, SysStringByteLen_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SysStringLen
+JNIEXPORT jint JNICALL COM_NATIVE(SysStringLen)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, SysStringLen_FUNC);
+       rc = (jint)SysStringLen((BSTR)arg0);
+       COM_NATIVE_EXIT(env, that, SysStringLen_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TYPEATTR_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(TYPEATTR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, TYPEATTR_1sizeof_FUNC);
+       rc = (jint)TYPEATTR_sizeof();
+       COM_NATIVE_EXIT(env, that, TYPEATTR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TYPEDESC_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(TYPEDESC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, TYPEDESC_1sizeof_FUNC);
+       rc = (jint)TYPEDESC_sizeof();
+       COM_NATIVE_EXIT(env, that, TYPEDESC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VARDESC_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(VARDESC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VARDESC_1sizeof_FUNC);
+       rc = (jint)VARDESC_sizeof();
+       COM_NATIVE_EXIT(env, that, VARDESC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VARIANT_1sizeof
+JNIEXPORT jint JNICALL COM_NATIVE(VARIANT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VARIANT_1sizeof_FUNC);
+       rc = (jint)VARIANT_sizeof();
+       COM_NATIVE_EXIT(env, that, VARIANT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VariantChangeType
+JNIEXPORT jint JNICALL COM_NATIVE(VariantChangeType)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jshort arg2, jshort arg3)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VariantChangeType_FUNC);
+       rc = (jint)VariantChangeType((VARIANTARG FAR* )arg0, (VARIANTARG FAR* )arg1, arg2, (VARTYPE)arg3);
+       COM_NATIVE_EXIT(env, that, VariantChangeType_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VariantClear
+JNIEXPORT jint JNICALL COM_NATIVE(VariantClear)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VariantClear_FUNC);
+       rc = (jint)VariantClear((VARIANTARG FAR* )arg0);
+       COM_NATIVE_EXIT(env, that, VariantClear_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VariantInit
+JNIEXPORT void JNICALL COM_NATIVE(VariantInit)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       COM_NATIVE_ENTER(env, that, VariantInit_FUNC);
+       VariantInit((VARIANTARG FAR* )arg0);
+       COM_NATIVE_EXIT(env, that, VariantInit_FUNC);
+}
+#endif
+
+#ifndef NO_VtblCall__IJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER_TRY(env, that, VtblCall__IJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong))(*(jlong **)arg1)[arg0])(arg1);
+       COM_NATIVE_EXIT_CATCH(env, that, VtblCall__IJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJI
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJI)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJI_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint))(*(jlong **)arg1)[arg0])(arg1, arg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJIIILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJIIILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jobject arg5, jlong arg6, jobject arg7, jlong arg8)
+{
+       DISPPARAMS _arg5, *lparg5=NULL;
+       EXCEPINFO _arg7, *lparg7=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJIIILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2J_FUNC);
+       if (arg5) if ((lparg5 = getDISPPARAMSFields(env, arg5, &_arg5)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = getEXCEPINFOFields(env, arg7, &_arg7)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jint, jint, DISPPARAMS *, jlong, EXCEPINFO *, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4, lparg5, arg6, lparg7, arg8);
+fail:
+       if (arg7 && lparg7) setEXCEPINFOFields(env, arg7, lparg7);
+       if (arg5 && lparg5) setDISPPARAMSFields(env, arg5, lparg5);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJIIILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJIIJLorg_eclipse_swt_internal_win32_SIZE_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJIIJLorg_eclipse_swt_internal_win32_SIZE_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jint arg3, jlong arg4, jobject arg5)
+{
+       SIZE _arg5, *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJIIJLorg_eclipse_swt_internal_win32_SIZE_2_FUNC);
+       if (arg5) if ((lparg5 = getSIZEFields(env, arg5, &_arg5)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jint, jlong, SIZE *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4, lparg5);
+fail:
+       if (arg5 && lparg5) setSIZEFields(env, arg5, lparg5);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJIIJLorg_eclipse_swt_internal_win32_SIZE_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJIJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJIJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlong arg3)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJIJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJIJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJIJI_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJIJI_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlong arg3, jint arg4, jlongArray arg5)
+{
+       jlong *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJIJI_3J_FUNC);
+       if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4, lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJIJI_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJIJJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJIJJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJIJJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJIJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJIJ_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJIJ_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlong arg3, jintArray arg4)
+{
+       jint *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJIJ_3I_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJIJ_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jobject arg3)
+{
+       GUID _arg3, *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC);
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, GUID *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2IILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2IILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jobject arg3, jint arg4, jint arg5, jobject arg6, jlong arg7, jobject arg8, jintArray arg9)
+{
+       GUID _arg3, *lparg3=NULL;
+       DISPPARAMS _arg6, *lparg6=NULL;
+       EXCEPINFO _arg8, *lparg8=NULL;
+       jint *lparg9=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2IILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2_3I_FUNC);
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = getDISPPARAMSFields(env, arg6, &_arg6)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = getEXCEPINFOFields(env, arg8, &_arg8)) == NULL) goto fail;
+       if (arg9) if ((lparg9 = (*env)->GetIntArrayElements(env, arg9, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, GUID *, jint, jint, DISPPARAMS *, jlong, EXCEPINFO *, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, arg4, arg5, lparg6, arg7, lparg8, lparg9);
+fail:
+       if (arg9 && lparg9) (*env)->ReleaseIntArrayElements(env, arg9, lparg9, 0);
+       if (arg8 && lparg8) setEXCEPINFOFields(env, arg8, lparg8);
+       if (arg6 && lparg6) setDISPPARAMSFields(env, arg6, lparg6);
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2IILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2JJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2JJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jobject arg3, jlong arg4, jlong arg5)
+{
+       GUID _arg3, *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2JJ_FUNC);
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, GUID *, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, arg4, arg5);
+fail:
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2JJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jobject arg3, jobject arg4, jobject arg5)
+{
+       GUID _arg3, *lparg3=NULL;
+       GUID _arg4, *lparg4=NULL;
+       GUID _arg5, *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC);
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getGUIDFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = getGUIDFields(env, arg5, &_arg5)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, GUID *, GUID *, GUID *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, lparg4, lparg5);
+fail:
+       if (arg5 && lparg5) setGUIDFields(env, arg5, lparg5);
+       if (arg4 && lparg4) setGUIDFields(env, arg4, lparg4);
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJILorg_eclipse_swt_internal_win32_MSG_2JIJLorg_eclipse_swt_internal_win32_RECT_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJILorg_eclipse_swt_internal_win32_MSG_2JIJLorg_eclipse_swt_internal_win32_RECT_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jobject arg3, jlong arg4, jint arg5, jlong arg6, jobject arg7)
+{
+       MSG _arg3, *lparg3=NULL;
+       RECT _arg7, *lparg7=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJILorg_eclipse_swt_internal_win32_MSG_2JIJLorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       if (arg3) if ((lparg3 = getMSGFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = getRECTFields(env, arg7, &_arg7)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, MSG *, jlong, jint, jlong, RECT *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, arg4, arg5, arg6, lparg7);
+fail:
+       if (arg7 && lparg7) setRECTFields(env, arg7, lparg7);
+       if (arg3 && lparg3) setMSGFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJILorg_eclipse_swt_internal_win32_MSG_2JIJLorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJILorg_eclipse_swt_internal_win32_SIZE_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJILorg_eclipse_swt_internal_win32_SIZE_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jobject arg3)
+{
+       SIZE _arg3, *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJILorg_eclipse_swt_internal_win32_SIZE_2_FUNC);
+       if (arg3) if ((lparg3 = getSIZEFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, SIZE *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) setSIZEFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJILorg_eclipse_swt_internal_win32_SIZE_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJI_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJI_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jintArray arg3)
+{
+       jint *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJI_3I_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJI_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJI_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJI_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlongArray arg3)
+{
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJI_3J_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJI_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJI_3JI_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJI_3JI_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlongArray arg3, jint arg4, jintArray arg5)
+{
+       jlong *lparg3=NULL;
+       jint *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJI_3JI_3I_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong *, jint, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, arg4, lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJI_3JI_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJI_3J_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJI_3J_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlongArray arg3, jintArray arg4)
+{
+       jlong *lparg3=NULL;
+       jint *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJI_3J_3I_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong *, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJI_3J_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJI_3J_3J_3I_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJI_3J_3J_3I_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jlongArray arg3, jlongArray arg4, jintArray arg5, jlongArray arg6)
+{
+       jlong *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jint *lparg5=NULL;
+       jlong *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJI_3J_3J_3I_3J_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetLongArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint, jlong *, jlong *, jint *, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, lparg4, lparg5, lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseLongArrayElements(env, arg6, lparg6, 0);
+       if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJI_3J_3J_3I_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJI
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJI)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jint arg3)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJI_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jint))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJII_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJII_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jint arg3, jint arg4, jlongArray arg5)
+{
+       jlong *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJII_3J_FUNC);
+       if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jint, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4, lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJII_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJI_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJI_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jint arg3, jintArray arg4)
+{
+       jint *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJI_3I_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jint, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJI_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJI_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJI_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jint arg3, jlongArray arg4)
+{
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJI_3J_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJI_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJI_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJI_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3, jint arg4, jlongArray arg5)
+{
+       jlong *lparg5=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJI_3J_FUNC);
+       if (arg5) if ((lparg5 = (*env)->GetLongArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4, lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseLongArrayElements(env, arg5, lparg5, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJI_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJJJJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJJJJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4, jlong arg5, jlong arg6)
+{
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJJJJ_FUNC);
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong, jlong, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, arg4, arg5, arg6);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJJJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJLorg_eclipse_swt_internal_ole_win32_GUID_2J_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJLorg_eclipse_swt_internal_ole_win32_GUID_2J_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3, jobject arg4, jlong arg5, jlongArray arg6)
+{
+       GUID _arg4, *lparg4=NULL;
+       jlong *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJLorg_eclipse_swt_internal_ole_win32_GUID_2J_3J_FUNC);
+       if (arg4) if ((lparg4 = getGUIDFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetLongArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong, GUID *, jlong, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, lparg4, arg5, lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseLongArrayElements(env, arg6, lparg6, 0);
+       if (arg4 && lparg4) setGUIDFields(env, arg4, lparg4);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJLorg_eclipse_swt_internal_ole_win32_GUID_2J_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJLorg_eclipse_swt_internal_win32_POINT_2I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJLorg_eclipse_swt_internal_win32_POINT_2I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3, jobject arg4, jint arg5)
+{
+       POINT _arg4, *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC);
+       if (arg4) if ((lparg4 = getPOINTFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong, POINT *, jint))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, lparg4, arg5);
+fail:
+       if (arg4 && lparg4) setPOINTFields(env, arg4, lparg4);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJJ_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJJ_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlong arg3, jlongArray arg4)
+{
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJJ_3J_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, arg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJJ_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJLorg_eclipse_swt_internal_win32_POINT_2J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJLorg_eclipse_swt_internal_win32_POINT_2J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jobject arg3, jlong arg4)
+{
+       POINT _arg3, *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJLorg_eclipse_swt_internal_win32_POINT_2J_FUNC);
+       if (arg3) if ((lparg3 = getPOINTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, POINT *, jlong))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3, arg4);
+fail:
+       if (arg3 && lparg3) setPOINTFields(env, arg3, lparg3);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJLorg_eclipse_swt_internal_win32_POINT_2J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJ_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJ_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jintArray arg3)
+{
+       jint *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJ_3I_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jint *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJ_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJJ_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJJ_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jlongArray arg3)
+{
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJJ_3J_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong, jlong *))(*(jlong **)arg1)[arg0])(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJJ_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CAUUID_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CAUUID_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       CAUUID _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CAUUID_2_FUNC);
+       if (arg2) if ((lparg2 = getCAUUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, CAUUID *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setCAUUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CAUUID_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CONTROLINFO_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CONTROLINFO_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       CONTROLINFO _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CONTROLINFO_2_FUNC);
+       if (arg2) if ((lparg2 = getCONTROLINFOFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, CONTROLINFO *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setCONTROLINFOFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CONTROLINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       FORMATETC _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2_FUNC);
+       if (arg2) if ((lparg2 = getFORMATETCFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, FORMATETC *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setFORMATETCFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jobject arg3)
+{
+       FORMATETC _arg2, *lparg2=NULL;
+       STGMEDIUM _arg3, *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2_FUNC);
+       if (arg2) if ((lparg2 = getFORMATETCFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getSTGMEDIUMFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, FORMATETC *, STGMEDIUM *))(*(jlong **)arg1)[arg0])(arg1, lparg2, lparg3);
+fail:
+       if (arg3 && lparg3) setSTGMEDIUMFields(env, arg3, lparg3);
+       if (arg2 && lparg2) setFORMATETCFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       GUID _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, GUID *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2IIJJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2IIJJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jint arg3, jint arg4, jlong arg5, jlong arg6)
+{
+       GUID _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2IIJJ_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, GUID *, jint, jint, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4, arg5, arg6);
+fail:
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2IIJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2ILorg_eclipse_swt_internal_ole_win32_OLECMD_2J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2ILorg_eclipse_swt_internal_ole_win32_OLECMD_2J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jint arg3, jobject arg4, jlong arg5)
+{
+       GUID _arg2, *lparg2=NULL;
+       OLECMD _arg4, *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2ILorg_eclipse_swt_internal_ole_win32_OLECMD_2J_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getOLECMDFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, GUID *, jint, OLECMD *, jlong))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, lparg4, arg5);
+fail:
+       if (arg4 && lparg4) setOLECMDFields(env, arg4, lparg4);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2ILorg_eclipse_swt_internal_ole_win32_OLECMD_2J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2JII_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2JII_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jlong arg3, jint arg4, jint arg5, jintArray arg6)
+{
+       GUID _arg2, *lparg2=NULL;
+       jint *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2JII_3I_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, GUID *, jlong, jint, jint, jint *))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4, arg5, lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2JII_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jobject arg3, jlongArray arg4)
+{
+       GUID _arg2, *lparg2=NULL;
+       GUID _arg3, *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, GUID *, GUID *, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2, lparg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jlongArray arg3)
+{
+       GUID _arg2, *lparg2=NULL;
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC);
+       if (arg2) if ((lparg2 = getGUIDFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, GUID *, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) setGUIDFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_ole_win32_LICINFO_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_ole_win32_LICINFO_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       LICINFO _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_LICINFO_2_FUNC);
+       if (arg2) if ((lparg2 = getLICINFOFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, LICINFO *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setLICINFOFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_ole_win32_LICINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_MSG_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_MSG_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       MSG _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_MSG_2_FUNC);
+       if (arg2) if ((lparg2 = getMSGFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, MSG *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setMSGFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_MSG_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_POINT_2I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_POINT_2I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jint arg3)
+{
+       POINT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC);
+       if (arg2) if ((lparg2 = getPOINTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, POINT *, jint))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setPOINTFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_PROPERTYKEY_2J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_PROPERTYKEY_2J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jlong arg3)
+{
+       PROPERTYKEY _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_PROPERTYKEY_2J_FUNC);
+       if (arg2) if ((lparg2 = getPROPERTYKEYFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, PROPERTYKEY *, jlong))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setPROPERTYKEYFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_PROPERTYKEY_2J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       RECT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, RECT *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JI
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JI)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jlong arg3, jint arg4)
+{
+       RECT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JI_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, RECT *, jlong, jint))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4);
+fail:
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jlong arg3, jlong arg4)
+{
+       RECT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JJ_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, RECT, jlong, jlong))(*(jlong **)arg1)[arg0])(arg1, *lparg2, arg3, arg4);
+fail:
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2Lorg_eclipse_swt_internal_win32_RECT_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2Lorg_eclipse_swt_internal_win32_RECT_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2, jobject arg3)
+{
+       RECT _arg2, *lparg2=NULL;
+       RECT _arg3, *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2Lorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getRECTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, RECT *, RECT *))(*(jlong **)arg1)[arg0])(arg1, lparg2, lparg3);
+fail:
+       if (arg3 && lparg3) setRECTFields(env, arg3, lparg3);
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2Lorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJLorg_eclipse_swt_internal_win32_TF_1DISPLAYATTRIBUTE_2
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJLorg_eclipse_swt_internal_win32_TF_1DISPLAYATTRIBUTE_2)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2)
+{
+       TF_DISPLAYATTRIBUTE _arg2, *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_TF_1DISPLAYATTRIBUTE_2_FUNC);
+       if (arg2) if ((lparg2 = getTF_DISPLAYATTRIBUTEFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, TF_DISPLAYATTRIBUTE *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setTF_DISPLAYATTRIBUTEFields(env, arg2, lparg2);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJLorg_eclipse_swt_internal_win32_TF_1DISPLAYATTRIBUTE_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3C
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3C)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3C_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3C_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3CI
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3CI)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jint arg3)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3CI_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jint))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3CI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3CIII_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3CIII_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jint arg3, jint arg4, jint arg5, jlongArray arg6)
+{
+       jchar *lparg2=NULL;
+       jlong *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3CIII_3J_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetLongArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jint, jint, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4, arg5, lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseLongArrayElements(env, arg6, lparg6, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3CIII_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3CII_3I_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3CII_3I_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jint arg3, jint arg4, jintArray arg5, jintArray arg6)
+{
+       jchar *lparg2=NULL;
+       jint *lparg5=NULL;
+       jint *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3CII_3I_3I_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jint, jint, jint *, jint *))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4, lparg5, lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
+       if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3CII_3I_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3CJ
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3CJ)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jlong arg3)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3CJ_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jlong))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3CJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3CJIII_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3CJIII_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jlong arg3, jint arg4, jint arg5, jint arg6, jlongArray arg7)
+{
+       jchar *lparg2=NULL;
+       jlong *lparg7=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3CJIII_3J_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = (*env)->GetLongArrayElements(env, arg7, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jlong, jint, jint, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4, arg5, arg6, lparg7);
+fail:
+       if (arg7 && lparg7) (*env)->ReleaseLongArrayElements(env, arg7, lparg7, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3CJIII_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3CJII_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3CJII_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jlong arg3, jint arg4, jint arg5, jlongArray arg6)
+{
+       jchar *lparg2=NULL;
+       jlong *lparg6=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3CJII_3J_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetLongArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jlong, jint, jint, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2, arg3, arg4, arg5, lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseLongArrayElements(env, arg6, lparg6, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3CJII_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3C_3C
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3C_3C)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jcharArray arg2, jcharArray arg3)
+{
+       jchar *lparg2=NULL;
+       jchar *lparg3=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3C_3C_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jchar *, jchar *))(*(jlong **)arg1)[arg0])(arg1, lparg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3C_3C_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3I
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3I)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jintArray arg2)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3I_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3ILorg_eclipse_swt_internal_ole_win32_GUID_2_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3ILorg_eclipse_swt_internal_ole_win32_GUID_2_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jintArray arg2, jobject arg3, jlongArray arg4)
+{
+       jint *lparg2=NULL;
+       GUID _arg3, *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3ILorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getGUIDFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jint *, GUID *, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2, lparg3, lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) setGUIDFields(env, arg3, lparg3);
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3ILorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VtblCall__IJ_3J
+JNIEXPORT jint JNICALL COM_NATIVE(VtblCall__IJ_3J)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlongArray arg2)
+{
+       jlong *lparg2=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, VtblCall__IJ_3J_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((jint (STDMETHODCALLTYPE *)(jlong, jlong *))(*(jlong **)arg1)[arg0])(arg1, lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0);
+       COM_NATIVE_EXIT(env, that, VtblCall__IJ_3J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WriteClassStg
+JNIEXPORT jint JNICALL COM_NATIVE(WriteClassStg)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       GUID _arg1, *lparg1=NULL;
+       jint rc = 0;
+       COM_NATIVE_ENTER(env, that, WriteClassStg_FUNC);
+       if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)WriteClassStg((IStorage *)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setGUIDFields(env, arg1, lparg1);
+       COM_NATIVE_EXIT(env, that, WriteClassStg_FUNC);
+       return rc;
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com.h
new file mode 100644 (file)
index 0000000..c6784f9
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#ifndef INC_com_H
+#define INC_com_H
+
+#include "os_structs.h"
+#include "com_custom.h"
+
+#define COM_LOAD_FUNCTION LOAD_FUNCTION
+
+#define COM_NATIVE_ENTER_TRY(env, that, func) \
+       COM_NATIVE_ENTER(env, that, func); \
+       NATIVE_TRY(env, that, func);
+#define COM_NATIVE_EXIT_CATCH(env, that, func) \
+       NATIVE_CATCH(env, that, func); \
+       COM_NATIVE_EXIT(env, that, func);
+
+#endif /* INC_com_H */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_custom.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_custom.cpp
new file mode 100644 (file)
index 0000000..791d8df
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *    Paul Pazderski - Bug 547634: PathToPIDL
+ *******************************************************************************/
+
+#include "swt.h"
+#include "com_structs.h"
+#include "com_stats.h"
+#include <Shlobj.h>
+
+#define COM_NATIVE(func) Java_org_eclipse_swt_internal_ole_win32_COM_##func
+
+class CFileSysBindData : public IFileSystemBindData
+{
+public:
+       CFileSysBindData() : refCount(1)
+       {
+               ZeroMemory(&findData, sizeof(findData));
+       }
+
+       IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
+       {
+               *ppv = nullptr;
+               HRESULT hr = E_NOINTERFACE;
+               if (riid == IID_IUnknown || riid == IID_IFileSystemBindData) {
+                       *ppv = static_cast<IFileSystemBindData*>(this);
+                       AddRef();
+                       hr = S_OK;
+               }
+               return hr;
+       }
+
+       IFACEMETHODIMP_(ULONG) AddRef()
+       {
+               return InterlockedIncrement(&refCount);
+       }
+
+       IFACEMETHODIMP_(ULONG) Release()
+       {
+               long rc = InterlockedDecrement(&refCount);
+               if (!rc)
+                       delete this;
+               return rc;
+       }
+
+       IFACEMETHODIMP SetFindData(const WIN32_FIND_DATAW *pfd)
+       {
+               findData = *pfd;
+               return S_OK;
+       }
+
+       IFACEMETHODIMP GetFindData(WIN32_FIND_DATAW *pfd)
+       {
+               *pfd = findData;
+               return S_OK;
+       }
+
+private:
+       long refCount;
+       WIN32_FIND_DATAW findData;
+};
+
+/*
+ * An extended version of SHParseDisplayName which use bind context to support
+ * creation of simple PIDLs in case the normal PIDL creation failed.
+ * (most likley due to non existing file/directory)
+ */
+extern "C" HRESULT PathToPIDL(PCWSTR pszName, PIDLIST_ABSOLUTE *ppidl)
+{
+       if (!ppidl) return E_FAIL;
+       *ppidl = nullptr;
+       
+       SFGAOF sfgao = 0;
+       HRESULT hr = SHParseDisplayName(pszName, nullptr, ppidl, sfgao, &sfgao);
+       if (hr == S_OK) return hr;
+
+       IFileSystemBindData *pfsbd = new CFileSysBindData();
+       if (!pfsbd) return E_OUTOFMEMORY;
+
+       WIN32_FIND_DATAW data = {};
+       pfsbd->SetFindData(&data);
+
+       IBindCtx* pbc;
+
+       hr = CreateBindCtx(0, &pbc);
+       if (hr == S_OK)
+       {
+               BIND_OPTS bo = { sizeof(bo), 0, STGM_CREATE, 0 };
+               hr = pbc->SetBindOptions(&bo);
+               if (hr == S_OK)
+               {
+                       hr = pbc->RegisterObjectParam(STR_FILE_SYS_BIND_DATA, pfsbd);
+                       if (hr == S_OK)
+                       {
+                               sfgao = 0;
+                               hr = SHParseDisplayName(pszName, pbc, ppidl, sfgao, &sfgao);
+                       }
+               }
+               pbc->Release();
+       }
+       pfsbd->Release();
+       return hr;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_custom.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_custom.h
new file mode 100644 (file)
index 0000000..eff05db
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Special sizeof's */
+#define ELEMDESC_sizeof() sizeof(ELEMDESC)
+#define TYPEDESC_sizeof() sizeof(TYPEDESC)
+
+/* Libraries for dynamic loaded functions */
+#define AccessibleChildren_LIB "oleacc.dll"
+#define AccessibleObjectFromWindow_LIB "oleacc.dll"
+#define CreateStdAccessibleObject_LIB "oleacc.dll"
+#define LresultFromObject_LIB "oleacc.dll"
+
+/* Custom functions */
+#ifdef __cplusplus
+extern "C" {
+#endif
+HRESULT PathToPIDL(_In_ PCWSTR pszName, _Outptr_ PIDLIST_ABSOLUTE *ppidl);
+#ifdef __cplusplus
+}
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_stats.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_stats.c
new file mode 100644 (file)
index 0000000..64eec0e
--- /dev/null
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "com_stats.h"
+
+#ifdef NATIVE_STATS
+
+char * COM_nativeFunctionNames[] = {
+       "AccessibleChildren",
+       "AccessibleObjectFromWindow",
+       "CAUUID_1sizeof",
+       "CLSIDFromProgID",
+       "CLSIDFromString",
+       "CONTROLINFO_1sizeof",
+       "CoCreateInstance",
+       "CoFreeUnusedLibraries",
+       "CoGetClassObject",
+       "CoLockObjectExternal",
+       "CreateStdAccessibleObject",
+       "DISPPARAMS_1sizeof",
+       "DoDragDrop",
+       "ELEMDESC_1sizeof",
+       "EXCEPINFO_1sizeof",
+       "FORMATETC_1sizeof",
+       "FUNCDESC_1sizeof",
+       "GUID_1sizeof",
+       "GetClassFile",
+       "IIDFromString",
+       "IsEqualGUID",
+       "LICINFO_1sizeof",
+       "LresultFromObject",
+       "MoveMemory__JLorg_eclipse_swt_internal_ole_win32_FORMATETC_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_ole_win32_OLEINPLACEFRAMEINFO_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2I",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FORMATETC_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FUNCDESC_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_GUID_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_TYPEATTR_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARDESC_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARIANT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_RECT_2JI",
+       "OLECMD_1sizeof",
+       "OLEINPLACEFRAMEINFO_1sizeof",
+       "OleCreate",
+       "OleCreateFromFile",
+       "OleCreatePropertyFrame",
+       "OleDraw",
+       "OleFlushClipboard",
+       "OleGetClipboard",
+       "OleIsCurrentClipboard",
+       "OleIsRunning",
+       "OleRun",
+       "OleSave",
+       "OleSetClipboard",
+       "OleSetContainedObject",
+       "OleSetMenuDescriptor",
+       "OleTranslateColor",
+       "PathToPIDL",
+       "ProgIDFromCLSID",
+       "RegisterDragDrop",
+       "ReleaseStgMedium",
+       "RevokeDragDrop",
+       "SHCreateItemFromParsingName",
+       "STGMEDIUM_1sizeof",
+       "StgCreateDocfile",
+       "StgIsStorageFile",
+       "StgOpenStorage",
+       "SysAllocString",
+       "SysFreeString",
+       "SysStringByteLen",
+       "SysStringLen",
+       "TYPEATTR_1sizeof",
+       "TYPEDESC_1sizeof",
+       "VARDESC_1sizeof",
+       "VARIANT_1sizeof",
+       "VariantChangeType",
+       "VariantClear",
+       "VariantInit",
+       "VtblCall__IJ",
+       "VtblCall__IJI",
+       "VtblCall__IJIIILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2J",
+       "VtblCall__IJIIJLorg_eclipse_swt_internal_win32_SIZE_2",
+       "VtblCall__IJIJ",
+       "VtblCall__IJIJI_3J",
+       "VtblCall__IJIJJ",
+       "VtblCall__IJIJ_3I",
+       "VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2",
+       "VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2IILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2_3I",
+       "VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2JJ",
+       "VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2",
+       "VtblCall__IJILorg_eclipse_swt_internal_win32_MSG_2JIJLorg_eclipse_swt_internal_win32_RECT_2",
+       "VtblCall__IJILorg_eclipse_swt_internal_win32_SIZE_2",
+       "VtblCall__IJI_3I",
+       "VtblCall__IJI_3J",
+       "VtblCall__IJI_3JI_3I",
+       "VtblCall__IJI_3J_3I",
+       "VtblCall__IJI_3J_3J_3I_3J",
+       "VtblCall__IJJ",
+       "VtblCall__IJJI",
+       "VtblCall__IJJII_3J",
+       "VtblCall__IJJI_3I",
+       "VtblCall__IJJI_3J",
+       "VtblCall__IJJJ",
+       "VtblCall__IJJJI_3J",
+       "VtblCall__IJJJJ",
+       "VtblCall__IJJJJJJ",
+       "VtblCall__IJJJLorg_eclipse_swt_internal_ole_win32_GUID_2J_3J",
+       "VtblCall__IJJJLorg_eclipse_swt_internal_win32_POINT_2I",
+       "VtblCall__IJJJ_3J",
+       "VtblCall__IJJLorg_eclipse_swt_internal_win32_POINT_2J",
+       "VtblCall__IJJ_3I",
+       "VtblCall__IJJ_3J",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CAUUID_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CONTROLINFO_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2IIJJ",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2ILorg_eclipse_swt_internal_ole_win32_OLECMD_2J",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2JII_3I",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_3J",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_3J",
+       "VtblCall__IJLorg_eclipse_swt_internal_ole_win32_LICINFO_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_MSG_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_POINT_2I",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_PROPERTYKEY_2J",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JI",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JJ",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2Lorg_eclipse_swt_internal_win32_RECT_2",
+       "VtblCall__IJLorg_eclipse_swt_internal_win32_TF_1DISPLAYATTRIBUTE_2",
+       "VtblCall__IJ_3C",
+       "VtblCall__IJ_3CI",
+       "VtblCall__IJ_3CIII_3J",
+       "VtblCall__IJ_3CII_3I_3I",
+       "VtblCall__IJ_3CJ",
+       "VtblCall__IJ_3CJIII_3J",
+       "VtblCall__IJ_3CJII_3J",
+       "VtblCall__IJ_3C_3C",
+       "VtblCall__IJ_3I",
+       "VtblCall__IJ_3ILorg_eclipse_swt_internal_ole_win32_GUID_2_3J",
+       "VtblCall__IJ_3J",
+       "WriteClassStg",
+};
+#define NATIVE_FUNCTION_COUNT sizeof(COM_nativeFunctionNames) / sizeof(char*)
+int COM_nativeFunctionCount = NATIVE_FUNCTION_COUNT;
+int COM_nativeFunctionCallCount[NATIVE_FUNCTION_COUNT];
+
+#define STATS_NATIVE(func) Java_org_eclipse_swt_tools_internal_NativeStats_##func
+
+JNIEXPORT jint JNICALL STATS_NATIVE(COM_1GetFunctionCount)
+       (JNIEnv *env, jclass that)
+{
+       return COM_nativeFunctionCount;
+}
+
+JNIEXPORT jstring JNICALL STATS_NATIVE(COM_1GetFunctionName)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return (*env)->NewStringUTF(env, COM_nativeFunctionNames[index]);
+}
+
+JNIEXPORT jint JNICALL STATS_NATIVE(COM_1GetFunctionCallCount)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return COM_nativeFunctionCallCount[index];
+}
+
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_stats.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_stats.h
new file mode 100644 (file)
index 0000000..6480352
--- /dev/null
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#ifdef NATIVE_STATS
+extern int COM_nativeFunctionCount;
+extern int COM_nativeFunctionCallCount[];
+extern char* COM_nativeFunctionNames[];
+#define COM_NATIVE_ENTER(env, that, func) COM_nativeFunctionCallCount[func]++;
+#define COM_NATIVE_EXIT(env, that, func) 
+#else
+#ifndef COM_NATIVE_ENTER
+#define COM_NATIVE_ENTER(env, that, func) 
+#endif
+#ifndef COM_NATIVE_EXIT
+#define COM_NATIVE_EXIT(env, that, func) 
+#endif
+#endif
+
+typedef enum {
+       AccessibleChildren_FUNC,
+       AccessibleObjectFromWindow_FUNC,
+       CAUUID_1sizeof_FUNC,
+       CLSIDFromProgID_FUNC,
+       CLSIDFromString_FUNC,
+       CONTROLINFO_1sizeof_FUNC,
+       CoCreateInstance_FUNC,
+       CoFreeUnusedLibraries_FUNC,
+       CoGetClassObject_FUNC,
+       CoLockObjectExternal_FUNC,
+       CreateStdAccessibleObject_FUNC,
+       DISPPARAMS_1sizeof_FUNC,
+       DoDragDrop_FUNC,
+       ELEMDESC_1sizeof_FUNC,
+       EXCEPINFO_1sizeof_FUNC,
+       FORMATETC_1sizeof_FUNC,
+       FUNCDESC_1sizeof_FUNC,
+       GUID_1sizeof_FUNC,
+       GetClassFile_FUNC,
+       IIDFromString_FUNC,
+       IsEqualGUID_FUNC,
+       LICINFO_1sizeof_FUNC,
+       LresultFromObject_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_ole_win32_FORMATETC_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_ole_win32_OLEINPLACEFRAMEINFO_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2I_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FORMATETC_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_FUNCDESC_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_GUID_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_TYPEATTR_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARDESC_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_ole_win32_VARIANT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_RECT_2JI_FUNC,
+       OLECMD_1sizeof_FUNC,
+       OLEINPLACEFRAMEINFO_1sizeof_FUNC,
+       OleCreate_FUNC,
+       OleCreateFromFile_FUNC,
+       OleCreatePropertyFrame_FUNC,
+       OleDraw_FUNC,
+       OleFlushClipboard_FUNC,
+       OleGetClipboard_FUNC,
+       OleIsCurrentClipboard_FUNC,
+       OleIsRunning_FUNC,
+       OleRun_FUNC,
+       OleSave_FUNC,
+       OleSetClipboard_FUNC,
+       OleSetContainedObject_FUNC,
+       OleSetMenuDescriptor_FUNC,
+       OleTranslateColor_FUNC,
+       PathToPIDL_FUNC,
+       ProgIDFromCLSID_FUNC,
+       RegisterDragDrop_FUNC,
+       ReleaseStgMedium_FUNC,
+       RevokeDragDrop_FUNC,
+       SHCreateItemFromParsingName_FUNC,
+       STGMEDIUM_1sizeof_FUNC,
+       StgCreateDocfile_FUNC,
+       StgIsStorageFile_FUNC,
+       StgOpenStorage_FUNC,
+       SysAllocString_FUNC,
+       SysFreeString_FUNC,
+       SysStringByteLen_FUNC,
+       SysStringLen_FUNC,
+       TYPEATTR_1sizeof_FUNC,
+       TYPEDESC_1sizeof_FUNC,
+       VARDESC_1sizeof_FUNC,
+       VARIANT_1sizeof_FUNC,
+       VariantChangeType_FUNC,
+       VariantClear_FUNC,
+       VariantInit_FUNC,
+       VtblCall__IJ_FUNC,
+       VtblCall__IJI_FUNC,
+       VtblCall__IJIIILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2J_FUNC,
+       VtblCall__IJIIJLorg_eclipse_swt_internal_win32_SIZE_2_FUNC,
+       VtblCall__IJIJ_FUNC,
+       VtblCall__IJIJI_3J_FUNC,
+       VtblCall__IJIJJ_FUNC,
+       VtblCall__IJIJ_3I_FUNC,
+       VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC,
+       VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2IILorg_eclipse_swt_internal_ole_win32_DISPPARAMS_2JLorg_eclipse_swt_internal_ole_win32_EXCEPINFO_2_3I_FUNC,
+       VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2JJ_FUNC,
+       VtblCall__IJILorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC,
+       VtblCall__IJILorg_eclipse_swt_internal_win32_MSG_2JIJLorg_eclipse_swt_internal_win32_RECT_2_FUNC,
+       VtblCall__IJILorg_eclipse_swt_internal_win32_SIZE_2_FUNC,
+       VtblCall__IJI_3I_FUNC,
+       VtblCall__IJI_3J_FUNC,
+       VtblCall__IJI_3JI_3I_FUNC,
+       VtblCall__IJI_3J_3I_FUNC,
+       VtblCall__IJI_3J_3J_3I_3J_FUNC,
+       VtblCall__IJJ_FUNC,
+       VtblCall__IJJI_FUNC,
+       VtblCall__IJJII_3J_FUNC,
+       VtblCall__IJJI_3I_FUNC,
+       VtblCall__IJJI_3J_FUNC,
+       VtblCall__IJJJ_FUNC,
+       VtblCall__IJJJI_3J_FUNC,
+       VtblCall__IJJJJ_FUNC,
+       VtblCall__IJJJJJJ_FUNC,
+       VtblCall__IJJJLorg_eclipse_swt_internal_ole_win32_GUID_2J_3J_FUNC,
+       VtblCall__IJJJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC,
+       VtblCall__IJJJ_3J_FUNC,
+       VtblCall__IJJLorg_eclipse_swt_internal_win32_POINT_2J_FUNC,
+       VtblCall__IJJ_3I_FUNC,
+       VtblCall__IJJ_3J_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CAUUID_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_CONTROLINFO_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_FORMATETC_2Lorg_eclipse_swt_internal_ole_win32_STGMEDIUM_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2IIJJ_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2ILorg_eclipse_swt_internal_ole_win32_OLECMD_2J_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2JII_3I_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2Lorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_ole_win32_LICINFO_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_MSG_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_PROPERTYKEY_2J_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JI_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2JJ_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_RECT_2Lorg_eclipse_swt_internal_win32_RECT_2_FUNC,
+       VtblCall__IJLorg_eclipse_swt_internal_win32_TF_1DISPLAYATTRIBUTE_2_FUNC,
+       VtblCall__IJ_3C_FUNC,
+       VtblCall__IJ_3CI_FUNC,
+       VtblCall__IJ_3CIII_3J_FUNC,
+       VtblCall__IJ_3CII_3I_3I_FUNC,
+       VtblCall__IJ_3CJ_FUNC,
+       VtblCall__IJ_3CJIII_3J_FUNC,
+       VtblCall__IJ_3CJII_3J_FUNC,
+       VtblCall__IJ_3C_3C_FUNC,
+       VtblCall__IJ_3I_FUNC,
+       VtblCall__IJ_3ILorg_eclipse_swt_internal_ole_win32_GUID_2_3J_FUNC,
+       VtblCall__IJ_3J_FUNC,
+       WriteClassStg_FUNC,
+} COM_FUNCS;
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_structs.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_structs.c
new file mode 100644 (file)
index 0000000..19ee53f
--- /dev/null
@@ -0,0 +1,703 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "com_structs.h"
+
+#ifndef NO_CAUUID
+typedef struct CAUUID_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cElems, pElems;
+} CAUUID_FID_CACHE;
+
+CAUUID_FID_CACHE CAUUIDFc;
+
+void cacheCAUUIDFields(JNIEnv *env, jobject lpObject)
+{
+       if (CAUUIDFc.cached) return;
+       CAUUIDFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CAUUIDFc.cElems = (*env)->GetFieldID(env, CAUUIDFc.clazz, "cElems", "I");
+       CAUUIDFc.pElems = (*env)->GetFieldID(env, CAUUIDFc.clazz, "pElems", "J");
+       CAUUIDFc.cached = 1;
+}
+
+CAUUID *getCAUUIDFields(JNIEnv *env, jobject lpObject, CAUUID *lpStruct)
+{
+       if (!CAUUIDFc.cached) cacheCAUUIDFields(env, lpObject);
+       lpStruct->cElems = (*env)->GetIntField(env, lpObject, CAUUIDFc.cElems);
+       lpStruct->pElems = (GUID FAR *)(*env)->GetLongField(env, lpObject, CAUUIDFc.pElems);
+       return lpStruct;
+}
+
+void setCAUUIDFields(JNIEnv *env, jobject lpObject, CAUUID *lpStruct)
+{
+       if (!CAUUIDFc.cached) cacheCAUUIDFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CAUUIDFc.cElems, (jint)lpStruct->cElems);
+       (*env)->SetLongField(env, lpObject, CAUUIDFc.pElems, (jlong)lpStruct->pElems);
+}
+#endif
+
+#ifndef NO_CONTROLINFO
+typedef struct CONTROLINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cb, hAccel, cAccel, dwFlags;
+} CONTROLINFO_FID_CACHE;
+
+CONTROLINFO_FID_CACHE CONTROLINFOFc;
+
+void cacheCONTROLINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (CONTROLINFOFc.cached) return;
+       CONTROLINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CONTROLINFOFc.cb = (*env)->GetFieldID(env, CONTROLINFOFc.clazz, "cb", "I");
+       CONTROLINFOFc.hAccel = (*env)->GetFieldID(env, CONTROLINFOFc.clazz, "hAccel", "J");
+       CONTROLINFOFc.cAccel = (*env)->GetFieldID(env, CONTROLINFOFc.clazz, "cAccel", "S");
+       CONTROLINFOFc.dwFlags = (*env)->GetFieldID(env, CONTROLINFOFc.clazz, "dwFlags", "I");
+       CONTROLINFOFc.cached = 1;
+}
+
+CONTROLINFO *getCONTROLINFOFields(JNIEnv *env, jobject lpObject, CONTROLINFO *lpStruct)
+{
+       if (!CONTROLINFOFc.cached) cacheCONTROLINFOFields(env, lpObject);
+       lpStruct->cb = (*env)->GetIntField(env, lpObject, CONTROLINFOFc.cb);
+       lpStruct->hAccel = (HACCEL)(*env)->GetLongField(env, lpObject, CONTROLINFOFc.hAccel);
+       lpStruct->cAccel = (*env)->GetShortField(env, lpObject, CONTROLINFOFc.cAccel);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, CONTROLINFOFc.dwFlags);
+       return lpStruct;
+}
+
+void setCONTROLINFOFields(JNIEnv *env, jobject lpObject, CONTROLINFO *lpStruct)
+{
+       if (!CONTROLINFOFc.cached) cacheCONTROLINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CONTROLINFOFc.cb, (jint)lpStruct->cb);
+       (*env)->SetLongField(env, lpObject, CONTROLINFOFc.hAccel, (jlong)lpStruct->hAccel);
+       (*env)->SetShortField(env, lpObject, CONTROLINFOFc.cAccel, (jshort)lpStruct->cAccel);
+       (*env)->SetIntField(env, lpObject, CONTROLINFOFc.dwFlags, (jint)lpStruct->dwFlags);
+}
+#endif
+
+#ifndef NO_DISPPARAMS
+typedef struct DISPPARAMS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID rgvarg, rgdispidNamedArgs, cArgs, cNamedArgs;
+} DISPPARAMS_FID_CACHE;
+
+DISPPARAMS_FID_CACHE DISPPARAMSFc;
+
+void cacheDISPPARAMSFields(JNIEnv *env, jobject lpObject)
+{
+       if (DISPPARAMSFc.cached) return;
+       DISPPARAMSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DISPPARAMSFc.rgvarg = (*env)->GetFieldID(env, DISPPARAMSFc.clazz, "rgvarg", "J");
+       DISPPARAMSFc.rgdispidNamedArgs = (*env)->GetFieldID(env, DISPPARAMSFc.clazz, "rgdispidNamedArgs", "J");
+       DISPPARAMSFc.cArgs = (*env)->GetFieldID(env, DISPPARAMSFc.clazz, "cArgs", "I");
+       DISPPARAMSFc.cNamedArgs = (*env)->GetFieldID(env, DISPPARAMSFc.clazz, "cNamedArgs", "I");
+       DISPPARAMSFc.cached = 1;
+}
+
+DISPPARAMS *getDISPPARAMSFields(JNIEnv *env, jobject lpObject, DISPPARAMS *lpStruct)
+{
+       if (!DISPPARAMSFc.cached) cacheDISPPARAMSFields(env, lpObject);
+       lpStruct->rgvarg = (VARIANTARG FAR *)(*env)->GetLongField(env, lpObject, DISPPARAMSFc.rgvarg);
+       lpStruct->rgdispidNamedArgs = (DISPID FAR *)(*env)->GetLongField(env, lpObject, DISPPARAMSFc.rgdispidNamedArgs);
+       lpStruct->cArgs = (*env)->GetIntField(env, lpObject, DISPPARAMSFc.cArgs);
+       lpStruct->cNamedArgs = (*env)->GetIntField(env, lpObject, DISPPARAMSFc.cNamedArgs);
+       return lpStruct;
+}
+
+void setDISPPARAMSFields(JNIEnv *env, jobject lpObject, DISPPARAMS *lpStruct)
+{
+       if (!DISPPARAMSFc.cached) cacheDISPPARAMSFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, DISPPARAMSFc.rgvarg, (jlong)lpStruct->rgvarg);
+       (*env)->SetLongField(env, lpObject, DISPPARAMSFc.rgdispidNamedArgs, (jlong)lpStruct->rgdispidNamedArgs);
+       (*env)->SetIntField(env, lpObject, DISPPARAMSFc.cArgs, (jint)lpStruct->cArgs);
+       (*env)->SetIntField(env, lpObject, DISPPARAMSFc.cNamedArgs, (jint)lpStruct->cNamedArgs);
+}
+#endif
+
+#ifndef NO_EXCEPINFO
+typedef struct EXCEPINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID wCode, wReserved, bstrSource, bstrDescription, bstrHelpFile, dwHelpContext, pvReserved, pfnDeferredFillIn, scode;
+} EXCEPINFO_FID_CACHE;
+
+EXCEPINFO_FID_CACHE EXCEPINFOFc;
+
+void cacheEXCEPINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (EXCEPINFOFc.cached) return;
+       EXCEPINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       EXCEPINFOFc.wCode = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "wCode", "S");
+       EXCEPINFOFc.wReserved = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "wReserved", "S");
+       EXCEPINFOFc.bstrSource = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "bstrSource", "J");
+       EXCEPINFOFc.bstrDescription = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "bstrDescription", "J");
+       EXCEPINFOFc.bstrHelpFile = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "bstrHelpFile", "J");
+       EXCEPINFOFc.dwHelpContext = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "dwHelpContext", "I");
+       EXCEPINFOFc.pvReserved = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "pvReserved", "J");
+       EXCEPINFOFc.pfnDeferredFillIn = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "pfnDeferredFillIn", "J");
+       EXCEPINFOFc.scode = (*env)->GetFieldID(env, EXCEPINFOFc.clazz, "scode", "I");
+       EXCEPINFOFc.cached = 1;
+}
+
+EXCEPINFO *getEXCEPINFOFields(JNIEnv *env, jobject lpObject, EXCEPINFO *lpStruct)
+{
+       if (!EXCEPINFOFc.cached) cacheEXCEPINFOFields(env, lpObject);
+       lpStruct->wCode = (*env)->GetShortField(env, lpObject, EXCEPINFOFc.wCode);
+       lpStruct->wReserved = (*env)->GetShortField(env, lpObject, EXCEPINFOFc.wReserved);
+       lpStruct->bstrSource = (BSTR)(*env)->GetLongField(env, lpObject, EXCEPINFOFc.bstrSource);
+       lpStruct->bstrDescription = (BSTR)(*env)->GetLongField(env, lpObject, EXCEPINFOFc.bstrDescription);
+       lpStruct->bstrHelpFile = (BSTR)(*env)->GetLongField(env, lpObject, EXCEPINFOFc.bstrHelpFile);
+       lpStruct->dwHelpContext = (*env)->GetIntField(env, lpObject, EXCEPINFOFc.dwHelpContext);
+       lpStruct->pvReserved = (void FAR *)(*env)->GetLongField(env, lpObject, EXCEPINFOFc.pvReserved);
+       lpStruct->pfnDeferredFillIn = (HRESULT (STDAPICALLTYPE FAR* )(struct tagEXCEPINFO FAR*))(*env)->GetLongField(env, lpObject, EXCEPINFOFc.pfnDeferredFillIn);
+       lpStruct->scode = (*env)->GetIntField(env, lpObject, EXCEPINFOFc.scode);
+       return lpStruct;
+}
+
+void setEXCEPINFOFields(JNIEnv *env, jobject lpObject, EXCEPINFO *lpStruct)
+{
+       if (!EXCEPINFOFc.cached) cacheEXCEPINFOFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, EXCEPINFOFc.wCode, (jshort)lpStruct->wCode);
+       (*env)->SetShortField(env, lpObject, EXCEPINFOFc.wReserved, (jshort)lpStruct->wReserved);
+       (*env)->SetLongField(env, lpObject, EXCEPINFOFc.bstrSource, (jlong)lpStruct->bstrSource);
+       (*env)->SetLongField(env, lpObject, EXCEPINFOFc.bstrDescription, (jlong)lpStruct->bstrDescription);
+       (*env)->SetLongField(env, lpObject, EXCEPINFOFc.bstrHelpFile, (jlong)lpStruct->bstrHelpFile);
+       (*env)->SetIntField(env, lpObject, EXCEPINFOFc.dwHelpContext, (jint)lpStruct->dwHelpContext);
+       (*env)->SetLongField(env, lpObject, EXCEPINFOFc.pvReserved, (jlong)lpStruct->pvReserved);
+       (*env)->SetLongField(env, lpObject, EXCEPINFOFc.pfnDeferredFillIn, (jlong)lpStruct->pfnDeferredFillIn);
+       (*env)->SetIntField(env, lpObject, EXCEPINFOFc.scode, (jint)lpStruct->scode);
+}
+#endif
+
+#ifndef NO_FORMATETC
+typedef struct FORMATETC_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cfFormat, ptd, dwAspect, lindex, tymed;
+} FORMATETC_FID_CACHE;
+
+FORMATETC_FID_CACHE FORMATETCFc;
+
+void cacheFORMATETCFields(JNIEnv *env, jobject lpObject)
+{
+       if (FORMATETCFc.cached) return;
+       FORMATETCFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       FORMATETCFc.cfFormat = (*env)->GetFieldID(env, FORMATETCFc.clazz, "cfFormat", "I");
+       FORMATETCFc.ptd = (*env)->GetFieldID(env, FORMATETCFc.clazz, "ptd", "J");
+       FORMATETCFc.dwAspect = (*env)->GetFieldID(env, FORMATETCFc.clazz, "dwAspect", "I");
+       FORMATETCFc.lindex = (*env)->GetFieldID(env, FORMATETCFc.clazz, "lindex", "I");
+       FORMATETCFc.tymed = (*env)->GetFieldID(env, FORMATETCFc.clazz, "tymed", "I");
+       FORMATETCFc.cached = 1;
+}
+
+FORMATETC *getFORMATETCFields(JNIEnv *env, jobject lpObject, FORMATETC *lpStruct)
+{
+       if (!FORMATETCFc.cached) cacheFORMATETCFields(env, lpObject);
+       lpStruct->cfFormat = (CLIPFORMAT)(*env)->GetIntField(env, lpObject, FORMATETCFc.cfFormat);
+       lpStruct->ptd = (DVTARGETDEVICE *)(*env)->GetLongField(env, lpObject, FORMATETCFc.ptd);
+       lpStruct->dwAspect = (*env)->GetIntField(env, lpObject, FORMATETCFc.dwAspect);
+       lpStruct->lindex = (*env)->GetIntField(env, lpObject, FORMATETCFc.lindex);
+       lpStruct->tymed = (*env)->GetIntField(env, lpObject, FORMATETCFc.tymed);
+       return lpStruct;
+}
+
+void setFORMATETCFields(JNIEnv *env, jobject lpObject, FORMATETC *lpStruct)
+{
+       if (!FORMATETCFc.cached) cacheFORMATETCFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, FORMATETCFc.cfFormat, (jint)lpStruct->cfFormat);
+       (*env)->SetLongField(env, lpObject, FORMATETCFc.ptd, (jlong)lpStruct->ptd);
+       (*env)->SetIntField(env, lpObject, FORMATETCFc.dwAspect, (jint)lpStruct->dwAspect);
+       (*env)->SetIntField(env, lpObject, FORMATETCFc.lindex, (jint)lpStruct->lindex);
+       (*env)->SetIntField(env, lpObject, FORMATETCFc.tymed, (jint)lpStruct->tymed);
+}
+#endif
+
+#ifndef NO_FUNCDESC
+typedef struct FUNCDESC_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID memid, lprgscode, lprgelemdescParam, funckind, invkind, callconv, cParams, cParamsOpt, oVft, cScodes, elemdescFunc_tdesc_union, elemdescFunc_tdesc_vt, elemdescFunc_paramdesc_pparamdescex, elemdescFunc_paramdesc_wParamFlags, wFuncFlags;
+} FUNCDESC_FID_CACHE;
+
+FUNCDESC_FID_CACHE FUNCDESCFc;
+
+void cacheFUNCDESCFields(JNIEnv *env, jobject lpObject)
+{
+       if (FUNCDESCFc.cached) return;
+       FUNCDESCFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       FUNCDESCFc.memid = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "memid", "I");
+       FUNCDESCFc.lprgscode = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "lprgscode", "J");
+       FUNCDESCFc.lprgelemdescParam = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "lprgelemdescParam", "J");
+       FUNCDESCFc.funckind = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "funckind", "I");
+       FUNCDESCFc.invkind = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "invkind", "I");
+       FUNCDESCFc.callconv = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "callconv", "I");
+       FUNCDESCFc.cParams = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "cParams", "S");
+       FUNCDESCFc.cParamsOpt = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "cParamsOpt", "S");
+       FUNCDESCFc.oVft = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "oVft", "S");
+       FUNCDESCFc.cScodes = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "cScodes", "S");
+       FUNCDESCFc.elemdescFunc_tdesc_union = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "elemdescFunc_tdesc_union", "J");
+       FUNCDESCFc.elemdescFunc_tdesc_vt = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "elemdescFunc_tdesc_vt", "S");
+       FUNCDESCFc.elemdescFunc_paramdesc_pparamdescex = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "elemdescFunc_paramdesc_pparamdescex", "J");
+       FUNCDESCFc.elemdescFunc_paramdesc_wParamFlags = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "elemdescFunc_paramdesc_wParamFlags", "S");
+       FUNCDESCFc.wFuncFlags = (*env)->GetFieldID(env, FUNCDESCFc.clazz, "wFuncFlags", "S");
+       FUNCDESCFc.cached = 1;
+}
+
+FUNCDESC *getFUNCDESCFields(JNIEnv *env, jobject lpObject, FUNCDESC *lpStruct)
+{
+       if (!FUNCDESCFc.cached) cacheFUNCDESCFields(env, lpObject);
+       lpStruct->memid = (MEMBERID)(*env)->GetIntField(env, lpObject, FUNCDESCFc.memid);
+       lpStruct->lprgscode = (SCODE FAR *)(*env)->GetLongField(env, lpObject, FUNCDESCFc.lprgscode);
+       lpStruct->lprgelemdescParam = (ELEMDESC FAR *)(*env)->GetLongField(env, lpObject, FUNCDESCFc.lprgelemdescParam);
+       lpStruct->funckind = (FUNCKIND)(*env)->GetIntField(env, lpObject, FUNCDESCFc.funckind);
+       lpStruct->invkind = (INVOKEKIND)(*env)->GetIntField(env, lpObject, FUNCDESCFc.invkind);
+       lpStruct->callconv = (CALLCONV)(*env)->GetIntField(env, lpObject, FUNCDESCFc.callconv);
+       lpStruct->cParams = (*env)->GetShortField(env, lpObject, FUNCDESCFc.cParams);
+       lpStruct->cParamsOpt = (*env)->GetShortField(env, lpObject, FUNCDESCFc.cParamsOpt);
+       lpStruct->oVft = (*env)->GetShortField(env, lpObject, FUNCDESCFc.oVft);
+       lpStruct->cScodes = (*env)->GetShortField(env, lpObject, FUNCDESCFc.cScodes);
+       lpStruct->elemdescFunc.tdesc.lptdesc = (struct FARSTRUCT tagTYPEDESC FAR* )(*env)->GetLongField(env, lpObject, FUNCDESCFc.elemdescFunc_tdesc_union);
+       lpStruct->elemdescFunc.tdesc.vt = (*env)->GetShortField(env, lpObject, FUNCDESCFc.elemdescFunc_tdesc_vt);
+       lpStruct->elemdescFunc.paramdesc.pparamdescex = (LPPARAMDESCEX)(*env)->GetLongField(env, lpObject, FUNCDESCFc.elemdescFunc_paramdesc_pparamdescex);
+       lpStruct->elemdescFunc.paramdesc.wParamFlags = (*env)->GetShortField(env, lpObject, FUNCDESCFc.elemdescFunc_paramdesc_wParamFlags);
+       lpStruct->wFuncFlags = (*env)->GetShortField(env, lpObject, FUNCDESCFc.wFuncFlags);
+       return lpStruct;
+}
+
+void setFUNCDESCFields(JNIEnv *env, jobject lpObject, FUNCDESC *lpStruct)
+{
+       if (!FUNCDESCFc.cached) cacheFUNCDESCFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, FUNCDESCFc.memid, (jint)lpStruct->memid);
+       (*env)->SetLongField(env, lpObject, FUNCDESCFc.lprgscode, (jlong)lpStruct->lprgscode);
+       (*env)->SetLongField(env, lpObject, FUNCDESCFc.lprgelemdescParam, (jlong)lpStruct->lprgelemdescParam);
+       (*env)->SetIntField(env, lpObject, FUNCDESCFc.funckind, (jint)lpStruct->funckind);
+       (*env)->SetIntField(env, lpObject, FUNCDESCFc.invkind, (jint)lpStruct->invkind);
+       (*env)->SetIntField(env, lpObject, FUNCDESCFc.callconv, (jint)lpStruct->callconv);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.cParams, (jshort)lpStruct->cParams);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.cParamsOpt, (jshort)lpStruct->cParamsOpt);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.oVft, (jshort)lpStruct->oVft);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.cScodes, (jshort)lpStruct->cScodes);
+       (*env)->SetLongField(env, lpObject, FUNCDESCFc.elemdescFunc_tdesc_union, (jlong)lpStruct->elemdescFunc.tdesc.lptdesc);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.elemdescFunc_tdesc_vt, (jshort)lpStruct->elemdescFunc.tdesc.vt);
+       (*env)->SetLongField(env, lpObject, FUNCDESCFc.elemdescFunc_paramdesc_pparamdescex, (jlong)lpStruct->elemdescFunc.paramdesc.pparamdescex);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.elemdescFunc_paramdesc_wParamFlags, (jshort)lpStruct->elemdescFunc.paramdesc.wParamFlags);
+       (*env)->SetShortField(env, lpObject, FUNCDESCFc.wFuncFlags, (jshort)lpStruct->wFuncFlags);
+}
+#endif
+
+#ifndef NO_GUID
+typedef struct GUID_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID Data1, Data2, Data3, Data4;
+} GUID_FID_CACHE;
+
+GUID_FID_CACHE GUIDFc;
+
+void cacheGUIDFields(JNIEnv *env, jobject lpObject)
+{
+       if (GUIDFc.cached) return;
+       GUIDFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       GUIDFc.Data1 = (*env)->GetFieldID(env, GUIDFc.clazz, "Data1", "I");
+       GUIDFc.Data2 = (*env)->GetFieldID(env, GUIDFc.clazz, "Data2", "S");
+       GUIDFc.Data3 = (*env)->GetFieldID(env, GUIDFc.clazz, "Data3", "S");
+       GUIDFc.Data4 = (*env)->GetFieldID(env, GUIDFc.clazz, "Data4", "[B");
+       GUIDFc.cached = 1;
+}
+
+GUID *getGUIDFields(JNIEnv *env, jobject lpObject, GUID *lpStruct)
+{
+       if (!GUIDFc.cached) cacheGUIDFields(env, lpObject);
+       lpStruct->Data1 = (*env)->GetIntField(env, lpObject, GUIDFc.Data1);
+       lpStruct->Data2 = (*env)->GetShortField(env, lpObject, GUIDFc.Data2);
+       lpStruct->Data3 = (*env)->GetShortField(env, lpObject, GUIDFc.Data3);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, GUIDFc.Data4);
+       (*env)->GetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->Data4), (jbyte *)lpStruct->Data4);
+       }
+       return lpStruct;
+}
+
+void setGUIDFields(JNIEnv *env, jobject lpObject, GUID *lpStruct)
+{
+       if (!GUIDFc.cached) cacheGUIDFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, GUIDFc.Data1, (jint)lpStruct->Data1);
+       (*env)->SetShortField(env, lpObject, GUIDFc.Data2, (jshort)lpStruct->Data2);
+       (*env)->SetShortField(env, lpObject, GUIDFc.Data3, (jshort)lpStruct->Data3);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, GUIDFc.Data4);
+       (*env)->SetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->Data4), (jbyte *)lpStruct->Data4);
+       }
+}
+#endif
+
+#ifndef NO_LICINFO
+typedef struct LICINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbLicInfo, fRuntimeKeyAvail, fLicVerified;
+} LICINFO_FID_CACHE;
+
+LICINFO_FID_CACHE LICINFOFc;
+
+void cacheLICINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (LICINFOFc.cached) return;
+       LICINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LICINFOFc.cbLicInfo = (*env)->GetFieldID(env, LICINFOFc.clazz, "cbLicInfo", "I");
+       LICINFOFc.fRuntimeKeyAvail = (*env)->GetFieldID(env, LICINFOFc.clazz, "fRuntimeKeyAvail", "Z");
+       LICINFOFc.fLicVerified = (*env)->GetFieldID(env, LICINFOFc.clazz, "fLicVerified", "Z");
+       LICINFOFc.cached = 1;
+}
+
+LICINFO *getLICINFOFields(JNIEnv *env, jobject lpObject, LICINFO *lpStruct)
+{
+       if (!LICINFOFc.cached) cacheLICINFOFields(env, lpObject);
+       lpStruct->cbLicInfo = (*env)->GetIntField(env, lpObject, LICINFOFc.cbLicInfo);
+       lpStruct->fRuntimeKeyAvail = (*env)->GetBooleanField(env, lpObject, LICINFOFc.fRuntimeKeyAvail);
+       lpStruct->fLicVerified = (*env)->GetBooleanField(env, lpObject, LICINFOFc.fLicVerified);
+       return lpStruct;
+}
+
+void setLICINFOFields(JNIEnv *env, jobject lpObject, LICINFO *lpStruct)
+{
+       if (!LICINFOFc.cached) cacheLICINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LICINFOFc.cbLicInfo, (jint)lpStruct->cbLicInfo);
+       (*env)->SetBooleanField(env, lpObject, LICINFOFc.fRuntimeKeyAvail, (jboolean)lpStruct->fRuntimeKeyAvail);
+       (*env)->SetBooleanField(env, lpObject, LICINFOFc.fLicVerified, (jboolean)lpStruct->fLicVerified);
+}
+#endif
+
+#ifndef NO_OLECMD
+typedef struct OLECMD_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cmdID, cmdf;
+} OLECMD_FID_CACHE;
+
+OLECMD_FID_CACHE OLECMDFc;
+
+void cacheOLECMDFields(JNIEnv *env, jobject lpObject)
+{
+       if (OLECMDFc.cached) return;
+       OLECMDFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       OLECMDFc.cmdID = (*env)->GetFieldID(env, OLECMDFc.clazz, "cmdID", "I");
+       OLECMDFc.cmdf = (*env)->GetFieldID(env, OLECMDFc.clazz, "cmdf", "I");
+       OLECMDFc.cached = 1;
+}
+
+OLECMD *getOLECMDFields(JNIEnv *env, jobject lpObject, OLECMD *lpStruct)
+{
+       if (!OLECMDFc.cached) cacheOLECMDFields(env, lpObject);
+       lpStruct->cmdID = (*env)->GetIntField(env, lpObject, OLECMDFc.cmdID);
+       lpStruct->cmdf = (*env)->GetIntField(env, lpObject, OLECMDFc.cmdf);
+       return lpStruct;
+}
+
+void setOLECMDFields(JNIEnv *env, jobject lpObject, OLECMD *lpStruct)
+{
+       if (!OLECMDFc.cached) cacheOLECMDFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, OLECMDFc.cmdID, (jint)lpStruct->cmdID);
+       (*env)->SetIntField(env, lpObject, OLECMDFc.cmdf, (jint)lpStruct->cmdf);
+}
+#endif
+
+#ifndef NO_OLEINPLACEFRAMEINFO
+typedef struct OLEINPLACEFRAMEINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cb, fMDIApp, hwndFrame, haccel, cAccelEntries;
+} OLEINPLACEFRAMEINFO_FID_CACHE;
+
+OLEINPLACEFRAMEINFO_FID_CACHE OLEINPLACEFRAMEINFOFc;
+
+void cacheOLEINPLACEFRAMEINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (OLEINPLACEFRAMEINFOFc.cached) return;
+       OLEINPLACEFRAMEINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       OLEINPLACEFRAMEINFOFc.cb = (*env)->GetFieldID(env, OLEINPLACEFRAMEINFOFc.clazz, "cb", "I");
+       OLEINPLACEFRAMEINFOFc.fMDIApp = (*env)->GetFieldID(env, OLEINPLACEFRAMEINFOFc.clazz, "fMDIApp", "I");
+       OLEINPLACEFRAMEINFOFc.hwndFrame = (*env)->GetFieldID(env, OLEINPLACEFRAMEINFOFc.clazz, "hwndFrame", "J");
+       OLEINPLACEFRAMEINFOFc.haccel = (*env)->GetFieldID(env, OLEINPLACEFRAMEINFOFc.clazz, "haccel", "J");
+       OLEINPLACEFRAMEINFOFc.cAccelEntries = (*env)->GetFieldID(env, OLEINPLACEFRAMEINFOFc.clazz, "cAccelEntries", "I");
+       OLEINPLACEFRAMEINFOFc.cached = 1;
+}
+
+OLEINPLACEFRAMEINFO *getOLEINPLACEFRAMEINFOFields(JNIEnv *env, jobject lpObject, OLEINPLACEFRAMEINFO *lpStruct)
+{
+       if (!OLEINPLACEFRAMEINFOFc.cached) cacheOLEINPLACEFRAMEINFOFields(env, lpObject);
+       lpStruct->cb = (*env)->GetIntField(env, lpObject, OLEINPLACEFRAMEINFOFc.cb);
+       lpStruct->fMDIApp = (*env)->GetIntField(env, lpObject, OLEINPLACEFRAMEINFOFc.fMDIApp);
+       lpStruct->hwndFrame = (HWND)(*env)->GetLongField(env, lpObject, OLEINPLACEFRAMEINFOFc.hwndFrame);
+       lpStruct->haccel = (HACCEL)(*env)->GetLongField(env, lpObject, OLEINPLACEFRAMEINFOFc.haccel);
+       lpStruct->cAccelEntries = (*env)->GetIntField(env, lpObject, OLEINPLACEFRAMEINFOFc.cAccelEntries);
+       return lpStruct;
+}
+
+void setOLEINPLACEFRAMEINFOFields(JNIEnv *env, jobject lpObject, OLEINPLACEFRAMEINFO *lpStruct)
+{
+       if (!OLEINPLACEFRAMEINFOFc.cached) cacheOLEINPLACEFRAMEINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, OLEINPLACEFRAMEINFOFc.cb, (jint)lpStruct->cb);
+       (*env)->SetIntField(env, lpObject, OLEINPLACEFRAMEINFOFc.fMDIApp, (jint)lpStruct->fMDIApp);
+       (*env)->SetLongField(env, lpObject, OLEINPLACEFRAMEINFOFc.hwndFrame, (jlong)lpStruct->hwndFrame);
+       (*env)->SetLongField(env, lpObject, OLEINPLACEFRAMEINFOFc.haccel, (jlong)lpStruct->haccel);
+       (*env)->SetIntField(env, lpObject, OLEINPLACEFRAMEINFOFc.cAccelEntries, (jint)lpStruct->cAccelEntries);
+}
+#endif
+
+#ifndef NO_STGMEDIUM
+typedef struct STGMEDIUM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID tymed, unionField, pUnkForRelease;
+} STGMEDIUM_FID_CACHE;
+
+STGMEDIUM_FID_CACHE STGMEDIUMFc;
+
+void cacheSTGMEDIUMFields(JNIEnv *env, jobject lpObject)
+{
+       if (STGMEDIUMFc.cached) return;
+       STGMEDIUMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       STGMEDIUMFc.tymed = (*env)->GetFieldID(env, STGMEDIUMFc.clazz, "tymed", "I");
+       STGMEDIUMFc.unionField = (*env)->GetFieldID(env, STGMEDIUMFc.clazz, "unionField", "J");
+       STGMEDIUMFc.pUnkForRelease = (*env)->GetFieldID(env, STGMEDIUMFc.clazz, "pUnkForRelease", "J");
+       STGMEDIUMFc.cached = 1;
+}
+
+STGMEDIUM *getSTGMEDIUMFields(JNIEnv *env, jobject lpObject, STGMEDIUM *lpStruct)
+{
+       if (!STGMEDIUMFc.cached) cacheSTGMEDIUMFields(env, lpObject);
+       lpStruct->tymed = (*env)->GetIntField(env, lpObject, STGMEDIUMFc.tymed);
+       lpStruct->hGlobal = (HGLOBAL)(*env)->GetLongField(env, lpObject, STGMEDIUMFc.unionField);
+       lpStruct->pUnkForRelease = (IUnknown *)(*env)->GetLongField(env, lpObject, STGMEDIUMFc.pUnkForRelease);
+       return lpStruct;
+}
+
+void setSTGMEDIUMFields(JNIEnv *env, jobject lpObject, STGMEDIUM *lpStruct)
+{
+       if (!STGMEDIUMFc.cached) cacheSTGMEDIUMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, STGMEDIUMFc.tymed, (jint)lpStruct->tymed);
+       (*env)->SetLongField(env, lpObject, STGMEDIUMFc.unionField, (jlong)lpStruct->hGlobal);
+       (*env)->SetLongField(env, lpObject, STGMEDIUMFc.pUnkForRelease, (jlong)lpStruct->pUnkForRelease);
+}
+#endif
+
+#ifndef NO_TYPEATTR
+typedef struct TYPEATTR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID guid_Data1, guid_Data2, guid_Data3, guid_Data4, lcid, dwReserved, memidConstructor, memidDestructor, lpstrSchema, cbSizeInstance, typekind, cFuncs, cVars, cImplTypes, cbSizeVft, cbAlignment, wTypeFlags, wMajorVerNum, wMinorVerNum, tdescAlias_unionField, tdescAlias_vt, idldescType_dwReserved, idldescType_wIDLFlags;
+} TYPEATTR_FID_CACHE;
+
+TYPEATTR_FID_CACHE TYPEATTRFc;
+
+void cacheTYPEATTRFields(JNIEnv *env, jobject lpObject)
+{
+       if (TYPEATTRFc.cached) return;
+       TYPEATTRFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TYPEATTRFc.guid_Data1 = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "guid_Data1", "I");
+       TYPEATTRFc.guid_Data2 = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "guid_Data2", "S");
+       TYPEATTRFc.guid_Data3 = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "guid_Data3", "S");
+       TYPEATTRFc.guid_Data4 = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "guid_Data4", "[B");
+       TYPEATTRFc.lcid = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "lcid", "I");
+       TYPEATTRFc.dwReserved = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "dwReserved", "I");
+       TYPEATTRFc.memidConstructor = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "memidConstructor", "I");
+       TYPEATTRFc.memidDestructor = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "memidDestructor", "I");
+       TYPEATTRFc.lpstrSchema = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "lpstrSchema", "J");
+       TYPEATTRFc.cbSizeInstance = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "cbSizeInstance", "I");
+       TYPEATTRFc.typekind = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "typekind", "I");
+       TYPEATTRFc.cFuncs = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "cFuncs", "S");
+       TYPEATTRFc.cVars = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "cVars", "S");
+       TYPEATTRFc.cImplTypes = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "cImplTypes", "S");
+       TYPEATTRFc.cbSizeVft = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "cbSizeVft", "S");
+       TYPEATTRFc.cbAlignment = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "cbAlignment", "S");
+       TYPEATTRFc.wTypeFlags = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "wTypeFlags", "S");
+       TYPEATTRFc.wMajorVerNum = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "wMajorVerNum", "S");
+       TYPEATTRFc.wMinorVerNum = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "wMinorVerNum", "S");
+       TYPEATTRFc.tdescAlias_unionField = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "tdescAlias_unionField", "J");
+       TYPEATTRFc.tdescAlias_vt = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "tdescAlias_vt", "S");
+       TYPEATTRFc.idldescType_dwReserved = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "idldescType_dwReserved", "I");
+       TYPEATTRFc.idldescType_wIDLFlags = (*env)->GetFieldID(env, TYPEATTRFc.clazz, "idldescType_wIDLFlags", "S");
+       TYPEATTRFc.cached = 1;
+}
+
+TYPEATTR *getTYPEATTRFields(JNIEnv *env, jobject lpObject, TYPEATTR *lpStruct)
+{
+       if (!TYPEATTRFc.cached) cacheTYPEATTRFields(env, lpObject);
+       lpStruct->guid.Data1 = (*env)->GetIntField(env, lpObject, TYPEATTRFc.guid_Data1);
+       lpStruct->guid.Data2 = (*env)->GetShortField(env, lpObject, TYPEATTRFc.guid_Data2);
+       lpStruct->guid.Data3 = (*env)->GetShortField(env, lpObject, TYPEATTRFc.guid_Data3);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, TYPEATTRFc.guid_Data4);
+       (*env)->GetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->guid.Data4), (jbyte *)lpStruct->guid.Data4);
+       }
+       lpStruct->lcid = (*env)->GetIntField(env, lpObject, TYPEATTRFc.lcid);
+       lpStruct->dwReserved = (*env)->GetIntField(env, lpObject, TYPEATTRFc.dwReserved);
+       lpStruct->memidConstructor = (*env)->GetIntField(env, lpObject, TYPEATTRFc.memidConstructor);
+       lpStruct->memidDestructor = (*env)->GetIntField(env, lpObject, TYPEATTRFc.memidDestructor);
+       lpStruct->lpstrSchema = (OLECHAR FAR *)(*env)->GetLongField(env, lpObject, TYPEATTRFc.lpstrSchema);
+       lpStruct->cbSizeInstance = (*env)->GetIntField(env, lpObject, TYPEATTRFc.cbSizeInstance);
+       lpStruct->typekind = (*env)->GetIntField(env, lpObject, TYPEATTRFc.typekind);
+       lpStruct->cFuncs = (*env)->GetShortField(env, lpObject, TYPEATTRFc.cFuncs);
+       lpStruct->cVars = (*env)->GetShortField(env, lpObject, TYPEATTRFc.cVars);
+       lpStruct->cImplTypes = (*env)->GetShortField(env, lpObject, TYPEATTRFc.cImplTypes);
+       lpStruct->cbSizeVft = (*env)->GetShortField(env, lpObject, TYPEATTRFc.cbSizeVft);
+       lpStruct->cbAlignment = (*env)->GetShortField(env, lpObject, TYPEATTRFc.cbAlignment);
+       lpStruct->wTypeFlags = (*env)->GetShortField(env, lpObject, TYPEATTRFc.wTypeFlags);
+       lpStruct->wMajorVerNum = (*env)->GetShortField(env, lpObject, TYPEATTRFc.wMajorVerNum);
+       lpStruct->wMinorVerNum = (*env)->GetShortField(env, lpObject, TYPEATTRFc.wMinorVerNum);
+       lpStruct->tdescAlias.lptdesc = (struct FARSTRUCT tagTYPEDESC FAR *)(*env)->GetLongField(env, lpObject, TYPEATTRFc.tdescAlias_unionField);
+       lpStruct->tdescAlias.vt = (*env)->GetShortField(env, lpObject, TYPEATTRFc.tdescAlias_vt);
+       lpStruct->idldescType.dwReserved = (*env)->GetIntField(env, lpObject, TYPEATTRFc.idldescType_dwReserved);
+       lpStruct->idldescType.wIDLFlags = (*env)->GetShortField(env, lpObject, TYPEATTRFc.idldescType_wIDLFlags);
+       return lpStruct;
+}
+
+void setTYPEATTRFields(JNIEnv *env, jobject lpObject, TYPEATTR *lpStruct)
+{
+       if (!TYPEATTRFc.cached) cacheTYPEATTRFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.guid_Data1, (jint)lpStruct->guid.Data1);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.guid_Data2, (jshort)lpStruct->guid.Data2);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.guid_Data3, (jshort)lpStruct->guid.Data3);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, TYPEATTRFc.guid_Data4);
+       (*env)->SetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->guid.Data4), (jbyte *)lpStruct->guid.Data4);
+       }
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.lcid, (jint)lpStruct->lcid);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.dwReserved, (jint)lpStruct->dwReserved);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.memidConstructor, (jint)lpStruct->memidConstructor);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.memidDestructor, (jint)lpStruct->memidDestructor);
+       (*env)->SetLongField(env, lpObject, TYPEATTRFc.lpstrSchema, (jlong)lpStruct->lpstrSchema);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.cbSizeInstance, (jint)lpStruct->cbSizeInstance);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.typekind, (jint)lpStruct->typekind);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.cFuncs, (jshort)lpStruct->cFuncs);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.cVars, (jshort)lpStruct->cVars);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.cImplTypes, (jshort)lpStruct->cImplTypes);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.cbSizeVft, (jshort)lpStruct->cbSizeVft);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.cbAlignment, (jshort)lpStruct->cbAlignment);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.wTypeFlags, (jshort)lpStruct->wTypeFlags);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.wMajorVerNum, (jshort)lpStruct->wMajorVerNum);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.wMinorVerNum, (jshort)lpStruct->wMinorVerNum);
+       (*env)->SetLongField(env, lpObject, TYPEATTRFc.tdescAlias_unionField, (jlong)lpStruct->tdescAlias.lptdesc);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.tdescAlias_vt, (jshort)lpStruct->tdescAlias.vt);
+       (*env)->SetIntField(env, lpObject, TYPEATTRFc.idldescType_dwReserved, (jint)lpStruct->idldescType.dwReserved);
+       (*env)->SetShortField(env, lpObject, TYPEATTRFc.idldescType_wIDLFlags, (jshort)lpStruct->idldescType.wIDLFlags);
+}
+#endif
+
+#ifndef NO_VARDESC
+typedef struct VARDESC_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID memid, lpstrSchema, oInst, elemdescVar_tdesc_union, elemdescVar_tdesc_vt, elemdescVar_paramdesc_pparamdescex, elemdescVar_paramdesc_wParamFlags, wVarFlags, varkind;
+} VARDESC_FID_CACHE;
+
+VARDESC_FID_CACHE VARDESCFc;
+
+void cacheVARDESCFields(JNIEnv *env, jobject lpObject)
+{
+       if (VARDESCFc.cached) return;
+       VARDESCFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       VARDESCFc.memid = (*env)->GetFieldID(env, VARDESCFc.clazz, "memid", "I");
+       VARDESCFc.lpstrSchema = (*env)->GetFieldID(env, VARDESCFc.clazz, "lpstrSchema", "J");
+       VARDESCFc.oInst = (*env)->GetFieldID(env, VARDESCFc.clazz, "oInst", "I");
+       VARDESCFc.elemdescVar_tdesc_union = (*env)->GetFieldID(env, VARDESCFc.clazz, "elemdescVar_tdesc_union", "J");
+       VARDESCFc.elemdescVar_tdesc_vt = (*env)->GetFieldID(env, VARDESCFc.clazz, "elemdescVar_tdesc_vt", "S");
+       VARDESCFc.elemdescVar_paramdesc_pparamdescex = (*env)->GetFieldID(env, VARDESCFc.clazz, "elemdescVar_paramdesc_pparamdescex", "J");
+       VARDESCFc.elemdescVar_paramdesc_wParamFlags = (*env)->GetFieldID(env, VARDESCFc.clazz, "elemdescVar_paramdesc_wParamFlags", "S");
+       VARDESCFc.wVarFlags = (*env)->GetFieldID(env, VARDESCFc.clazz, "wVarFlags", "S");
+       VARDESCFc.varkind = (*env)->GetFieldID(env, VARDESCFc.clazz, "varkind", "I");
+       VARDESCFc.cached = 1;
+}
+
+VARDESC *getVARDESCFields(JNIEnv *env, jobject lpObject, VARDESC *lpStruct)
+{
+       if (!VARDESCFc.cached) cacheVARDESCFields(env, lpObject);
+       lpStruct->memid = (*env)->GetIntField(env, lpObject, VARDESCFc.memid);
+       lpStruct->lpstrSchema = (OLECHAR FAR *)(*env)->GetLongField(env, lpObject, VARDESCFc.lpstrSchema);
+       lpStruct->oInst = (*env)->GetIntField(env, lpObject, VARDESCFc.oInst);
+       lpStruct->elemdescVar.tdesc.lptdesc = (struct FARSTRUCT tagTYPEDESC FAR *)(*env)->GetLongField(env, lpObject, VARDESCFc.elemdescVar_tdesc_union);
+       lpStruct->elemdescVar.tdesc.vt = (*env)->GetShortField(env, lpObject, VARDESCFc.elemdescVar_tdesc_vt);
+       lpStruct->elemdescVar.paramdesc.pparamdescex = (LPPARAMDESCEX)(*env)->GetLongField(env, lpObject, VARDESCFc.elemdescVar_paramdesc_pparamdescex);
+       lpStruct->elemdescVar.paramdesc.wParamFlags = (*env)->GetShortField(env, lpObject, VARDESCFc.elemdescVar_paramdesc_wParamFlags);
+       lpStruct->wVarFlags = (*env)->GetShortField(env, lpObject, VARDESCFc.wVarFlags);
+       lpStruct->varkind = (*env)->GetIntField(env, lpObject, VARDESCFc.varkind);
+       return lpStruct;
+}
+
+void setVARDESCFields(JNIEnv *env, jobject lpObject, VARDESC *lpStruct)
+{
+       if (!VARDESCFc.cached) cacheVARDESCFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, VARDESCFc.memid, (jint)lpStruct->memid);
+       (*env)->SetLongField(env, lpObject, VARDESCFc.lpstrSchema, (jlong)lpStruct->lpstrSchema);
+       (*env)->SetIntField(env, lpObject, VARDESCFc.oInst, (jint)lpStruct->oInst);
+       (*env)->SetLongField(env, lpObject, VARDESCFc.elemdescVar_tdesc_union, (jlong)lpStruct->elemdescVar.tdesc.lptdesc);
+       (*env)->SetShortField(env, lpObject, VARDESCFc.elemdescVar_tdesc_vt, (jshort)lpStruct->elemdescVar.tdesc.vt);
+       (*env)->SetLongField(env, lpObject, VARDESCFc.elemdescVar_paramdesc_pparamdescex, (jlong)lpStruct->elemdescVar.paramdesc.pparamdescex);
+       (*env)->SetShortField(env, lpObject, VARDESCFc.elemdescVar_paramdesc_wParamFlags, (jshort)lpStruct->elemdescVar.paramdesc.wParamFlags);
+       (*env)->SetShortField(env, lpObject, VARDESCFc.wVarFlags, (jshort)lpStruct->wVarFlags);
+       (*env)->SetIntField(env, lpObject, VARDESCFc.varkind, (jint)lpStruct->varkind);
+}
+#endif
+
+#ifndef NO_VARIANT
+typedef struct VARIANT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID vt, wReserved1, wReserved2, wReserved3, lVal;
+} VARIANT_FID_CACHE;
+
+VARIANT_FID_CACHE VARIANTFc;
+
+void cacheVARIANTFields(JNIEnv *env, jobject lpObject)
+{
+       if (VARIANTFc.cached) return;
+       VARIANTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       VARIANTFc.vt = (*env)->GetFieldID(env, VARIANTFc.clazz, "vt", "S");
+       VARIANTFc.wReserved1 = (*env)->GetFieldID(env, VARIANTFc.clazz, "wReserved1", "S");
+       VARIANTFc.wReserved2 = (*env)->GetFieldID(env, VARIANTFc.clazz, "wReserved2", "S");
+       VARIANTFc.wReserved3 = (*env)->GetFieldID(env, VARIANTFc.clazz, "wReserved3", "S");
+       VARIANTFc.lVal = (*env)->GetFieldID(env, VARIANTFc.clazz, "lVal", "I");
+       VARIANTFc.cached = 1;
+}
+
+VARIANT *getVARIANTFields(JNIEnv *env, jobject lpObject, VARIANT *lpStruct)
+{
+       if (!VARIANTFc.cached) cacheVARIANTFields(env, lpObject);
+       lpStruct->vt = (*env)->GetShortField(env, lpObject, VARIANTFc.vt);
+       lpStruct->wReserved1 = (*env)->GetShortField(env, lpObject, VARIANTFc.wReserved1);
+       lpStruct->wReserved2 = (*env)->GetShortField(env, lpObject, VARIANTFc.wReserved2);
+       lpStruct->wReserved3 = (*env)->GetShortField(env, lpObject, VARIANTFc.wReserved3);
+       lpStruct->lVal = (*env)->GetIntField(env, lpObject, VARIANTFc.lVal);
+       return lpStruct;
+}
+
+void setVARIANTFields(JNIEnv *env, jobject lpObject, VARIANT *lpStruct)
+{
+       if (!VARIANTFc.cached) cacheVARIANTFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, VARIANTFc.vt, (jshort)lpStruct->vt);
+       (*env)->SetShortField(env, lpObject, VARIANTFc.wReserved1, (jshort)lpStruct->wReserved1);
+       (*env)->SetShortField(env, lpObject, VARIANTFc.wReserved2, (jshort)lpStruct->wReserved2);
+       (*env)->SetShortField(env, lpObject, VARIANTFc.wReserved3, (jshort)lpStruct->wReserved3);
+       (*env)->SetIntField(env, lpObject, VARIANTFc.lVal, (jint)lpStruct->lVal);
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_structs.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/com_structs.h
new file mode 100644 (file)
index 0000000..0a84aa3
--- /dev/null
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "com.h"
+
+#ifndef NO_CAUUID
+void cacheCAUUIDFields(JNIEnv *env, jobject lpObject);
+CAUUID *getCAUUIDFields(JNIEnv *env, jobject lpObject, CAUUID *lpStruct);
+void setCAUUIDFields(JNIEnv *env, jobject lpObject, CAUUID *lpStruct);
+#define CAUUID_sizeof() sizeof(CAUUID)
+#else
+#define cacheCAUUIDFields(a,b)
+#define getCAUUIDFields(a,b,c) NULL
+#define setCAUUIDFields(a,b,c)
+#define CAUUID_sizeof() 0
+#endif
+
+#ifndef NO_CONTROLINFO
+void cacheCONTROLINFOFields(JNIEnv *env, jobject lpObject);
+CONTROLINFO *getCONTROLINFOFields(JNIEnv *env, jobject lpObject, CONTROLINFO *lpStruct);
+void setCONTROLINFOFields(JNIEnv *env, jobject lpObject, CONTROLINFO *lpStruct);
+#define CONTROLINFO_sizeof() sizeof(CONTROLINFO)
+#else
+#define cacheCONTROLINFOFields(a,b)
+#define getCONTROLINFOFields(a,b,c) NULL
+#define setCONTROLINFOFields(a,b,c)
+#define CONTROLINFO_sizeof() 0
+#endif
+
+#ifndef NO_DISPPARAMS
+void cacheDISPPARAMSFields(JNIEnv *env, jobject lpObject);
+DISPPARAMS *getDISPPARAMSFields(JNIEnv *env, jobject lpObject, DISPPARAMS *lpStruct);
+void setDISPPARAMSFields(JNIEnv *env, jobject lpObject, DISPPARAMS *lpStruct);
+#define DISPPARAMS_sizeof() sizeof(DISPPARAMS)
+#else
+#define cacheDISPPARAMSFields(a,b)
+#define getDISPPARAMSFields(a,b,c) NULL
+#define setDISPPARAMSFields(a,b,c)
+#define DISPPARAMS_sizeof() 0
+#endif
+
+#ifndef NO_EXCEPINFO
+void cacheEXCEPINFOFields(JNIEnv *env, jobject lpObject);
+EXCEPINFO *getEXCEPINFOFields(JNIEnv *env, jobject lpObject, EXCEPINFO *lpStruct);
+void setEXCEPINFOFields(JNIEnv *env, jobject lpObject, EXCEPINFO *lpStruct);
+#define EXCEPINFO_sizeof() sizeof(EXCEPINFO)
+#else
+#define cacheEXCEPINFOFields(a,b)
+#define getEXCEPINFOFields(a,b,c) NULL
+#define setEXCEPINFOFields(a,b,c)
+#define EXCEPINFO_sizeof() 0
+#endif
+
+#ifndef NO_FORMATETC
+void cacheFORMATETCFields(JNIEnv *env, jobject lpObject);
+FORMATETC *getFORMATETCFields(JNIEnv *env, jobject lpObject, FORMATETC *lpStruct);
+void setFORMATETCFields(JNIEnv *env, jobject lpObject, FORMATETC *lpStruct);
+#define FORMATETC_sizeof() sizeof(FORMATETC)
+#else
+#define cacheFORMATETCFields(a,b)
+#define getFORMATETCFields(a,b,c) NULL
+#define setFORMATETCFields(a,b,c)
+#define FORMATETC_sizeof() 0
+#endif
+
+#ifndef NO_FUNCDESC
+void cacheFUNCDESCFields(JNIEnv *env, jobject lpObject);
+FUNCDESC *getFUNCDESCFields(JNIEnv *env, jobject lpObject, FUNCDESC *lpStruct);
+void setFUNCDESCFields(JNIEnv *env, jobject lpObject, FUNCDESC *lpStruct);
+#define FUNCDESC_sizeof() sizeof(FUNCDESC)
+#else
+#define cacheFUNCDESCFields(a,b)
+#define getFUNCDESCFields(a,b,c) NULL
+#define setFUNCDESCFields(a,b,c)
+#define FUNCDESC_sizeof() 0
+#endif
+
+#ifndef NO_GUID
+void cacheGUIDFields(JNIEnv *env, jobject lpObject);
+GUID *getGUIDFields(JNIEnv *env, jobject lpObject, GUID *lpStruct);
+void setGUIDFields(JNIEnv *env, jobject lpObject, GUID *lpStruct);
+#define GUID_sizeof() sizeof(GUID)
+#else
+#define cacheGUIDFields(a,b)
+#define getGUIDFields(a,b,c) NULL
+#define setGUIDFields(a,b,c)
+#define GUID_sizeof() 0
+#endif
+
+#ifndef NO_LICINFO
+void cacheLICINFOFields(JNIEnv *env, jobject lpObject);
+LICINFO *getLICINFOFields(JNIEnv *env, jobject lpObject, LICINFO *lpStruct);
+void setLICINFOFields(JNIEnv *env, jobject lpObject, LICINFO *lpStruct);
+#define LICINFO_sizeof() sizeof(LICINFO)
+#else
+#define cacheLICINFOFields(a,b)
+#define getLICINFOFields(a,b,c) NULL
+#define setLICINFOFields(a,b,c)
+#define LICINFO_sizeof() 0
+#endif
+
+#ifndef NO_OLECMD
+void cacheOLECMDFields(JNIEnv *env, jobject lpObject);
+OLECMD *getOLECMDFields(JNIEnv *env, jobject lpObject, OLECMD *lpStruct);
+void setOLECMDFields(JNIEnv *env, jobject lpObject, OLECMD *lpStruct);
+#define OLECMD_sizeof() sizeof(OLECMD)
+#else
+#define cacheOLECMDFields(a,b)
+#define getOLECMDFields(a,b,c) NULL
+#define setOLECMDFields(a,b,c)
+#define OLECMD_sizeof() 0
+#endif
+
+#ifndef NO_OLEINPLACEFRAMEINFO
+void cacheOLEINPLACEFRAMEINFOFields(JNIEnv *env, jobject lpObject);
+OLEINPLACEFRAMEINFO *getOLEINPLACEFRAMEINFOFields(JNIEnv *env, jobject lpObject, OLEINPLACEFRAMEINFO *lpStruct);
+void setOLEINPLACEFRAMEINFOFields(JNIEnv *env, jobject lpObject, OLEINPLACEFRAMEINFO *lpStruct);
+#define OLEINPLACEFRAMEINFO_sizeof() sizeof(OLEINPLACEFRAMEINFO)
+#else
+#define cacheOLEINPLACEFRAMEINFOFields(a,b)
+#define getOLEINPLACEFRAMEINFOFields(a,b,c) NULL
+#define setOLEINPLACEFRAMEINFOFields(a,b,c)
+#define OLEINPLACEFRAMEINFO_sizeof() 0
+#endif
+
+#ifndef NO_STGMEDIUM
+void cacheSTGMEDIUMFields(JNIEnv *env, jobject lpObject);
+STGMEDIUM *getSTGMEDIUMFields(JNIEnv *env, jobject lpObject, STGMEDIUM *lpStruct);
+void setSTGMEDIUMFields(JNIEnv *env, jobject lpObject, STGMEDIUM *lpStruct);
+#define STGMEDIUM_sizeof() sizeof(STGMEDIUM)
+#else
+#define cacheSTGMEDIUMFields(a,b)
+#define getSTGMEDIUMFields(a,b,c) NULL
+#define setSTGMEDIUMFields(a,b,c)
+#define STGMEDIUM_sizeof() 0
+#endif
+
+#ifndef NO_TYPEATTR
+void cacheTYPEATTRFields(JNIEnv *env, jobject lpObject);
+TYPEATTR *getTYPEATTRFields(JNIEnv *env, jobject lpObject, TYPEATTR *lpStruct);
+void setTYPEATTRFields(JNIEnv *env, jobject lpObject, TYPEATTR *lpStruct);
+#define TYPEATTR_sizeof() sizeof(TYPEATTR)
+#else
+#define cacheTYPEATTRFields(a,b)
+#define getTYPEATTRFields(a,b,c) NULL
+#define setTYPEATTRFields(a,b,c)
+#define TYPEATTR_sizeof() 0
+#endif
+
+#ifndef NO_VARDESC
+void cacheVARDESCFields(JNIEnv *env, jobject lpObject);
+VARDESC *getVARDESCFields(JNIEnv *env, jobject lpObject, VARDESC *lpStruct);
+void setVARDESCFields(JNIEnv *env, jobject lpObject, VARDESC *lpStruct);
+#define VARDESC_sizeof() sizeof(VARDESC)
+#else
+#define cacheVARDESCFields(a,b)
+#define getVARDESCFields(a,b,c) NULL
+#define setVARDESCFields(a,b,c)
+#define VARDESC_sizeof() 0
+#endif
+
+#ifndef NO_VARIANT
+void cacheVARIANTFields(JNIEnv *env, jobject lpObject);
+VARIANT *getVARIANTFields(JNIEnv *env, jobject lpObject, VARIANT *lpStruct);
+void setVARIANTFields(JNIEnv *env, jobject lpObject, VARIANT *lpStruct);
+#define VARIANT_sizeof() sizeof(VARIANT)
+#else
+#define cacheVARIANTFields(a,b)
+#define getVARIANTFields(a,b,c) NULL
+#define setVARIANTFields(a,b,c)
+#define VARIANT_sizeof() 0
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/defines.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/defines.h
new file mode 100644 (file)
index 0000000..f5d9b9b
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * - Size Optimization -
+ * You can specify here which structs and SWT JNI calls
+ * you want to exclude. This can be useful to create
+ * a smaller library, based on your particular requirements.
+ * For example, if your application does not use the type ACCEL
+ * you can add:
+ * #define NO_ACCEL
+ * If your application does not require the function Arc,
+ * you can add:
+ * #define NO_Arc
+ * By default, all types and JNI calls relevant to a
+ * platform are included.
+ *
+ */
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip.cpp
new file mode 100644 (file)
index 0000000..3296efd
--- /dev/null
@@ -0,0 +1,2585 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "gdip_structs.h"
+#include "gdip_stats.h"
+
+#ifndef Gdip_NATIVE
+#define Gdip_NATIVE(func) Java_org_eclipse_swt_internal_gdip_Gdip_##func
+#endif
+
+#ifndef NO_BitmapData_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(BitmapData_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(BitmapData_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, BitmapData_1delete_FUNC);
+       delete (BitmapData *)arg0;
+       Gdip_NATIVE_EXIT(env, that, BitmapData_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_BitmapData_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(BitmapData_1new)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(BitmapData_1new)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, BitmapData_1new_FUNC);
+       rc = (jlong)new BitmapData();
+       Gdip_NATIVE_EXIT(env, that, BitmapData_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1GetHBITMAP
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1GetHBITMAP)(JNIEnv *env, jclass that, jlong arg0, jint arg1, jlongArray arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1GetHBITMAP)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlongArray arg2)
+{
+       jlong *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1GetHBITMAP_FUNC);
+       if (arg2) if ((lparg2 = env->GetLongArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((Bitmap*)arg0)->GetHBITMAP((Color)arg1, (HBITMAP*)lparg2);
+fail:
+       if (arg2 && lparg2) env->ReleaseLongArrayElements(arg2, lparg2, 0);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1GetHBITMAP_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1GetHICON
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1GetHICON)(JNIEnv *env, jclass that, jlong arg0, jlongArray arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1GetHICON)
+       (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1)
+{
+       jlong *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1GetHICON_FUNC);
+       if (arg1) if ((lparg1 = env->GetLongArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((Bitmap*)arg0)->GetHICON((HICON*)lparg1);
+fail:
+       if (arg1 && lparg1) env->ReleaseLongArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1GetHICON_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1LockBits
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1LockBits)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jlong arg4);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1LockBits)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jlong arg4)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1LockBits_FUNC);
+       rc = (jint)((Bitmap*)arg0)->LockBits((Rect*)arg1, arg2, (PixelFormat)arg3, (BitmapData*)arg4);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1LockBits_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1UnlockBits
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1UnlockBits)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Bitmap_1UnlockBits)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1UnlockBits_FUNC);
+       rc = (jint)((Bitmap*)arg0)->UnlockBits((BitmapData*)arg1);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1UnlockBits_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Bitmap_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Bitmap_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1delete_FUNC);
+       delete (Bitmap *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Bitmap_1new__IIIIJ
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new__IIIIJ)(JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3, jlong arg4);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new__IIIIJ)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3, jlong arg4)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1new__IIIIJ_FUNC);
+       rc = (jlong)new Bitmap(arg0, arg1, arg2, (PixelFormat)arg3, (BYTE *)arg4);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1new__IIIIJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1new__J
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new__J)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new__J)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1new__J_FUNC);
+       rc = (jlong)new Bitmap((HICON)arg0);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1new__J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1new__JJ
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new__JJ)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new__JJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1new__JJ_FUNC);
+       rc = (jlong)new Bitmap((HBITMAP)arg0, (HPALETTE)arg1);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1new__JJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Bitmap_1new___3CZ
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new___3CZ)(JNIEnv *env, jclass that, jcharArray arg0, jboolean arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Bitmap_1new___3CZ)
+       (JNIEnv *env, jclass that, jcharArray arg0, jboolean arg1)
+{
+       jchar *lparg0=NULL;
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Bitmap_1new___3CZ_FUNC);
+       if (arg0) if ((lparg0 = env->GetCharArrayElements(arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)new Bitmap((WCHAR*)lparg0, arg1);
+fail:
+       if (arg0 && lparg0) env->ReleaseCharArrayElements(arg0, lparg0, 0);
+       Gdip_NATIVE_EXIT(env, that, Bitmap_1new___3CZ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Brush_1Clone
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Brush_1Clone)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Brush_1Clone)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Brush_1Clone_FUNC);
+       rc = (jlong)((Brush *)arg0)->Clone();
+       Gdip_NATIVE_EXIT(env, that, Brush_1Clone_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Brush_1GetType
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Brush_1GetType)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Brush_1GetType)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Brush_1GetType_FUNC);
+       rc = (jint)((Brush *)arg0)->GetType();
+       Gdip_NATIVE_EXIT(env, that, Brush_1GetType_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ColorPalette_1sizeof
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(ColorPalette_1sizeof)(JNIEnv *env, jclass that);
+JNIEXPORT jint JNICALL Gdip_NATIVE(ColorPalette_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, ColorPalette_1sizeof_FUNC);
+       rc = (jint)ColorPalette_sizeof();
+       Gdip_NATIVE_EXIT(env, that, ColorPalette_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FontFamily_1GetFamilyName
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(FontFamily_1GetFamilyName)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jchar arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(FontFamily_1GetFamilyName)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jchar arg2)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, FontFamily_1GetFamilyName_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((FontFamily *)arg0)->GetFamilyName((WCHAR *)lparg1, (WCHAR)arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, FontFamily_1GetFamilyName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FontFamily_1IsAvailable
+extern "C" JNIEXPORT jboolean JNICALL Gdip_NATIVE(FontFamily_1IsAvailable)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jboolean JNICALL Gdip_NATIVE(FontFamily_1IsAvailable)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       Gdip_NATIVE_ENTER(env, that, FontFamily_1IsAvailable_FUNC);
+       rc = (jboolean)((FontFamily *)arg0)->IsAvailable();
+       Gdip_NATIVE_EXIT(env, that, FontFamily_1IsAvailable_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FontFamily_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(FontFamily_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(FontFamily_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, FontFamily_1delete_FUNC);
+       delete (FontFamily *)arg0;
+       Gdip_NATIVE_EXIT(env, that, FontFamily_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_FontFamily_1new__
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(FontFamily_1new__)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(FontFamily_1new__)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, FontFamily_1new___FUNC);
+       rc = (jlong)new FontFamily();
+       Gdip_NATIVE_EXIT(env, that, FontFamily_1new___FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FontFamily_1new___3CJ
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(FontFamily_1new___3CJ)(JNIEnv *env, jclass that, jcharArray arg0, jlong arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(FontFamily_1new___3CJ)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlong arg1)
+{
+       jchar *lparg0=NULL;
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, FontFamily_1new___3CJ_FUNC);
+       if (arg0) if ((lparg0 = env->GetCharArrayElements(arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)new FontFamily((const WCHAR *)lparg0, (const FontCollection *)arg1);
+fail:
+       if (arg0 && lparg0) env->ReleaseCharArrayElements(arg0, lparg0, 0);
+       Gdip_NATIVE_EXIT(env, that, FontFamily_1new___3CJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1GetFamily
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Font_1GetFamily)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Font_1GetFamily)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1GetFamily_FUNC);
+       rc = (jint)((Font *)arg0)->GetFamily((FontFamily *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Font_1GetFamily_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1GetLogFontW
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Font_1GetLogFontW)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Font_1GetLogFontW)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1GetLogFontW_FUNC);
+       rc = (jint)((Font *)arg0)->GetLogFontW((const Graphics *)arg1, (LOGFONTW *)arg2);
+       Gdip_NATIVE_EXIT(env, that, Font_1GetLogFontW_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1GetSize
+extern "C" JNIEXPORT jfloat JNICALL Gdip_NATIVE(Font_1GetSize)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jfloat JNICALL Gdip_NATIVE(Font_1GetSize)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jfloat rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1GetSize_FUNC);
+       rc = (jfloat)((Font *)arg0)->GetSize();
+       Gdip_NATIVE_EXIT(env, that, Font_1GetSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1GetStyle
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Font_1GetStyle)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Font_1GetStyle)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1GetStyle_FUNC);
+       rc = (jint)((Font *)arg0)->GetStyle();
+       Gdip_NATIVE_EXIT(env, that, Font_1GetStyle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1IsAvailable
+extern "C" JNIEXPORT jboolean JNICALL Gdip_NATIVE(Font_1IsAvailable)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jboolean JNICALL Gdip_NATIVE(Font_1IsAvailable)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1IsAvailable_FUNC);
+       rc = (jboolean)((Font *)arg0)->IsAvailable();
+       Gdip_NATIVE_EXIT(env, that, Font_1IsAvailable_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Font_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Font_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Font_1delete_FUNC);
+       delete (Font *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Font_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Font_1new__JFII
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Font_1new__JFII)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jint arg2, jint arg3);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Font_1new__JFII)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jint arg2, jint arg3)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1new__JFII_FUNC);
+       rc = (jlong)new Font((const FontFamily *)arg0, (REAL)arg1, (INT)arg2, (Unit)arg3);
+       Gdip_NATIVE_EXIT(env, that, Font_1new__JFII_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1new__JJ
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Font_1new__JJ)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Font_1new__JJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1new__JJ_FUNC);
+       rc = (jlong)new Font((HDC)arg0, (HFONT)arg1);
+       Gdip_NATIVE_EXIT(env, that, Font_1new__JJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Font_1new___3CFIIJ
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Font_1new___3CFIIJ)(JNIEnv *env, jclass that, jcharArray arg0, jfloat arg1, jint arg2, jint arg3, jlong arg4);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Font_1new___3CFIIJ)
+       (JNIEnv *env, jclass that, jcharArray arg0, jfloat arg1, jint arg2, jint arg3, jlong arg4)
+{
+       jchar *lparg0=NULL;
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Font_1new___3CFIIJ_FUNC);
+       if (arg0) if ((lparg0 = env->GetCharArrayElements(arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)new Font((const WCHAR *)lparg0, (REAL)arg1, (INT)arg2, (Unit)arg3, (const FontCollection *)arg4);
+fail:
+       if (arg0 && lparg0) env->ReleaseCharArrayElements(arg0, lparg0, 0);
+       Gdip_NATIVE_EXIT(env, that, Font_1new___3CFIIJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GdiplusShutdown
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(GdiplusShutdown)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(GdiplusShutdown)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, GdiplusShutdown_FUNC);
+       GdiplusShutdown((ULONG_PTR)arg0);
+       Gdip_NATIVE_EXIT(env, that, GdiplusShutdown_FUNC);
+}
+#endif
+
+#ifndef NO_GdiplusStartup
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GdiplusStartup)(JNIEnv *env, jclass that, jlongArray arg0, jobject arg1, jlong arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GdiplusStartup)
+       (JNIEnv *env, jclass that, jlongArray arg0, jobject arg1, jlong arg2)
+{
+       jlong *lparg0=NULL;
+       GdiplusStartupInput _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GdiplusStartup_FUNC);
+       if (arg0) if ((lparg0 = env->GetLongArrayElements(arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getGdiplusStartupInputFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)GdiplusStartup((ULONG_PTR *)lparg0, (const GdiplusStartupInput *)lparg1, (GdiplusStartupOutput *)arg2);
+fail:
+       if (arg1 && lparg1) setGdiplusStartupInputFields(env, arg1, lparg1);
+       if (arg0 && lparg0) env->ReleaseLongArrayElements(arg0, lparg0, 0);
+       Gdip_NATIVE_EXIT(env, that, GdiplusStartup_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GdiplusStartupInput_1sizeof
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GdiplusStartupInput_1sizeof)(JNIEnv *env, jclass that);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GdiplusStartupInput_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GdiplusStartupInput_1sizeof_FUNC);
+       rc = (jint)GdiplusStartupInput_sizeof();
+       Gdip_NATIVE_EXIT(env, that, GdiplusStartupInput_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1AddArc
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddArc)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5, jfloat arg6);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddArc)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5, jfloat arg6)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1AddArc_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->AddArc((REAL)arg1, (REAL)arg2, (REAL)arg3, (REAL)arg4, (REAL)arg5, (REAL)arg6);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1AddArc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1AddBezier
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddBezier)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5, jfloat arg6, jfloat arg7, jfloat arg8);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddBezier)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5, jfloat arg6, jfloat arg7, jfloat arg8)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1AddBezier_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->AddBezier((REAL)arg1, (REAL)arg2, (REAL)arg3, (REAL)arg4, (REAL)arg5, (REAL)arg6, (REAL)arg7, (REAL)arg8);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1AddBezier_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1AddLine
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddLine)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddLine)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1AddLine_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->AddLine((REAL)arg1, (REAL)arg2, (REAL)arg3, (REAL)arg4);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1AddLine_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1AddPath
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddPath)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddPath)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1AddPath_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->AddPath((GraphicsPath *)arg1, (BOOL)arg2);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1AddPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1AddRectangle
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddRectangle)(JNIEnv *env, jclass that, jlong arg0, jobject arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddRectangle)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RectF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1AddRectangle_FUNC);
+       if (arg1) if ((lparg1 = getRectFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((GraphicsPath *)arg0)->AddRectangle(*lparg1);
+fail:
+       if (arg1 && lparg1) setRectFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1AddRectangle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1AddString
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddString)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jint arg4, jfloat arg5, jobject arg6, jlong arg7);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1AddString)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jint arg4, jfloat arg5, jobject arg6, jlong arg7)
+{
+       jchar *lparg1=NULL;
+       PointF _arg6, *lparg6=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1AddString_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = getPointFFields(env, arg6, &_arg6)) == NULL) goto fail;
+       rc = (jint)((GraphicsPath *)arg0)->AddString((const WCHAR *)lparg1, (INT)arg2, (const FontFamily *)arg3, (INT)arg4, (REAL)arg5, *(const PointF *)lparg6, (const StringFormat *)arg7);
+fail:
+       if (arg6 && lparg6) setPointFFields(env, arg6, lparg6);
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1AddString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1Clone
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(GraphicsPath_1Clone)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(GraphicsPath_1Clone)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1Clone_FUNC);
+       rc = (jlong)((GraphicsPath *)arg0)->Clone();
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1Clone_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1CloseFigure
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1CloseFigure)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1CloseFigure)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1CloseFigure_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->CloseFigure();
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1CloseFigure_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1Flatten
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1Flatten)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jfloat arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1Flatten)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jfloat arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1Flatten_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->Flatten((Matrix *)arg1, arg2);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1Flatten_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1GetBounds
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetBounds)(JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2, jlong arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetBounds)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2, jlong arg3)
+{
+       RectF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1GetBounds_FUNC);
+       if (arg1) if ((lparg1 = getRectFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((GraphicsPath *)arg0)->GetBounds(lparg1, (Matrix *)arg2, (Pen *)arg3);
+fail:
+       if (arg1 && lparg1) setRectFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1GetBounds_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1GetLastPoint
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetLastPoint)(JNIEnv *env, jclass that, jlong arg0, jobject arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetLastPoint)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       PointF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1GetLastPoint_FUNC);
+       if (arg1) if ((lparg1 = getPointFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((GraphicsPath *)arg0)->GetLastPoint((PointF *)lparg1);
+fail:
+       if (arg1 && lparg1) setPointFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1GetLastPoint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1GetPathPoints
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetPathPoints)(JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetPathPoints)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2)
+{
+       jfloat *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1GetPathPoints_FUNC);
+       if (arg1) if ((lparg1 = env->GetFloatArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((GraphicsPath *)arg0)->GetPathPoints((PointF *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseFloatArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1GetPathPoints_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1GetPathTypes
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetPathTypes)(JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetPathTypes)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jint arg2)
+{
+       jbyte *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1GetPathTypes_FUNC);
+       if (arg1) if ((lparg1 = env->GetByteArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((GraphicsPath *)arg0)->GetPathTypes((BYTE *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseByteArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1GetPathTypes_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1GetPointCount
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetPointCount)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1GetPointCount)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1GetPointCount_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->GetPointCount();
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1GetPointCount_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1IsOutlineVisible
+extern "C" JNIEXPORT jboolean JNICALL Gdip_NATIVE(GraphicsPath_1IsOutlineVisible)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jlong arg3, jlong arg4);
+JNIEXPORT jboolean JNICALL Gdip_NATIVE(GraphicsPath_1IsOutlineVisible)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jlong arg3, jlong arg4)
+{
+       jboolean rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1IsOutlineVisible_FUNC);
+       rc = (jboolean)((GraphicsPath *)arg0)->IsOutlineVisible(arg1, arg2, (const Pen *)arg3, (const Graphics *)arg4);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1IsOutlineVisible_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1IsVisible
+extern "C" JNIEXPORT jboolean JNICALL Gdip_NATIVE(GraphicsPath_1IsVisible)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jlong arg3);
+JNIEXPORT jboolean JNICALL Gdip_NATIVE(GraphicsPath_1IsVisible)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jlong arg3)
+{
+       jboolean rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1IsVisible_FUNC);
+       rc = (jboolean)((GraphicsPath *)arg0)->IsVisible(arg1, arg2, (const Graphics *)arg3);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1IsVisible_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1SetFillMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1SetFillMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1SetFillMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1SetFillMode_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->SetFillMode((FillMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1SetFillMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1StartFigure
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1StartFigure)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1StartFigure)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1StartFigure_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->StartFigure();
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1StartFigure_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1Transform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1Transform)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(GraphicsPath_1Transform)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1Transform_FUNC);
+       rc = (jint)((GraphicsPath *)arg0)->Transform((Matrix *)arg1);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1Transform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(GraphicsPath_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(GraphicsPath_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1delete_FUNC);
+       delete (GraphicsPath *)arg0;
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_GraphicsPath_1new__I
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(GraphicsPath_1new__I)(JNIEnv *env, jclass that, jint arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(GraphicsPath_1new__I)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1new__I_FUNC);
+       rc = (jlong)new GraphicsPath((FillMode)arg0);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1new__I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GraphicsPath_1new___3I_3BII
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(GraphicsPath_1new___3I_3BII)(JNIEnv *env, jclass that, jintArray arg0, jbyteArray arg1, jint arg2, jint arg3);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(GraphicsPath_1new___3I_3BII)
+       (JNIEnv *env, jclass that, jintArray arg0, jbyteArray arg1, jint arg2, jint arg3)
+{
+       jint *lparg0=NULL;
+       jbyte *lparg1=NULL;
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, GraphicsPath_1new___3I_3BII_FUNC);
+       if (arg0) if ((lparg0 = env->GetIntArrayElements(arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = env->GetByteArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jlong)new GraphicsPath((const Point *)lparg0, (const BYTE *)lparg1, arg2, (FillMode)arg3);
+fail:
+       if (arg1 && lparg1) env->ReleaseByteArrayElements(arg1, lparg1, JNI_ABORT);
+       if (arg0 && lparg0) env->ReleaseIntArrayElements(arg0, lparg0, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, GraphicsPath_1new___3I_3BII_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawArc
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawArc)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jfloat arg6, jfloat arg7);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawArc)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jfloat arg6, jfloat arg7)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawArc_FUNC);
+       rc = (jint)((Graphics *)arg0)->DrawArc((Pen *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawArc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4, jobject arg5, jint arg6, jlong arg7);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4, jobject arg5, jint arg6, jlong arg7)
+{
+       PointF _arg5, *lparg5=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ_FUNC);
+       if (arg5) if ((lparg5 = getPointFFields(env, arg5, &_arg5)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawDriverString((const UINT16 *)arg1, arg2, (const Font *)arg3, (const Brush *)arg4, (const PointF *)lparg5, arg6, (const Matrix *)arg7);
+fail:
+       if (arg5 && lparg5) setPointFFields(env, arg5, lparg5);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawDriverString__JJIJJ_3FIJ
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawDriverString__JJIJJ_3FIJ)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4, jfloatArray arg5, jint arg6, jlong arg7);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawDriverString__JJIJJ_3FIJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4, jfloatArray arg5, jint arg6, jlong arg7)
+{
+       jfloat *lparg5=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawDriverString__JJIJJ_3FIJ_FUNC);
+       if (arg5) if ((lparg5 = env->GetFloatArrayElements(arg5, NULL)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawDriverString((const UINT16 *)arg1, arg2, (const Font *)arg3, (const Brush *)arg4, (const PointF *)lparg5, arg6, (const Matrix *)arg7);
+fail:
+       if (arg5 && lparg5) env->ReleaseFloatArrayElements(arg5, lparg5, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawDriverString__JJIJJ_3FIJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawEllipse
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawEllipse)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawEllipse)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawEllipse_FUNC);
+       rc = (jint)((Graphics *)arg0)->DrawEllipse((Pen *)arg1, arg2, arg3, arg4, arg5);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawEllipse_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawImage__JJII
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawImage__JJII)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawImage__JJII)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawImage__JJII_FUNC);
+       rc = (jint)((Graphics *)arg0)->DrawImage((Image *)arg1, (INT)arg2, (INT)arg3);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawImage__JJII_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7, jlong arg8, jlong arg9, jlong arg10);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7, jlong arg8, jlong arg9, jlong arg10)
+{
+       Rect _arg2, *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ_FUNC);
+       if (arg2) if ((lparg2 = getRectFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawImage((Image *)arg1, *(const Rect *)lparg2, (INT)arg3, (INT)arg4, (INT)arg5, (INT)arg6, (Unit)arg7, (ImageAttributes *)arg8, (DrawImageAbort)arg9, (VOID *)arg10);
+fail:
+       if (arg2 && lparg2) setRectFields(env, arg2, lparg2);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawLine
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawLine)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawLine)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawLine_FUNC);
+       rc = (jint)((Graphics *)arg0)->DrawLine((Pen *)arg1, arg2, arg3, arg4, arg5);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawLine_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawLines
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawLines)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawLines)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2, jint arg3)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawLines_FUNC);
+       if (arg2) if ((lparg2 = env->GetIntArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawLines((Pen *)arg1, (const Point *)lparg2, (INT)arg3);
+fail:
+       if (arg2 && lparg2) env->ReleaseIntArrayElements(arg2, lparg2, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawLines_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawPath
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawPath)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawPath)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawPath_FUNC);
+       rc = (jint)((Graphics *)arg0)->DrawPath((Pen *)arg1, (GraphicsPath *)arg2);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawPolygon
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawPolygon)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawPolygon)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2, jint arg3)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawPolygon_FUNC);
+       if (arg2) if ((lparg2 = env->GetIntArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawPolygon((Pen *)arg1, (Point *)lparg2, (INT)arg3);
+fail:
+       if (arg2 && lparg2) env->ReleaseIntArrayElements(arg2, lparg2, 0);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawPolygon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawRectangle
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawRectangle)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawRectangle)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawRectangle_FUNC);
+       rc = (jint)((Graphics *)arg0)->DrawRectangle((Pen *)arg1, arg2, arg3, arg4, arg5);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawRectangle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jlong arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jlong arg5)
+{
+       jchar *lparg1=NULL;
+       PointF _arg4, *lparg4=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getPointFFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawString((WCHAR *)lparg1, (int)arg2, (Font *)arg3, *lparg4, (Brush *)arg5);
+fail:
+       if (arg4 && lparg4) setPointFFields(env, arg4, lparg4);
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jlong arg5, jlong arg6);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jlong arg5, jlong arg6)
+{
+       jchar *lparg1=NULL;
+       PointF _arg4, *lparg4=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getPointFFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->DrawString((WCHAR *)lparg1, (int)arg2, (Font *)arg3, *lparg4, (StringFormat *)arg5, (Brush *)arg6);
+fail:
+       if (arg4 && lparg4) setPointFFields(env, arg4, lparg4);
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1FillEllipse
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillEllipse)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillEllipse)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1FillEllipse_FUNC);
+       rc = (jint)((Graphics *)arg0)->FillEllipse((Brush *)arg1, (INT)arg2, (INT)arg3, (INT)arg4, (INT)arg5);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1FillEllipse_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1FillPath
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillPath)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillPath)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1FillPath_FUNC);
+       rc = (jint)((Graphics *)arg0)->FillPath((Brush *)arg1, (GraphicsPath *)arg2);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1FillPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1FillPie
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillPie)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jfloat arg6, jfloat arg7);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillPie)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jfloat arg6, jfloat arg7)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1FillPie_FUNC);
+       rc = (jint)((Graphics *)arg0)->FillPie((Brush *)arg1, (INT)arg2, (INT)arg3, (INT)arg4, (INT)arg5, (REAL)arg6, (REAL)arg7);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1FillPie_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1FillPolygon
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillPolygon)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2, jint arg3, jint arg4);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillPolygon)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2, jint arg3, jint arg4)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1FillPolygon_FUNC);
+       if (arg2) if ((lparg2 = env->GetIntArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->FillPolygon((Brush *)arg1, (const Point *)lparg2, (INT)arg3, (FillMode)arg4);
+fail:
+       if (arg2 && lparg2) env->ReleaseIntArrayElements(arg2, lparg2, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1FillPolygon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1FillRectangle
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillRectangle)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1FillRectangle)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1FillRectangle_FUNC);
+       rc = (jint)((Graphics *)arg0)->FillRectangle((Brush *)arg1, (INT)arg2, (INT)arg3, (INT)arg4, (INT)arg5);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1FillRectangle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1Flush
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Graphics_1Flush)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT void JNICALL Gdip_NATIVE(Graphics_1Flush)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       Gdip_NATIVE_ENTER(env, that, Graphics_1Flush_FUNC);
+       ((Graphics *)arg0)->Flush((FlushIntention)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1Flush_FUNC);
+}
+#endif
+
+#ifndef NO_Graphics_1GetClip
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetClip)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetClip)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetClip_FUNC);
+       rc = (jint)((Graphics *)arg0)->GetClip((Region *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetClip_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2)(JNIEnv *env, jclass that, jlong arg0, jobject arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RectF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2_FUNC);
+       if (arg1) if ((lparg1 = getRectFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->GetClipBounds(lparg1);
+fail:
+       if (arg1 && lparg1) setRectFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2)(JNIEnv *env, jclass that, jlong arg0, jobject arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       Rect _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2_FUNC);
+       if (arg1) if ((lparg1 = getRectFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->GetClipBounds(lparg1);
+fail:
+       if (arg1 && lparg1) setRectFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetHDC
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Graphics_1GetHDC)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Graphics_1GetHDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetHDC_FUNC);
+       rc = (jlong)((Graphics *)arg0)->GetHDC();
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetHDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetInterpolationMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetInterpolationMode)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetInterpolationMode)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetInterpolationMode_FUNC);
+       rc = (jint)((Graphics *)arg0)->GetInterpolationMode();
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetInterpolationMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetSmoothingMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetSmoothingMode)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetSmoothingMode)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetSmoothingMode_FUNC);
+       rc = (jint)((Graphics *)arg0)->GetSmoothingMode();
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetSmoothingMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetTextRenderingHint
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetTextRenderingHint)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetTextRenderingHint)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetTextRenderingHint_FUNC);
+       rc = (jint)((Graphics *)arg0)->GetTextRenderingHint();
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetTextRenderingHint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetTransform)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetTransform_FUNC);
+       rc = (jint)((Graphics *)arg0)->GetTransform((Matrix *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1GetVisibleClipBounds
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetVisibleClipBounds)(JNIEnv *env, jclass that, jlong arg0, jobject arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1GetVisibleClipBounds)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       Rect _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1GetVisibleClipBounds_FUNC);
+       if (arg1) if ((lparg1 = getRectFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->GetVisibleClipBounds(lparg1);
+fail:
+       if (arg1 && lparg1) setRectFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1GetVisibleClipBounds_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1MeasureDriverString
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1MeasureDriverString)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jfloatArray arg4, jint arg5, jlong arg6, jobject arg7);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1MeasureDriverString)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jfloatArray arg4, jint arg5, jlong arg6, jobject arg7)
+{
+       jfloat *lparg4=NULL;
+       RectF _arg7, *lparg7=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1MeasureDriverString_FUNC);
+       if (arg4) if ((lparg4 = env->GetFloatArrayElements(arg4, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = getRectFFields(env, arg7, &_arg7)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->MeasureDriverString((const UINT16 *)arg1, arg2, (Font *)arg3, (const PointF *)lparg4, arg5, (const Matrix *)arg6, lparg7);
+fail:
+       if (arg7 && lparg7) setRectFFields(env, arg7, lparg7);
+       if (arg4 && lparg4) env->ReleaseFloatArrayElements(arg4, lparg4, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1MeasureDriverString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jlong arg5, jobject arg6);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jlong arg5, jobject arg6)
+{
+       jchar *lparg1=NULL;
+       PointF _arg4, *lparg4=NULL;
+       RectF _arg6, *lparg6=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getPointFFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = getRectFFields(env, arg6, &_arg6)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->MeasureString((const WCHAR *)lparg1, (INT)arg2, (const Font *)arg3, *(const PointF *)lparg4, (StringFormat *)arg5, lparg6);
+fail:
+       if (arg6 && lparg6) setRectFFields(env, arg6, lparg6);
+       if (arg4 && lparg4) setPointFFields(env, arg4, lparg4);
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jobject arg5);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jlong arg3, jobject arg4, jobject arg5)
+{
+       jchar *lparg1=NULL;
+       PointF _arg4, *lparg4=NULL;
+       RectF _arg5, *lparg5=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getPointFFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = getRectFFields(env, arg5, &_arg5)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->MeasureString((const WCHAR *)lparg1, (INT)arg2, (const Font *)arg3, *(const PointF *)lparg4, (RectF *)lparg5);
+fail:
+       if (arg5 && lparg5) setRectFFields(env, arg5, lparg5);
+       if (arg4 && lparg4) setPointFFields(env, arg4, lparg4);
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1ReleaseHDC
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Graphics_1ReleaseHDC)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT void JNICALL Gdip_NATIVE(Graphics_1ReleaseHDC)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       Gdip_NATIVE_ENTER(env, that, Graphics_1ReleaseHDC_FUNC);
+       ((Graphics *)arg0)->ReleaseHDC((HDC)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1ReleaseHDC_FUNC);
+}
+#endif
+
+#ifndef NO_Graphics_1ResetClip
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1ResetClip)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1ResetClip)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1ResetClip_FUNC);
+       rc = (jint)((Graphics *)arg0)->ResetClip();
+       Gdip_NATIVE_EXIT(env, that, Graphics_1ResetClip_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1Restore
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1Restore)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1Restore)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1Restore_FUNC);
+       rc = (jint)((Graphics *)arg0)->Restore((GraphicsState)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1Restore_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1Save
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1Save)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1Save)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1Save_FUNC);
+       rc = (jint)((Graphics *)arg0)->Save();
+       Gdip_NATIVE_EXIT(env, that, Graphics_1Save_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1ScaleTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1ScaleTransform)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1ScaleTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1ScaleTransform_FUNC);
+       rc = (jint)((Graphics *)arg0)->ScaleTransform(arg1, arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1ScaleTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetClip__JJI
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClip__JJI)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClip__JJI)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetClip__JJI_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetClip((Region *)arg1, (CombineMode)arg2);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetClip__JJI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I)(JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       Rect _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I_FUNC);
+       if (arg1) if ((lparg1 = getRectFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((Graphics *)arg0)->SetClip(*(Rect *)lparg1, (CombineMode)arg2);
+fail:
+       if (arg1 && lparg1) setRectFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetClipPath__JJ
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClipPath__JJ)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClipPath__JJ)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetClipPath__JJ_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetClip((GraphicsPath *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetClipPath__JJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetClipPath__JJI
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClipPath__JJI)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetClipPath__JJI)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetClipPath__JJI_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetClip((GraphicsPath *)arg1, (CombineMode)arg2);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetClipPath__JJI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetCompositingQuality
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetCompositingQuality)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetCompositingQuality)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetCompositingQuality_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetCompositingQuality((CompositingQuality)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetCompositingQuality_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetInterpolationMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetInterpolationMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetInterpolationMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetInterpolationMode_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetInterpolationMode((InterpolationMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetInterpolationMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetPageUnit
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetPageUnit)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetPageUnit)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetPageUnit_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetPageUnit((Unit)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetPageUnit_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetPixelOffsetMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetPixelOffsetMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetPixelOffsetMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetPixelOffsetMode_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetPixelOffsetMode((PixelOffsetMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetPixelOffsetMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetSmoothingMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetSmoothingMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetSmoothingMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetSmoothingMode_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetSmoothingMode((SmoothingMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetSmoothingMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetTextRenderingHint
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetTextRenderingHint)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetTextRenderingHint)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetTextRenderingHint_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetTextRenderingHint((TextRenderingHint)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetTextRenderingHint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1SetTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetTransform)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1SetTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1SetTransform_FUNC);
+       rc = (jint)((Graphics *)arg0)->SetTransform((Matrix *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1SetTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1TranslateTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1TranslateTransform)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Graphics_1TranslateTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1TranslateTransform_FUNC);
+       rc = (jint)((Graphics *)arg0)->TranslateTransform(arg1, arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1TranslateTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Graphics_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Graphics_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Graphics_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Graphics_1delete_FUNC);
+       delete (Graphics *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Graphics_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Graphics_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Graphics_1new)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Graphics_1new)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Graphics_1new_FUNC);
+       rc = (jlong)new Graphics((HDC)arg0);
+       Gdip_NATIVE_EXIT(env, that, Graphics_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HatchBrush_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(HatchBrush_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(HatchBrush_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, HatchBrush_1delete_FUNC);
+       delete (HatchBrush *)arg0;
+       Gdip_NATIVE_EXIT(env, that, HatchBrush_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_HatchBrush_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(HatchBrush_1new)(JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(HatchBrush_1new)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, HatchBrush_1new_FUNC);
+       rc = (jlong)new HatchBrush((HatchStyle)arg0, (Color)arg1, (Color)arg2);
+       Gdip_NATIVE_EXIT(env, that, HatchBrush_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageAttributes_1SetColorMatrix
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(ImageAttributes_1SetColorMatrix)(JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(ImageAttributes_1SetColorMatrix)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2, jint arg3)
+{
+       jfloat *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, ImageAttributes_1SetColorMatrix_FUNC);
+       if (arg1) if ((lparg1 = env->GetFloatArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((ImageAttributes *)arg0)->SetColorMatrix((ColorMatrix *)lparg1, (ColorMatrixFlags)arg2, (ColorAdjustType)arg3);
+fail:
+       if (arg1 && lparg1) env->ReleaseFloatArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, ImageAttributes_1SetColorMatrix_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageAttributes_1SetWrapMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(ImageAttributes_1SetWrapMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(ImageAttributes_1SetWrapMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, ImageAttributes_1SetWrapMode_FUNC);
+       rc = (jint)((ImageAttributes *)arg0)->SetWrapMode((WrapMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, ImageAttributes_1SetWrapMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageAttributes_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(ImageAttributes_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(ImageAttributes_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, ImageAttributes_1delete_FUNC);
+       delete (ImageAttributes *)arg0;
+       Gdip_NATIVE_EXIT(env, that, ImageAttributes_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_ImageAttributes_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(ImageAttributes_1new)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(ImageAttributes_1new)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, ImageAttributes_1new_FUNC);
+       rc = (jlong)new ImageAttributes();
+       Gdip_NATIVE_EXIT(env, that, ImageAttributes_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Image_1GetHeight
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetHeight)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetHeight)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Image_1GetHeight_FUNC);
+       rc = (jint)((Image *)arg0)->GetHeight();
+       Gdip_NATIVE_EXIT(env, that, Image_1GetHeight_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Image_1GetLastStatus
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetLastStatus)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetLastStatus)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Image_1GetLastStatus_FUNC);
+       rc = (jint)((Image*)arg0)->GetLastStatus();
+       Gdip_NATIVE_EXIT(env, that, Image_1GetLastStatus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Image_1GetPalette
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetPalette)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetPalette)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Image_1GetPalette_FUNC);
+       rc = (jint)((Image*)arg0)->GetPalette((ColorPalette*)arg1, arg2);
+       Gdip_NATIVE_EXIT(env, that, Image_1GetPalette_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Image_1GetPaletteSize
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetPaletteSize)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetPaletteSize)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Image_1GetPaletteSize_FUNC);
+       rc = (jint)((Image*)arg0)->GetPaletteSize();
+       Gdip_NATIVE_EXIT(env, that, Image_1GetPaletteSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Image_1GetPixelFormat
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetPixelFormat)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetPixelFormat)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Image_1GetPixelFormat_FUNC);
+       rc = (jint)((Image*)arg0)->GetPixelFormat();
+       Gdip_NATIVE_EXIT(env, that, Image_1GetPixelFormat_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Image_1GetWidth
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetWidth)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Image_1GetWidth)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Image_1GetWidth_FUNC);
+       rc = (jint)((Image *)arg0)->GetWidth();
+       Gdip_NATIVE_EXIT(env, that, Image_1GetWidth_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1ResetTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1ResetTransform)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1ResetTransform)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1ResetTransform_FUNC);
+       rc = (jint)((LinearGradientBrush *)arg0)->ResetTransform();
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1ResetTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1ScaleTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1ScaleTransform)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1ScaleTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1ScaleTransform_FUNC);
+       rc = (jint)((LinearGradientBrush *)arg0)->ScaleTransform(arg1, arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1ScaleTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1SetInterpolationColors
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1SetInterpolationColors)(JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jfloatArray arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1SetInterpolationColors)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jfloatArray arg2, jint arg3)
+{
+       jint *lparg1=NULL;
+       jfloat *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1SetInterpolationColors_FUNC);
+       if (arg1) if ((lparg1 = env->GetIntArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = env->GetFloatArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((LinearGradientBrush *)arg0)->SetInterpolationColors((const Color *)lparg1, (const REAL *)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) env->ReleaseFloatArrayElements(arg2, lparg2, JNI_ABORT);
+       if (arg1 && lparg1) env->ReleaseIntArrayElements(arg1, lparg1, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1SetInterpolationColors_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1SetWrapMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1SetWrapMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1SetWrapMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1SetWrapMode_FUNC);
+       rc = (jint)((LinearGradientBrush *)arg0)->SetWrapMode((WrapMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1SetWrapMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1TranslateTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1TranslateTransform)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(LinearGradientBrush_1TranslateTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1TranslateTransform_FUNC);
+       rc = (jint)((LinearGradientBrush *)arg0)->TranslateTransform(arg1, arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1TranslateTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(LinearGradientBrush_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(LinearGradientBrush_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1delete_FUNC);
+       delete (LinearGradientBrush *)arg0;
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_LinearGradientBrush_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(LinearGradientBrush_1new)(JNIEnv *env, jclass that, jobject arg0, jobject arg1, jint arg2, jint arg3);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(LinearGradientBrush_1new)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1, jint arg2, jint arg3)
+{
+       PointF _arg0, *lparg0=NULL;
+       PointF _arg1, *lparg1=NULL;
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, LinearGradientBrush_1new_FUNC);
+       if (arg0) if ((lparg0 = getPointFFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getPointFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jlong)new LinearGradientBrush(*lparg0, *lparg1, (Color)arg2, (Color)arg3);
+fail:
+       if (arg1 && lparg1) setPointFFields(env, arg1, lparg1);
+       if (arg0 && lparg0) setPointFFields(env, arg0, lparg0);
+       Gdip_NATIVE_EXIT(env, that, LinearGradientBrush_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1GetElements
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1GetElements)(JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1GetElements)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1)
+{
+       jfloat *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1GetElements_FUNC);
+       if (arg1) if ((lparg1 = env->GetFloatArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((Matrix *)arg0)->GetElements((REAL *)lparg1);
+fail:
+       if (arg1 && lparg1) env->ReleaseFloatArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1GetElements_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1Invert
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Invert)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Invert)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1Invert_FUNC);
+       rc = (jint)((Matrix *)arg0)->Invert();
+       Gdip_NATIVE_EXIT(env, that, Matrix_1Invert_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1IsIdentity
+extern "C" JNIEXPORT jboolean JNICALL Gdip_NATIVE(Matrix_1IsIdentity)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jboolean JNICALL Gdip_NATIVE(Matrix_1IsIdentity)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1IsIdentity_FUNC);
+       rc = (jboolean)((Matrix *)arg0)->IsIdentity();
+       Gdip_NATIVE_EXIT(env, that, Matrix_1IsIdentity_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1Multiply
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Multiply)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Multiply)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1Multiply_FUNC);
+       rc = (jint)((Matrix *)arg0)->Multiply((Matrix *)arg1, (MatrixOrder)arg2);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1Multiply_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1Rotate
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Rotate)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Rotate)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jint arg2)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1Rotate_FUNC);
+       rc = (jint)((Matrix *)arg0)->Rotate((REAL)arg1, (MatrixOrder)arg2);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1Rotate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1Scale
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Scale)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Scale)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1Scale_FUNC);
+       rc = (jint)((Matrix *)arg0)->Scale((REAL)arg1, (REAL)arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1Scale_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1SetElements
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1SetElements)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5, jfloat arg6);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1SetElements)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5, jfloat arg6)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1SetElements_FUNC);
+       rc = (jint)((Matrix *)arg0)->SetElements((REAL)arg1, (REAL)arg2, (REAL)arg3, (REAL)arg4, (REAL)arg5, (REAL)arg6);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1SetElements_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1Shear
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Shear)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Shear)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1Shear_FUNC);
+       rc = (jint)((Matrix *)arg0)->Shear((REAL)arg1, (REAL)arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1Shear_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I)(JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       PointF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I_FUNC);
+       if (arg1) if ((lparg1 = getPointFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((Matrix *)arg0)->TransformPoints(lparg1, arg2);
+fail:
+       if (arg1 && lparg1) setPointFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1TransformPoints__J_3FI
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1TransformPoints__J_3FI)(JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1TransformPoints__J_3FI)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2)
+{
+       jfloat *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1TransformPoints__J_3FI_FUNC);
+       if (arg1) if ((lparg1 = env->GetFloatArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((Matrix *)arg0)->TransformPoints((PointF *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseFloatArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1TransformPoints__J_3FI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1TransformVectors
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1TransformVectors)(JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1TransformVectors)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       PointF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1TransformVectors_FUNC);
+       if (arg1) if ((lparg1 = getPointFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((Matrix *)arg0)->TransformVectors(lparg1, arg2);
+fail:
+       if (arg1 && lparg1) setPointFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1TransformVectors_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1Translate
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Translate)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Matrix_1Translate)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1Translate_FUNC);
+       rc = (jint)((Matrix *)arg0)->Translate((REAL)arg1, (REAL)arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1Translate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Matrix_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Matrix_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Matrix_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Matrix_1delete_FUNC);
+       delete (Matrix *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Matrix_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Matrix_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Matrix_1new)(JNIEnv *env, jclass that, jfloat arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Matrix_1new)
+       (JNIEnv *env, jclass that, jfloat arg0, jfloat arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Matrix_1new_FUNC);
+       rc = (jlong)new Matrix((REAL)arg0, (REAL)arg1, (REAL)arg2, (REAL)arg3, (REAL)arg4, (REAL)arg5);
+       Gdip_NATIVE_EXIT(env, that, Matrix_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J)(JNIEnv *env, jclass that, jobject arg0, jlong arg1);
+JNIEXPORT void JNICALL Gdip_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1)
+{
+       Gdip_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J_FUNC);
+       if (arg0) setBitmapDataFields(env, arg0, (BitmapData *)arg1);
+       Gdip_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI)(JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2);
+JNIEXPORT void JNICALL Gdip_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       ColorPalette _arg0, *lparg0=NULL;
+       Gdip_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI_FUNC);
+       if (arg0) if ((lparg0 = getColorPaletteFields(env, arg0, &_arg0)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID*)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setColorPaletteFields(env, arg0, lparg0);
+       Gdip_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1SetCenterColor
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetCenterColor)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetCenterColor)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1SetCenterColor_FUNC);
+       rc = (jint)((PathGradientBrush *)arg0)->SetCenterColor((Color)arg1);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1SetCenterColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1SetCenterPoint
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetCenterPoint)(JNIEnv *env, jclass that, jlong arg0, jobject arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetCenterPoint)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       PointF _arg1, *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1SetCenterPoint_FUNC);
+       if (arg1) if ((lparg1 = getPointFFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)((PathGradientBrush *)arg0)->SetCenterPoint(*lparg1);
+fail:
+       if (arg1 && lparg1) setPointFFields(env, arg1, lparg1);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1SetCenterPoint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1SetGraphicsPath
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetGraphicsPath)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetGraphicsPath)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1SetGraphicsPath_FUNC);
+       rc = (jint)((PathGradientBrush *)arg0)->SetGraphicsPath((GraphicsPath *)arg1);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1SetGraphicsPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1SetInterpolationColors
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetInterpolationColors)(JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jfloatArray arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetInterpolationColors)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jfloatArray arg2, jint arg3)
+{
+       jint *lparg1=NULL;
+       jfloat *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1SetInterpolationColors_FUNC);
+       if (arg1) if ((lparg1 = env->GetIntArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = env->GetFloatArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((PathGradientBrush *)arg0)->SetInterpolationColors((const Color *)lparg1, (const REAL *)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) env->ReleaseFloatArrayElements(arg2, lparg2, JNI_ABORT);
+       if (arg1 && lparg1) env->ReleaseIntArrayElements(arg1, lparg1, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1SetInterpolationColors_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1SetSurroundColors
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetSurroundColors)(JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetSurroundColors)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2)
+{
+       jint *lparg1=NULL;
+       jint *lparg2=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1SetSurroundColors_FUNC);
+       if (arg1) if ((lparg1 = env->GetIntArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = env->GetIntArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jint)((PathGradientBrush *)arg0)->SetSurroundColors((const Color *)lparg1, (INT *)lparg2);
+fail:
+       if (arg2 && lparg2) env->ReleaseIntArrayElements(arg2, lparg2, 0);
+       if (arg1 && lparg1) env->ReleaseIntArrayElements(arg1, lparg1, JNI_ABORT);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1SetSurroundColors_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1SetWrapMode
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetWrapMode)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PathGradientBrush_1SetWrapMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1SetWrapMode_FUNC);
+       rc = (jint)((PathGradientBrush *)arg0)->SetWrapMode((WrapMode)arg1);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1SetWrapMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(PathGradientBrush_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(PathGradientBrush_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1delete_FUNC);
+       delete (PathGradientBrush *)arg0;
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_PathGradientBrush_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(PathGradientBrush_1new)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(PathGradientBrush_1new)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PathGradientBrush_1new_FUNC);
+       rc = (jlong)new PathGradientBrush((GraphicsPath *)arg0);
+       Gdip_NATIVE_EXIT(env, that, PathGradientBrush_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1GetBrush
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Pen_1GetBrush)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Pen_1GetBrush)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1GetBrush_FUNC);
+       rc = (jlong)((Pen *)arg0)->GetBrush();
+       Gdip_NATIVE_EXIT(env, that, Pen_1GetBrush_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetBrush
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetBrush)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetBrush)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetBrush_FUNC);
+       rc = (jint)((Pen *)arg0)->SetBrush((Brush *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetBrush_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetDashOffset
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetDashOffset)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetDashOffset)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetDashOffset_FUNC);
+       rc = (jint)((Pen *)arg0)->SetDashOffset(arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetDashOffset_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetDashPattern
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetDashPattern)(JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetDashPattern)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2)
+{
+       jfloat *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetDashPattern_FUNC);
+       if (arg1) if ((lparg1 = env->GetFloatArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((Pen *)arg0)->SetDashPattern((REAL *)lparg1, (int)arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseFloatArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetDashPattern_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetDashStyle
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetDashStyle)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetDashStyle)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetDashStyle_FUNC);
+       rc = (jint)((Pen *)arg0)->SetDashStyle((DashStyle)arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetDashStyle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetLineCap
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetLineCap)(JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetLineCap)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetLineCap_FUNC);
+       rc = (jint)((Pen *)arg0)->SetLineCap((LineCap)arg1, (LineCap)arg2, (DashCap)arg3);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetLineCap_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetLineJoin
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetLineJoin)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetLineJoin)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetLineJoin_FUNC);
+       rc = (jint)((Pen *)arg0)->SetLineJoin((LineJoin)arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetLineJoin_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetMiterLimit
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetMiterLimit)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetMiterLimit)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetMiterLimit_FUNC);
+       rc = (jint)((Pen *)arg0)->SetMiterLimit(arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetMiterLimit_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1SetWidth
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetWidth)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(Pen_1SetWidth)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1SetWidth_FUNC);
+       rc = (jint)((Pen *)arg0)->SetWidth((REAL)arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1SetWidth_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pen_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Pen_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Pen_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Pen_1delete_FUNC);
+       delete (Pen *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Pen_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Pen_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Pen_1new)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Pen_1new)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Pen_1new_FUNC);
+       rc = (jlong)new Pen((Brush *)arg0, (REAL)arg1);
+       Gdip_NATIVE_EXIT(env, that, Pen_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Point_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Point_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Point_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Point_1delete_FUNC);
+       delete (Point *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Point_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Point_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Point_1new)(JNIEnv *env, jclass that, jint arg0, jint arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Point_1new)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Point_1new_FUNC);
+       rc = (jlong)new Point(arg0, arg1);
+       Gdip_NATIVE_EXIT(env, that, Point_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PrivateFontCollection_1AddFontFile
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(PrivateFontCollection_1AddFontFile)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(PrivateFontCollection_1AddFontFile)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PrivateFontCollection_1AddFontFile_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)((PrivateFontCollection *)arg0)->AddFontFile((const WCHAR *)lparg1);
+fail:
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       Gdip_NATIVE_EXIT(env, that, PrivateFontCollection_1AddFontFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PrivateFontCollection_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(PrivateFontCollection_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(PrivateFontCollection_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, PrivateFontCollection_1delete_FUNC);
+       delete (PrivateFontCollection *)arg0;
+       Gdip_NATIVE_EXIT(env, that, PrivateFontCollection_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_PrivateFontCollection_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(PrivateFontCollection_1new)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(PrivateFontCollection_1new)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, PrivateFontCollection_1new_FUNC);
+       rc = (jlong)new PrivateFontCollection();
+       Gdip_NATIVE_EXIT(env, that, PrivateFontCollection_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Region_1GetHRGN
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1GetHRGN)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1GetHRGN)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Region_1GetHRGN_FUNC);
+       rc = (jlong)((Region *)arg0)->GetHRGN((Graphics *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Region_1GetHRGN_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Region_1IsInfinite
+extern "C" JNIEXPORT jboolean JNICALL Gdip_NATIVE(Region_1IsInfinite)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jboolean JNICALL Gdip_NATIVE(Region_1IsInfinite)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jboolean rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Region_1IsInfinite_FUNC);
+       rc = (jboolean)((Region *)arg0)->IsInfinite((Graphics *)arg1);
+       Gdip_NATIVE_EXIT(env, that, Region_1IsInfinite_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Region_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(Region_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(Region_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, Region_1delete_FUNC);
+       delete (Region *)arg0;
+       Gdip_NATIVE_EXIT(env, that, Region_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_Region_1new__
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1new__)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1new__)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Region_1new___FUNC);
+       rc = (jlong)new Region();
+       Gdip_NATIVE_EXIT(env, that, Region_1new___FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Region_1new__J
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1new__J)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1new__J)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Region_1new__J_FUNC);
+       rc = (jlong)new Region((HRGN)arg0);
+       Gdip_NATIVE_EXIT(env, that, Region_1new__J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Region_1newGraphicsPath
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1newGraphicsPath)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(Region_1newGraphicsPath)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, Region_1newGraphicsPath_FUNC);
+       rc = (jlong)new Region((GraphicsPath*)arg0);
+       Gdip_NATIVE_EXIT(env, that, Region_1newGraphicsPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SolidBrush_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(SolidBrush_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(SolidBrush_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, SolidBrush_1delete_FUNC);
+       delete (SolidBrush *)arg0;
+       Gdip_NATIVE_EXIT(env, that, SolidBrush_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_SolidBrush_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(SolidBrush_1new)(JNIEnv *env, jclass that, jint arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(SolidBrush_1new)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, SolidBrush_1new_FUNC);
+       rc = (jlong)new SolidBrush((Color)arg0);
+       Gdip_NATIVE_EXIT(env, that, SolidBrush_1new_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1Clone
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(StringFormat_1Clone)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(StringFormat_1Clone)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1Clone_FUNC);
+       rc = (jlong)((StringFormat *)arg0)->Clone();
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1Clone_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1GenericDefault
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(StringFormat_1GenericDefault)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(StringFormat_1GenericDefault)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1GenericDefault_FUNC);
+       rc = (jlong)StringFormat::GenericDefault();
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1GenericDefault_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1GenericTypographic
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(StringFormat_1GenericTypographic)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(StringFormat_1GenericTypographic)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1GenericTypographic_FUNC);
+       rc = (jlong)StringFormat::GenericTypographic();
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1GenericTypographic_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1GetFormatFlags
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1GetFormatFlags)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1GetFormatFlags)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1GetFormatFlags_FUNC);
+       rc = (jint)((StringFormat *)arg0)->GetFormatFlags();
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1GetFormatFlags_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1SetFormatFlags
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1SetFormatFlags)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1SetFormatFlags)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1SetFormatFlags_FUNC);
+       rc = (jint)((StringFormat *)arg0)->SetFormatFlags((StringFormatFlags)arg1);
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1SetFormatFlags_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1SetHotkeyPrefix
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1SetHotkeyPrefix)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1SetHotkeyPrefix)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1SetHotkeyPrefix_FUNC);
+       rc = (jint)((StringFormat *)arg0)->SetHotkeyPrefix((HotkeyPrefix)arg1);
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1SetHotkeyPrefix_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1SetTabStops
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1SetTabStops)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jint arg2, jfloatArray arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(StringFormat_1SetTabStops)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jint arg2, jfloatArray arg3)
+{
+       jfloat *lparg3=NULL;
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1SetTabStops_FUNC);
+       if (arg3) if ((lparg3 = env->GetFloatArrayElements(arg3, NULL)) == NULL) goto fail;
+       rc = (jint)((StringFormat *)arg0)->SetTabStops(arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) env->ReleaseFloatArrayElements(arg3, lparg3, 0);
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1SetTabStops_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StringFormat_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(StringFormat_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(StringFormat_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, StringFormat_1delete_FUNC);
+       delete (StringFormat *)arg0;
+       Gdip_NATIVE_EXIT(env, that, StringFormat_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_TextureBrush_1ResetTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1ResetTransform)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1ResetTransform)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, TextureBrush_1ResetTransform_FUNC);
+       rc = (jint)((TextureBrush *)arg0)->ResetTransform();
+       Gdip_NATIVE_EXIT(env, that, TextureBrush_1ResetTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TextureBrush_1ScaleTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1ScaleTransform)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1ScaleTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, TextureBrush_1ScaleTransform_FUNC);
+       rc = (jint)((TextureBrush *)arg0)->ScaleTransform(arg1, arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, TextureBrush_1ScaleTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TextureBrush_1SetTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1SetTransform)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1SetTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, TextureBrush_1SetTransform_FUNC);
+       rc = (jint)((TextureBrush *)arg0)->SetTransform((Matrix *)arg1);
+       Gdip_NATIVE_EXIT(env, that, TextureBrush_1SetTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TextureBrush_1TranslateTransform
+extern "C" JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1TranslateTransform)(JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3);
+JNIEXPORT jint JNICALL Gdip_NATIVE(TextureBrush_1TranslateTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloat arg1, jfloat arg2, jint arg3)
+{
+       jint rc = 0;
+       Gdip_NATIVE_ENTER(env, that, TextureBrush_1TranslateTransform_FUNC);
+       rc = (jint)((TextureBrush *)arg0)->TranslateTransform(arg1, arg2, (MatrixOrder)arg3);
+       Gdip_NATIVE_EXIT(env, that, TextureBrush_1TranslateTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TextureBrush_1delete
+extern "C" JNIEXPORT void JNICALL Gdip_NATIVE(TextureBrush_1delete)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL Gdip_NATIVE(TextureBrush_1delete)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       Gdip_NATIVE_ENTER(env, that, TextureBrush_1delete_FUNC);
+       delete (TextureBrush *)arg0;
+       Gdip_NATIVE_EXIT(env, that, TextureBrush_1delete_FUNC);
+}
+#endif
+
+#ifndef NO_TextureBrush_1new
+extern "C" JNIEXPORT jlong JNICALL Gdip_NATIVE(TextureBrush_1new)(JNIEnv *env, jclass that, jlong arg0, jint arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5);
+JNIEXPORT jlong JNICALL Gdip_NATIVE(TextureBrush_1new)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jfloat arg2, jfloat arg3, jfloat arg4, jfloat arg5)
+{
+       jlong rc = 0;
+       Gdip_NATIVE_ENTER(env, that, TextureBrush_1new_FUNC);
+       rc = (jlong)new TextureBrush((Image *)arg0, (WrapMode)arg1, arg2, arg3, arg4, arg5);
+       Gdip_NATIVE_EXIT(env, that, TextureBrush_1new_FUNC);
+       return rc;
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip.h
new file mode 100644 (file)
index 0000000..6ec9abc
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#ifndef INC_gdip_H
+#define INC_gdip_H
+
+#include <windows.h>
+#include <gdiplus.h>
+using namespace Gdiplus;
+
+/* Optional custom definitions to exclude some types */
+#include "defines.h"
+
+#endif /* INC_gdip_H */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_custom.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_custom.cpp
new file mode 100644 (file)
index 0000000..730ba7e
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#include "swt.h"
+#include "gdip_structs.h"
+#include "gdip_stats.h"
+
+#define Gdip_NATIVE(func) Java_org_eclipse_swt_internal_gdip_Gdip_##func
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_stats.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_stats.cpp
new file mode 100644 (file)
index 0000000..26cf2a2
--- /dev/null
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "gdip_stats.h"
+
+#ifdef NATIVE_STATS
+
+char * Gdip_nativeFunctionNames[] = {
+       "BitmapData_1delete",
+       "BitmapData_1new",
+       "Bitmap_1GetHBITMAP",
+       "Bitmap_1GetHICON",
+       "Bitmap_1LockBits",
+       "Bitmap_1UnlockBits",
+       "Bitmap_1delete",
+       "Bitmap_1new__IIIIJ",
+       "Bitmap_1new__J",
+       "Bitmap_1new__JJ",
+       "Bitmap_1new___3CZ",
+       "Brush_1Clone",
+       "Brush_1GetType",
+       "ColorPalette_1sizeof",
+       "FontFamily_1GetFamilyName",
+       "FontFamily_1IsAvailable",
+       "FontFamily_1delete",
+       "FontFamily_1new__",
+       "FontFamily_1new___3CJ",
+       "Font_1GetFamily",
+       "Font_1GetLogFontW",
+       "Font_1GetSize",
+       "Font_1GetStyle",
+       "Font_1IsAvailable",
+       "Font_1delete",
+       "Font_1new__JFII",
+       "Font_1new__JJ",
+       "Font_1new___3CFIIJ",
+       "GdiplusShutdown",
+       "GdiplusStartup",
+       "GdiplusStartupInput_1sizeof",
+       "GraphicsPath_1AddArc",
+       "GraphicsPath_1AddBezier",
+       "GraphicsPath_1AddLine",
+       "GraphicsPath_1AddPath",
+       "GraphicsPath_1AddRectangle",
+       "GraphicsPath_1AddString",
+       "GraphicsPath_1Clone",
+       "GraphicsPath_1CloseFigure",
+       "GraphicsPath_1Flatten",
+       "GraphicsPath_1GetBounds",
+       "GraphicsPath_1GetLastPoint",
+       "GraphicsPath_1GetPathPoints",
+       "GraphicsPath_1GetPathTypes",
+       "GraphicsPath_1GetPointCount",
+       "GraphicsPath_1IsOutlineVisible",
+       "GraphicsPath_1IsVisible",
+       "GraphicsPath_1SetFillMode",
+       "GraphicsPath_1StartFigure",
+       "GraphicsPath_1Transform",
+       "GraphicsPath_1delete",
+       "GraphicsPath_1new__I",
+       "GraphicsPath_1new___3I_3BII",
+       "Graphics_1DrawArc",
+       "Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ",
+       "Graphics_1DrawDriverString__JJIJJ_3FIJ",
+       "Graphics_1DrawEllipse",
+       "Graphics_1DrawImage__JJII",
+       "Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ",
+       "Graphics_1DrawLine",
+       "Graphics_1DrawLines",
+       "Graphics_1DrawPath",
+       "Graphics_1DrawPolygon",
+       "Graphics_1DrawRectangle",
+       "Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J",
+       "Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ",
+       "Graphics_1FillEllipse",
+       "Graphics_1FillPath",
+       "Graphics_1FillPie",
+       "Graphics_1FillPolygon",
+       "Graphics_1FillRectangle",
+       "Graphics_1Flush",
+       "Graphics_1GetClip",
+       "Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2",
+       "Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2",
+       "Graphics_1GetHDC",
+       "Graphics_1GetInterpolationMode",
+       "Graphics_1GetSmoothingMode",
+       "Graphics_1GetTextRenderingHint",
+       "Graphics_1GetTransform",
+       "Graphics_1GetVisibleClipBounds",
+       "Graphics_1MeasureDriverString",
+       "Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2",
+       "Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2",
+       "Graphics_1ReleaseHDC",
+       "Graphics_1ResetClip",
+       "Graphics_1Restore",
+       "Graphics_1Save",
+       "Graphics_1ScaleTransform",
+       "Graphics_1SetClip__JJI",
+       "Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I",
+       "Graphics_1SetClipPath__JJ",
+       "Graphics_1SetClipPath__JJI",
+       "Graphics_1SetCompositingQuality",
+       "Graphics_1SetInterpolationMode",
+       "Graphics_1SetPageUnit",
+       "Graphics_1SetPixelOffsetMode",
+       "Graphics_1SetSmoothingMode",
+       "Graphics_1SetTextRenderingHint",
+       "Graphics_1SetTransform",
+       "Graphics_1TranslateTransform",
+       "Graphics_1delete",
+       "Graphics_1new",
+       "HatchBrush_1delete",
+       "HatchBrush_1new",
+       "ImageAttributes_1SetColorMatrix",
+       "ImageAttributes_1SetWrapMode",
+       "ImageAttributes_1delete",
+       "ImageAttributes_1new",
+       "Image_1GetHeight",
+       "Image_1GetLastStatus",
+       "Image_1GetPalette",
+       "Image_1GetPaletteSize",
+       "Image_1GetPixelFormat",
+       "Image_1GetWidth",
+       "LinearGradientBrush_1ResetTransform",
+       "LinearGradientBrush_1ScaleTransform",
+       "LinearGradientBrush_1SetInterpolationColors",
+       "LinearGradientBrush_1SetWrapMode",
+       "LinearGradientBrush_1TranslateTransform",
+       "LinearGradientBrush_1delete",
+       "LinearGradientBrush_1new",
+       "Matrix_1GetElements",
+       "Matrix_1Invert",
+       "Matrix_1IsIdentity",
+       "Matrix_1Multiply",
+       "Matrix_1Rotate",
+       "Matrix_1Scale",
+       "Matrix_1SetElements",
+       "Matrix_1Shear",
+       "Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I",
+       "Matrix_1TransformPoints__J_3FI",
+       "Matrix_1TransformVectors",
+       "Matrix_1Translate",
+       "Matrix_1delete",
+       "Matrix_1new",
+       "MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J",
+       "MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI",
+       "PathGradientBrush_1SetCenterColor",
+       "PathGradientBrush_1SetCenterPoint",
+       "PathGradientBrush_1SetGraphicsPath",
+       "PathGradientBrush_1SetInterpolationColors",
+       "PathGradientBrush_1SetSurroundColors",
+       "PathGradientBrush_1SetWrapMode",
+       "PathGradientBrush_1delete",
+       "PathGradientBrush_1new",
+       "Pen_1GetBrush",
+       "Pen_1SetBrush",
+       "Pen_1SetDashOffset",
+       "Pen_1SetDashPattern",
+       "Pen_1SetDashStyle",
+       "Pen_1SetLineCap",
+       "Pen_1SetLineJoin",
+       "Pen_1SetMiterLimit",
+       "Pen_1SetWidth",
+       "Pen_1delete",
+       "Pen_1new",
+       "Point_1delete",
+       "Point_1new",
+       "PrivateFontCollection_1AddFontFile",
+       "PrivateFontCollection_1delete",
+       "PrivateFontCollection_1new",
+       "Region_1GetHRGN",
+       "Region_1IsInfinite",
+       "Region_1delete",
+       "Region_1new__",
+       "Region_1new__J",
+       "Region_1newGraphicsPath",
+       "SolidBrush_1delete",
+       "SolidBrush_1new",
+       "StringFormat_1Clone",
+       "StringFormat_1GenericDefault",
+       "StringFormat_1GenericTypographic",
+       "StringFormat_1GetFormatFlags",
+       "StringFormat_1SetFormatFlags",
+       "StringFormat_1SetHotkeyPrefix",
+       "StringFormat_1SetTabStops",
+       "StringFormat_1delete",
+       "TextureBrush_1ResetTransform",
+       "TextureBrush_1ScaleTransform",
+       "TextureBrush_1SetTransform",
+       "TextureBrush_1TranslateTransform",
+       "TextureBrush_1delete",
+       "TextureBrush_1new",
+};
+#define NATIVE_FUNCTION_COUNT sizeof(Gdip_nativeFunctionNames) / sizeof(char*)
+int Gdip_nativeFunctionCount = NATIVE_FUNCTION_COUNT;
+int Gdip_nativeFunctionCallCount[NATIVE_FUNCTION_COUNT];
+
+#define STATS_NATIVE(func) Java_org_eclipse_swt_tools_internal_NativeStats_##func
+
+JNIEXPORT jint JNICALL STATS_NATIVE(Gdip_1GetFunctionCount)
+       (JNIEnv *env, jclass that)
+{
+       return Gdip_nativeFunctionCount;
+}
+
+JNIEXPORT jstring JNICALL STATS_NATIVE(Gdip_1GetFunctionName)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return env->NewStringUTF(Gdip_nativeFunctionNames[index]);
+}
+
+JNIEXPORT jint JNICALL STATS_NATIVE(Gdip_1GetFunctionCallCount)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return Gdip_nativeFunctionCallCount[index];
+}
+
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_stats.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_stats.h
new file mode 100644 (file)
index 0000000..03c0320
--- /dev/null
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#ifdef NATIVE_STATS
+extern int Gdip_nativeFunctionCount;
+extern int Gdip_nativeFunctionCallCount[];
+extern char* Gdip_nativeFunctionNames[];
+#define Gdip_NATIVE_ENTER(env, that, func) Gdip_nativeFunctionCallCount[func]++;
+#define Gdip_NATIVE_EXIT(env, that, func) 
+#else
+#ifndef Gdip_NATIVE_ENTER
+#define Gdip_NATIVE_ENTER(env, that, func) 
+#endif
+#ifndef Gdip_NATIVE_EXIT
+#define Gdip_NATIVE_EXIT(env, that, func) 
+#endif
+#endif
+
+typedef enum {
+       BitmapData_1delete_FUNC,
+       BitmapData_1new_FUNC,
+       Bitmap_1GetHBITMAP_FUNC,
+       Bitmap_1GetHICON_FUNC,
+       Bitmap_1LockBits_FUNC,
+       Bitmap_1UnlockBits_FUNC,
+       Bitmap_1delete_FUNC,
+       Bitmap_1new__IIIIJ_FUNC,
+       Bitmap_1new__J_FUNC,
+       Bitmap_1new__JJ_FUNC,
+       Bitmap_1new___3CZ_FUNC,
+       Brush_1Clone_FUNC,
+       Brush_1GetType_FUNC,
+       ColorPalette_1sizeof_FUNC,
+       FontFamily_1GetFamilyName_FUNC,
+       FontFamily_1IsAvailable_FUNC,
+       FontFamily_1delete_FUNC,
+       FontFamily_1new___FUNC,
+       FontFamily_1new___3CJ_FUNC,
+       Font_1GetFamily_FUNC,
+       Font_1GetLogFontW_FUNC,
+       Font_1GetSize_FUNC,
+       Font_1GetStyle_FUNC,
+       Font_1IsAvailable_FUNC,
+       Font_1delete_FUNC,
+       Font_1new__JFII_FUNC,
+       Font_1new__JJ_FUNC,
+       Font_1new___3CFIIJ_FUNC,
+       GdiplusShutdown_FUNC,
+       GdiplusStartup_FUNC,
+       GdiplusStartupInput_1sizeof_FUNC,
+       GraphicsPath_1AddArc_FUNC,
+       GraphicsPath_1AddBezier_FUNC,
+       GraphicsPath_1AddLine_FUNC,
+       GraphicsPath_1AddPath_FUNC,
+       GraphicsPath_1AddRectangle_FUNC,
+       GraphicsPath_1AddString_FUNC,
+       GraphicsPath_1Clone_FUNC,
+       GraphicsPath_1CloseFigure_FUNC,
+       GraphicsPath_1Flatten_FUNC,
+       GraphicsPath_1GetBounds_FUNC,
+       GraphicsPath_1GetLastPoint_FUNC,
+       GraphicsPath_1GetPathPoints_FUNC,
+       GraphicsPath_1GetPathTypes_FUNC,
+       GraphicsPath_1GetPointCount_FUNC,
+       GraphicsPath_1IsOutlineVisible_FUNC,
+       GraphicsPath_1IsVisible_FUNC,
+       GraphicsPath_1SetFillMode_FUNC,
+       GraphicsPath_1StartFigure_FUNC,
+       GraphicsPath_1Transform_FUNC,
+       GraphicsPath_1delete_FUNC,
+       GraphicsPath_1new__I_FUNC,
+       GraphicsPath_1new___3I_3BII_FUNC,
+       Graphics_1DrawArc_FUNC,
+       Graphics_1DrawDriverString__JJIJJLorg_eclipse_swt_internal_gdip_PointF_2IJ_FUNC,
+       Graphics_1DrawDriverString__JJIJJ_3FIJ_FUNC,
+       Graphics_1DrawEllipse_FUNC,
+       Graphics_1DrawImage__JJII_FUNC,
+       Graphics_1DrawImage__JJLorg_eclipse_swt_internal_gdip_Rect_2IIIIIJJJ_FUNC,
+       Graphics_1DrawLine_FUNC,
+       Graphics_1DrawLines_FUNC,
+       Graphics_1DrawPath_FUNC,
+       Graphics_1DrawPolygon_FUNC,
+       Graphics_1DrawRectangle_FUNC,
+       Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2J_FUNC,
+       Graphics_1DrawString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JJ_FUNC,
+       Graphics_1FillEllipse_FUNC,
+       Graphics_1FillPath_FUNC,
+       Graphics_1FillPie_FUNC,
+       Graphics_1FillPolygon_FUNC,
+       Graphics_1FillRectangle_FUNC,
+       Graphics_1Flush_FUNC,
+       Graphics_1GetClip_FUNC,
+       Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_RectF_2_FUNC,
+       Graphics_1GetClipBounds__JLorg_eclipse_swt_internal_gdip_Rect_2_FUNC,
+       Graphics_1GetHDC_FUNC,
+       Graphics_1GetInterpolationMode_FUNC,
+       Graphics_1GetSmoothingMode_FUNC,
+       Graphics_1GetTextRenderingHint_FUNC,
+       Graphics_1GetTransform_FUNC,
+       Graphics_1GetVisibleClipBounds_FUNC,
+       Graphics_1MeasureDriverString_FUNC,
+       Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2JLorg_eclipse_swt_internal_gdip_RectF_2_FUNC,
+       Graphics_1MeasureString__J_3CIJLorg_eclipse_swt_internal_gdip_PointF_2Lorg_eclipse_swt_internal_gdip_RectF_2_FUNC,
+       Graphics_1ReleaseHDC_FUNC,
+       Graphics_1ResetClip_FUNC,
+       Graphics_1Restore_FUNC,
+       Graphics_1Save_FUNC,
+       Graphics_1ScaleTransform_FUNC,
+       Graphics_1SetClip__JJI_FUNC,
+       Graphics_1SetClip__JLorg_eclipse_swt_internal_gdip_Rect_2I_FUNC,
+       Graphics_1SetClipPath__JJ_FUNC,
+       Graphics_1SetClipPath__JJI_FUNC,
+       Graphics_1SetCompositingQuality_FUNC,
+       Graphics_1SetInterpolationMode_FUNC,
+       Graphics_1SetPageUnit_FUNC,
+       Graphics_1SetPixelOffsetMode_FUNC,
+       Graphics_1SetSmoothingMode_FUNC,
+       Graphics_1SetTextRenderingHint_FUNC,
+       Graphics_1SetTransform_FUNC,
+       Graphics_1TranslateTransform_FUNC,
+       Graphics_1delete_FUNC,
+       Graphics_1new_FUNC,
+       HatchBrush_1delete_FUNC,
+       HatchBrush_1new_FUNC,
+       ImageAttributes_1SetColorMatrix_FUNC,
+       ImageAttributes_1SetWrapMode_FUNC,
+       ImageAttributes_1delete_FUNC,
+       ImageAttributes_1new_FUNC,
+       Image_1GetHeight_FUNC,
+       Image_1GetLastStatus_FUNC,
+       Image_1GetPalette_FUNC,
+       Image_1GetPaletteSize_FUNC,
+       Image_1GetPixelFormat_FUNC,
+       Image_1GetWidth_FUNC,
+       LinearGradientBrush_1ResetTransform_FUNC,
+       LinearGradientBrush_1ScaleTransform_FUNC,
+       LinearGradientBrush_1SetInterpolationColors_FUNC,
+       LinearGradientBrush_1SetWrapMode_FUNC,
+       LinearGradientBrush_1TranslateTransform_FUNC,
+       LinearGradientBrush_1delete_FUNC,
+       LinearGradientBrush_1new_FUNC,
+       Matrix_1GetElements_FUNC,
+       Matrix_1Invert_FUNC,
+       Matrix_1IsIdentity_FUNC,
+       Matrix_1Multiply_FUNC,
+       Matrix_1Rotate_FUNC,
+       Matrix_1Scale_FUNC,
+       Matrix_1SetElements_FUNC,
+       Matrix_1Shear_FUNC,
+       Matrix_1TransformPoints__JLorg_eclipse_swt_internal_gdip_PointF_2I_FUNC,
+       Matrix_1TransformPoints__J_3FI_FUNC,
+       Matrix_1TransformVectors_FUNC,
+       Matrix_1Translate_FUNC,
+       Matrix_1delete_FUNC,
+       Matrix_1new_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_gdip_BitmapData_2J_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_gdip_ColorPalette_2JI_FUNC,
+       PathGradientBrush_1SetCenterColor_FUNC,
+       PathGradientBrush_1SetCenterPoint_FUNC,
+       PathGradientBrush_1SetGraphicsPath_FUNC,
+       PathGradientBrush_1SetInterpolationColors_FUNC,
+       PathGradientBrush_1SetSurroundColors_FUNC,
+       PathGradientBrush_1SetWrapMode_FUNC,
+       PathGradientBrush_1delete_FUNC,
+       PathGradientBrush_1new_FUNC,
+       Pen_1GetBrush_FUNC,
+       Pen_1SetBrush_FUNC,
+       Pen_1SetDashOffset_FUNC,
+       Pen_1SetDashPattern_FUNC,
+       Pen_1SetDashStyle_FUNC,
+       Pen_1SetLineCap_FUNC,
+       Pen_1SetLineJoin_FUNC,
+       Pen_1SetMiterLimit_FUNC,
+       Pen_1SetWidth_FUNC,
+       Pen_1delete_FUNC,
+       Pen_1new_FUNC,
+       Point_1delete_FUNC,
+       Point_1new_FUNC,
+       PrivateFontCollection_1AddFontFile_FUNC,
+       PrivateFontCollection_1delete_FUNC,
+       PrivateFontCollection_1new_FUNC,
+       Region_1GetHRGN_FUNC,
+       Region_1IsInfinite_FUNC,
+       Region_1delete_FUNC,
+       Region_1new___FUNC,
+       Region_1new__J_FUNC,
+       Region_1newGraphicsPath_FUNC,
+       SolidBrush_1delete_FUNC,
+       SolidBrush_1new_FUNC,
+       StringFormat_1Clone_FUNC,
+       StringFormat_1GenericDefault_FUNC,
+       StringFormat_1GenericTypographic_FUNC,
+       StringFormat_1GetFormatFlags_FUNC,
+       StringFormat_1SetFormatFlags_FUNC,
+       StringFormat_1SetHotkeyPrefix_FUNC,
+       StringFormat_1SetTabStops_FUNC,
+       StringFormat_1delete_FUNC,
+       TextureBrush_1ResetTransform_FUNC,
+       TextureBrush_1ScaleTransform_FUNC,
+       TextureBrush_1SetTransform_FUNC,
+       TextureBrush_1TranslateTransform_FUNC,
+       TextureBrush_1delete_FUNC,
+       TextureBrush_1new_FUNC,
+} Gdip_FUNCS;
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_structs.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_structs.cpp
new file mode 100644 (file)
index 0000000..d9fe2b9
--- /dev/null
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "gdip_structs.h"
+
+#ifndef NO_BitmapData
+typedef struct BitmapData_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID Width, Height, Stride, PixelFormat, Scan0, Reserved;
+} BitmapData_FID_CACHE;
+
+BitmapData_FID_CACHE BitmapDataFc;
+
+void cacheBitmapDataFields(JNIEnv *env, jobject lpObject)
+{
+       if (BitmapDataFc.cached) return;
+       BitmapDataFc.clazz = env->GetObjectClass(lpObject);
+       BitmapDataFc.Width = env->GetFieldID(BitmapDataFc.clazz, "Width", "I");
+       BitmapDataFc.Height = env->GetFieldID(BitmapDataFc.clazz, "Height", "I");
+       BitmapDataFc.Stride = env->GetFieldID(BitmapDataFc.clazz, "Stride", "I");
+       BitmapDataFc.PixelFormat = env->GetFieldID(BitmapDataFc.clazz, "PixelFormat", "I");
+       BitmapDataFc.Scan0 = env->GetFieldID(BitmapDataFc.clazz, "Scan0", "J");
+       BitmapDataFc.Reserved = env->GetFieldID(BitmapDataFc.clazz, "Reserved", "J");
+       BitmapDataFc.cached = 1;
+}
+
+BitmapData *getBitmapDataFields(JNIEnv *env, jobject lpObject, BitmapData *lpStruct)
+{
+       if (!BitmapDataFc.cached) cacheBitmapDataFields(env, lpObject);
+       lpStruct->Width = env->GetIntField(lpObject, BitmapDataFc.Width);
+       lpStruct->Height = env->GetIntField(lpObject, BitmapDataFc.Height);
+       lpStruct->Stride = env->GetIntField(lpObject, BitmapDataFc.Stride);
+       lpStruct->PixelFormat = (PixelFormat)env->GetIntField(lpObject, BitmapDataFc.PixelFormat);
+       lpStruct->Scan0 = (void*)env->GetLongField(lpObject, BitmapDataFc.Scan0);
+       lpStruct->Reserved = (UINT_PTR)env->GetLongField(lpObject, BitmapDataFc.Reserved);
+       return lpStruct;
+}
+
+void setBitmapDataFields(JNIEnv *env, jobject lpObject, BitmapData *lpStruct)
+{
+       if (!BitmapDataFc.cached) cacheBitmapDataFields(env, lpObject);
+       env->SetIntField(lpObject, BitmapDataFc.Width, (jint)lpStruct->Width);
+       env->SetIntField(lpObject, BitmapDataFc.Height, (jint)lpStruct->Height);
+       env->SetIntField(lpObject, BitmapDataFc.Stride, (jint)lpStruct->Stride);
+       env->SetIntField(lpObject, BitmapDataFc.PixelFormat, (jint)lpStruct->PixelFormat);
+       env->SetLongField(lpObject, BitmapDataFc.Scan0, (jlong)lpStruct->Scan0);
+       env->SetLongField(lpObject, BitmapDataFc.Reserved, (jlong)lpStruct->Reserved);
+}
+#endif
+
+#ifndef NO_ColorPalette
+typedef struct ColorPalette_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID Flags, Count, Entries;
+} ColorPalette_FID_CACHE;
+
+ColorPalette_FID_CACHE ColorPaletteFc;
+
+void cacheColorPaletteFields(JNIEnv *env, jobject lpObject)
+{
+       if (ColorPaletteFc.cached) return;
+       ColorPaletteFc.clazz = env->GetObjectClass(lpObject);
+       ColorPaletteFc.Flags = env->GetFieldID(ColorPaletteFc.clazz, "Flags", "I");
+       ColorPaletteFc.Count = env->GetFieldID(ColorPaletteFc.clazz, "Count", "I");
+       ColorPaletteFc.Entries = env->GetFieldID(ColorPaletteFc.clazz, "Entries", "[I");
+       ColorPaletteFc.cached = 1;
+}
+
+ColorPalette *getColorPaletteFields(JNIEnv *env, jobject lpObject, ColorPalette *lpStruct)
+{
+       if (!ColorPaletteFc.cached) cacheColorPaletteFields(env, lpObject);
+       lpStruct->Flags = env->GetIntField(lpObject, ColorPaletteFc.Flags);
+       lpStruct->Count = env->GetIntField(lpObject, ColorPaletteFc.Count);
+       {
+       jintArray lpObject1 = (jintArray)env->GetObjectField(lpObject, ColorPaletteFc.Entries);
+       env->GetIntArrayRegion(lpObject1, 0, sizeof(lpStruct->Entries) / sizeof(jint), (jint *)lpStruct->Entries);
+       }
+       return lpStruct;
+}
+
+void setColorPaletteFields(JNIEnv *env, jobject lpObject, ColorPalette *lpStruct)
+{
+       if (!ColorPaletteFc.cached) cacheColorPaletteFields(env, lpObject);
+       env->SetIntField(lpObject, ColorPaletteFc.Flags, (jint)lpStruct->Flags);
+       env->SetIntField(lpObject, ColorPaletteFc.Count, (jint)lpStruct->Count);
+       {
+       jintArray lpObject1 = (jintArray)env->GetObjectField(lpObject, ColorPaletteFc.Entries);
+       env->SetIntArrayRegion(lpObject1, 0, sizeof(lpStruct->Entries) / sizeof(jint), (jint *)lpStruct->Entries);
+       }
+}
+#endif
+
+#ifndef NO_GdiplusStartupInput
+typedef struct GdiplusStartupInput_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID GdiplusVersion, DebugEventCallback, SuppressBackgroundThread, SuppressExternalCodecs;
+} GdiplusStartupInput_FID_CACHE;
+
+GdiplusStartupInput_FID_CACHE GdiplusStartupInputFc;
+
+void cacheGdiplusStartupInputFields(JNIEnv *env, jobject lpObject)
+{
+       if (GdiplusStartupInputFc.cached) return;
+       GdiplusStartupInputFc.clazz = env->GetObjectClass(lpObject);
+       GdiplusStartupInputFc.GdiplusVersion = env->GetFieldID(GdiplusStartupInputFc.clazz, "GdiplusVersion", "I");
+       GdiplusStartupInputFc.DebugEventCallback = env->GetFieldID(GdiplusStartupInputFc.clazz, "DebugEventCallback", "J");
+       GdiplusStartupInputFc.SuppressBackgroundThread = env->GetFieldID(GdiplusStartupInputFc.clazz, "SuppressBackgroundThread", "Z");
+       GdiplusStartupInputFc.SuppressExternalCodecs = env->GetFieldID(GdiplusStartupInputFc.clazz, "SuppressExternalCodecs", "Z");
+       GdiplusStartupInputFc.cached = 1;
+}
+
+GdiplusStartupInput *getGdiplusStartupInputFields(JNIEnv *env, jobject lpObject, GdiplusStartupInput *lpStruct)
+{
+       if (!GdiplusStartupInputFc.cached) cacheGdiplusStartupInputFields(env, lpObject);
+       lpStruct->GdiplusVersion = env->GetIntField(lpObject, GdiplusStartupInputFc.GdiplusVersion);
+       lpStruct->DebugEventCallback = (DebugEventProc)env->GetLongField(lpObject, GdiplusStartupInputFc.DebugEventCallback);
+       lpStruct->SuppressBackgroundThread = (BOOL)env->GetBooleanField(lpObject, GdiplusStartupInputFc.SuppressBackgroundThread);
+       lpStruct->SuppressExternalCodecs = (BOOL)env->GetBooleanField(lpObject, GdiplusStartupInputFc.SuppressExternalCodecs);
+       return lpStruct;
+}
+
+void setGdiplusStartupInputFields(JNIEnv *env, jobject lpObject, GdiplusStartupInput *lpStruct)
+{
+       if (!GdiplusStartupInputFc.cached) cacheGdiplusStartupInputFields(env, lpObject);
+       env->SetIntField(lpObject, GdiplusStartupInputFc.GdiplusVersion, (jint)lpStruct->GdiplusVersion);
+       env->SetLongField(lpObject, GdiplusStartupInputFc.DebugEventCallback, (jlong)lpStruct->DebugEventCallback);
+       env->SetBooleanField(lpObject, GdiplusStartupInputFc.SuppressBackgroundThread, (jboolean)lpStruct->SuppressBackgroundThread);
+       env->SetBooleanField(lpObject, GdiplusStartupInputFc.SuppressExternalCodecs, (jboolean)lpStruct->SuppressExternalCodecs);
+}
+#endif
+
+#ifndef NO_PointF
+typedef struct PointF_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID X, Y;
+} PointF_FID_CACHE;
+
+PointF_FID_CACHE PointFFc;
+
+void cachePointFFields(JNIEnv *env, jobject lpObject)
+{
+       if (PointFFc.cached) return;
+       PointFFc.clazz = env->GetObjectClass(lpObject);
+       PointFFc.X = env->GetFieldID(PointFFc.clazz, "X", "F");
+       PointFFc.Y = env->GetFieldID(PointFFc.clazz, "Y", "F");
+       PointFFc.cached = 1;
+}
+
+PointF *getPointFFields(JNIEnv *env, jobject lpObject, PointF *lpStruct)
+{
+       if (!PointFFc.cached) cachePointFFields(env, lpObject);
+       lpStruct->X = (REAL)env->GetFloatField(lpObject, PointFFc.X);
+       lpStruct->Y = (REAL)env->GetFloatField(lpObject, PointFFc.Y);
+       return lpStruct;
+}
+
+void setPointFFields(JNIEnv *env, jobject lpObject, PointF *lpStruct)
+{
+       if (!PointFFc.cached) cachePointFFields(env, lpObject);
+       env->SetFloatField(lpObject, PointFFc.X, (jfloat)lpStruct->X);
+       env->SetFloatField(lpObject, PointFFc.Y, (jfloat)lpStruct->Y);
+}
+#endif
+
+#ifndef NO_Rect
+typedef struct Rect_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID X, Y, Width, Height;
+} Rect_FID_CACHE;
+
+Rect_FID_CACHE RectFc;
+
+void cacheRectFields(JNIEnv *env, jobject lpObject)
+{
+       if (RectFc.cached) return;
+       RectFc.clazz = env->GetObjectClass(lpObject);
+       RectFc.X = env->GetFieldID(RectFc.clazz, "X", "I");
+       RectFc.Y = env->GetFieldID(RectFc.clazz, "Y", "I");
+       RectFc.Width = env->GetFieldID(RectFc.clazz, "Width", "I");
+       RectFc.Height = env->GetFieldID(RectFc.clazz, "Height", "I");
+       RectFc.cached = 1;
+}
+
+Rect *getRectFields(JNIEnv *env, jobject lpObject, Rect *lpStruct)
+{
+       if (!RectFc.cached) cacheRectFields(env, lpObject);
+       lpStruct->X = env->GetIntField(lpObject, RectFc.X);
+       lpStruct->Y = env->GetIntField(lpObject, RectFc.Y);
+       lpStruct->Width = env->GetIntField(lpObject, RectFc.Width);
+       lpStruct->Height = env->GetIntField(lpObject, RectFc.Height);
+       return lpStruct;
+}
+
+void setRectFields(JNIEnv *env, jobject lpObject, Rect *lpStruct)
+{
+       if (!RectFc.cached) cacheRectFields(env, lpObject);
+       env->SetIntField(lpObject, RectFc.X, (jint)lpStruct->X);
+       env->SetIntField(lpObject, RectFc.Y, (jint)lpStruct->Y);
+       env->SetIntField(lpObject, RectFc.Width, (jint)lpStruct->Width);
+       env->SetIntField(lpObject, RectFc.Height, (jint)lpStruct->Height);
+}
+#endif
+
+#ifndef NO_RectF
+typedef struct RectF_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID X, Y, Width, Height;
+} RectF_FID_CACHE;
+
+RectF_FID_CACHE RectFFc;
+
+void cacheRectFFields(JNIEnv *env, jobject lpObject)
+{
+       if (RectFFc.cached) return;
+       RectFFc.clazz = env->GetObjectClass(lpObject);
+       RectFFc.X = env->GetFieldID(RectFFc.clazz, "X", "F");
+       RectFFc.Y = env->GetFieldID(RectFFc.clazz, "Y", "F");
+       RectFFc.Width = env->GetFieldID(RectFFc.clazz, "Width", "F");
+       RectFFc.Height = env->GetFieldID(RectFFc.clazz, "Height", "F");
+       RectFFc.cached = 1;
+}
+
+RectF *getRectFFields(JNIEnv *env, jobject lpObject, RectF *lpStruct)
+{
+       if (!RectFFc.cached) cacheRectFFields(env, lpObject);
+       lpStruct->X = env->GetFloatField(lpObject, RectFFc.X);
+       lpStruct->Y = env->GetFloatField(lpObject, RectFFc.Y);
+       lpStruct->Width = env->GetFloatField(lpObject, RectFFc.Width);
+       lpStruct->Height = env->GetFloatField(lpObject, RectFFc.Height);
+       return lpStruct;
+}
+
+void setRectFFields(JNIEnv *env, jobject lpObject, RectF *lpStruct)
+{
+       if (!RectFFc.cached) cacheRectFFields(env, lpObject);
+       env->SetFloatField(lpObject, RectFFc.X, (jfloat)lpStruct->X);
+       env->SetFloatField(lpObject, RectFFc.Y, (jfloat)lpStruct->Y);
+       env->SetFloatField(lpObject, RectFFc.Width, (jfloat)lpStruct->Width);
+       env->SetFloatField(lpObject, RectFFc.Height, (jfloat)lpStruct->Height);
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_structs.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/gdip_structs.h
new file mode 100644 (file)
index 0000000..c457313
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "gdip.h"
+
+#ifndef NO_BitmapData
+void cacheBitmapDataFields(JNIEnv *env, jobject lpObject);
+BitmapData *getBitmapDataFields(JNIEnv *env, jobject lpObject, BitmapData *lpStruct);
+void setBitmapDataFields(JNIEnv *env, jobject lpObject, BitmapData *lpStruct);
+#define BitmapData_sizeof() sizeof(BitmapData)
+#else
+#define cacheBitmapDataFields(a,b)
+#define getBitmapDataFields(a,b,c) NULL
+#define setBitmapDataFields(a,b,c)
+#define BitmapData_sizeof() 0
+#endif
+
+#ifndef NO_ColorPalette
+void cacheColorPaletteFields(JNIEnv *env, jobject lpObject);
+ColorPalette *getColorPaletteFields(JNIEnv *env, jobject lpObject, ColorPalette *lpStruct);
+void setColorPaletteFields(JNIEnv *env, jobject lpObject, ColorPalette *lpStruct);
+#define ColorPalette_sizeof() sizeof(ColorPalette)
+#else
+#define cacheColorPaletteFields(a,b)
+#define getColorPaletteFields(a,b,c) NULL
+#define setColorPaletteFields(a,b,c)
+#define ColorPalette_sizeof() 0
+#endif
+
+#ifndef NO_GdiplusStartupInput
+void cacheGdiplusStartupInputFields(JNIEnv *env, jobject lpObject);
+GdiplusStartupInput *getGdiplusStartupInputFields(JNIEnv *env, jobject lpObject, GdiplusStartupInput *lpStruct);
+void setGdiplusStartupInputFields(JNIEnv *env, jobject lpObject, GdiplusStartupInput *lpStruct);
+#define GdiplusStartupInput_sizeof() sizeof(GdiplusStartupInput)
+#else
+#define cacheGdiplusStartupInputFields(a,b)
+#define getGdiplusStartupInputFields(a,b,c) NULL
+#define setGdiplusStartupInputFields(a,b,c)
+#define GdiplusStartupInput_sizeof() 0
+#endif
+
+#ifndef NO_PointF
+void cachePointFFields(JNIEnv *env, jobject lpObject);
+PointF *getPointFFields(JNIEnv *env, jobject lpObject, PointF *lpStruct);
+void setPointFFields(JNIEnv *env, jobject lpObject, PointF *lpStruct);
+#define PointF_sizeof() sizeof(PointF)
+#else
+#define cachePointFFields(a,b)
+#define getPointFFields(a,b,c) NULL
+#define setPointFFields(a,b,c)
+#define PointF_sizeof() 0
+#endif
+
+#ifndef NO_Rect
+void cacheRectFields(JNIEnv *env, jobject lpObject);
+Rect *getRectFields(JNIEnv *env, jobject lpObject, Rect *lpStruct);
+void setRectFields(JNIEnv *env, jobject lpObject, Rect *lpStruct);
+#define Rect_sizeof() sizeof(Rect)
+#else
+#define cacheRectFields(a,b)
+#define getRectFields(a,b,c) NULL
+#define setRectFields(a,b,c)
+#define Rect_sizeof() 0
+#endif
+
+#ifndef NO_RectF
+void cacheRectFFields(JNIEnv *env, jobject lpObject);
+RectF *getRectFFields(JNIEnv *env, jobject lpObject, RectF *lpStruct);
+void setRectFFields(JNIEnv *env, jobject lpObject, RectF *lpStruct);
+#define RectF_sizeof() sizeof(RectF)
+#else
+#define cacheRectFFields(a,b)
+#define getRectFFields(a,b,c) NULL
+#define setRectFFields(a,b,c)
+#define RectF_sizeof() 0
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/javaw.exe.manifest b/bundles/org.eclipse.swt.win32.win32.x86_64/library/javaw.exe.manifest
new file mode 100644 (file)
index 0000000..2778a89
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+   <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SWT.javaw" type="win32" />
+   <description>Standard Widget Toolkit</description>
+   <dependency>
+      <dependentAssembly>
+         <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
+      </dependentAssembly>
+   </dependency>
+   <application xmlns="urn:schemas-microsoft-com:asm.v3">
+      <windowsSettings>
+         <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
+         <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
+         <!-- Un-comment the line below to enable GDI-scaling in this project. This will enable text -->
+         <!-- to render crisply in DPI-unaware content -->
+         <!--<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>-->
+      </windowsSettings>
+   </application>
+   <!--Specifically targeting your application for Windows 8.1 or Windows 10: https://msdn.microsoft.com/en-us/library/windows/desktop/dn481241(v=vs.85).aspx -->
+   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+        <application>
+            <!-- Windows 10 -->
+            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+            <!-- Windows 8.1 -->
+            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+            <!-- Windows Vista -->
+            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+            <!-- Windows 7 -->
+            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+            <!-- Windows 8 -->
+            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+        </application>
+    </compatibility>
+</assembly>
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/make_common.mak b/bundles/org.eclipse.swt.win32.win32.x86_64/library/make_common.mak
new file mode 100644 (file)
index 0000000..97d18a0
--- /dev/null
@@ -0,0 +1,18 @@
+#*******************************************************************************
+# Copyright (c) 2000, 2018 IBM Corporation and others.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+#*******************************************************************************
+
+maj_ver=4
+min_ver=930
+rev=7
+comma_ver=4,930,7,0
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/make_win32.mak b/bundles/org.eclipse.swt.win32.win32.x86_64/library/make_win32.mak
new file mode 100644 (file)
index 0000000..6b7637b
--- /dev/null
@@ -0,0 +1,157 @@
+#*******************************************************************************
+# Copyright (c) 2000, 2018 IBM Corporation and others.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+#*******************************************************************************
+
+# Makefile for SWT libraries on Windows
+
+# assumes these variables are set in the environment from which nmake is run
+#      SWT_JAVA_HOME
+#      OUTPUT_DIR
+
+!include <make_common.mak>
+
+SWT_PREFIX  = swt
+WS_PREFIX   = win32
+SWT_VERSION = $(maj_ver)$(min_ver)r$(rev)
+SWT_LIB     = $(SWT_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).dll
+SWT_LIBS    = comctl32.lib shell32.lib imm32.lib oleacc.lib usp10.lib \
+       wininet.lib Crypt32.lib Shlwapi.lib Uxtheme.lib Propsys.lib Urlmon.lib \
+       Msimg32.lib
+SWT_OBJS    = swt.obj callback.obj c.obj c_stats.obj \
+       os.obj os_structs.obj os_custom.obj os_stats.obj \
+       com_structs.obj com.obj com_stats.obj com_custom.obj
+
+GDIP_PREFIX  = swt-gdip
+GDIP_LIB     = $(GDIP_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).dll
+GDIP_LIBS    = gdiplus.lib
+GDIP_OBJS    = gdip.obj gdip_structs.obj gdip_stats.obj gdip_custom.obj
+
+AWT_PREFIX = swt-awt
+AWT_LIB    = $(AWT_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).dll
+AWT_LIBS   = "$(SWT_JAVA_HOME)\lib\jawt.lib"
+AWT_OBJS   = swt_awt.obj
+
+WEBKIT_PREFIX = swt-webkit
+WEBKIT_LIB    = $(WEBKIT_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).dll
+WEBKIT_LIBS   = $(WEBKIT_DIR)\lib\webkit.lib $(WEBKIT_SUPPORT_DIR)\win\lib\CFNetwork.lib $(WEBKIT_SUPPORT_DIR)\win\lib\CoreFoundation.lib
+WEBKIT_OBJS   = webkit_win32.obj webkit_win32_stats.obj webkit_win32_custom.obj webkit_win32_structs.obj
+
+WGL_PREFIX = swt-wgl
+WGL_LIB    = $(WGL_PREFIX)-$(WS_PREFIX)-$(SWT_VERSION).dll
+WGL_LIBS   = opengl32.lib
+WGL_OBJS   = wgl.obj wgl_structs.obj wgl_stats.obj
+
+# Uncomment for Native Stats tool
+#NATIVE_STATS = -DNATIVE_STATS
+
+WEBKITCFLAGS = -c -O1\
+       -DSWT_VERSION=$(SWT_VERSION) \
+       $(NATIVE_STATS) \
+       -I"$(SWT_JAVA_HOME)\include" -I"$(SWT_JAVA_HOME)\include\win32" \
+       -I"$(WEBKIT_DIR)" \
+       -I"$(WEBKIT_DIR)\WebKit\win" \
+       -I"$(WEBKIT_DIR)\JavaScriptCore\ForwardingHeaders" \
+       -I"$(WEBKIT_SUPPORT_DIR)\win\include"
+
+#CFLAGS = $(cdebug) $(cflags) $(cvarsmt) $(CFLAGS) \
+CFLAGS = -O1 -DNDEBUG -DUNICODE -D_UNICODE /c $(cflags) $(cvarsmt) $(CFLAGS) \
+       -DSWT_VERSION=$(maj_ver)$(min_ver) -DSWT_REVISION=$(rev) $(NATIVE_STATS) -DUSE_ASSEMBLER \
+       /I"$(SWT_JAVA_HOME)\include" /I"$(SWT_JAVA_HOME)\include\win32" /I.
+RCFLAGS = $(rcflags) $(rcvars) $(RCFLAGS) -DSWT_FILE_VERSION=\"$(maj_ver).$(min_ver).$(rev).0\" -DSWT_COMMA_VERSION=$(comma_ver)
+ldebug = /RELEASE  /INCREMENTAL:NO /NOLOGO
+dlllflags = -dll
+guilibsmt = kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib bufferoverflowu.lib user32.lib gdi32.lib comdlg32.lib winspool.lib
+olelibsmt = ole32.lib uuid.lib oleaut32.lib $(guilibsmt)
+
+all: make_swt make_awt make_gdip make_wgl
+
+webkit_win32_custom.obj: webkit_win32_custom.cpp
+       cl $(WEBKITCFLAGS) webkit_win32_custom.cpp
+webkit_win32_stats.obj: webkit_win32_stats.cpp
+       cl $(WEBKITCFLAGS) webkit_win32_stats.cpp
+webkit_win32_structs.obj: webkit_win32_structs.cpp
+       cl $(WEBKITCFLAGS) webkit_win32_structs.cpp
+webkit_win32.obj: webkit_win32.cpp
+       cl $(WEBKITCFLAGS) webkit_win32.cpp
+
+.c.obj:
+       cl $(CFLAGS) $*.c
+
+.cpp.obj:
+       cl $(CFLAGS) $*.cpp
+
+make_swt: $(SWT_OBJS) swt.res
+       echo $(ldebug) $(dlllflags) $(olelibsmt) >templrf
+       echo $(SWT_LIBS) >>templrf
+       echo $(SWT_OBJS) >>templrf
+       echo swt.res >>templrf
+       echo -out:$(SWT_LIB) >>templrf
+       link @templrf
+       del templrf
+
+make_gdip: $(GDIP_OBJS) swt_gdip.res
+       echo $(ldebug) $(dlllflags) $(guilibsmt) >templrf
+       echo $(GDIP_LIBS) >>templrf
+       echo $(GDIP_OBJS) >>templrf
+       echo swt_gdip.res >>templrf
+       echo -out:$(GDIP_LIB) >>templrf
+       link @templrf
+       del templrf
+
+make_awt: $(AWT_OBJS) swt_awt.res
+       echo $(ldebug) $(dlllflags) $(guilibsmt) >templrf
+       echo $(AWT_LIBS) >>templrf
+       echo $(AWT_OBJS) >>templrf
+       echo swt_awt.res >>templrf
+       echo -out:$(AWT_LIB) >>templrf
+       link @templrf
+       del templrf
+
+make_webkit: $(WEBKIT_OBJS) swt_webkit.res
+       echo $(ldebug) $(dlllflags) >templrf
+       echo $(WEBKIT_LIBS) >>templrf
+       echo $(WEBKIT_OBJS) >>templrf
+       echo swt_webkit.res >>templrf
+       echo -out:$(WEBKIT_LIB) >>templrf
+       link @templrf
+       del templrf
+
+make_wgl: $(WGL_OBJS) swt_wgl.res
+       echo $(ldebug) $(dlllflags) $(guilibsmt) >templrf
+       echo $(WGL_LIBS) >>templrf
+       echo $(WGL_OBJS) >>templrf
+       echo swt_wgl.res >>templrf
+       echo -out:$(WGL_LIB) >>templrf
+       link @templrf
+       del templrf
+
+swt.res:
+       rc $(RCFLAGS) -DSWT_ORG_FILENAME=\"$(SWT_LIB)\" -r -fo swt.res swt.rc
+
+swt_gdip.res:
+       rc $(RCFLAGS) -DSWT_ORG_FILENAME=\"$(GDIP_LIB)\" -r -fo swt_gdip.res swt_gdip.rc
+
+swt_awt.res:
+       rc $(RCFLAGS) -DSWT_ORG_FILENAME=\"$(AWT_LIB)\" -r -fo swt_awt.res swt_awt.rc
+
+swt_webkit.res:
+       rc $(RCFLAGS) -DSWT_ORG_FILENAME=\"$(WEBKIT_LIB)\" -r -fo swt_webkit.res swt_webkit.rc
+
+swt_wgl.res:
+       rc $(RCFLAGS) -DSWT_ORG_FILENAME=\"$(WGL_LIB)\" -r -fo swt_wgl.res swt_wgl.rc
+
+install:
+       copy *.dll "$(OUTPUT_DIR)"
+
+clean:
+    del *.obj *.res *.dll *.lib *.exp
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os.c
new file mode 100644 (file)
index 0000000..dd3dbaa
--- /dev/null
@@ -0,0 +1,10483 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "os_structs.h"
+#include "os_stats.h"
+
+#ifndef OS_NATIVE
+#define OS_NATIVE(func) Java_org_eclipse_swt_internal_win32_OS_##func
+#endif
+
+#ifndef NO_ACCEL_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(ACCEL_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ACCEL_1sizeof_FUNC);
+       rc = (jint)ACCEL_sizeof();
+       OS_NATIVE_EXIT(env, that, ACCEL_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ACTCTX_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(ACTCTX_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ACTCTX_1sizeof_FUNC);
+       rc = (jint)ACTCTX_sizeof();
+       OS_NATIVE_EXIT(env, that, ACTCTX_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AbortDoc
+JNIEXPORT jint JNICALL OS_NATIVE(AbortDoc)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, AbortDoc_FUNC);
+       rc = (jint)AbortDoc((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, AbortDoc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ActivateActCtx
+JNIEXPORT jboolean JNICALL OS_NATIVE(ActivateActCtx)
+       (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1)
+{
+       jlong *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ActivateActCtx_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)ActivateActCtx((HANDLE)arg0, (ULONG_PTR*)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, ActivateActCtx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ActivateKeyboardLayout
+JNIEXPORT jlong JNICALL OS_NATIVE(ActivateKeyboardLayout)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ActivateKeyboardLayout_FUNC);
+       rc = (jlong)ActivateKeyboardLayout((HKL)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, ActivateKeyboardLayout_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AddFontResourceEx
+JNIEXPORT jint JNICALL OS_NATIVE(AddFontResourceEx)
+       (JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jlong arg2)
+{
+       jchar *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, AddFontResourceEx_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)AddFontResourceEx(lparg0, arg1, (PVOID)arg2);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, AddFontResourceEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AdjustWindowRectEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(AdjustWindowRectEx)
+       (JNIEnv *env, jclass that, jobject arg0, jint arg1, jboolean arg2, jint arg3)
+{
+       RECT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, AdjustWindowRectEx_FUNC);
+       if (arg0) if ((lparg0 = getRECTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)AdjustWindowRectEx(lparg0, arg1, arg2, arg3);
+fail:
+       if (arg0 && lparg0) setRECTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, AdjustWindowRectEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AllowSetForegroundWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(AllowSetForegroundWindow)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, AllowSetForegroundWindow_FUNC);
+       rc = (jboolean)AllowSetForegroundWindow(arg0);
+       OS_NATIVE_EXIT(env, that, AllowSetForegroundWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AlphaBlend
+JNIEXPORT jboolean JNICALL OS_NATIVE(AlphaBlend)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jlong arg5, jint arg6, jint arg7, jint arg8, jint arg9, jobject arg10)
+{
+       BLENDFUNCTION _arg10, *lparg10=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, AlphaBlend_FUNC);
+       if (arg10) if ((lparg10 = getBLENDFUNCTIONFields(env, arg10, &_arg10)) == NULL) goto fail;
+       rc = (jboolean)AlphaBlend((HDC)arg0, arg1, arg2, arg3, arg4, (HDC)arg5, arg6, arg7, arg8, arg9, *lparg10);
+fail:
+       if (arg10 && lparg10) setBLENDFUNCTIONFields(env, arg10, lparg10);
+       OS_NATIVE_EXIT(env, that, AlphaBlend_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Arc
+JNIEXPORT jboolean JNICALL OS_NATIVE(Arc)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7, jint arg8)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Arc_FUNC);
+       rc = (jboolean)Arc((HDC)arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+       OS_NATIVE_EXIT(env, that, Arc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_AssocQueryString
+JNIEXPORT jint JNICALL OS_NATIVE(AssocQueryString)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jcharArray arg2, jcharArray arg3, jcharArray arg4, jintArray arg5)
+{
+       jchar *lparg2=NULL;
+       jchar *lparg3=NULL;
+       jchar *lparg4=NULL;
+       jint *lparg5=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, AssocQueryString_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetCharArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)AssocQueryString(arg0, arg1, lparg2, lparg3, lparg4, lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
+       if (arg4 && lparg4) (*env)->ReleaseCharArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, AssocQueryString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BITMAPINFOHEADER_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(BITMAPINFOHEADER_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BITMAPINFOHEADER_1sizeof_FUNC);
+       rc = (jint)BITMAPINFOHEADER_sizeof();
+       OS_NATIVE_EXIT(env, that, BITMAPINFOHEADER_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BITMAP_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(BITMAP_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BITMAP_1sizeof_FUNC);
+       rc = (jint)BITMAP_sizeof();
+       OS_NATIVE_EXIT(env, that, BITMAP_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BLENDFUNCTION_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(BLENDFUNCTION_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BLENDFUNCTION_1sizeof_FUNC);
+       rc = (jint)BLENDFUNCTION_sizeof();
+       OS_NATIVE_EXIT(env, that, BLENDFUNCTION_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BP_1PAINTPARAMS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(BP_1PAINTPARAMS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BP_1PAINTPARAMS_1sizeof_FUNC);
+       rc = (jint)BP_PAINTPARAMS_sizeof();
+       OS_NATIVE_EXIT(env, that, BP_1PAINTPARAMS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BROWSEINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(BROWSEINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BROWSEINFO_1sizeof_FUNC);
+       rc = (jint)BROWSEINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, BROWSEINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BUTTON_1IMAGELIST_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(BUTTON_1IMAGELIST_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BUTTON_1IMAGELIST_1sizeof_FUNC);
+       rc = (jint)BUTTON_IMAGELIST_sizeof();
+       OS_NATIVE_EXIT(env, that, BUTTON_1IMAGELIST_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BeginBufferedPaint
+JNIEXPORT jlong JNICALL OS_NATIVE(BeginBufferedPaint)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2, jobject arg3, jlongArray arg4)
+{
+       RECT _arg1, *lparg1=NULL;
+       BP_PAINTPARAMS _arg3, *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, BeginBufferedPaint_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getBP_PAINTPARAMSFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jlong)BeginBufferedPaint((HDC)arg0, lparg1, arg2, lparg3, (HDC*)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) setBP_PAINTPARAMSFields(env, arg3, lparg3);
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, BeginBufferedPaint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BeginDeferWindowPos
+JNIEXPORT jlong JNICALL OS_NATIVE(BeginDeferWindowPos)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, BeginDeferWindowPos_FUNC);
+       rc = (jlong)BeginDeferWindowPos(arg0);
+       OS_NATIVE_EXIT(env, that, BeginDeferWindowPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BeginPaint
+JNIEXPORT jlong JNICALL OS_NATIVE(BeginPaint)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       PAINTSTRUCT _arg1, *lparg1=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, BeginPaint_FUNC);
+       if (arg1) if ((lparg1 = getPAINTSTRUCTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jlong)BeginPaint((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPAINTSTRUCTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, BeginPaint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BeginPath
+JNIEXPORT jboolean JNICALL OS_NATIVE(BeginPath)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, BeginPath_FUNC);
+       rc = (jboolean)BeginPath((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, BeginPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BitBlt
+JNIEXPORT jboolean JNICALL OS_NATIVE(BitBlt)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jlong arg5, jint arg6, jint arg7, jint arg8)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, BitBlt_FUNC);
+       rc = (jboolean)BitBlt((HDC)arg0, arg1, arg2, arg3, arg4, (HDC)arg5, arg6, arg7, arg8);
+       OS_NATIVE_EXIT(env, that, BitBlt_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BringWindowToTop
+JNIEXPORT jboolean JNICALL OS_NATIVE(BringWindowToTop)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, BringWindowToTop_FUNC);
+       rc = (jboolean)BringWindowToTop((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, BringWindowToTop_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BufferedPaintInit
+JNIEXPORT jint JNICALL OS_NATIVE(BufferedPaintInit)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BufferedPaintInit_FUNC);
+       rc = (jint)BufferedPaintInit();
+       OS_NATIVE_EXIT(env, that, BufferedPaintInit_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_BufferedPaintUnInit
+JNIEXPORT jint JNICALL OS_NATIVE(BufferedPaintUnInit)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, BufferedPaintUnInit_FUNC);
+       rc = (jint)BufferedPaintUnInit();
+       OS_NATIVE_EXIT(env, that, BufferedPaintUnInit_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CANDIDATEFORM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CANDIDATEFORM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CANDIDATEFORM_1sizeof_FUNC);
+       rc = (jint)CANDIDATEFORM_sizeof();
+       OS_NATIVE_EXIT(env, that, CANDIDATEFORM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CERT_1CONTEXT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CERT_1CONTEXT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CERT_1CONTEXT_1sizeof_FUNC);
+       rc = (jint)CERT_CONTEXT_sizeof();
+       OS_NATIVE_EXIT(env, that, CERT_1CONTEXT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CERT_1INFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CERT_1INFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CERT_1INFO_1sizeof_FUNC);
+       rc = (jint)CERT_INFO_sizeof();
+       OS_NATIVE_EXIT(env, that, CERT_1INFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CERT_1NAME_1BLOB_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CERT_1NAME_1BLOB_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CERT_1NAME_1BLOB_1sizeof_FUNC);
+       rc = (jint)CERT_NAME_BLOB_sizeof();
+       OS_NATIVE_EXIT(env, that, CERT_1NAME_1BLOB_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CERT_1PUBLIC_1KEY_1INFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CERT_1PUBLIC_1KEY_1INFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CERT_1PUBLIC_1KEY_1INFO_1sizeof_FUNC);
+       rc = (jint)CERT_PUBLIC_KEY_INFO_sizeof();
+       OS_NATIVE_EXIT(env, that, CERT_1PUBLIC_1KEY_1INFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CHOOSECOLOR_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CHOOSECOLOR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CHOOSECOLOR_1sizeof_FUNC);
+       rc = (jint)CHOOSECOLOR_sizeof();
+       OS_NATIVE_EXIT(env, that, CHOOSECOLOR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CHOOSEFONT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CHOOSEFONT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CHOOSEFONT_1sizeof_FUNC);
+       rc = (jint)CHOOSEFONT_sizeof();
+       OS_NATIVE_EXIT(env, that, CHOOSEFONT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CIDA_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CIDA_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CIDA_1sizeof_FUNC);
+       rc = (jint)CIDA_sizeof();
+       OS_NATIVE_EXIT(env, that, CIDA_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_COMBOBOXINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(COMBOBOXINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, COMBOBOXINFO_1sizeof_FUNC);
+       rc = (jint)COMBOBOXINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, COMBOBOXINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_COMPOSITIONFORM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(COMPOSITIONFORM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, COMPOSITIONFORM_1sizeof_FUNC);
+       rc = (jint)COMPOSITIONFORM_sizeof();
+       OS_NATIVE_EXIT(env, that, COMPOSITIONFORM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CREATESTRUCT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CREATESTRUCT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CREATESTRUCT_1sizeof_FUNC);
+       rc = (jint)CREATESTRUCT_sizeof();
+       OS_NATIVE_EXIT(env, that, CREATESTRUCT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CRYPT_1ALGORITHM_1IDENTIFIER_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CRYPT_1ALGORITHM_1IDENTIFIER_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CRYPT_1ALGORITHM_1IDENTIFIER_1sizeof_FUNC);
+       rc = (jint)CRYPT_ALGORITHM_IDENTIFIER_sizeof();
+       OS_NATIVE_EXIT(env, that, CRYPT_1ALGORITHM_1IDENTIFIER_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CRYPT_1BIT_1BLOB_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CRYPT_1BIT_1BLOB_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CRYPT_1BIT_1BLOB_1sizeof_FUNC);
+       rc = (jint)CRYPT_BIT_BLOB_sizeof();
+       OS_NATIVE_EXIT(env, that, CRYPT_1BIT_1BLOB_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CRYPT_1INTEGER_1BLOB_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CRYPT_1INTEGER_1BLOB_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CRYPT_1INTEGER_1BLOB_1sizeof_FUNC);
+       rc = (jint)CRYPT_INTEGER_BLOB_sizeof();
+       OS_NATIVE_EXIT(env, that, CRYPT_1INTEGER_1BLOB_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CRYPT_1OBJID_1BLOB_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CRYPT_1OBJID_1BLOB_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CRYPT_1OBJID_1BLOB_1sizeof_FUNC);
+       rc = (jint)CRYPT_OBJID_BLOB_sizeof();
+       OS_NATIVE_EXIT(env, that, CRYPT_1OBJID_1BLOB_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CallNextHookEx
+JNIEXPORT jlong JNICALL OS_NATIVE(CallNextHookEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CallNextHookEx_FUNC);
+       rc = (jlong)CallNextHookEx((HHOOK)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
+       OS_NATIVE_EXIT(env, that, CallNextHookEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CallWindowProc
+JNIEXPORT jlong JNICALL OS_NATIVE(CallWindowProc)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CallWindowProc_FUNC);
+       rc = (jlong)CallWindowProc((WNDPROC)arg0, (HWND)arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, CallWindowProc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CertNameToStr
+JNIEXPORT jint JNICALL OS_NATIVE(CertNameToStr)
+       (JNIEnv *env, jclass that, jint arg0, jobject arg1, jint arg2, jcharArray arg3, jint arg4)
+{
+       CERT_NAME_BLOB _arg1, *lparg1=NULL;
+       jchar *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CertNameToStr_FUNC);
+       if (arg1) if ((lparg1 = getCERT_NAME_BLOBFields(env, arg1, &_arg1)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)CertNameToStr(arg0, (PCERT_NAME_BLOB)lparg1, arg2, (LPWSTR)lparg3, arg4);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg1 && lparg1) setCERT_NAME_BLOBFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, CertNameToStr_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CharLower
+JNIEXPORT jlong JNICALL OS_NATIVE(CharLower)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CharLower_FUNC);
+       rc = (jlong)CharLower((LPWSTR)arg0);
+       OS_NATIVE_EXIT(env, that, CharLower_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CharUpper
+JNIEXPORT jlong JNICALL OS_NATIVE(CharUpper)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CharUpper_FUNC);
+       rc = (jlong)CharUpper((LPWSTR)arg0);
+       OS_NATIVE_EXIT(env, that, CharUpper_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ChildWindowFromPointEx
+JNIEXPORT jlong JNICALL OS_NATIVE(ChildWindowFromPointEx)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       POINT _arg1, *lparg1=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ChildWindowFromPointEx_FUNC);
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jlong)ChildWindowFromPointEx((HWND)arg0, *lparg1, (UINT)arg2);
+fail:
+       if (arg1 && lparg1) setPOINTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ChildWindowFromPointEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ChooseColor
+JNIEXPORT jboolean JNICALL OS_NATIVE(ChooseColor)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       CHOOSECOLOR _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ChooseColor_FUNC);
+       if (arg0) if ((lparg0 = getCHOOSECOLORFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)ChooseColor((LPCHOOSECOLORW)lparg0);
+fail:
+       if (arg0 && lparg0) setCHOOSECOLORFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, ChooseColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ChooseFont
+JNIEXPORT jboolean JNICALL OS_NATIVE(ChooseFont)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       CHOOSEFONT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ChooseFont_FUNC);
+       if (arg0) if ((lparg0 = getCHOOSEFONTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)ChooseFont((LPCHOOSEFONTW)lparg0);
+fail:
+       if (arg0 && lparg0) setCHOOSEFONTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, ChooseFont_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ClientToScreen
+JNIEXPORT jboolean JNICALL OS_NATIVE(ClientToScreen)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       POINT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ClientToScreen_FUNC);
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ClientToScreen((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPOINTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ClientToScreen_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CloseClipboard
+JNIEXPORT jboolean JNICALL OS_NATIVE(CloseClipboard)
+       (JNIEnv *env, jclass that)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, CloseClipboard_FUNC);
+       rc = (jboolean)CloseClipboard();
+       OS_NATIVE_EXIT(env, that, CloseClipboard_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CloseEnhMetaFile
+JNIEXPORT jlong JNICALL OS_NATIVE(CloseEnhMetaFile)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CloseEnhMetaFile_FUNC);
+       rc = (jlong)CloseEnhMetaFile((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, CloseEnhMetaFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CloseGestureInfoHandle
+JNIEXPORT jlong JNICALL OS_NATIVE(CloseGestureInfoHandle)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CloseGestureInfoHandle_FUNC);
+/*
+       rc = (jlong)CloseGestureInfoHandle((HGESTUREINFO)arg0);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, CloseGestureInfoHandle)
+               if (fp) {
+                       rc = (jlong)((jlong (CALLING_CONVENTION*)(HGESTUREINFO))fp)((HGESTUREINFO)arg0);
+               }
+       }
+       OS_NATIVE_EXIT(env, that, CloseGestureInfoHandle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CloseHandle
+JNIEXPORT jboolean JNICALL OS_NATIVE(CloseHandle)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, CloseHandle_FUNC);
+       rc = (jboolean)CloseHandle((HANDLE)arg0);
+       OS_NATIVE_EXIT(env, that, CloseHandle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ClosePrinter
+JNIEXPORT jboolean JNICALL OS_NATIVE(ClosePrinter)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ClosePrinter_FUNC);
+       rc = (jboolean)ClosePrinter((HANDLE)arg0);
+       OS_NATIVE_EXIT(env, that, ClosePrinter_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CloseThemeData
+JNIEXPORT jint JNICALL OS_NATIVE(CloseThemeData)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CloseThemeData_FUNC);
+       rc = (jint)CloseThemeData((HTHEME)arg0);
+       OS_NATIVE_EXIT(env, that, CloseThemeData_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CloseTouchInputHandle
+JNIEXPORT jboolean JNICALL OS_NATIVE(CloseTouchInputHandle)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, CloseTouchInputHandle_FUNC);
+/*
+       rc = (jboolean)CloseTouchInputHandle((HTOUCHINPUT)arg0);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, CloseTouchInputHandle)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HTOUCHINPUT))fp)((HTOUCHINPUT)arg0);
+               }
+       }
+       OS_NATIVE_EXIT(env, that, CloseTouchInputHandle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoCreateInstance
+JNIEXPORT jint JNICALL OS_NATIVE(CoCreateInstance)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jlong arg1, jint arg2, jbyteArray arg3, jlongArray arg4)
+{
+       jbyte *lparg0=NULL;
+       jbyte *lparg3=NULL;
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CoCreateInstance_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetByteArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)CoCreateInstance((REFCLSID)lparg0, (LPUNKNOWN)arg1, arg2, (REFIID)lparg3, (LPVOID *)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseByteArrayElements(env, arg3, lparg3, 0);
+       if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, CoCreateInstance_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoInternetIsFeatureEnabled
+JNIEXPORT jint JNICALL OS_NATIVE(CoInternetIsFeatureEnabled)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CoInternetIsFeatureEnabled_FUNC);
+       rc = (jint)CoInternetIsFeatureEnabled(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, CoInternetIsFeatureEnabled_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoInternetSetFeatureEnabled
+JNIEXPORT jint JNICALL OS_NATIVE(CoInternetSetFeatureEnabled)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jboolean arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CoInternetSetFeatureEnabled_FUNC);
+       rc = (jint)CoInternetSetFeatureEnabled(arg0, arg1, (BOOL)arg2);
+       OS_NATIVE_EXIT(env, that, CoInternetSetFeatureEnabled_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoTaskMemAlloc
+JNIEXPORT jlong JNICALL OS_NATIVE(CoTaskMemAlloc)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CoTaskMemAlloc_FUNC);
+       rc = (jlong)CoTaskMemAlloc((ULONG)arg0);
+       OS_NATIVE_EXIT(env, that, CoTaskMemAlloc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CoTaskMemFree
+JNIEXPORT void JNICALL OS_NATIVE(CoTaskMemFree)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       OS_NATIVE_ENTER(env, that, CoTaskMemFree_FUNC);
+       CoTaskMemFree((LPVOID)arg0);
+       OS_NATIVE_EXIT(env, that, CoTaskMemFree_FUNC);
+}
+#endif
+
+#ifndef NO_CombineRgn
+JNIEXPORT jint JNICALL OS_NATIVE(CombineRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jint arg3)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CombineRgn_FUNC);
+       rc = (jint)CombineRgn((HRGN)arg0, (HRGN)arg1, (HRGN)arg2, arg3);
+       OS_NATIVE_EXIT(env, that, CombineRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CommDlgExtendedError
+JNIEXPORT jint JNICALL OS_NATIVE(CommDlgExtendedError)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CommDlgExtendedError_FUNC);
+       rc = (jint)CommDlgExtendedError();
+       OS_NATIVE_EXIT(env, that, CommDlgExtendedError_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CopyImage
+JNIEXPORT jlong JNICALL OS_NATIVE(CopyImage)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CopyImage_FUNC);
+       rc = (jlong)CopyImage((HANDLE)arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, CopyImage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateAcceleratorTable
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateAcceleratorTable)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jint arg1)
+{
+       jbyte *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateAcceleratorTable_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateAcceleratorTable((LPACCEL)lparg0, arg1);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, CreateAcceleratorTable_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateActCtx
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateActCtx)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       ACTCTX _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateActCtx_FUNC);
+       if (arg0) if ((lparg0 = getACTCTXFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jlong)CreateActCtx(lparg0);
+fail:
+       OS_NATIVE_EXIT(env, that, CreateActCtx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateBitmap
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateBitmap)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3, jbyteArray arg4)
+{
+       jbyte *lparg4=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateBitmap_FUNC);
+               if (arg4) if ((lparg4 = (*env)->GetPrimitiveArrayCritical(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateBitmap(arg0, arg1, arg2, arg3, (CONST VOID *)lparg4);
+fail:
+               if (arg4 && lparg4) (*env)->ReleasePrimitiveArrayCritical(env, arg4, lparg4, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, CreateBitmap_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateCaret
+JNIEXPORT jboolean JNICALL OS_NATIVE(CreateCaret)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateCaret_FUNC);
+       rc = (jboolean)CreateCaret((HWND)arg0, (HBITMAP)arg1, arg2, arg3);
+       OS_NATIVE_EXIT(env, that, CreateCaret_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateCompatibleBitmap
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateCompatibleBitmap)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateCompatibleBitmap_FUNC);
+       rc = (jlong)CreateCompatibleBitmap((HDC)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, CreateCompatibleBitmap_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateCompatibleDC
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateCompatibleDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateCompatibleDC_FUNC);
+       rc = (jlong)CreateCompatibleDC((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, CreateCompatibleDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateCursor
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateCursor)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jbyteArray arg5, jbyteArray arg6)
+{
+       jbyte *lparg5=NULL;
+       jbyte *lparg6=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateCursor_FUNC);
+               if (arg5) if ((lparg5 = (*env)->GetPrimitiveArrayCritical(env, arg5, NULL)) == NULL) goto fail;
+               if (arg6) if ((lparg6 = (*env)->GetPrimitiveArrayCritical(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateCursor((HINSTANCE)arg0, arg1, arg2, arg3, arg4, (CONST VOID *)lparg5, (CONST VOID *)lparg6);
+fail:
+               if (arg6 && lparg6) (*env)->ReleasePrimitiveArrayCritical(env, arg6, lparg6, JNI_ABORT);
+               if (arg5 && lparg5) (*env)->ReleasePrimitiveArrayCritical(env, arg5, lparg5, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, CreateCursor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateDC
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateDC)
+       (JNIEnv *env, jclass that, jcharArray arg0, jcharArray arg1, jlong arg2, jlong arg3)
+{
+       jchar *lparg0=NULL;
+       jchar *lparg1=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateDC_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateDC((LPWSTR)lparg0, (LPWSTR)lparg1, (LPWSTR)arg2, (CONST DEVMODEW *)arg3);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, CreateDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateDIBSection__JJI_3JJI
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateDIBSection__JJI_3JJI)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlongArray arg3, jlong arg4, jint arg5)
+{
+       jlong *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateDIBSection__JJI_3JJI_FUNC);
+               if (arg3) if ((lparg3 = (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateDIBSection((HDC)arg0, (BITMAPINFO *)arg1, arg2, (VOID **)lparg3, (HANDLE)arg4, arg5);
+fail:
+               if (arg3 && lparg3) (*env)->ReleasePrimitiveArrayCritical(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, CreateDIBSection__JJI_3JJI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateDIBSection__J_3BI_3JJI
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateDIBSection__J_3BI_3JJI)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jint arg2, jlongArray arg3, jlong arg4, jint arg5)
+{
+       jbyte *lparg1=NULL;
+       jlong *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateDIBSection__J_3BI_3JJI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+               if (arg3) if ((lparg3 = (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateDIBSection((HDC)arg0, (BITMAPINFO *)lparg1, arg2, (VOID **)lparg3, (HANDLE)arg4, arg5);
+fail:
+               if (arg3 && lparg3) (*env)->ReleasePrimitiveArrayCritical(env, arg3, lparg3, 0);
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, CreateDIBSection__J_3BI_3JJI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateEnhMetaFile
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateEnhMetaFile)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jobject arg2, jcharArray arg3)
+{
+       jchar *lparg1=NULL;
+       RECT _arg2, *lparg2=NULL;
+       jchar *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateEnhMetaFile_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)CreateEnhMetaFile((HDC)arg0, (LPCWSTR)lparg1, lparg2, (LPCWSTR)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, CreateEnhMetaFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateFontIndirect__J
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateFontIndirect__J)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateFontIndirect__J_FUNC);
+       rc = (jlong)CreateFontIndirect((LPLOGFONTW)arg0);
+       OS_NATIVE_EXIT(env, that, CreateFontIndirect__J_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateFontIndirect__Lorg_eclipse_swt_internal_win32_LOGFONT_2
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateFontIndirect__Lorg_eclipse_swt_internal_win32_LOGFONT_2)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       LOGFONT _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateFontIndirect__Lorg_eclipse_swt_internal_win32_LOGFONT_2_FUNC);
+       if (arg0) if ((lparg0 = getLOGFONTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jlong)CreateFontIndirect(lparg0);
+fail:
+       OS_NATIVE_EXIT(env, that, CreateFontIndirect__Lorg_eclipse_swt_internal_win32_LOGFONT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateIconIndirect
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateIconIndirect)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       ICONINFO _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateIconIndirect_FUNC);
+       if (arg0) if ((lparg0 = getICONINFOFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jlong)CreateIconIndirect(lparg0);
+fail:
+       OS_NATIVE_EXIT(env, that, CreateIconIndirect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateMenu
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateMenu)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateMenu_FUNC);
+       rc = (jlong)CreateMenu();
+       OS_NATIVE_EXIT(env, that, CreateMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreatePatternBrush
+JNIEXPORT jlong JNICALL OS_NATIVE(CreatePatternBrush)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreatePatternBrush_FUNC);
+       rc = (jlong)CreatePatternBrush((HBITMAP)arg0);
+       OS_NATIVE_EXIT(env, that, CreatePatternBrush_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreatePen
+JNIEXPORT jlong JNICALL OS_NATIVE(CreatePen)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreatePen_FUNC);
+       rc = (jlong)CreatePen(arg0, arg1, (COLORREF)arg2);
+       OS_NATIVE_EXIT(env, that, CreatePen_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreatePolygonRgn
+JNIEXPORT jlong JNICALL OS_NATIVE(CreatePolygonRgn)
+       (JNIEnv *env, jclass that, jintArray arg0, jint arg1, jint arg2)
+{
+       jint *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreatePolygonRgn_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetIntArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)CreatePolygonRgn((CONST POINT *)lparg0, arg1, arg2);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseIntArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, CreatePolygonRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreatePopupMenu
+JNIEXPORT jlong JNICALL OS_NATIVE(CreatePopupMenu)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreatePopupMenu_FUNC);
+       rc = (jlong)CreatePopupMenu();
+       OS_NATIVE_EXIT(env, that, CreatePopupMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateProcess
+JNIEXPORT jboolean JNICALL OS_NATIVE(CreateProcess)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jboolean arg4, jint arg5, jlong arg6, jlong arg7, jobject arg8, jobject arg9)
+{
+       STARTUPINFO _arg8, *lparg8=NULL;
+       PROCESS_INFORMATION _arg9, *lparg9=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateProcess_FUNC);
+       if (arg8) if ((lparg8 = getSTARTUPINFOFields(env, arg8, &_arg8)) == NULL) goto fail;
+       if (arg9) if ((lparg9 = getPROCESS_INFORMATIONFields(env, arg9, &_arg9)) == NULL) goto fail;
+       rc = (jboolean)CreateProcess((LPCWSTR)arg0, (LPWSTR)arg1, (LPSECURITY_ATTRIBUTES)arg2, (LPSECURITY_ATTRIBUTES)arg3, arg4, arg5, (LPVOID)arg6, (LPWSTR)arg7, (LPSTARTUPINFOW)lparg8, (LPPROCESS_INFORMATION)lparg9);
+fail:
+       if (arg9 && lparg9) setPROCESS_INFORMATIONFields(env, arg9, lparg9);
+       if (arg8 && lparg8) setSTARTUPINFOFields(env, arg8, lparg8);
+       OS_NATIVE_EXIT(env, that, CreateProcess_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateRectRgn
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateRectRgn)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateRectRgn_FUNC);
+       rc = (jlong)CreateRectRgn(arg0, arg1, arg2, arg3);
+       OS_NATIVE_EXIT(env, that, CreateRectRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateSolidBrush
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateSolidBrush)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateSolidBrush_FUNC);
+       rc = (jlong)CreateSolidBrush((COLORREF)arg0);
+       OS_NATIVE_EXIT(env, that, CreateSolidBrush_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateStreamOnHGlobal
+JNIEXPORT jint JNICALL OS_NATIVE(CreateStreamOnHGlobal)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1, jlongArray arg2)
+{
+       jlong *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateStreamOnHGlobal_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)CreateStreamOnHGlobal((HGLOBAL)arg0, (BOOL)arg1, (LPSTREAM *)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, CreateStreamOnHGlobal_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CreateWindowEx
+JNIEXPORT jlong JNICALL OS_NATIVE(CreateWindowEx)
+       (JNIEnv *env, jclass that, jint arg0, jcharArray arg1, jcharArray arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7, jlong arg8, jlong arg9, jlong arg10, jobject arg11)
+{
+       jchar *lparg1=NULL;
+       jchar *lparg2=NULL;
+       CREATESTRUCT _arg11, *lparg11=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, CreateWindowEx_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg11) if ((lparg11 = getCREATESTRUCTFields(env, arg11, &_arg11)) == NULL) goto fail;
+       rc = (jlong)CreateWindowEx(arg0, (LPWSTR)lparg1, (LPWSTR)lparg2, arg3, arg4, arg5, arg6, arg7, (HWND)arg8, (HMENU)arg9, (HINSTANCE)arg10, lparg11);
+fail:
+       if (arg11 && lparg11) setCREATESTRUCTFields(env, arg11, lparg11);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, CreateWindowEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DEVMODE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DEVMODE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DEVMODE_1sizeof_FUNC);
+       rc = (jint)DEVMODE_sizeof();
+       OS_NATIVE_EXIT(env, that, DEVMODE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DIBSECTION_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DIBSECTION_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DIBSECTION_1sizeof_FUNC);
+       rc = (jint)DIBSECTION_sizeof();
+       OS_NATIVE_EXIT(env, that, DIBSECTION_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DOCHOSTUIINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DOCHOSTUIINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DOCHOSTUIINFO_1sizeof_FUNC);
+       rc = (jint)DOCHOSTUIINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, DOCHOSTUIINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DOCINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DOCINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DOCINFO_1sizeof_FUNC);
+       rc = (jint)DOCINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, DOCINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DRAWITEMSTRUCT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DRAWITEMSTRUCT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DRAWITEMSTRUCT_1sizeof_FUNC);
+       rc = (jint)DRAWITEMSTRUCT_sizeof();
+       OS_NATIVE_EXIT(env, that, DRAWITEMSTRUCT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DROPFILES_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DROPFILES_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DROPFILES_1sizeof_FUNC);
+       rc = (jint)DROPFILES_sizeof();
+       OS_NATIVE_EXIT(env, that, DROPFILES_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DTTOPTS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(DTTOPTS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DTTOPTS_1sizeof_FUNC);
+       rc = (jint)DTTOPTS_sizeof();
+       OS_NATIVE_EXIT(env, that, DTTOPTS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DefFrameProc
+JNIEXPORT jlong JNICALL OS_NATIVE(DefFrameProc)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jlong arg4)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, DefFrameProc_FUNC);
+       rc = (jlong)DefFrameProc((HWND)arg0, (HWND)arg1, arg2, (WPARAM)arg3, (LPARAM)arg4);
+       OS_NATIVE_EXIT(env, that, DefFrameProc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DefMDIChildProc
+JNIEXPORT jlong JNICALL OS_NATIVE(DefMDIChildProc)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, DefMDIChildProc_FUNC);
+       rc = (jlong)DefMDIChildProc((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
+       OS_NATIVE_EXIT(env, that, DefMDIChildProc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DefWindowProc
+JNIEXPORT jlong JNICALL OS_NATIVE(DefWindowProc)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, DefWindowProc_FUNC);
+       rc = (jlong)DefWindowProc((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
+       OS_NATIVE_EXIT(env, that, DefWindowProc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DeferWindowPos
+JNIEXPORT jlong JNICALL OS_NATIVE(DeferWindowPos)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, DeferWindowPos_FUNC);
+       rc = (jlong)DeferWindowPos((HDWP)arg0, (HWND)arg1, (HWND)arg2, arg3, arg4, arg5, arg6, arg7);
+       OS_NATIVE_EXIT(env, that, DeferWindowPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DeleteDC
+JNIEXPORT jboolean JNICALL OS_NATIVE(DeleteDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DeleteDC_FUNC);
+       rc = (jboolean)DeleteDC((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, DeleteDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DeleteEnhMetaFile
+JNIEXPORT jboolean JNICALL OS_NATIVE(DeleteEnhMetaFile)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DeleteEnhMetaFile_FUNC);
+       rc = (jboolean)DeleteEnhMetaFile((HENHMETAFILE)arg0);
+       OS_NATIVE_EXIT(env, that, DeleteEnhMetaFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DeleteMenu
+JNIEXPORT jboolean JNICALL OS_NATIVE(DeleteMenu)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DeleteMenu_FUNC);
+       rc = (jboolean)DeleteMenu((HMENU)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, DeleteMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DeleteObject
+JNIEXPORT jboolean JNICALL OS_NATIVE(DeleteObject)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DeleteObject_FUNC);
+       rc = (jboolean)DeleteObject((HGDIOBJ)arg0);
+       OS_NATIVE_EXIT(env, that, DeleteObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DestroyAcceleratorTable
+JNIEXPORT jboolean JNICALL OS_NATIVE(DestroyAcceleratorTable)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DestroyAcceleratorTable_FUNC);
+       rc = (jboolean)DestroyAcceleratorTable((HACCEL)arg0);
+       OS_NATIVE_EXIT(env, that, DestroyAcceleratorTable_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DestroyCaret
+JNIEXPORT jboolean JNICALL OS_NATIVE(DestroyCaret)
+       (JNIEnv *env, jclass that)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DestroyCaret_FUNC);
+       rc = (jboolean)DestroyCaret();
+       OS_NATIVE_EXIT(env, that, DestroyCaret_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DestroyCursor
+JNIEXPORT jboolean JNICALL OS_NATIVE(DestroyCursor)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DestroyCursor_FUNC);
+       rc = (jboolean)DestroyCursor((HCURSOR)arg0);
+       OS_NATIVE_EXIT(env, that, DestroyCursor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DestroyIcon
+JNIEXPORT jboolean JNICALL OS_NATIVE(DestroyIcon)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DestroyIcon_FUNC);
+       rc = (jboolean)DestroyIcon((HICON)arg0);
+       OS_NATIVE_EXIT(env, that, DestroyIcon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DestroyMenu
+JNIEXPORT jboolean JNICALL OS_NATIVE(DestroyMenu)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DestroyMenu_FUNC);
+       rc = (jboolean)DestroyMenu((HMENU)arg0);
+       OS_NATIVE_EXIT(env, that, DestroyMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DestroyWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(DestroyWindow)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DestroyWindow_FUNC);
+       rc = (jboolean)DestroyWindow((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, DestroyWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DispatchMessage
+JNIEXPORT jlong JNICALL OS_NATIVE(DispatchMessage)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       MSG _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, DispatchMessage_FUNC);
+       if (arg0) if ((lparg0 = getMSGFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jlong)DispatchMessage(lparg0);
+fail:
+       if (arg0 && lparg0) setMSGFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, DispatchMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DocumentProperties
+JNIEXPORT jint JNICALL OS_NATIVE(DocumentProperties)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jcharArray arg2, jlong arg3, jlong arg4, jint arg5)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DocumentProperties_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)DocumentProperties((HWND)arg0, (HANDLE)arg1, (LPWSTR)lparg2, (PDEVMODEW)arg3, (PDEVMODEW)arg4, arg5);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, DocumentProperties_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DragDetect
+JNIEXPORT jboolean JNICALL OS_NATIVE(DragDetect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       POINT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DragDetect_FUNC);
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)DragDetect((HWND)arg0, *lparg1);
+fail:
+       if (arg1 && lparg1) setPOINTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, DragDetect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DragFinish
+JNIEXPORT void JNICALL OS_NATIVE(DragFinish)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       OS_NATIVE_ENTER(env, that, DragFinish_FUNC);
+       DragFinish((HDROP)arg0);
+       OS_NATIVE_EXIT(env, that, DragFinish_FUNC);
+}
+#endif
+
+#ifndef NO_DragQueryFile
+JNIEXPORT jint JNICALL OS_NATIVE(DragQueryFile)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jcharArray arg2, jint arg3)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DragQueryFile_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)DragQueryFile((HDROP)arg0, arg1, (LPWSTR)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, DragQueryFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawEdge
+JNIEXPORT jboolean JNICALL OS_NATIVE(DrawEdge)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2, jint arg3)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawEdge_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)DrawEdge((HDC)arg0, lparg1, arg2, arg3);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, DrawEdge_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawFocusRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(DrawFocusRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawFocusRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)DrawFocusRect((HDC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, DrawFocusRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawFrameControl
+JNIEXPORT jboolean JNICALL OS_NATIVE(DrawFrameControl)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2, jint arg3)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawFrameControl_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)DrawFrameControl((HDC)arg0, lparg1, arg2, arg3);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, DrawFrameControl_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawIconEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(DrawIconEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jlong arg3, jint arg4, jint arg5, jint arg6, jlong arg7, jint arg8)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawIconEx_FUNC);
+       rc = (jboolean)DrawIconEx((HDC)arg0, arg1, arg2, (HICON)arg3, arg4, arg5, arg6, (HBRUSH)arg7, arg8);
+       OS_NATIVE_EXIT(env, that, DrawIconEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawMenuBar
+JNIEXPORT jboolean JNICALL OS_NATIVE(DrawMenuBar)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawMenuBar_FUNC);
+       rc = (jboolean)DrawMenuBar((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, DrawMenuBar_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawText
+JNIEXPORT jint JNICALL OS_NATIVE(DrawText)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jobject arg3, jint arg4)
+{
+       jchar *lparg1=NULL;
+       RECT _arg3, *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawText_FUNC);
+       if (arg3) if ((lparg3 = getRECTFields(env, arg3, &_arg3)) == NULL) goto fail;
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)DrawText((HDC)arg0, (LPWSTR)lparg1, arg2, lparg3, arg4);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       if (arg3 && lparg3) setRECTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, DrawText_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawThemeBackground
+JNIEXPORT jint JNICALL OS_NATIVE(DrawThemeBackground)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jobject arg4, jobject arg5)
+{
+       RECT _arg4, *lparg4=NULL;
+       RECT _arg5, *lparg5=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawThemeBackground_FUNC);
+       if (arg4) if ((lparg4 = getRECTFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = getRECTFields(env, arg5, &_arg5)) == NULL) goto fail;
+       rc = (jint)DrawThemeBackground((HTHEME)arg0, (HDC)arg1, arg2, arg3, (const RECT *)lparg4, (const RECT *)lparg5);
+fail:
+       if (arg5 && lparg5) setRECTFields(env, arg5, lparg5);
+       if (arg4 && lparg4) setRECTFields(env, arg4, lparg4);
+       OS_NATIVE_EXIT(env, that, DrawThemeBackground_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DrawThemeText
+JNIEXPORT jint JNICALL OS_NATIVE(DrawThemeText)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jcharArray arg4, jint arg5, jint arg6, jint arg7, jobject arg8)
+{
+       jchar *lparg4=NULL;
+       RECT _arg8, *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, DrawThemeText_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetCharArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = getRECTFields(env, arg8, &_arg8)) == NULL) goto fail;
+       rc = (jint)DrawThemeText((HTHEME)arg0, (HDC)arg1, arg2, arg3, lparg4, arg5, arg6, arg7, lparg8);
+fail:
+       if (arg8 && lparg8) setRECTFields(env, arg8, lparg8);
+       if (arg4 && lparg4) (*env)->ReleaseCharArrayElements(env, arg4, lparg4, 0);
+       OS_NATIVE_EXIT(env, that, DrawThemeText_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DuplicateHandle
+JNIEXPORT jboolean JNICALL OS_NATIVE(DuplicateHandle)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlongArray arg3, jint arg4, jboolean arg5, jint arg6)
+{
+       jlong *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, DuplicateHandle_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jboolean)DuplicateHandle((HANDLE)arg0, (HANDLE)arg1, (HANDLE)arg2, (LPHANDLE)lparg3, (DWORD)arg4, arg5, (DWORD)arg6);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, DuplicateHandle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EMREXTCREATEFONTINDIRECTW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(EMREXTCREATEFONTINDIRECTW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EMREXTCREATEFONTINDIRECTW_1sizeof_FUNC);
+       rc = (jint)EMREXTCREATEFONTINDIRECTW_sizeof();
+       OS_NATIVE_EXIT(env, that, EMREXTCREATEFONTINDIRECTW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EMR_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(EMR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EMR_1sizeof_FUNC);
+       rc = (jint)EMR_sizeof();
+       OS_NATIVE_EXIT(env, that, EMR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EXTLOGFONTW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(EXTLOGFONTW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EXTLOGFONTW_1sizeof_FUNC);
+       rc = (jint)EXTLOGFONTW_sizeof();
+       OS_NATIVE_EXIT(env, that, EXTLOGFONTW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Ellipse
+JNIEXPORT jboolean JNICALL OS_NATIVE(Ellipse)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Ellipse_FUNC);
+       rc = (jboolean)Ellipse((HDC)arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, Ellipse_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnableMenuItem
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnableMenuItem)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnableMenuItem_FUNC);
+       rc = (jboolean)EnableMenuItem((HMENU)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, EnableMenuItem_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnableScrollBar
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnableScrollBar)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnableScrollBar_FUNC);
+       rc = (jboolean)EnableScrollBar((HWND)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, EnableScrollBar_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnableWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnableWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnableWindow_FUNC);
+       rc = (jboolean)EnableWindow((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, EnableWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EndBufferedPaint
+JNIEXPORT jint JNICALL OS_NATIVE(EndBufferedPaint)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EndBufferedPaint_FUNC);
+       rc = (jint)EndBufferedPaint((HPAINTBUFFER)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, EndBufferedPaint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EndDeferWindowPos
+JNIEXPORT jboolean JNICALL OS_NATIVE(EndDeferWindowPos)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EndDeferWindowPos_FUNC);
+       rc = (jboolean)EndDeferWindowPos((HDWP)arg0);
+       OS_NATIVE_EXIT(env, that, EndDeferWindowPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EndDoc
+JNIEXPORT jint JNICALL OS_NATIVE(EndDoc)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EndDoc_FUNC);
+       rc = (jint)EndDoc((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, EndDoc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EndPage
+JNIEXPORT jint JNICALL OS_NATIVE(EndPage)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EndPage_FUNC);
+       rc = (jint)EndPage((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, EndPage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EndPaint
+JNIEXPORT jint JNICALL OS_NATIVE(EndPaint)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       PAINTSTRUCT _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EndPaint_FUNC);
+       if (arg1) if ((lparg1 = getPAINTSTRUCTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)EndPaint((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPAINTSTRUCTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, EndPaint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnumDisplayMonitors
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnumDisplayMonitors)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2, jint arg3)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnumDisplayMonitors_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)EnumDisplayMonitors((HDC)arg0, (LPCRECT)lparg1, (MONITORENUMPROC)arg2, (LPARAM)arg3);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, EnumDisplayMonitors_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnumEnhMetaFile
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnumEnhMetaFile)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jobject arg4)
+{
+       RECT _arg4, *lparg4=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnumEnhMetaFile_FUNC);
+       if (arg4) if ((lparg4 = getRECTFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jboolean)EnumEnhMetaFile((HDC)arg0, (HENHMETAFILE)arg1, (ENHMFENUMPROC)arg2, (LPVOID)arg3, lparg4);
+fail:
+       if (arg4 && lparg4) setRECTFields(env, arg4, lparg4);
+       OS_NATIVE_EXIT(env, that, EnumEnhMetaFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnumFontFamilies
+JNIEXPORT jint JNICALL OS_NATIVE(EnumFontFamilies)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2, jlong arg3)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, EnumFontFamilies_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)EnumFontFamilies((HDC)arg0, (LPCWSTR)lparg1, (FONTENUMPROCW)arg2, (LPARAM)arg3);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, EnumFontFamilies_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnumSystemLanguageGroups
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnumSystemLanguageGroups)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnumSystemLanguageGroups_FUNC);
+       rc = (jboolean)EnumSystemLanguageGroups((LANGUAGEGROUP_ENUMPROCW)arg0, arg1, (LONG_PTR)arg2);
+       OS_NATIVE_EXIT(env, that, EnumSystemLanguageGroups_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EnumSystemLocales
+JNIEXPORT jboolean JNICALL OS_NATIVE(EnumSystemLocales)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EnumSystemLocales_FUNC);
+       rc = (jboolean)EnumSystemLocales((LOCALE_ENUMPROCW)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, EnumSystemLocales_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_EqualRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(EqualRect)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1)
+{
+       RECT _arg0, *lparg0=NULL;
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, EqualRect_FUNC);
+       if (arg0) if ((lparg0 = getRECTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)EqualRect((CONST RECT *)lparg0, (CONST RECT *)lparg1);
+fail:
+       OS_NATIVE_EXIT(env, that, EqualRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ExcludeClipRect
+JNIEXPORT jint JNICALL OS_NATIVE(ExcludeClipRect)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ExcludeClipRect_FUNC);
+       rc = (jint)ExcludeClipRect((HDC)arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, ExcludeClipRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ExpandEnvironmentStrings
+JNIEXPORT jint JNICALL OS_NATIVE(ExpandEnvironmentStrings)
+       (JNIEnv *env, jclass that, jcharArray arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg0=NULL;
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ExpandEnvironmentStrings_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)ExpandEnvironmentStrings(lparg0, lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, ExpandEnvironmentStrings_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ExtCreatePen
+JNIEXPORT jlong JNICALL OS_NATIVE(ExtCreatePen)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jobject arg2, jint arg3, jintArray arg4)
+{
+       LOGBRUSH _arg2, *lparg2=NULL;
+       jint *lparg4=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ExtCreatePen_FUNC);
+       if (arg2) if ((lparg2 = getLOGBRUSHFields(env, arg2, &_arg2)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jlong)ExtCreatePen(arg0, arg1, (CONST LOGBRUSH *)lparg2, arg3, (CONST DWORD *)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       if (arg2 && lparg2) setLOGBRUSHFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, ExtCreatePen_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ExtCreateRegion
+JNIEXPORT jlong JNICALL OS_NATIVE(ExtCreateRegion)
+       (JNIEnv *env, jclass that, jfloatArray arg0, jint arg1, jintArray arg2)
+{
+       jfloat *lparg0=NULL;
+       jint *lparg2=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ExtCreateRegion_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetFloatArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jlong)ExtCreateRegion((XFORM *)lparg0, arg1, (CONST RGNDATA *)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       if (arg0 && lparg0) (*env)->ReleaseFloatArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, ExtCreateRegion_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ExtTextOut
+JNIEXPORT jboolean JNICALL OS_NATIVE(ExtTextOut)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jobject arg4, jcharArray arg5, jint arg6, jintArray arg7)
+{
+       RECT _arg4, *lparg4=NULL;
+       jchar *lparg5=NULL;
+       jint *lparg7=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ExtTextOut_FUNC);
+       if (arg4) if ((lparg4 = getRECTFields(env, arg4, &_arg4)) == NULL) goto fail;
+               if (arg5) if ((lparg5 = (*env)->GetPrimitiveArrayCritical(env, arg5, NULL)) == NULL) goto fail;
+               if (arg7) if ((lparg7 = (*env)->GetPrimitiveArrayCritical(env, arg7, NULL)) == NULL) goto fail;
+       rc = (jboolean)ExtTextOut((HDC)arg0, arg1, arg2, arg3, lparg4, (LPWSTR)lparg5, arg6, (CONST INT *)lparg7);
+fail:
+               if (arg7 && lparg7) (*env)->ReleasePrimitiveArrayCritical(env, arg7, lparg7, JNI_ABORT);
+               if (arg5 && lparg5) (*env)->ReleasePrimitiveArrayCritical(env, arg5, lparg5, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, ExtTextOut_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ExtractIconEx
+JNIEXPORT jint JNICALL OS_NATIVE(ExtractIconEx)
+       (JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jlongArray arg2, jlongArray arg3, jint arg4)
+{
+       jchar *lparg0=NULL;
+       jlong *lparg2=NULL;
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ExtractIconEx_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)ExtractIconEx((LPWSTR)lparg0, arg1, (HICON FAR *)lparg2, (HICON FAR *)lparg3, arg4);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, ExtractIconEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FILETIME_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(FILETIME_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, FILETIME_1sizeof_FUNC);
+       rc = (jint)FILETIME_sizeof();
+       OS_NATIVE_EXIT(env, that, FILETIME_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FLICK_1DATA_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(FLICK_1DATA_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, FLICK_1DATA_1sizeof_FUNC);
+       rc = (jint)FLICK_DATA_sizeof();
+       OS_NATIVE_EXIT(env, that, FLICK_1DATA_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FLICK_1POINT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(FLICK_1POINT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, FLICK_1POINT_1sizeof_FUNC);
+       rc = (jint)FLICK_POINT_sizeof();
+       OS_NATIVE_EXIT(env, that, FLICK_1POINT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FileTimeToSystemTime
+JNIEXPORT jboolean JNICALL OS_NATIVE(FileTimeToSystemTime)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1)
+{
+       FILETIME _arg0, *lparg0=NULL;
+       SYSTEMTIME _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, FileTimeToSystemTime_FUNC);
+       if (arg0) if ((lparg0 = getFILETIMEFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getSYSTEMTIMEFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)FileTimeToSystemTime(lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setSYSTEMTIMEFields(env, arg1, lparg1);
+       if (arg0 && lparg0) setFILETIMEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, FileTimeToSystemTime_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FillRect
+JNIEXPORT jint JNICALL OS_NATIVE(FillRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2)
+{
+       RECT _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, FillRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)FillRect((HDC)arg0, lparg1, (HBRUSH)arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, FillRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_FormatMessage
+JNIEXPORT jint JNICALL OS_NATIVE(FormatMessage)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jint arg3, jlongArray arg4, jint arg5, jlong arg6)
+{
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, FormatMessage_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)FormatMessage(arg0, (LPCVOID)arg1, arg2, arg3, (LPWSTR)lparg4, arg5, (va_list*)arg6);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       OS_NATIVE_EXIT(env, that, FormatMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GCP_1RESULTS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(GCP_1RESULTS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GCP_1RESULTS_1sizeof_FUNC);
+       rc = (jint)GCP_RESULTS_sizeof();
+       OS_NATIVE_EXIT(env, that, GCP_1RESULTS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GESTURECONFIG_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(GESTURECONFIG_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GESTURECONFIG_1sizeof_FUNC);
+       rc = (jint)GESTURECONFIG_sizeof();
+       OS_NATIVE_EXIT(env, that, GESTURECONFIG_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GESTUREINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(GESTUREINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GESTUREINFO_1sizeof_FUNC);
+       rc = (jint)GESTUREINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, GESTUREINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GET_1WHEEL_1DELTA_1WPARAM
+JNIEXPORT jint JNICALL OS_NATIVE(GET_1WHEEL_1DELTA_1WPARAM)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GET_1WHEEL_1DELTA_1WPARAM_FUNC);
+       rc = (jint)GET_WHEEL_DELTA_WPARAM(arg0);
+       OS_NATIVE_EXIT(env, that, GET_1WHEEL_1DELTA_1WPARAM_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GET_1X_1LPARAM
+JNIEXPORT jint JNICALL OS_NATIVE(GET_1X_1LPARAM)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GET_1X_1LPARAM_FUNC);
+       rc = (jint)GET_X_LPARAM(arg0);
+       OS_NATIVE_EXIT(env, that, GET_1X_1LPARAM_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GET_1Y_1LPARAM
+JNIEXPORT jint JNICALL OS_NATIVE(GET_1Y_1LPARAM)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GET_1Y_1LPARAM_FUNC);
+       rc = (jint)GET_Y_LPARAM(arg0);
+       OS_NATIVE_EXIT(env, that, GET_1Y_1LPARAM_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GID_1ROTATE_1ANGLE_1FROM_1ARGUMENT
+JNIEXPORT jdouble JNICALL OS_NATIVE(GID_1ROTATE_1ANGLE_1FROM_1ARGUMENT)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jdouble rc = 0;
+       OS_NATIVE_ENTER(env, that, GID_1ROTATE_1ANGLE_1FROM_1ARGUMENT_FUNC);
+       rc = (jdouble)GID_ROTATE_ANGLE_FROM_ARGUMENT(arg0);
+       OS_NATIVE_EXIT(env, that, GID_1ROTATE_1ANGLE_1FROM_1ARGUMENT_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GRADIENT_1RECT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(GRADIENT_1RECT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GRADIENT_1RECT_1sizeof_FUNC);
+       rc = (jint)GRADIENT_RECT_sizeof();
+       OS_NATIVE_EXIT(env, that, GRADIENT_1RECT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GUITHREADINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(GUITHREADINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GUITHREADINFO_1sizeof_FUNC);
+       rc = (jint)GUITHREADINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, GUITHREADINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GdiSetBatchLimit
+JNIEXPORT jint JNICALL OS_NATIVE(GdiSetBatchLimit)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GdiSetBatchLimit_FUNC);
+       rc = (jint)GdiSetBatchLimit((DWORD)arg0);
+       OS_NATIVE_EXIT(env, that, GdiSetBatchLimit_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetACP
+JNIEXPORT jint JNICALL OS_NATIVE(GetACP)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetACP_FUNC);
+       rc = (jint)GetACP();
+       OS_NATIVE_EXIT(env, that, GetACP_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetActiveWindow
+JNIEXPORT jlong JNICALL OS_NATIVE(GetActiveWindow)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetActiveWindow_FUNC);
+       rc = (jlong)GetActiveWindow();
+       OS_NATIVE_EXIT(env, that, GetActiveWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetBkColor
+JNIEXPORT jint JNICALL OS_NATIVE(GetBkColor)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetBkColor_FUNC);
+       rc = (jint)GetBkColor((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetBkColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCapture
+JNIEXPORT jlong JNICALL OS_NATIVE(GetCapture)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCapture_FUNC);
+       rc = (jlong)GetCapture();
+       OS_NATIVE_EXIT(env, that, GetCapture_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCaretPos
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetCaretPos)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       POINT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCaretPos_FUNC);
+       if (arg0) if ((lparg0 = getPOINTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)GetCaretPos(lparg0);
+fail:
+       if (arg0 && lparg0) setPOINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, GetCaretPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCharABCWidths
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetCharABCWidths)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jintArray arg3)
+{
+       jint *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCharABCWidths_FUNC);
+               if (arg3) if ((lparg3 = (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jboolean)GetCharABCWidths((HDC)arg0, arg1, arg2, (LPABC)lparg3);
+fail:
+               if (arg3 && lparg3) (*env)->ReleasePrimitiveArrayCritical(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, GetCharABCWidths_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCharWidth
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetCharWidth)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jintArray arg3)
+{
+       jint *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCharWidth_FUNC);
+               if (arg3) if ((lparg3 = (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jboolean)GetCharWidth((HDC)arg0, arg1, arg2, (LPINT)lparg3);
+fail:
+               if (arg3 && lparg3) (*env)->ReleasePrimitiveArrayCritical(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, GetCharWidth_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCharacterPlacement
+JNIEXPORT jint JNICALL OS_NATIVE(GetCharacterPlacement)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jint arg3, jobject arg4, jint arg5)
+{
+       jchar *lparg1=NULL;
+       GCP_RESULTS _arg4, *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCharacterPlacement_FUNC);
+       if (arg4) if ((lparg4 = getGCP_RESULTSFields(env, arg4, &_arg4)) == NULL) goto fail;
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetCharacterPlacement((HDC)arg0, (LPWSTR)lparg1, arg2, arg3, (LPGCP_RESULTSW)lparg4, arg5);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       if (arg4 && lparg4) setGCP_RESULTSFields(env, arg4, lparg4);
+       OS_NATIVE_EXIT(env, that, GetCharacterPlacement_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClassInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetClassInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jobject arg2)
+{
+       jchar *lparg1=NULL;
+       WNDCLASS _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClassInfo_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getWNDCLASSFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)GetClassInfo((HINSTANCE)arg0, (LPWSTR)lparg1, (LPWNDCLASSW)lparg2);
+fail:
+       if (arg2 && lparg2) setWNDCLASSFields(env, arg2, lparg2);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetClassInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClassName
+JNIEXPORT jint JNICALL OS_NATIVE(GetClassName)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClassName_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetClassName((HWND)arg0, lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetClassName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClientRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetClientRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClientRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetClientRect((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetClientRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClipBox
+JNIEXPORT jint JNICALL OS_NATIVE(GetClipBox)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClipBox_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)GetClipBox((HDC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetClipBox_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClipRgn
+JNIEXPORT jint JNICALL OS_NATIVE(GetClipRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClipRgn_FUNC);
+       rc = (jint)GetClipRgn((HDC)arg0, (HRGN)arg1);
+       OS_NATIVE_EXIT(env, that, GetClipRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClipboardData
+JNIEXPORT jlong JNICALL OS_NATIVE(GetClipboardData)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClipboardData_FUNC);
+       rc = (jlong)GetClipboardData(arg0);
+       OS_NATIVE_EXIT(env, that, GetClipboardData_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetClipboardFormatName
+JNIEXPORT jint JNICALL OS_NATIVE(GetClipboardFormatName)
+       (JNIEnv *env, jclass that, jint arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetClipboardFormatName_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetClipboardFormatName(arg0, (LPWSTR)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetClipboardFormatName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetComboBoxInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetComboBoxInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       COMBOBOXINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetComboBoxInfo_FUNC);
+       if (arg1) if ((lparg1 = getCOMBOBOXINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetComboBoxInfo((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setCOMBOBOXINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetComboBoxInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCurrentObject
+JNIEXPORT jlong JNICALL OS_NATIVE(GetCurrentObject)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCurrentObject_FUNC);
+       rc = (jlong)GetCurrentObject((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetCurrentObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCurrentProcess
+JNIEXPORT jlong JNICALL OS_NATIVE(GetCurrentProcess)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCurrentProcess_FUNC);
+       rc = (jlong)GetCurrentProcess();
+       OS_NATIVE_EXIT(env, that, GetCurrentProcess_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCurrentProcessExplicitAppUserModelID
+JNIEXPORT jint JNICALL OS_NATIVE(GetCurrentProcessExplicitAppUserModelID)
+       (JNIEnv *env, jclass that, jlongArray arg0)
+{
+       jlong *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCurrentProcessExplicitAppUserModelID_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetLongArrayElements(env, arg0, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)GetCurrentProcessExplicitAppUserModelID(lparg0);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, GetCurrentProcessExplicitAppUserModelID)
+               if (fp) {
+                       rc = (jint)((jint (CALLING_CONVENTION*)(jlong *))fp)(lparg0);
+               }
+       }
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseLongArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, GetCurrentProcessExplicitAppUserModelID_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCurrentProcessId
+JNIEXPORT jint JNICALL OS_NATIVE(GetCurrentProcessId)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCurrentProcessId_FUNC);
+       rc = (jint)GetCurrentProcessId();
+       OS_NATIVE_EXIT(env, that, GetCurrentProcessId_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCurrentThreadId
+JNIEXPORT jint JNICALL OS_NATIVE(GetCurrentThreadId)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCurrentThreadId_FUNC);
+       rc = (jint)GetCurrentThreadId();
+       OS_NATIVE_EXIT(env, that, GetCurrentThreadId_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCursor
+JNIEXPORT jlong JNICALL OS_NATIVE(GetCursor)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCursor_FUNC);
+       rc = (jlong)GetCursor();
+       OS_NATIVE_EXIT(env, that, GetCursor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetCursorPos
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetCursorPos)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       POINT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetCursorPos_FUNC);
+       if (arg0) if ((lparg0 = getPOINTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)GetCursorPos(lparg0);
+fail:
+       if (arg0 && lparg0) setPOINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, GetCursorPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDC
+JNIEXPORT jlong JNICALL OS_NATIVE(GetDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDC_FUNC);
+       rc = (jlong)GetDC((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, GetDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDCEx
+JNIEXPORT jlong JNICALL OS_NATIVE(GetDCEx)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDCEx_FUNC);
+       rc = (jlong)GetDCEx((HWND)arg0, (HRGN)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, GetDCEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDIBColorTable
+JNIEXPORT jint JNICALL OS_NATIVE(GetDIBColorTable)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jbyteArray arg3)
+{
+       jbyte *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDIBColorTable_FUNC);
+               if (arg3) if ((lparg3 = (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)GetDIBColorTable((HDC)arg0, arg1, arg2, (RGBQUAD *)lparg3);
+fail:
+               if (arg3 && lparg3) (*env)->ReleasePrimitiveArrayCritical(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, GetDIBColorTable_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDIBits
+JNIEXPORT jint JNICALL OS_NATIVE(GetDIBits)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jbyteArray arg4, jbyteArray arg5, jint arg6)
+{
+       jbyte *lparg4=NULL;
+       jbyte *lparg5=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDIBits_FUNC);
+               if (arg4) if ((lparg4 = (*env)->GetPrimitiveArrayCritical(env, arg4, NULL)) == NULL) goto fail;
+               if (arg5) if ((lparg5 = (*env)->GetPrimitiveArrayCritical(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)GetDIBits((HDC)arg0, (HBITMAP)arg1, arg2, arg3, (LPVOID)lparg4, (LPBITMAPINFO)lparg5, arg6);
+fail:
+               if (arg5 && lparg5) (*env)->ReleasePrimitiveArrayCritical(env, arg5, lparg5, 0);
+               if (arg4 && lparg4) (*env)->ReleasePrimitiveArrayCritical(env, arg4, lparg4, 0);
+       OS_NATIVE_EXIT(env, that, GetDIBits_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDesktopWindow
+JNIEXPORT jlong JNICALL OS_NATIVE(GetDesktopWindow)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDesktopWindow_FUNC);
+       rc = (jlong)GetDesktopWindow();
+       OS_NATIVE_EXIT(env, that, GetDesktopWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDeviceCaps
+JNIEXPORT jint JNICALL OS_NATIVE(GetDeviceCaps)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDeviceCaps_FUNC);
+       rc = (jint)GetDeviceCaps((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetDeviceCaps_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDialogBaseUnits
+JNIEXPORT jint JNICALL OS_NATIVE(GetDialogBaseUnits)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDialogBaseUnits_FUNC);
+       rc = (jint)GetDialogBaseUnits();
+       OS_NATIVE_EXIT(env, that, GetDialogBaseUnits_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDlgItem
+JNIEXPORT jlong JNICALL OS_NATIVE(GetDlgItem)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDlgItem_FUNC);
+       rc = (jlong)GetDlgItem((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetDlgItem_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDoubleClickTime
+JNIEXPORT jint JNICALL OS_NATIVE(GetDoubleClickTime)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDoubleClickTime_FUNC);
+       rc = (jint)GetDoubleClickTime();
+       OS_NATIVE_EXIT(env, that, GetDoubleClickTime_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetDpiForMonitor
+JNIEXPORT jint JNICALL OS_NATIVE(GetDpiForMonitor)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jintArray arg2, jintArray arg3)
+{
+       jint *lparg2=NULL;
+       jint *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetDpiForMonitor_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)GetDpiForMonitor(arg0, arg1, lparg2, lparg3);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, GetDpiForMonitor)
+               if (fp) {
+                       rc = (jint)((jint (CALLING_CONVENTION*)(jlong, jint, jint *, jint *))fp)(arg0, arg1, lparg2, lparg3);
+               }
+       }
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, GetDpiForMonitor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetFocus
+JNIEXPORT jlong JNICALL OS_NATIVE(GetFocus)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetFocus_FUNC);
+       rc = (jlong)GetFocus();
+       OS_NATIVE_EXIT(env, that, GetFocus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetFontLanguageInfo
+JNIEXPORT jint JNICALL OS_NATIVE(GetFontLanguageInfo)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetFontLanguageInfo_FUNC);
+       rc = (jint)GetFontLanguageInfo((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetFontLanguageInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetForegroundWindow
+JNIEXPORT jlong JNICALL OS_NATIVE(GetForegroundWindow)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetForegroundWindow_FUNC);
+       rc = (jlong)GetForegroundWindow();
+       OS_NATIVE_EXIT(env, that, GetForegroundWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetGUIThreadInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetGUIThreadInfo)
+       (JNIEnv *env, jclass that, jint arg0, jobject arg1)
+{
+       GUITHREADINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetGUIThreadInfo_FUNC);
+       if (arg1) if ((lparg1 = getGUITHREADINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetGUIThreadInfo((DWORD)arg0, (LPGUITHREADINFO)lparg1);
+fail:
+       if (arg1 && lparg1) setGUITHREADINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetGUIThreadInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetGestureInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetGestureInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       GESTUREINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetGestureInfo_FUNC);
+       if (arg1) if ((lparg1 = getGESTUREINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+/*
+       rc = (jboolean)GetGestureInfo((HGESTUREINFO)arg0, (PGESTUREINFO)lparg1);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, GetGestureInfo)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HGESTUREINFO, PGESTUREINFO))fp)((HGESTUREINFO)arg0, (PGESTUREINFO)lparg1);
+               }
+       }
+fail:
+       if (arg1 && lparg1) setGESTUREINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetGestureInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetGlyphIndices
+JNIEXPORT jint JNICALL OS_NATIVE(GetGlyphIndices)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jshortArray arg3, jint arg4)
+{
+       jchar *lparg1=NULL;
+       jshort *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetGlyphIndices_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetShortArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)GetGlyphIndices((HDC)arg0, lparg1, arg2, (LPWORD)lparg3, arg4);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseShortArrayElements(env, arg3, lparg3, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetGlyphIndices_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetGraphicsMode
+JNIEXPORT jint JNICALL OS_NATIVE(GetGraphicsMode)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetGraphicsMode_FUNC);
+       rc = (jint)GetGraphicsMode((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetGraphicsMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetIconInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetIconInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       ICONINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetIconInfo_FUNC);
+       if (arg1) if ((lparg1 = &_arg1) == NULL) goto fail;
+       rc = (jboolean)GetIconInfo((HICON)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setICONINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetIconInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetKeyState
+JNIEXPORT jshort JNICALL OS_NATIVE(GetKeyState)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jshort rc = 0;
+       OS_NATIVE_ENTER(env, that, GetKeyState_FUNC);
+       rc = (jshort)GetKeyState(arg0);
+       OS_NATIVE_EXIT(env, that, GetKeyState_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetKeyboardLayout
+JNIEXPORT jlong JNICALL OS_NATIVE(GetKeyboardLayout)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetKeyboardLayout_FUNC);
+       rc = (jlong)GetKeyboardLayout(arg0);
+       OS_NATIVE_EXIT(env, that, GetKeyboardLayout_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetKeyboardLayoutList
+JNIEXPORT jint JNICALL OS_NATIVE(GetKeyboardLayoutList)
+       (JNIEnv *env, jclass that, jint arg0, jlongArray arg1)
+{
+       jlong *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetKeyboardLayoutList_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetKeyboardLayoutList(arg0, (HKL FAR *)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetKeyboardLayoutList_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetKeyboardState
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetKeyboardState)
+       (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+       jbyte *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetKeyboardState_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jboolean)GetKeyboardState((PBYTE)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, GetKeyboardState_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetLastActivePopup
+JNIEXPORT jlong JNICALL OS_NATIVE(GetLastActivePopup)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetLastActivePopup_FUNC);
+       rc = (jlong)GetLastActivePopup((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, GetLastActivePopup_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetLastError
+JNIEXPORT jint JNICALL OS_NATIVE(GetLastError)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetLastError_FUNC);
+       rc = (jint)GetLastError();
+       OS_NATIVE_EXIT(env, that, GetLastError_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetLayeredWindowAttributes
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetLayeredWindowAttributes)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jbyteArray arg2, jintArray arg3)
+{
+       jint *lparg1=NULL;
+       jbyte *lparg2=NULL;
+       jint *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetLayeredWindowAttributes_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jboolean)GetLayeredWindowAttributes((HWND)arg0, lparg1, lparg2, lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetLayeredWindowAttributes_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetLayout
+JNIEXPORT jint JNICALL OS_NATIVE(GetLayout)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetLayout_FUNC);
+       rc = (jint)GetLayout((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetLayout_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetLocaleInfo
+JNIEXPORT jint JNICALL OS_NATIVE(GetLocaleInfo)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jcharArray arg2, jint arg3)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetLocaleInfo_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)GetLocaleInfo(arg0, arg1, (LPWSTR)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, GetLocaleInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenu
+JNIEXPORT jlong JNICALL OS_NATIVE(GetMenu)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenu_FUNC);
+       rc = (jlong)GetMenu((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, GetMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenuBarInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetMenuBarInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jobject arg3)
+{
+       MENUBARINFO _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenuBarInfo_FUNC);
+       if (arg3) if ((lparg3 = getMENUBARINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)GetMenuBarInfo((HWND)arg0, arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) setMENUBARINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, GetMenuBarInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenuDefaultItem
+JNIEXPORT jint JNICALL OS_NATIVE(GetMenuDefaultItem)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenuDefaultItem_FUNC);
+       rc = (jint)GetMenuDefaultItem((HMENU)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, GetMenuDefaultItem_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenuInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetMenuInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       MENUINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenuInfo_FUNC);
+       if (arg1) if ((lparg1 = getMENUINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetMenuInfo((HMENU)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setMENUINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetMenuInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenuItemCount
+JNIEXPORT jint JNICALL OS_NATIVE(GetMenuItemCount)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenuItemCount_FUNC);
+       rc = (jint)GetMenuItemCount((HMENU)arg0);
+       OS_NATIVE_EXIT(env, that, GetMenuItemCount_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenuItemInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetMenuItemInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jboolean arg2, jobject arg3)
+{
+       MENUITEMINFO _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenuItemInfo_FUNC);
+       if (arg3) if ((lparg3 = getMENUITEMINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)GetMenuItemInfo((HMENU)arg0, arg1, arg2, (LPMENUITEMINFOW)lparg3);
+fail:
+       if (arg3 && lparg3) setMENUITEMINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, GetMenuItemInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMenuItemRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetMenuItemRect)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jobject arg3)
+{
+       RECT _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMenuItemRect_FUNC);
+       if (arg3) if ((lparg3 = getRECTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)GetMenuItemRect((HWND)arg0, (HMENU)arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) setRECTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, GetMenuItemRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetMessage)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2, jint arg3)
+{
+       MSG _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMessage_FUNC);
+       if (arg0) if ((lparg0 = getMSGFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)GetMessage(lparg0, (HWND)arg1, arg2, arg3);
+fail:
+       if (arg0 && lparg0) setMSGFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, GetMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMessagePos
+JNIEXPORT jint JNICALL OS_NATIVE(GetMessagePos)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMessagePos_FUNC);
+       rc = (jint)GetMessagePos();
+       OS_NATIVE_EXIT(env, that, GetMessagePos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMessageTime
+JNIEXPORT jint JNICALL OS_NATIVE(GetMessageTime)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMessageTime_FUNC);
+       rc = (jint)GetMessageTime();
+       OS_NATIVE_EXIT(env, that, GetMessageTime_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMetaRgn
+JNIEXPORT jint JNICALL OS_NATIVE(GetMetaRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMetaRgn_FUNC);
+       rc = (jint)GetMetaRgn((HDC)arg0, (HRGN)arg1);
+       OS_NATIVE_EXIT(env, that, GetMetaRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetModuleFileName
+JNIEXPORT jint JNICALL OS_NATIVE(GetModuleFileName)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetModuleFileName_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetModuleFileName((HMODULE)arg0, (LPWSTR)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetModuleFileName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetModuleHandle
+JNIEXPORT jlong JNICALL OS_NATIVE(GetModuleHandle)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetModuleHandle_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)GetModuleHandle((LPWSTR)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, GetModuleHandle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetMonitorInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetMonitorInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       MONITORINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetMonitorInfo_FUNC);
+       if (arg1) if ((lparg1 = getMONITORINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetMonitorInfo((HMONITOR)arg0, (LPMONITORINFO)lparg1);
+fail:
+       if (arg1 && lparg1) setMONITORINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetMonitorInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetObject__JIJ
+JNIEXPORT jint JNICALL OS_NATIVE(GetObject__JIJ)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetObject__JIJ_FUNC);
+       rc = (jint)GetObject((HGDIOBJ)arg0, arg1, (LPVOID)arg2);
+       OS_NATIVE_EXIT(env, that, GetObject__JIJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetObject__JILorg_eclipse_swt_internal_win32_BITMAP_2
+JNIEXPORT jint JNICALL OS_NATIVE(GetObject__JILorg_eclipse_swt_internal_win32_BITMAP_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       BITMAP _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetObject__JILorg_eclipse_swt_internal_win32_BITMAP_2_FUNC);
+       if (arg2) if ((lparg2 = &_arg2) == NULL) goto fail;
+       rc = (jint)GetObject((HGDIOBJ)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setBITMAPFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetObject__JILorg_eclipse_swt_internal_win32_BITMAP_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetObject__JILorg_eclipse_swt_internal_win32_DIBSECTION_2
+JNIEXPORT jint JNICALL OS_NATIVE(GetObject__JILorg_eclipse_swt_internal_win32_DIBSECTION_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       DIBSECTION _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetObject__JILorg_eclipse_swt_internal_win32_DIBSECTION_2_FUNC);
+       if (arg2) if ((lparg2 = &_arg2) == NULL) goto fail;
+       rc = (jint)GetObject((HGDIOBJ)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setDIBSECTIONFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetObject__JILorg_eclipse_swt_internal_win32_DIBSECTION_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetObject__JILorg_eclipse_swt_internal_win32_LOGBRUSH_2
+JNIEXPORT jint JNICALL OS_NATIVE(GetObject__JILorg_eclipse_swt_internal_win32_LOGBRUSH_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       LOGBRUSH _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetObject__JILorg_eclipse_swt_internal_win32_LOGBRUSH_2_FUNC);
+       if (arg2) if ((lparg2 = &_arg2) == NULL) goto fail;
+       rc = (jint)GetObject((HGDIOBJ)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setLOGBRUSHFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetObject__JILorg_eclipse_swt_internal_win32_LOGBRUSH_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetObject__JILorg_eclipse_swt_internal_win32_LOGFONT_2
+JNIEXPORT jint JNICALL OS_NATIVE(GetObject__JILorg_eclipse_swt_internal_win32_LOGFONT_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       LOGFONT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetObject__JILorg_eclipse_swt_internal_win32_LOGFONT_2_FUNC);
+       if (arg2) if ((lparg2 = &_arg2) == NULL) goto fail;
+       rc = (jint)GetObject((HGDIOBJ)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setLOGFONTFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetObject__JILorg_eclipse_swt_internal_win32_LOGFONT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetOpenFileName
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetOpenFileName)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       OPENFILENAME _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetOpenFileName_FUNC);
+       if (arg0) if ((lparg0 = getOPENFILENAMEFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)GetOpenFileName((LPOPENFILENAMEW)lparg0);
+fail:
+       if (arg0 && lparg0) setOPENFILENAMEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, GetOpenFileName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetOutlineTextMetrics
+JNIEXPORT jint JNICALL OS_NATIVE(GetOutlineTextMetrics)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       OUTLINETEXTMETRIC _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetOutlineTextMetrics_FUNC);
+       if (arg2) if ((lparg2 = getOUTLINETEXTMETRICFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)GetOutlineTextMetrics((HDC)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setOUTLINETEXTMETRICFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetOutlineTextMetrics_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetParent
+JNIEXPORT jlong JNICALL OS_NATIVE(GetParent)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetParent_FUNC);
+       rc = (jlong)GetParent((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, GetParent_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetPixel
+JNIEXPORT jint JNICALL OS_NATIVE(GetPixel)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetPixel_FUNC);
+       rc = (jint)GetPixel((HDC)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, GetPixel_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetPolyFillMode
+JNIEXPORT jint JNICALL OS_NATIVE(GetPolyFillMode)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetPolyFillMode_FUNC);
+       rc = (jint)GetPolyFillMode((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetPolyFillMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetProcessHeap
+JNIEXPORT jlong JNICALL OS_NATIVE(GetProcessHeap)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetProcessHeap_FUNC);
+       rc = (jlong)GetProcessHeap();
+       OS_NATIVE_EXIT(env, that, GetProcessHeap_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetProfileString
+JNIEXPORT jint JNICALL OS_NATIVE(GetProfileString)
+       (JNIEnv *env, jclass that, jcharArray arg0, jcharArray arg1, jcharArray arg2, jcharArray arg3, jint arg4)
+{
+       jchar *lparg0=NULL;
+       jchar *lparg1=NULL;
+       jchar *lparg2=NULL;
+       jchar *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetProfileString_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)GetProfileString((LPWSTR)lparg0, (LPWSTR)lparg1, (LPWSTR)lparg2, (LPWSTR)lparg3, arg4);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, GetProfileString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetProp
+JNIEXPORT jlong JNICALL OS_NATIVE(GetProp)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetProp_FUNC);
+       rc = (jlong)GetProp((HWND)arg0, (LPCWSTR)arg1);
+       OS_NATIVE_EXIT(env, that, GetProp_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetROP2
+JNIEXPORT jint JNICALL OS_NATIVE(GetROP2)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetROP2_FUNC);
+       rc = (jint)GetROP2((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetROP2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetRandomRgn
+JNIEXPORT jint JNICALL OS_NATIVE(GetRandomRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetRandomRgn_FUNC);
+       rc = (jint)GetRandomRgn((HDC)arg0, (HRGN)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, GetRandomRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetRegionData
+JNIEXPORT jint JNICALL OS_NATIVE(GetRegionData)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jintArray arg2)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetRegionData_FUNC);
+               if (arg2) if ((lparg2 = (*env)->GetPrimitiveArrayCritical(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)GetRegionData((HRGN)arg0, arg1, (RGNDATA *)lparg2);
+fail:
+               if (arg2 && lparg2) (*env)->ReleasePrimitiveArrayCritical(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, GetRegionData_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetRgnBox
+JNIEXPORT jint JNICALL OS_NATIVE(GetRgnBox)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetRgnBox_FUNC);
+       if (arg1) if ((lparg1 = &_arg1) == NULL) goto fail;
+       rc = (jint)GetRgnBox((HRGN)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetRgnBox_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetSaveFileName
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetSaveFileName)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       OPENFILENAME _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetSaveFileName_FUNC);
+       if (arg0) if ((lparg0 = getOPENFILENAMEFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)GetSaveFileName((LPOPENFILENAMEW)lparg0);
+fail:
+       if (arg0 && lparg0) setOPENFILENAMEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, GetSaveFileName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetScrollBarInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetScrollBarInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       SCROLLBARINFO _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetScrollBarInfo_FUNC);
+       if (arg2) if ((lparg2 = getSCROLLBARINFOFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)GetScrollBarInfo((HWND)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setSCROLLBARINFOFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetScrollBarInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetScrollInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetScrollInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       SCROLLINFO _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetScrollInfo_FUNC);
+       if (arg2) if ((lparg2 = getSCROLLINFOFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)GetScrollInfo((HWND)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setSCROLLINFOFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, GetScrollInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetStartupInfo
+JNIEXPORT void JNICALL OS_NATIVE(GetStartupInfo)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       STARTUPINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, GetStartupInfo_FUNC);
+       if (arg0) if ((lparg0 = getSTARTUPINFOFields(env, arg0, &_arg0)) == NULL) goto fail;
+       GetStartupInfo((LPSTARTUPINFOW)lparg0);
+fail:
+       if (arg0 && lparg0) setSTARTUPINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, GetStartupInfo_FUNC);
+}
+#endif
+
+#ifndef NO_GetStockObject
+JNIEXPORT jlong JNICALL OS_NATIVE(GetStockObject)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetStockObject_FUNC);
+       rc = (jlong)GetStockObject(arg0);
+       OS_NATIVE_EXIT(env, that, GetStockObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetSysColor
+JNIEXPORT jint JNICALL OS_NATIVE(GetSysColor)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetSysColor_FUNC);
+       rc = (jint)GetSysColor(arg0);
+       OS_NATIVE_EXIT(env, that, GetSysColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetSysColorBrush
+JNIEXPORT jlong JNICALL OS_NATIVE(GetSysColorBrush)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetSysColorBrush_FUNC);
+       rc = (jlong)GetSysColorBrush(arg0);
+       OS_NATIVE_EXIT(env, that, GetSysColorBrush_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetSystemDefaultUILanguage
+JNIEXPORT jshort JNICALL OS_NATIVE(GetSystemDefaultUILanguage)
+       (JNIEnv *env, jclass that)
+{
+       jshort rc = 0;
+       OS_NATIVE_ENTER(env, that, GetSystemDefaultUILanguage_FUNC);
+       rc = (jshort)GetSystemDefaultUILanguage();
+       OS_NATIVE_EXIT(env, that, GetSystemDefaultUILanguage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetSystemMenu
+JNIEXPORT jlong JNICALL OS_NATIVE(GetSystemMenu)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetSystemMenu_FUNC);
+       rc = (jlong)GetSystemMenu((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetSystemMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetSystemMetrics
+JNIEXPORT jint JNICALL OS_NATIVE(GetSystemMetrics)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetSystemMetrics_FUNC);
+       rc = (jint)GetSystemMetrics(arg0);
+       OS_NATIVE_EXIT(env, that, GetSystemMetrics_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetTextColor
+JNIEXPORT jint JNICALL OS_NATIVE(GetTextColor)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetTextColor_FUNC);
+       rc = (jint)GetTextColor((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, GetTextColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetTextExtentPoint32
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetTextExtentPoint32)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jobject arg3)
+{
+       jchar *lparg1=NULL;
+       SIZE _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetTextExtentPoint32_FUNC);
+       if (arg3) if ((lparg3 = &_arg3) == NULL) goto fail;
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)GetTextExtentPoint32((HDC)arg0, (LPWSTR)lparg1, arg2, lparg3);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       if (arg3 && lparg3) setSIZEFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, GetTextExtentPoint32_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetTextMetrics
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetTextMetrics)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       TEXTMETRIC _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetTextMetrics_FUNC);
+       if (arg1) if ((lparg1 = &_arg1) == NULL) goto fail;
+       rc = (jboolean)GetTextMetrics((HDC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setTEXTMETRICFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetTextMetrics_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetThemePartSize
+JNIEXPORT jint JNICALL OS_NATIVE(GetThemePartSize)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jobject arg4, jint arg5, jobject arg6)
+{
+       RECT _arg4, *lparg4=NULL;
+       SIZE _arg6, *lparg6=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetThemePartSize_FUNC);
+       if (arg4) if ((lparg4 = getRECTFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = &_arg6) == NULL) goto fail;
+       rc = (jint)GetThemePartSize((HTHEME)arg0, (HDC)arg1, arg2, arg3, lparg4, arg5, lparg6);
+fail:
+       if (arg6 && lparg6) setSIZEFields(env, arg6, lparg6);
+       OS_NATIVE_EXIT(env, that, GetThemePartSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetThemeTextExtent
+JNIEXPORT jint JNICALL OS_NATIVE(GetThemeTextExtent)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jcharArray arg4, jint arg5, jint arg6, jobject arg7, jobject arg8)
+{
+       jchar *lparg4=NULL;
+       RECT _arg7, *lparg7=NULL;
+       RECT _arg8, *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetThemeTextExtent_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetCharArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = getRECTFields(env, arg7, &_arg7)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = getRECTFields(env, arg8, &_arg8)) == NULL) goto fail;
+       rc = (jint)GetThemeTextExtent((HTHEME)arg0, (HDC)arg1, arg2, arg3, lparg4, arg5, arg6, lparg7, lparg8);
+fail:
+       if (arg8 && lparg8) setRECTFields(env, arg8, lparg8);
+       if (arg7 && lparg7) setRECTFields(env, arg7, lparg7);
+       if (arg4 && lparg4) (*env)->ReleaseCharArrayElements(env, arg4, lparg4, 0);
+       OS_NATIVE_EXIT(env, that, GetThemeTextExtent_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetTouchInputInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetTouchInputInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jint arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetTouchInputInfo_FUNC);
+/*
+       rc = (jboolean)GetTouchInputInfo((HTOUCHINPUT)arg0, (UINT)arg1, (PTOUCHINPUT)arg2, arg3);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, GetTouchInputInfo)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HTOUCHINPUT, UINT, PTOUCHINPUT, jint))fp)((HTOUCHINPUT)arg0, (UINT)arg1, (PTOUCHINPUT)arg2, arg3);
+               }
+       }
+       OS_NATIVE_EXIT(env, that, GetTouchInputInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetUpdateRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetUpdateRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jboolean arg2)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetUpdateRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetUpdateRect((HWND)arg0, (LPRECT)lparg1, (BOOL)arg2);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetUpdateRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetUpdateRgn
+JNIEXPORT jint JNICALL OS_NATIVE(GetUpdateRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetUpdateRgn_FUNC);
+       rc = (jint)GetUpdateRgn((HWND)arg0, (HRGN)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, GetUpdateRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetVersion
+JNIEXPORT jint JNICALL OS_NATIVE(GetVersion)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetVersion_FUNC);
+       rc = (jint)GetVersion();
+       OS_NATIVE_EXIT(env, that, GetVersion_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindow
+JNIEXPORT jlong JNICALL OS_NATIVE(GetWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindow_FUNC);
+       rc = (jlong)GetWindow((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowDC
+JNIEXPORT jlong JNICALL OS_NATIVE(GetWindowDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowDC_FUNC);
+       rc = (jlong)GetWindowDC((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, GetWindowDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowLong
+JNIEXPORT jint JNICALL OS_NATIVE(GetWindowLong)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowLong_FUNC);
+       rc = (jint)GetWindowLong((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetWindowLong_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowLongPtr
+JNIEXPORT jlong JNICALL OS_NATIVE(GetWindowLongPtr)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowLongPtr_FUNC);
+       rc = (jlong)GetWindowLongPtr((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GetWindowLongPtr_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowOrgEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetWindowOrgEx)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       POINT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowOrgEx_FUNC);
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetWindowOrgEx((HDC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPOINTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetWindowOrgEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowPlacement
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetWindowPlacement)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       WINDOWPLACEMENT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowPlacement_FUNC);
+       if (arg1) if ((lparg1 = getWINDOWPLACEMENTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetWindowPlacement((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setWINDOWPLACEMENTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetWindowPlacement_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(GetWindowRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)GetWindowRect((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, GetWindowRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowRgn
+JNIEXPORT jint JNICALL OS_NATIVE(GetWindowRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowRgn_FUNC);
+       rc = (jint)GetWindowRgn((HWND)arg0, (HRGN)arg1);
+       OS_NATIVE_EXIT(env, that, GetWindowRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowText
+JNIEXPORT jint JNICALL OS_NATIVE(GetWindowText)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowText_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetWindowText((HWND)arg0, (LPWSTR)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetWindowText_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowTextLength
+JNIEXPORT jint JNICALL OS_NATIVE(GetWindowTextLength)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowTextLength_FUNC);
+       rc = (jint)GetWindowTextLength((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, GetWindowTextLength_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetWindowThreadProcessId
+JNIEXPORT jint JNICALL OS_NATIVE(GetWindowThreadProcessId)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1)
+{
+       jint *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GetWindowThreadProcessId_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)GetWindowThreadProcessId((HWND)arg0, (LPDWORD)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, GetWindowThreadProcessId_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GlobalAddAtom
+JNIEXPORT jint JNICALL OS_NATIVE(GlobalAddAtom)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GlobalAddAtom_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)GlobalAddAtom((LPCWSTR)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, GlobalAddAtom_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GlobalAlloc
+JNIEXPORT jlong JNICALL OS_NATIVE(GlobalAlloc)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GlobalAlloc_FUNC);
+       rc = (jlong)GlobalAlloc(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, GlobalAlloc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GlobalFree
+JNIEXPORT jlong JNICALL OS_NATIVE(GlobalFree)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GlobalFree_FUNC);
+       rc = (jlong)GlobalFree((HANDLE)arg0);
+       OS_NATIVE_EXIT(env, that, GlobalFree_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GlobalLock
+JNIEXPORT jlong JNICALL OS_NATIVE(GlobalLock)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, GlobalLock_FUNC);
+       rc = (jlong)GlobalLock((HANDLE)arg0);
+       OS_NATIVE_EXIT(env, that, GlobalLock_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GlobalSize
+JNIEXPORT jint JNICALL OS_NATIVE(GlobalSize)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, GlobalSize_FUNC);
+       rc = (jint)GlobalSize((HANDLE)arg0);
+       OS_NATIVE_EXIT(env, that, GlobalSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GlobalUnlock
+JNIEXPORT jboolean JNICALL OS_NATIVE(GlobalUnlock)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GlobalUnlock_FUNC);
+       rc = (jboolean)GlobalUnlock((HANDLE)arg0);
+       OS_NATIVE_EXIT(env, that, GlobalUnlock_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GradientFill
+JNIEXPORT jboolean JNICALL OS_NATIVE(GradientFill)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3, jint arg4, jint arg5)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, GradientFill_FUNC);
+       rc = (jboolean)GradientFill((HDC)arg0, (PTRIVERTEX)arg1, (ULONG)arg2, (PVOID)arg3, (ULONG)arg4, (ULONG)arg5);
+       OS_NATIVE_EXIT(env, that, GradientFill_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HDHITTESTINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(HDHITTESTINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, HDHITTESTINFO_1sizeof_FUNC);
+       rc = (jint)HDHITTESTINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, HDHITTESTINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HDITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(HDITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, HDITEM_1sizeof_FUNC);
+       rc = (jint)HDITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, HDITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HDLAYOUT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(HDLAYOUT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, HDLAYOUT_1sizeof_FUNC);
+       rc = (jint)HDLAYOUT_sizeof();
+       OS_NATIVE_EXIT(env, that, HDLAYOUT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HELPINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(HELPINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, HELPINFO_1sizeof_FUNC);
+       rc = (jint)HELPINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, HELPINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HIGHCONTRAST_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(HIGHCONTRAST_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, HIGHCONTRAST_1sizeof_FUNC);
+       rc = (jint)HIGHCONTRAST_sizeof();
+       OS_NATIVE_EXIT(env, that, HIGHCONTRAST_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HIWORD
+JNIEXPORT jint JNICALL OS_NATIVE(HIWORD)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, HIWORD_FUNC);
+       rc = (jint)HIWORD(arg0);
+       OS_NATIVE_EXIT(env, that, HIWORD_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HeapAlloc
+JNIEXPORT jlong JNICALL OS_NATIVE(HeapAlloc)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, HeapAlloc_FUNC);
+       rc = (jlong)HeapAlloc((HANDLE)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, HeapAlloc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HeapFree
+JNIEXPORT jboolean JNICALL OS_NATIVE(HeapFree)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, HeapFree_FUNC);
+       rc = (jboolean)HeapFree((HANDLE)arg0, arg1, (LPVOID)arg2);
+       OS_NATIVE_EXIT(env, that, HeapFree_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_HideCaret
+JNIEXPORT jboolean JNICALL OS_NATIVE(HideCaret)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, HideCaret_FUNC);
+       rc = (jboolean)HideCaret((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, HideCaret_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ICONINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(ICONINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ICONINFO_1sizeof_FUNC);
+       rc = (jint)ICONINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, ICONINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IIDFromString
+JNIEXPORT jint JNICALL OS_NATIVE(IIDFromString)
+       (JNIEnv *env, jclass that, jcharArray arg0, jbyteArray arg1)
+{
+       jchar *lparg0=NULL;
+       jbyte *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, IIDFromString_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)IIDFromString((LPOLESTR)lparg0, (LPIID)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, IIDFromString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ILGetSize
+JNIEXPORT jint JNICALL OS_NATIVE(ILGetSize)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ILGetSize_FUNC);
+       rc = (jint)ILGetSize((PCIDLIST_ABSOLUTE)arg0);
+       OS_NATIVE_EXIT(env, that, ILGetSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_INITCOMMONCONTROLSEX_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(INITCOMMONCONTROLSEX_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, INITCOMMONCONTROLSEX_1sizeof_FUNC);
+       rc = (jint)INITCOMMONCONTROLSEX_sizeof();
+       OS_NATIVE_EXIT(env, that, INITCOMMONCONTROLSEX_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_INPUT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(INPUT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, INPUT_1sizeof_FUNC);
+       rc = (jint)INPUT_sizeof();
+       OS_NATIVE_EXIT(env, that, INPUT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1Add
+JNIEXPORT jint JNICALL OS_NATIVE(ImageList_1Add)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1Add_FUNC);
+       rc = (jint)ImageList_Add((HIMAGELIST)arg0, (HBITMAP)arg1, (HBITMAP)arg2);
+       OS_NATIVE_EXIT(env, that, ImageList_1Add_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1AddMasked
+JNIEXPORT jint JNICALL OS_NATIVE(ImageList_1AddMasked)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1AddMasked_FUNC);
+       rc = (jint)ImageList_AddMasked((HIMAGELIST)arg0, (HBITMAP)arg1, (COLORREF)arg2);
+       OS_NATIVE_EXIT(env, that, ImageList_1AddMasked_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1BeginDrag
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1BeginDrag)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1BeginDrag_FUNC);
+       rc = (jboolean)ImageList_BeginDrag((HIMAGELIST)arg0, arg1, arg2, arg3);
+       OS_NATIVE_EXIT(env, that, ImageList_1BeginDrag_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1Create
+JNIEXPORT jlong JNICALL OS_NATIVE(ImageList_1Create)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1Create_FUNC);
+       rc = (jlong)ImageList_Create(arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, ImageList_1Create_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1Destroy
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1Destroy)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1Destroy_FUNC);
+       rc = (jboolean)ImageList_Destroy((HIMAGELIST)arg0);
+       OS_NATIVE_EXIT(env, that, ImageList_1Destroy_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1DragEnter
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1DragEnter)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1DragEnter_FUNC);
+       rc = (jboolean)ImageList_DragEnter((HWND)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, ImageList_1DragEnter_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1DragLeave
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1DragLeave)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1DragLeave_FUNC);
+       rc = (jboolean)ImageList_DragLeave((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, ImageList_1DragLeave_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1DragMove
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1DragMove)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1DragMove_FUNC);
+       rc = (jboolean)ImageList_DragMove(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, ImageList_1DragMove_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1DragShowNolock
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1DragShowNolock)
+       (JNIEnv *env, jclass that, jboolean arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1DragShowNolock_FUNC);
+       rc = (jboolean)ImageList_DragShowNolock((BOOL)arg0);
+       OS_NATIVE_EXIT(env, that, ImageList_1DragShowNolock_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1EndDrag
+JNIEXPORT void JNICALL OS_NATIVE(ImageList_1EndDrag)
+       (JNIEnv *env, jclass that)
+{
+       OS_NATIVE_ENTER(env, that, ImageList_1EndDrag_FUNC);
+       ImageList_EndDrag();
+       OS_NATIVE_EXIT(env, that, ImageList_1EndDrag_FUNC);
+}
+#endif
+
+#ifndef NO_ImageList_1GetIconSize
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1GetIconSize)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2)
+{
+       jint *lparg1=NULL;
+       jint *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1GetIconSize_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jboolean)ImageList_GetIconSize((HIMAGELIST)arg0, (int *)lparg1, (int *)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, ImageList_1GetIconSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1GetImageCount
+JNIEXPORT jint JNICALL OS_NATIVE(ImageList_1GetImageCount)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1GetImageCount_FUNC);
+       rc = (jint)ImageList_GetImageCount((HIMAGELIST)arg0);
+       OS_NATIVE_EXIT(env, that, ImageList_1GetImageCount_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1Remove
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1Remove)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1Remove_FUNC);
+       rc = (jboolean)ImageList_Remove((HIMAGELIST)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, ImageList_1Remove_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1Replace
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1Replace)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1Replace_FUNC);
+       rc = (jboolean)ImageList_Replace((HIMAGELIST)arg0, arg1, (HBITMAP)arg2, (HBITMAP)arg3);
+       OS_NATIVE_EXIT(env, that, ImageList_1Replace_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1ReplaceIcon
+JNIEXPORT jint JNICALL OS_NATIVE(ImageList_1ReplaceIcon)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1ReplaceIcon_FUNC);
+       rc = (jint)ImageList_ReplaceIcon((HIMAGELIST)arg0, arg1, (HICON)arg2);
+       OS_NATIVE_EXIT(env, that, ImageList_1ReplaceIcon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImageList_1SetIconSize
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1SetIconSize)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImageList_1SetIconSize_FUNC);
+       rc = (jboolean)ImageList_SetIconSize((HIMAGELIST)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, ImageList_1SetIconSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmAssociateContext
+JNIEXPORT jlong JNICALL OS_NATIVE(ImmAssociateContext)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmAssociateContext_FUNC);
+       rc = (jlong)ImmAssociateContext((HWND)arg0, (HIMC)arg1);
+       OS_NATIVE_EXIT(env, that, ImmAssociateContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmCreateContext
+JNIEXPORT jlong JNICALL OS_NATIVE(ImmCreateContext)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmCreateContext_FUNC);
+       rc = (jlong)ImmCreateContext();
+       OS_NATIVE_EXIT(env, that, ImmCreateContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmDestroyContext
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmDestroyContext)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmDestroyContext_FUNC);
+       rc = (jboolean)ImmDestroyContext((HIMC)arg0);
+       OS_NATIVE_EXIT(env, that, ImmDestroyContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmEscape
+JNIEXPORT jlong JNICALL OS_NATIVE(ImmEscape)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jcharArray arg3)
+{
+       jchar *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmEscape_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)ImmEscape((HKL)arg0, (HIMC)arg1, arg2, (LPVOID)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, ImmEscape_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetCompositionFont
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmGetCompositionFont)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       LOGFONT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetCompositionFont_FUNC);
+       if (arg1) if ((lparg1 = getLOGFONTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ImmGetCompositionFont((HIMC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setLOGFONTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ImmGetCompositionFont_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetCompositionString__JI_3BI
+JNIEXPORT jint JNICALL OS_NATIVE(ImmGetCompositionString__JI_3BI)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jbyteArray arg2, jint arg3)
+{
+       jbyte *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetCompositionString__JI_3BI_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)ImmGetCompositionString((HIMC)arg0, arg1, (LPWSTR)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ImmGetCompositionString__JI_3BI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetCompositionString__JI_3CI
+JNIEXPORT jint JNICALL OS_NATIVE(ImmGetCompositionString__JI_3CI)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jcharArray arg2, jint arg3)
+{
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetCompositionString__JI_3CI_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)ImmGetCompositionString((HIMC)arg0, arg1, (LPWSTR)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ImmGetCompositionString__JI_3CI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetCompositionString__JI_3II
+JNIEXPORT jint JNICALL OS_NATIVE(ImmGetCompositionString__JI_3II)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jintArray arg2, jint arg3)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetCompositionString__JI_3II_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)ImmGetCompositionString((HIMC)arg0, arg1, (LPWSTR)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ImmGetCompositionString__JI_3II_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetContext
+JNIEXPORT jlong JNICALL OS_NATIVE(ImmGetContext)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetContext_FUNC);
+       rc = (jlong)ImmGetContext((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, ImmGetContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetConversionStatus
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmGetConversionStatus)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2)
+{
+       jint *lparg1=NULL;
+       jint *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetConversionStatus_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jboolean)ImmGetConversionStatus((HIMC)arg0, (LPDWORD)lparg1, (LPDWORD)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, ImmGetConversionStatus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetDefaultIMEWnd
+JNIEXPORT jlong JNICALL OS_NATIVE(ImmGetDefaultIMEWnd)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetDefaultIMEWnd_FUNC);
+       rc = (jlong)ImmGetDefaultIMEWnd((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, ImmGetDefaultIMEWnd_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmGetOpenStatus
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmGetOpenStatus)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmGetOpenStatus_FUNC);
+       rc = (jboolean)ImmGetOpenStatus((HIMC)arg0);
+       OS_NATIVE_EXIT(env, that, ImmGetOpenStatus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmNotifyIME
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmNotifyIME)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmNotifyIME_FUNC);
+       rc = (jboolean)ImmNotifyIME((HIMC)arg0, arg1, arg2, arg3);
+       OS_NATIVE_EXIT(env, that, ImmNotifyIME_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmReleaseContext
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmReleaseContext)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmReleaseContext_FUNC);
+       rc = (jboolean)ImmReleaseContext((HWND)arg0, (HIMC)arg1);
+       OS_NATIVE_EXIT(env, that, ImmReleaseContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmSetCandidateWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmSetCandidateWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       CANDIDATEFORM _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmSetCandidateWindow_FUNC);
+       if (arg1) if ((lparg1 = getCANDIDATEFORMFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ImmSetCandidateWindow((HIMC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setCANDIDATEFORMFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ImmSetCandidateWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmSetCompositionFont
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmSetCompositionFont)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       LOGFONT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmSetCompositionFont_FUNC);
+       if (arg1) if ((lparg1 = getLOGFONTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ImmSetCompositionFont((HIMC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setLOGFONTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ImmSetCompositionFont_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmSetCompositionWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmSetCompositionWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       COMPOSITIONFORM _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmSetCompositionWindow_FUNC);
+       if (arg1) if ((lparg1 = getCOMPOSITIONFORMFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ImmSetCompositionWindow((HIMC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setCOMPOSITIONFORMFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ImmSetCompositionWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmSetConversionStatus
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmSetConversionStatus)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmSetConversionStatus_FUNC);
+       rc = (jboolean)ImmSetConversionStatus((HIMC)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, ImmSetConversionStatus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ImmSetOpenStatus
+JNIEXPORT jboolean JNICALL OS_NATIVE(ImmSetOpenStatus)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ImmSetOpenStatus_FUNC);
+       rc = (jboolean)ImmSetOpenStatus((HIMC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, ImmSetOpenStatus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InitCommonControls
+JNIEXPORT void JNICALL OS_NATIVE(InitCommonControls)
+       (JNIEnv *env, jclass that)
+{
+       OS_NATIVE_ENTER(env, that, InitCommonControls_FUNC);
+       InitCommonControls();
+       OS_NATIVE_EXIT(env, that, InitCommonControls_FUNC);
+}
+#endif
+
+#ifndef NO_InitCommonControlsEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(InitCommonControlsEx)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       INITCOMMONCONTROLSEX _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InitCommonControlsEx_FUNC);
+       if (arg0) if ((lparg0 = getINITCOMMONCONTROLSEXFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)InitCommonControlsEx(lparg0);
+fail:
+       if (arg0 && lparg0) setINITCOMMONCONTROLSEXFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, InitCommonControlsEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InsertMenuItem
+JNIEXPORT jboolean JNICALL OS_NATIVE(InsertMenuItem)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jboolean arg2, jobject arg3)
+{
+       MENUITEMINFO _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InsertMenuItem_FUNC);
+       if (arg3) if ((lparg3 = getMENUITEMINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)InsertMenuItem((HMENU)arg0, arg1, arg2, (LPMENUITEMINFOW)lparg3);
+fail:
+       if (arg3 && lparg3) setMENUITEMINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, InsertMenuItem_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InternetGetCookie
+JNIEXPORT jboolean JNICALL OS_NATIVE(InternetGetCookie)
+       (JNIEnv *env, jclass that, jcharArray arg0, jcharArray arg1, jcharArray arg2, jintArray arg3)
+{
+       jchar *lparg0=NULL;
+       jchar *lparg1=NULL;
+       jchar *lparg2=NULL;
+       jint *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InternetGetCookie_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jboolean)InternetGetCookie((LPCWSTR)lparg0, (LPCWSTR)lparg1, (LPWSTR)lparg2, (LPDWORD)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, InternetGetCookie_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InternetSetCookie
+JNIEXPORT jboolean JNICALL OS_NATIVE(InternetSetCookie)
+       (JNIEnv *env, jclass that, jcharArray arg0, jcharArray arg1, jcharArray arg2)
+{
+       jchar *lparg0=NULL;
+       jchar *lparg1=NULL;
+       jchar *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InternetSetCookie_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jboolean)InternetSetCookie((LPCWSTR)lparg0, (LPCWSTR)lparg1, (LPCWSTR)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, InternetSetCookie_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InternetSetOption
+JNIEXPORT jboolean JNICALL OS_NATIVE(InternetSetOption)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jint arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InternetSetOption_FUNC);
+       rc = (jboolean)InternetSetOption((HINTERNET)arg0, arg1, (LPVOID)arg2, arg3);
+       OS_NATIVE_EXIT(env, that, InternetSetOption_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IntersectClipRect
+JNIEXPORT jint JNICALL OS_NATIVE(IntersectClipRect)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, IntersectClipRect_FUNC);
+       rc = (jint)IntersectClipRect((HDC)arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, IntersectClipRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IntersectRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(IntersectRect)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1, jobject arg2)
+{
+       RECT _arg0, *lparg0=NULL;
+       RECT _arg1, *lparg1=NULL;
+       RECT _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IntersectRect_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)IntersectRect(lparg0, lparg1, lparg2);
+fail:
+       if (arg0 && lparg0) setRECTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, IntersectRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InvalidateRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(InvalidateRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jboolean arg2)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InvalidateRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)InvalidateRect((HWND)arg0, lparg1, arg2);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, InvalidateRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_InvalidateRgn
+JNIEXPORT jboolean JNICALL OS_NATIVE(InvalidateRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, InvalidateRgn_FUNC);
+       rc = (jboolean)InvalidateRgn((HWND)arg0, (HRGN)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, InvalidateRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsAppThemed
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsAppThemed)
+       (JNIEnv *env, jclass that)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsAppThemed_FUNC);
+       rc = (jboolean)IsAppThemed();
+       OS_NATIVE_EXIT(env, that, IsAppThemed_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsHungAppWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsHungAppWindow)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsHungAppWindow_FUNC);
+       rc = (jboolean)IsHungAppWindow((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, IsHungAppWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsIconic
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsIconic)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsIconic_FUNC);
+       rc = (jboolean)IsIconic((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, IsIconic_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsTouchWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsTouchWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1)
+{
+       jlong *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsTouchWindow_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+/*
+       rc = (jboolean)IsTouchWindow((HWND)arg0, (PULONG)lparg1);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, IsTouchWindow)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HWND, PULONG))fp)((HWND)arg0, (PULONG)lparg1);
+               }
+       }
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, IsTouchWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsWindowEnabled
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsWindowEnabled)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsWindowEnabled_FUNC);
+       rc = (jboolean)IsWindowEnabled((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, IsWindowEnabled_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsWindowVisible
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsWindowVisible)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsWindowVisible_FUNC);
+       rc = (jboolean)IsWindowVisible((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, IsWindowVisible_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_IsZoomed
+JNIEXPORT jboolean JNICALL OS_NATIVE(IsZoomed)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, IsZoomed_FUNC);
+       rc = (jboolean)IsZoomed((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, IsZoomed_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_KEYBDINPUT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(KEYBDINPUT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, KEYBDINPUT_1sizeof_FUNC);
+       rc = (jint)KEYBDINPUT_sizeof();
+       OS_NATIVE_EXIT(env, that, KEYBDINPUT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_KillTimer
+JNIEXPORT jboolean JNICALL OS_NATIVE(KillTimer)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, KillTimer_FUNC);
+       rc = (jboolean)KillTimer((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, KillTimer_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LITEM_1sizeof_FUNC);
+       rc = (jint)LITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, LITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LODWORD
+JNIEXPORT jint JNICALL OS_NATIVE(LODWORD)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LODWORD_FUNC);
+       rc = (jint)LODWORD(arg0);
+       OS_NATIVE_EXIT(env, that, LODWORD_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LOGBRUSH_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LOGBRUSH_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LOGBRUSH_1sizeof_FUNC);
+       rc = (jint)LOGBRUSH_sizeof();
+       OS_NATIVE_EXIT(env, that, LOGBRUSH_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LOGFONT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LOGFONT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LOGFONT_1sizeof_FUNC);
+       rc = (jint)LOGFONT_sizeof();
+       OS_NATIVE_EXIT(env, that, LOGFONT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LOGPEN_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LOGPEN_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LOGPEN_1sizeof_FUNC);
+       rc = (jint)LOGPEN_sizeof();
+       OS_NATIVE_EXIT(env, that, LOGPEN_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LOWORD
+JNIEXPORT jint JNICALL OS_NATIVE(LOWORD)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LOWORD_FUNC);
+       rc = (jint)LOWORD(arg0);
+       OS_NATIVE_EXIT(env, that, LOWORD_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LPtoDP
+JNIEXPORT jboolean JNICALL OS_NATIVE(LPtoDP)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       POINT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, LPtoDP_FUNC);
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)LPtoDP((HDC)arg0, lparg1, arg2);
+fail:
+       if (arg1 && lparg1) setPOINTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, LPtoDP_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LVCOLUMN_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LVCOLUMN_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LVCOLUMN_1sizeof_FUNC);
+       rc = (jint)LVCOLUMN_sizeof();
+       OS_NATIVE_EXIT(env, that, LVCOLUMN_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LVHITTESTINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LVHITTESTINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LVHITTESTINFO_1sizeof_FUNC);
+       rc = (jint)LVHITTESTINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, LVHITTESTINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LVINSERTMARK_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LVINSERTMARK_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LVINSERTMARK_1sizeof_FUNC);
+       rc = (jint)LVINSERTMARK_sizeof();
+       OS_NATIVE_EXIT(env, that, LVINSERTMARK_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LVITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(LVITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LVITEM_1sizeof_FUNC);
+       rc = (jint)LVITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, LVITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LineTo
+JNIEXPORT jboolean JNICALL OS_NATIVE(LineTo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, LineTo_FUNC);
+       rc = (jboolean)LineTo((HDC)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, LineTo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LoadBitmap
+JNIEXPORT jlong JNICALL OS_NATIVE(LoadBitmap)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, LoadBitmap_FUNC);
+       rc = (jlong)LoadBitmap((HINSTANCE)arg0, (LPWSTR)arg1);
+       OS_NATIVE_EXIT(env, that, LoadBitmap_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LoadCursor
+JNIEXPORT jlong JNICALL OS_NATIVE(LoadCursor)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, LoadCursor_FUNC);
+       rc = (jlong)LoadCursor((HINSTANCE)arg0, (LPWSTR)arg1);
+       OS_NATIVE_EXIT(env, that, LoadCursor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LoadIcon
+JNIEXPORT jlong JNICALL OS_NATIVE(LoadIcon)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, LoadIcon_FUNC);
+       rc = (jlong)LoadIcon((HINSTANCE)arg0, (LPWSTR)arg1);
+       OS_NATIVE_EXIT(env, that, LoadIcon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LoadIconMetric
+JNIEXPORT jint JNICALL OS_NATIVE(LoadIconMetric)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlongArray arg3)
+{
+       jlong *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, LoadIconMetric_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)LoadIconMetric((HINSTANCE)arg0, (PCWSTR)arg1, arg2, (HICON *)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, LoadIconMetric_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LoadImage
+JNIEXPORT jlong JNICALL OS_NATIVE(LoadImage)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, LoadImage_FUNC);
+       rc = (jlong)LoadImage((HINSTANCE)arg0, (LPWSTR)arg1, arg2, arg3, arg4, arg5);
+       OS_NATIVE_EXIT(env, that, LoadImage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_LocalFree
+JNIEXPORT jlong JNICALL OS_NATIVE(LocalFree)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, LocalFree_FUNC);
+       rc = (jlong)LocalFree((HLOCAL)arg0);
+       OS_NATIVE_EXIT(env, that, LocalFree_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MAKELPARAM
+JNIEXPORT jlong JNICALL OS_NATIVE(MAKELPARAM)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, MAKELPARAM_FUNC);
+       rc = (jlong)MAKELPARAM(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, MAKELPARAM_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MAKELRESULT
+JNIEXPORT jlong JNICALL OS_NATIVE(MAKELRESULT)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, MAKELRESULT_FUNC);
+       rc = (jlong)MAKELRESULT(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, MAKELRESULT_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MAKEWORD
+JNIEXPORT jint JNICALL OS_NATIVE(MAKEWORD)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MAKEWORD_FUNC);
+       rc = (jint)MAKEWORD(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, MAKEWORD_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MAKEWPARAM
+JNIEXPORT jlong JNICALL OS_NATIVE(MAKEWPARAM)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, MAKEWPARAM_FUNC);
+       rc = (jlong)MAKEWPARAM(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, MAKEWPARAM_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MARGINS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MARGINS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MARGINS_1sizeof_FUNC);
+       rc = (jint)MARGINS_sizeof();
+       OS_NATIVE_EXIT(env, that, MARGINS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MCHITTESTINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MCHITTESTINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MCHITTESTINFO_1sizeof_FUNC);
+       rc = (jint)MCHITTESTINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, MCHITTESTINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MEASUREITEMSTRUCT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MEASUREITEMSTRUCT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MEASUREITEMSTRUCT_1sizeof_FUNC);
+       rc = (jint)MEASUREITEMSTRUCT_sizeof();
+       OS_NATIVE_EXIT(env, that, MEASUREITEMSTRUCT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MENUBARINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MENUBARINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MENUBARINFO_1sizeof_FUNC);
+       rc = (jint)MENUBARINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, MENUBARINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MENUINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MENUINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MENUINFO_1sizeof_FUNC);
+       rc = (jint)MENUINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, MENUINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MENUITEMINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MENUITEMINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MENUITEMINFO_1sizeof_FUNC);
+       rc = (jint)MENUITEMINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, MENUITEMINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MINMAXINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MINMAXINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MINMAXINFO_1sizeof_FUNC);
+       rc = (jint)MINMAXINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, MINMAXINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MONITORINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MONITORINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MONITORINFO_1sizeof_FUNC);
+       rc = (jint)MONITORINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, MONITORINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MOUSEINPUT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MOUSEINPUT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MOUSEINPUT_1sizeof_FUNC);
+       rc = (jint)MOUSEINPUT_sizeof();
+       OS_NATIVE_EXIT(env, that, MOUSEINPUT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MSG_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(MSG_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MSG_1sizeof_FUNC);
+       rc = (jint)MSG_sizeof();
+       OS_NATIVE_EXIT(env, that, MSG_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MapViewOfFile
+JNIEXPORT jlong JNICALL OS_NATIVE(MapViewOfFile)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, MapViewOfFile_FUNC);
+       rc = (jlong)MapViewOfFile((HANDLE)arg0, (DWORD)arg1, (DWORD)arg2, (DWORD)arg3, arg4);
+       OS_NATIVE_EXIT(env, that, MapViewOfFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MapVirtualKey
+JNIEXPORT jint JNICALL OS_NATIVE(MapVirtualKey)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MapVirtualKey_FUNC);
+       rc = (jint)MapVirtualKey(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, MapVirtualKey_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MapWindowPoints__JJLorg_eclipse_swt_internal_win32_POINT_2I
+JNIEXPORT jint JNICALL OS_NATIVE(MapWindowPoints__JJLorg_eclipse_swt_internal_win32_POINT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2, jint arg3)
+{
+       POINT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MapWindowPoints__JJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC);
+       if (arg2) if ((lparg2 = getPOINTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)MapWindowPoints((HWND)arg0, (HWND)arg1, (LPPOINT)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setPOINTFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, MapWindowPoints__JJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MapWindowPoints__JJLorg_eclipse_swt_internal_win32_RECT_2I
+JNIEXPORT jint JNICALL OS_NATIVE(MapWindowPoints__JJLorg_eclipse_swt_internal_win32_RECT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2, jint arg3)
+{
+       RECT _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MapWindowPoints__JJLorg_eclipse_swt_internal_win32_RECT_2I_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)MapWindowPoints((HWND)arg0, (HWND)arg1, (LPPOINT)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, MapWindowPoints__JJLorg_eclipse_swt_internal_win32_RECT_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MessageBeep
+JNIEXPORT jboolean JNICALL OS_NATIVE(MessageBeep)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, MessageBeep_FUNC);
+       rc = (jboolean)MessageBeep(arg0);
+       OS_NATIVE_EXIT(env, that, MessageBeep_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MessageBox
+JNIEXPORT jint JNICALL OS_NATIVE(MessageBox)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jcharArray arg2, jint arg3)
+{
+       jchar *lparg1=NULL;
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MessageBox_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)MessageBox((HWND)arg0, (LPWSTR)lparg1, (LPWSTR)lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, MessageBox_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ModifyWorldTransform
+JNIEXPORT jboolean JNICALL OS_NATIVE(ModifyWorldTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2)
+{
+       jfloat *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ModifyWorldTransform_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetFloatArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)ModifyWorldTransform((HDC)arg0, (XFORM *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseFloatArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, ModifyWorldTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MonitorFromWindow
+JNIEXPORT jlong JNICALL OS_NATIVE(MonitorFromWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, MonitorFromWindow_FUNC);
+       rc = (jlong)MonitorFromWindow((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, MonitorFromWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MoveMemory__JJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JJI)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       OS_NATIVE_ENTER(env, that, MoveMemory__JJI_FUNC);
+       MoveMemory((PVOID)arg0, (CONST VOID *)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, MoveMemory__JJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       CIDA _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I_FUNC);
+       if (arg1) if ((lparg1 = getCIDAFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       DEVMODE _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I_FUNC);
+       if (arg1) if ((lparg1 = getDEVMODEFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       DOCHOSTUIINFO _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I_FUNC);
+       if (arg1) if ((lparg1 = getDOCHOSTUIINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       DROPFILES _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I_FUNC);
+       if (arg1) if ((lparg1 = getDROPFILESFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_GESTURECONFIG_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_GESTURECONFIG_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       GESTURECONFIG _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_GESTURECONFIG_2I_FUNC);
+       if (arg1) if ((lparg1 = getGESTURECONFIGFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_GESTURECONFIG_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_GRADIENT_1RECT_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_GRADIENT_1RECT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       GRADIENT_RECT _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_GRADIENT_1RECT_2I_FUNC);
+       if (arg1) if ((lparg1 = getGRADIENT_RECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_GRADIENT_1RECT_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_KEYBDINPUT_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_KEYBDINPUT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       KEYBDINPUT _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_KEYBDINPUT_2I_FUNC);
+       if (arg1) if ((lparg1 = getKEYBDINPUTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_KEYBDINPUT_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_LOGFONT_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_LOGFONT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       LOGFONT _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_LOGFONT_2I_FUNC);
+       if (arg1) if ((lparg1 = getLOGFONTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_LOGFONT_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       MEASUREITEMSTRUCT _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2I_FUNC);
+       if (arg1) if ((lparg1 = getMEASUREITEMSTRUCTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_MINMAXINFO_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_MINMAXINFO_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       MINMAXINFO _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MINMAXINFO_2I_FUNC);
+       if (arg1) if ((lparg1 = getMINMAXINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MINMAXINFO_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_MOUSEINPUT_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_MOUSEINPUT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       MOUSEINPUT _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MOUSEINPUT_2I_FUNC);
+       if (arg1) if ((lparg1 = getMOUSEINPUTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MOUSEINPUT_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_MSG_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_MSG_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       MSG _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MSG_2I_FUNC);
+       if (arg1) if ((lparg1 = getMSGFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_MSG_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       NMLVCUSTOMDRAW _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2I_FUNC);
+       if (arg1) if ((lparg1 = getNMLVCUSTOMDRAWFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVDISPINFO_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVDISPINFO_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       NMLVDISPINFO _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVDISPINFO_2I_FUNC);
+       if (arg1) if ((lparg1 = getNMLVDISPINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVDISPINFO_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       NMTBCUSTOMDRAW _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2I_FUNC);
+       if (arg1) if ((lparg1 = getNMTBCUSTOMDRAWFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_NMTTDISPINFO_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_NMTTDISPINFO_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       NMTTDISPINFO _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTTDISPINFO_2I_FUNC);
+       if (arg1) if ((lparg1 = getNMTTDISPINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTTDISPINFO_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       NMTVCUSTOMDRAW _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2I_FUNC);
+       if (arg1) if ((lparg1 = getNMTVCUSTOMDRAWFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVDISPINFO_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVDISPINFO_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       NMTVDISPINFO _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVDISPINFO_2I_FUNC);
+       if (arg1) if ((lparg1 = getNMTVDISPINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVDISPINFO_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_OPENFILENAME_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_OPENFILENAME_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       OPENFILENAME _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_OPENFILENAME_2I_FUNC);
+       if (arg1) if ((lparg1 = getOPENFILENAMEFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) setOPENFILENAMEFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_OPENFILENAME_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_RECT_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_RECT_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       RECT _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_RECT_2I_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_RECT_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_SAFEARRAY_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_SAFEARRAY_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       SAFEARRAY _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_SAFEARRAY_2I_FUNC);
+       if (arg1) if ((lparg1 = getSAFEARRAYFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_SAFEARRAY_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       SHDRAGIMAGE _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2I_FUNC);
+       if (arg1) if ((lparg1 = getSHDRAGIMAGEFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_TRIVERTEX_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_TRIVERTEX_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       TRIVERTEX _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_TRIVERTEX_2I_FUNC);
+       if (arg1) if ((lparg1 = getTRIVERTEXFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_TRIVERTEX_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_UDACCEL_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_UDACCEL_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       UDACCEL _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_UDACCEL_2I_FUNC);
+       if (arg1) if ((lparg1 = getUDACCELFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_UDACCEL_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_WINDOWPOS_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_WINDOWPOS_2I)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+       WINDOWPOS _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_WINDOWPOS_2I_FUNC);
+       if (arg1) if ((lparg1 = getWINDOWPOSFields(env, arg1, &_arg1)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+       OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_WINDOWPOS_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3BI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3BI)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jint arg2)
+{
+       jbyte *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3BI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3BI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3CI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3CI)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3CI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3CI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3DI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3DI)
+       (JNIEnv *env, jclass that, jlong arg0, jdoubleArray arg1, jint arg2)
+{
+       jdouble *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3DI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3DI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3FI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3FI)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1, jint arg2)
+{
+       jfloat *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3FI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3FI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3II
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3II)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jint arg2)
+{
+       jint *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3II_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3II_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3JI)
+       (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1, jint arg2)
+{
+       jlong *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3JI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__J_3SI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__J_3SI)
+       (JNIEnv *env, jclass that, jlong arg0, jshortArray arg1, jint arg2)
+{
+       jshort *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__J_3SI_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MoveMemory__J_3SI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       BITMAPINFOHEADER _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setBITMAPINFOHEADERFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI)
+       (JNIEnv *env, jclass that, jobject arg0, jbyteArray arg1, jint arg2)
+{
+       BITMAPINFOHEADER _arg0, *lparg0=NULL;
+       jbyte *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       if (arg0 && lparg0) setBITMAPINFOHEADERFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       CERT_CONTEXT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setCERT_CONTEXTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       CERT_INFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setCERT_INFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       CIDA _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setCIDAFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       DEVMODE _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setDEVMODEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       DOCHOSTUIINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setDOCHOSTUIINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       DRAWITEMSTRUCT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setDRAWITEMSTRUCTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_EMREXTCREATEFONTINDIRECTW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_EMREXTCREATEFONTINDIRECTW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       EMREXTCREATEFONTINDIRECTW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_EMREXTCREATEFONTINDIRECTW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setEMREXTCREATEFONTINDIRECTWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_EMREXTCREATEFONTINDIRECTW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_EMR_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_EMR_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       EMR _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_EMR_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setEMRFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_EMR_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1DATA_2_3JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1DATA_2_3JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlongArray arg1, jint arg2)
+{
+       FLICK_DATA _arg0, *lparg0=NULL;
+       jlong *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1DATA_2_3JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, JNI_ABORT);
+       if (arg0 && lparg0) setFLICK_DATAFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1DATA_2_3JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1POINT_2_3JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1POINT_2_3JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlongArray arg1, jint arg2)
+{
+       FLICK_POINT _arg0, *lparg0=NULL;
+       jlong *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1POINT_2_3JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, JNI_ABORT);
+       if (arg0 && lparg0) setFLICK_POINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1POINT_2_3JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_HDITEM_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_HDITEM_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       HDITEM _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_HDITEM_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setHDITEMFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_HDITEM_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_HELPINFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_HELPINFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       HELPINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_HELPINFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setHELPINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_HELPINFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_LOGFONT_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_LOGFONT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       LOGFONT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_LOGFONT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setLOGFONTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_LOGFONT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       MEASUREITEMSTRUCT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setMEASUREITEMSTRUCTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_MINMAXINFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_MINMAXINFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       MINMAXINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_MINMAXINFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setMINMAXINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_MINMAXINFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_MSG_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_MSG_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       MSG _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_MSG_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setMSGFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_MSG_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMCUSTOMDRAW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMCUSTOMDRAW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMCUSTOMDRAW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMCUSTOMDRAW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMCUSTOMDRAWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMCUSTOMDRAW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMHDR_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMHDR_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMHDR _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMHDR_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMHDRFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMHDR_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMHEADER_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMHEADER_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMHEADER _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMHEADER_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMHEADERFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMHEADER_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMLINK_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMLINK_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMLINK _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLINK_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMLINKFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLINK_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMLISTVIEW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMLISTVIEW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMLISTVIEW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLISTVIEW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMLISTVIEWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLISTVIEW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMLVCUSTOMDRAW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMLVCUSTOMDRAWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVDISPINFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVDISPINFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMLVDISPINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVDISPINFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMLVDISPINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVDISPINFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVODSTATECHANGE_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVODSTATECHANGE_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMLVODSTATECHANGE _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVODSTATECHANGE_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMLVODSTATECHANGEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVODSTATECHANGE_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHEVRON_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHEVRON_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMREBARCHEVRON _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHEVRON_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMREBARCHEVRONFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHEVRON_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHILDSIZE_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHILDSIZE_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMREBARCHILDSIZE _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHILDSIZE_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMREBARCHILDSIZEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHILDSIZE_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTBCUSTOMDRAW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTBCUSTOMDRAWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBHOTITEM_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBHOTITEM_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTBHOTITEM _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBHOTITEM_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTBHOTITEMFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBHOTITEM_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTOOLBAR_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTOOLBAR_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTOOLBAR _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTOOLBAR_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTOOLBARFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTOOLBAR_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTREEVIEW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTREEVIEW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTREEVIEW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTREEVIEW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTREEVIEWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTREEVIEW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTCUSTOMDRAW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTCUSTOMDRAW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTTCUSTOMDRAW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTCUSTOMDRAW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTTCUSTOMDRAWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTCUSTOMDRAW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTDISPINFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTDISPINFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTTDISPINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTDISPINFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTTDISPINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTDISPINFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTVCUSTOMDRAW _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTVCUSTOMDRAWFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVDISPINFO_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVDISPINFO_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTVDISPINFO _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVDISPINFO_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTVDISPINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVDISPINFO_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVITEMCHANGE_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVITEMCHANGE_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMTVITEMCHANGE _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVITEMCHANGE_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMTVITEMCHANGEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVITEMCHANGE_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_NMUPDOWN_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_NMUPDOWN_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       NMUPDOWN _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMUPDOWN_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setNMUPDOWNFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_NMUPDOWN_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_OFNOTIFY_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_OFNOTIFY_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       OFNOTIFY _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_OFNOTIFY_2JI_FUNC);
+       if (arg0) if ((lparg0 = getOFNOTIFYFields(env, arg0, &_arg0)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setOFNOTIFYFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_OFNOTIFY_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_OPENFILENAME_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_OPENFILENAME_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       OPENFILENAME _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_OPENFILENAME_2JI_FUNC);
+       if (arg0) if ((lparg0 = getOPENFILENAMEFields(env, arg0, &_arg0)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setOPENFILENAMEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_OPENFILENAME_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       POINT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setPOINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2_3JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2_3JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlongArray arg1, jint arg2)
+{
+       POINT _arg0, *lparg0=NULL;
+       jlong *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2_3JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       if (arg0 && lparg0) setPOINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2_3JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_SAFEARRAY_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_SAFEARRAY_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       SAFEARRAY _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SAFEARRAY_2JI_FUNC);
+       if (arg0) if ((lparg0 = getSAFEARRAYFields(env, arg0, &_arg0)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setSAFEARRAYFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SAFEARRAY_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1ITEM_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1ITEM_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       SCRIPT_ITEM _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1ITEM_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setSCRIPT_ITEMFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1ITEM_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1LOGATTR_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1LOGATTR_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       SCRIPT_LOGATTR _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1LOGATTR_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setSCRIPT_LOGATTRFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1LOGATTR_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1PROPERTIES_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1PROPERTIES_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       SCRIPT_PROPERTIES _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1PROPERTIES_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setSCRIPT_PROPERTIESFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1PROPERTIES_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_TEXTMETRIC_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_TEXTMETRIC_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       TEXTMETRIC _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_TEXTMETRIC_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setTEXTMETRICFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_TEXTMETRIC_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_TOUCHINPUT_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_TOUCHINPUT_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       TOUCHINPUT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_TOUCHINPUT_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setTOUCHINPUTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_TOUCHINPUT_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_UDACCEL_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_UDACCEL_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       UDACCEL _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_UDACCEL_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setUDACCELFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_UDACCEL_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_WINDOWPOS_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_WINDOWPOS_2JI)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+       WINDOWPOS _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_WINDOWPOS_2JI_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+       if (arg0 && lparg0) setWINDOWPOSFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_WINDOWPOS_2JI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3BJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3BJI)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jlong arg1, jint arg2)
+{
+       jbyte *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3BJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3BJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3BLorg_eclipse_swt_internal_win32_ACCEL_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3BLorg_eclipse_swt_internal_win32_ACCEL_2I)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jobject arg1, jint arg2)
+{
+       jbyte *lparg0=NULL;
+       ACCEL _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3BLorg_eclipse_swt_internal_win32_ACCEL_2I_FUNC);
+       if (arg1) if ((lparg1 = getACCELFields(env, arg1, &_arg1)) == NULL) goto fail;
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3BLorg_eclipse_swt_internal_win32_ACCEL_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3BLorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3BLorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2I)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jobject arg1, jint arg2)
+{
+       jbyte *lparg0=NULL;
+       BITMAPINFOHEADER _arg1, *lparg1=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3BLorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2I_FUNC);
+       if (arg1) if ((lparg1 = getBITMAPINFOHEADERFields(env, arg1, &_arg1)) == NULL) goto fail;
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)lparg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3BLorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2I_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3CJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3CJI)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlong arg1, jint arg2)
+{
+       jchar *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3CJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3CJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3DJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3DJI)
+       (JNIEnv *env, jclass that, jdoubleArray arg0, jlong arg1, jint arg2)
+{
+       jdouble *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3DJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3DJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3FJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3FJI)
+       (JNIEnv *env, jclass that, jfloatArray arg0, jlong arg1, jint arg2)
+{
+       jfloat *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3FJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3FJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3IJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3IJI)
+       (JNIEnv *env, jclass that, jintArray arg0, jlong arg1, jint arg2)
+{
+       jint *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3IJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3IJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3JJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3JJI)
+       (JNIEnv *env, jclass that, jlongArray arg0, jlong arg1, jint arg2)
+{
+       jlong *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3JJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3JJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveMemory___3SJI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory___3SJI)
+       (JNIEnv *env, jclass that, jshortArray arg0, jlong arg1, jint arg2)
+{
+       jshort *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, MoveMemory___3SJI_FUNC);
+               if (arg0) if ((lparg0 = (*env)->GetPrimitiveArrayCritical(env, arg0, NULL)) == NULL) goto fail;
+       MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+               if (arg0 && lparg0) (*env)->ReleasePrimitiveArrayCritical(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, MoveMemory___3SJI_FUNC);
+}
+#endif
+
+#ifndef NO_MoveToEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(MoveToEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jlong arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, MoveToEx_FUNC);
+       rc = (jboolean)MoveToEx((HDC)arg0, arg1, arg2, (LPPOINT)arg3);
+       OS_NATIVE_EXIT(env, that, MoveToEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MultiByteToWideChar__IIJI_3CI
+JNIEXPORT jint JNICALL OS_NATIVE(MultiByteToWideChar__IIJI_3CI)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jlong arg2, jint arg3, jcharArray arg4, jint arg5)
+{
+       jchar *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MultiByteToWideChar__IIJI_3CI_FUNC);
+               if (arg4) if ((lparg4 = (*env)->GetPrimitiveArrayCritical(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)MultiByteToWideChar(arg0, arg1, (LPCSTR)arg2, arg3, (LPWSTR)lparg4, arg5);
+fail:
+               if (arg4 && lparg4) (*env)->ReleasePrimitiveArrayCritical(env, arg4, lparg4, 0);
+       OS_NATIVE_EXIT(env, that, MultiByteToWideChar__IIJI_3CI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_MultiByteToWideChar__II_3BI_3CI
+JNIEXPORT jint JNICALL OS_NATIVE(MultiByteToWideChar__II_3BI_3CI)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jbyteArray arg2, jint arg3, jcharArray arg4, jint arg5)
+{
+       jbyte *lparg2=NULL;
+       jchar *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, MultiByteToWideChar__II_3BI_3CI_FUNC);
+               if (arg2) if ((lparg2 = (*env)->GetPrimitiveArrayCritical(env, arg2, NULL)) == NULL) goto fail;
+               if (arg4) if ((lparg4 = (*env)->GetPrimitiveArrayCritical(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)MultiByteToWideChar(arg0, arg1, (LPCSTR)lparg2, arg3, (LPWSTR)lparg4, arg5);
+fail:
+               if (arg4 && lparg4) (*env)->ReleasePrimitiveArrayCritical(env, arg4, lparg4, 0);
+               if (arg2 && lparg2) (*env)->ReleasePrimitiveArrayCritical(env, arg2, lparg2, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, MultiByteToWideChar__II_3BI_3CI_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMCUSTOMDRAW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMCUSTOMDRAW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMCUSTOMDRAW_1sizeof_FUNC);
+       rc = (jint)NMCUSTOMDRAW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMCUSTOMDRAW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMHDR_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMHDR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMHDR_1sizeof_FUNC);
+       rc = (jint)NMHDR_sizeof();
+       OS_NATIVE_EXIT(env, that, NMHDR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMHEADER_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMHEADER_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMHEADER_1sizeof_FUNC);
+       rc = (jint)NMHEADER_sizeof();
+       OS_NATIVE_EXIT(env, that, NMHEADER_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMLINK_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMLINK_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMLINK_1sizeof_FUNC);
+       rc = (jint)NMLINK_sizeof();
+       OS_NATIVE_EXIT(env, that, NMLINK_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMLISTVIEW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMLISTVIEW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMLISTVIEW_1sizeof_FUNC);
+       rc = (jint)NMLISTVIEW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMLISTVIEW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMLVCUSTOMDRAW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMLVCUSTOMDRAW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMLVCUSTOMDRAW_1sizeof_FUNC);
+       rc = (jint)NMLVCUSTOMDRAW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMLVCUSTOMDRAW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMLVDISPINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMLVDISPINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMLVDISPINFO_1sizeof_FUNC);
+       rc = (jint)NMLVDISPINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, NMLVDISPINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMLVFINDITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMLVFINDITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMLVFINDITEM_1sizeof_FUNC);
+       rc = (jint)NMLVFINDITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, NMLVFINDITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMLVODSTATECHANGE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMLVODSTATECHANGE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMLVODSTATECHANGE_1sizeof_FUNC);
+       rc = (jint)NMLVODSTATECHANGE_sizeof();
+       OS_NATIVE_EXIT(env, that, NMLVODSTATECHANGE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMREBARCHEVRON_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMREBARCHEVRON_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMREBARCHEVRON_1sizeof_FUNC);
+       rc = (jint)NMREBARCHEVRON_sizeof();
+       OS_NATIVE_EXIT(env, that, NMREBARCHEVRON_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMREBARCHILDSIZE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMREBARCHILDSIZE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMREBARCHILDSIZE_1sizeof_FUNC);
+       rc = (jint)NMREBARCHILDSIZE_sizeof();
+       OS_NATIVE_EXIT(env, that, NMREBARCHILDSIZE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTBCUSTOMDRAW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTBCUSTOMDRAW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTBCUSTOMDRAW_1sizeof_FUNC);
+       rc = (jint)NMTBCUSTOMDRAW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTBCUSTOMDRAW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTBHOTITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTBHOTITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTBHOTITEM_1sizeof_FUNC);
+       rc = (jint)NMTBHOTITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTBHOTITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTOOLBAR_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTOOLBAR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTOOLBAR_1sizeof_FUNC);
+       rc = (jint)NMTOOLBAR_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTOOLBAR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTREEVIEW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTREEVIEW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTREEVIEW_1sizeof_FUNC);
+       rc = (jint)NMTREEVIEW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTREEVIEW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTTCUSTOMDRAW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTTCUSTOMDRAW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTTCUSTOMDRAW_1sizeof_FUNC);
+       rc = (jint)NMTTCUSTOMDRAW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTTCUSTOMDRAW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTTDISPINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTTDISPINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTTDISPINFO_1sizeof_FUNC);
+       rc = (jint)NMTTDISPINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTTDISPINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTVCUSTOMDRAW_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTVCUSTOMDRAW_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTVCUSTOMDRAW_1sizeof_FUNC);
+       rc = (jint)NMTVCUSTOMDRAW_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTVCUSTOMDRAW_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTVDISPINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTVDISPINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTVDISPINFO_1sizeof_FUNC);
+       rc = (jint)NMTVDISPINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTVDISPINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMTVITEMCHANGE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMTVITEMCHANGE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMTVITEMCHANGE_1sizeof_FUNC);
+       rc = (jint)NMTVITEMCHANGE_sizeof();
+       OS_NATIVE_EXIT(env, that, NMTVITEMCHANGE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NMUPDOWN_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NMUPDOWN_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NMUPDOWN_1sizeof_FUNC);
+       rc = (jint)NMUPDOWN_sizeof();
+       OS_NATIVE_EXIT(env, that, NMUPDOWN_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NONCLIENTMETRICS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(NONCLIENTMETRICS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NONCLIENTMETRICS_1sizeof_FUNC);
+       rc = (jint)NONCLIENTMETRICS_sizeof();
+       OS_NATIVE_EXIT(env, that, NONCLIENTMETRICS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NOTIFYICONDATA_1V2_1SIZE
+JNIEXPORT jint JNICALL OS_NATIVE(NOTIFYICONDATA_1V2_1SIZE)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, NOTIFYICONDATA_1V2_1SIZE_FUNC);
+       rc = (jint)NOTIFYICONDATA_V2_SIZE;
+       OS_NATIVE_EXIT(env, that, NOTIFYICONDATA_1V2_1SIZE_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_NotifyWinEvent
+JNIEXPORT void JNICALL OS_NATIVE(NotifyWinEvent)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jint arg3)
+{
+       OS_NATIVE_ENTER(env, that, NotifyWinEvent_FUNC);
+       NotifyWinEvent((DWORD)arg0, (HWND)arg1, (LONG)arg2, (LONG)arg3);
+       OS_NATIVE_EXIT(env, that, NotifyWinEvent_FUNC);
+}
+#endif
+
+#ifndef NO_OFNOTIFY_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(OFNOTIFY_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, OFNOTIFY_1sizeof_FUNC);
+       rc = (jint)OFNOTIFY_sizeof();
+       OS_NATIVE_EXIT(env, that, OFNOTIFY_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OPENFILENAME_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(OPENFILENAME_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, OPENFILENAME_1sizeof_FUNC);
+       rc = (jint)OPENFILENAME_sizeof();
+       OS_NATIVE_EXIT(env, that, OPENFILENAME_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OUTLINETEXTMETRIC_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(OUTLINETEXTMETRIC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, OUTLINETEXTMETRIC_1sizeof_FUNC);
+       rc = (jint)OUTLINETEXTMETRIC_sizeof();
+       OS_NATIVE_EXIT(env, that, OUTLINETEXTMETRIC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OffsetRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(OffsetRect)
+       (JNIEnv *env, jclass that, jobject arg0, jint arg1, jint arg2)
+{
+       RECT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, OffsetRect_FUNC);
+       if (arg0) if ((lparg0 = getRECTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)OffsetRect(lparg0, arg1, arg2);
+fail:
+       if (arg0 && lparg0) setRECTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, OffsetRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OffsetRgn
+JNIEXPORT jint JNICALL OS_NATIVE(OffsetRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, OffsetRgn_FUNC);
+       rc = (jint)OffsetRgn((HRGN)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, OffsetRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleInitialize
+JNIEXPORT jint JNICALL OS_NATIVE(OleInitialize)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, OleInitialize_FUNC);
+       rc = (jint)OleInitialize((LPVOID)arg0);
+       OS_NATIVE_EXIT(env, that, OleInitialize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OleUninitialize
+JNIEXPORT void JNICALL OS_NATIVE(OleUninitialize)
+       (JNIEnv *env, jclass that)
+{
+       OS_NATIVE_ENTER(env, that, OleUninitialize_FUNC);
+       OleUninitialize();
+       OS_NATIVE_EXIT(env, that, OleUninitialize_FUNC);
+}
+#endif
+
+#ifndef NO_OpenClipboard
+JNIEXPORT jboolean JNICALL OS_NATIVE(OpenClipboard)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, OpenClipboard_FUNC);
+       rc = (jboolean)OpenClipboard((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, OpenClipboard_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OpenPrinter
+JNIEXPORT jboolean JNICALL OS_NATIVE(OpenPrinter)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlongArray arg1, jlong arg2)
+{
+       jchar *lparg0=NULL;
+       jlong *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, OpenPrinter_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)OpenPrinter((LPWSTR)lparg0, (LPHANDLE)lparg1, (LPPRINTER_DEFAULTSW)arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, OpenPrinter_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OpenProcess
+JNIEXPORT jlong JNICALL OS_NATIVE(OpenProcess)
+       (JNIEnv *env, jclass that, jint arg0, jboolean arg1, jint arg2)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, OpenProcess_FUNC);
+       rc = (jlong)OpenProcess((DWORD)arg0, arg1, (DWORD)arg2);
+       OS_NATIVE_EXIT(env, that, OpenProcess_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_OpenThemeData
+JNIEXPORT jlong JNICALL OS_NATIVE(OpenThemeData)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1)
+{
+       jchar *lparg1=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, OpenThemeData_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jlong)OpenThemeData((HWND)arg0, (LPCWSTR)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, OpenThemeData_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PAINTSTRUCT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(PAINTSTRUCT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PAINTSTRUCT_1sizeof_FUNC);
+       rc = (jint)PAINTSTRUCT_sizeof();
+       OS_NATIVE_EXIT(env, that, PAINTSTRUCT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PANOSE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(PANOSE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PANOSE_1sizeof_FUNC);
+       rc = (jint)PANOSE_sizeof();
+       OS_NATIVE_EXIT(env, that, PANOSE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_POINTSTOPOINT
+JNIEXPORT void JNICALL OS_NATIVE(POINTSTOPOINT)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1)
+{
+       POINT _arg0, *lparg0=NULL;
+       OS_NATIVE_ENTER(env, that, POINTSTOPOINT_FUNC);
+       if (arg0) if ((lparg0 = getPOINTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       POINTSTOPOINT(*lparg0, arg1);
+fail:
+       if (arg0 && lparg0) setPOINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, POINTSTOPOINT_FUNC);
+}
+#endif
+
+#ifndef NO_POINT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(POINT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, POINT_1sizeof_FUNC);
+       rc = (jint)POINT_sizeof();
+       OS_NATIVE_EXIT(env, that, POINT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PRIMARYLANGID
+JNIEXPORT jshort JNICALL OS_NATIVE(PRIMARYLANGID)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jshort rc = 0;
+       OS_NATIVE_ENTER(env, that, PRIMARYLANGID_FUNC);
+       rc = (jshort)PRIMARYLANGID(arg0);
+       OS_NATIVE_EXIT(env, that, PRIMARYLANGID_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PRINTDLG_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(PRINTDLG_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PRINTDLG_1sizeof_FUNC);
+       rc = (jint)PRINTDLG_sizeof();
+       OS_NATIVE_EXIT(env, that, PRINTDLG_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PROCESS_1INFORMATION_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(PROCESS_1INFORMATION_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PROCESS_1INFORMATION_1sizeof_FUNC);
+       rc = (jint)PROCESS_INFORMATION_sizeof();
+       OS_NATIVE_EXIT(env, that, PROCESS_1INFORMATION_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PROPERTYKEY_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(PROPERTYKEY_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PROPERTYKEY_1sizeof_FUNC);
+       rc = (jint)PROPERTYKEY_sizeof();
+       OS_NATIVE_EXIT(env, that, PROPERTYKEY_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PROPVARIANT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(PROPVARIANT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PROPVARIANT_1sizeof_FUNC);
+       rc = (jint)PROPVARIANT_sizeof();
+       OS_NATIVE_EXIT(env, that, PROPVARIANT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PSPropertyKeyFromString
+JNIEXPORT jint JNICALL OS_NATIVE(PSPropertyKeyFromString)
+       (JNIEnv *env, jclass that, jcharArray arg0, jobject arg1)
+{
+       jchar *lparg0=NULL;
+       PROPERTYKEY _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, PSPropertyKeyFromString_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getPROPERTYKEYFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)PSPropertyKeyFromString(lparg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPROPERTYKEYFields(env, arg1, lparg1);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, PSPropertyKeyFromString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PatBlt
+JNIEXPORT jboolean JNICALL OS_NATIVE(PatBlt)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jint arg5)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PatBlt_FUNC);
+       rc = (jboolean)PatBlt((HDC)arg0, arg1, arg2, arg3, arg4, arg5);
+       OS_NATIVE_EXIT(env, that, PatBlt_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PathIsExe
+JNIEXPORT jboolean JNICALL OS_NATIVE(PathIsExe)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PathIsExe_FUNC);
+       rc = (jboolean)PathIsExe((LPCWSTR)arg0);
+       OS_NATIVE_EXIT(env, that, PathIsExe_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PeekMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(PeekMessage)
+       (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2, jint arg3, jint arg4)
+{
+       MSG _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PeekMessage_FUNC);
+       if (arg0) if ((lparg0 = getMSGFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)PeekMessage(lparg0, (HWND)arg1, arg2, arg3, arg4);
+fail:
+       if (arg0 && lparg0) setMSGFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, PeekMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Pie
+JNIEXPORT jboolean JNICALL OS_NATIVE(Pie)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7, jint arg8)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Pie_FUNC);
+       rc = (jboolean)Pie((HDC)arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+       OS_NATIVE_EXIT(env, that, Pie_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Polygon
+JNIEXPORT jboolean JNICALL OS_NATIVE(Polygon)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jint arg2)
+{
+       jint *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Polygon_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)Polygon((HDC)arg0, (CONST POINT *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, Polygon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Polyline
+JNIEXPORT jboolean JNICALL OS_NATIVE(Polyline)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jint arg2)
+{
+       jint *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Polyline_FUNC);
+               if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)Polyline((HDC)arg0, (CONST POINT *)lparg1, arg2);
+fail:
+               if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, Polyline_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PostMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(PostMessage)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PostMessage_FUNC);
+       rc = (jboolean)PostMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
+       OS_NATIVE_EXIT(env, that, PostMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PostThreadMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(PostThreadMessage)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PostThreadMessage_FUNC);
+       rc = (jboolean)PostThreadMessage(arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
+       OS_NATIVE_EXIT(env, that, PostThreadMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PrintDlg
+JNIEXPORT jboolean JNICALL OS_NATIVE(PrintDlg)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       PRINTDLG _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PrintDlg_FUNC);
+       if (arg0) if ((lparg0 = getPRINTDLGFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)PrintDlg((LPPRINTDLGW)lparg0);
+fail:
+       if (arg0 && lparg0) setPRINTDLGFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, PrintDlg_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PrintWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(PrintWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PrintWindow_FUNC);
+       rc = (jboolean)PrintWindow((HWND)arg0, (HDC)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, PrintWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PtInRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(PtInRect)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1)
+{
+       RECT _arg0, *lparg0=NULL;
+       POINT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PtInRect_FUNC);
+       if (arg0) if ((lparg0 = getRECTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)PtInRect(lparg0, *lparg1);
+fail:
+       OS_NATIVE_EXIT(env, that, PtInRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_PtInRegion
+JNIEXPORT jboolean JNICALL OS_NATIVE(PtInRegion)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, PtInRegion_FUNC);
+       rc = (jboolean)PtInRegion((HRGN)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, PtInRegion_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_REBARBANDINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(REBARBANDINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, REBARBANDINFO_1sizeof_FUNC);
+       rc = (jint)REBARBANDINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, REBARBANDINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RECT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(RECT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RECT_1sizeof_FUNC);
+       rc = (jint)RECT_sizeof();
+       OS_NATIVE_EXIT(env, that, RECT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RectInRegion
+JNIEXPORT jboolean JNICALL OS_NATIVE(RectInRegion)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, RectInRegion_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)RectInRegion((HRGN)arg0, lparg1);
+fail:
+       OS_NATIVE_EXIT(env, that, RectInRegion_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Rectangle
+JNIEXPORT jboolean JNICALL OS_NATIVE(Rectangle)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Rectangle_FUNC);
+       rc = (jboolean)Rectangle((HDC)arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, Rectangle_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RedrawWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(RedrawWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2, jint arg3)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, RedrawWindow_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)RedrawWindow((HWND)arg0, lparg1, (HRGN)arg2, arg3);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, RedrawWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegCloseKey
+JNIEXPORT jint JNICALL OS_NATIVE(RegCloseKey)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegCloseKey_FUNC);
+       rc = (jint)RegCloseKey((HKEY)arg0);
+       OS_NATIVE_EXIT(env, that, RegCloseKey_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegCreateKeyEx
+JNIEXPORT jint JNICALL OS_NATIVE(RegCreateKeyEx)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jcharArray arg3, jint arg4, jint arg5, jlong arg6, jlongArray arg7, jlongArray arg8)
+{
+       jchar *lparg1=NULL;
+       jchar *lparg3=NULL;
+       jlong *lparg7=NULL;
+       jlong *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegCreateKeyEx_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = (*env)->GetLongArrayElements(env, arg7, NULL)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = (*env)->GetLongArrayElements(env, arg8, NULL)) == NULL) goto fail;
+       rc = (jint)RegCreateKeyEx((HKEY)arg0, (LPWSTR)lparg1, arg2, (LPWSTR)lparg3, arg4, arg5, (LPSECURITY_ATTRIBUTES)arg6, (PHKEY)lparg7, (LPDWORD)lparg8);
+fail:
+       if (arg8 && lparg8) (*env)->ReleaseLongArrayElements(env, arg8, lparg8, 0);
+       if (arg7 && lparg7) (*env)->ReleaseLongArrayElements(env, arg7, lparg7, 0);
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, RegCreateKeyEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegDeleteValue
+JNIEXPORT jint JNICALL OS_NATIVE(RegDeleteValue)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegDeleteValue_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)RegDeleteValue((HKEY)arg0, (LPWSTR)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, RegDeleteValue_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegEnumKeyEx
+JNIEXPORT jint JNICALL OS_NATIVE(RegEnumKeyEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jcharArray arg2, jintArray arg3, jintArray arg4, jcharArray arg5, jintArray arg6, jobject arg7)
+{
+       jchar *lparg2=NULL;
+       jint *lparg3=NULL;
+       jint *lparg4=NULL;
+       jchar *lparg5=NULL;
+       jint *lparg6=NULL;
+       FILETIME _arg7, *lparg7=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegEnumKeyEx_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetCharArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = getFILETIMEFields(env, arg7, &_arg7)) == NULL) goto fail;
+       rc = (jint)RegEnumKeyEx((HKEY)arg0, arg1, (LPWSTR)lparg2, (LPDWORD)lparg3, (LPDWORD)lparg4, (LPWSTR)lparg5, (LPDWORD)lparg6, lparg7);
+fail:
+       if (arg7 && lparg7) setFILETIMEFields(env, arg7, lparg7);
+       if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
+       if (arg5 && lparg5) (*env)->ReleaseCharArrayElements(env, arg5, lparg5, 0);
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, RegEnumKeyEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegOpenKeyEx
+JNIEXPORT jint JNICALL OS_NATIVE(RegOpenKeyEx)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jint arg3, jlongArray arg4)
+{
+       jchar *lparg1=NULL;
+       jlong *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegOpenKeyEx_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetLongArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)RegOpenKeyEx((HKEY)arg0, (LPWSTR)lparg1, arg2, arg3, (PHKEY)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseLongArrayElements(env, arg4, lparg4, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, RegOpenKeyEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegQueryValueEx__J_3CJ_3I_3C_3I
+JNIEXPORT jint JNICALL OS_NATIVE(RegQueryValueEx__J_3CJ_3I_3C_3I)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2, jintArray arg3, jcharArray arg4, jintArray arg5)
+{
+       jchar *lparg1=NULL;
+       jint *lparg3=NULL;
+       jchar *lparg4=NULL;
+       jint *lparg5=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegQueryValueEx__J_3CJ_3I_3C_3I_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetCharArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)RegQueryValueEx((HKEY)arg0, (LPWSTR)lparg1, (LPDWORD)arg2, (LPDWORD)lparg3, (LPBYTE)lparg4, (LPDWORD)lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
+       if (arg4 && lparg4) (*env)->ReleaseCharArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, RegQueryValueEx__J_3CJ_3I_3C_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegQueryValueEx__J_3CJ_3I_3I_3I
+JNIEXPORT jint JNICALL OS_NATIVE(RegQueryValueEx__J_3CJ_3I_3I_3I)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2, jintArray arg3, jintArray arg4, jintArray arg5)
+{
+       jchar *lparg1=NULL;
+       jint *lparg3=NULL;
+       jint *lparg4=NULL;
+       jint *lparg5=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegQueryValueEx__J_3CJ_3I_3I_3I_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)RegQueryValueEx((HKEY)arg0, (LPWSTR)lparg1, (LPDWORD)arg2, (LPDWORD)lparg3, (LPBYTE)lparg4, (LPDWORD)lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, RegQueryValueEx__J_3CJ_3I_3I_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegSetValueEx
+JNIEXPORT jint JNICALL OS_NATIVE(RegSetValueEx)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jint arg3, jintArray arg4, jint arg5)
+{
+       jchar *lparg1=NULL;
+       jint *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegSetValueEx_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)RegSetValueEx((HKEY)arg0, (LPWSTR)lparg1, arg2, arg3, (const BYTE*)lparg4, arg5);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, RegSetValueEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegisterClass
+JNIEXPORT jint JNICALL OS_NATIVE(RegisterClass)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       WNDCLASS _arg0, *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegisterClass_FUNC);
+       if (arg0) if ((lparg0 = getWNDCLASSFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jint)RegisterClass((LPWNDCLASSW)lparg0);
+fail:
+       if (arg0 && lparg0) setWNDCLASSFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, RegisterClass_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegisterClipboardFormat
+JNIEXPORT jint JNICALL OS_NATIVE(RegisterClipboardFormat)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegisterClipboardFormat_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)RegisterClipboardFormat((LPWSTR)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, RegisterClipboardFormat_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegisterTouchWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(RegisterTouchWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, RegisterTouchWindow_FUNC);
+/*
+       rc = (jboolean)RegisterTouchWindow((HWND)arg0, (ULONG)arg1);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, RegisterTouchWindow)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HWND, ULONG))fp)((HWND)arg0, (ULONG)arg1);
+               }
+       }
+       OS_NATIVE_EXIT(env, that, RegisterTouchWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RegisterWindowMessage
+JNIEXPORT jint JNICALL OS_NATIVE(RegisterWindowMessage)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, RegisterWindowMessage_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)RegisterWindowMessage((LPWSTR)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, RegisterWindowMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ReleaseCapture
+JNIEXPORT jboolean JNICALL OS_NATIVE(ReleaseCapture)
+       (JNIEnv *env, jclass that)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ReleaseCapture_FUNC);
+       rc = (jboolean)ReleaseCapture();
+       OS_NATIVE_EXIT(env, that, ReleaseCapture_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ReleaseDC
+JNIEXPORT jint JNICALL OS_NATIVE(ReleaseDC)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ReleaseDC_FUNC);
+       rc = (jint)ReleaseDC((HWND)arg0, (HDC)arg1);
+       OS_NATIVE_EXIT(env, that, ReleaseDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RemoveMenu
+JNIEXPORT jboolean JNICALL OS_NATIVE(RemoveMenu)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, RemoveMenu_FUNC);
+       rc = (jboolean)RemoveMenu((HMENU)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, RemoveMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RemoveProp
+JNIEXPORT jlong JNICALL OS_NATIVE(RemoveProp)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, RemoveProp_FUNC);
+       rc = (jlong)RemoveProp((HWND)arg0, (LPCWSTR)arg1);
+       OS_NATIVE_EXIT(env, that, RemoveProp_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ReplyMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(ReplyMessage)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ReplyMessage_FUNC);
+       rc = (jboolean)ReplyMessage(arg0);
+       OS_NATIVE_EXIT(env, that, ReplyMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RestoreDC
+JNIEXPORT jboolean JNICALL OS_NATIVE(RestoreDC)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, RestoreDC_FUNC);
+       rc = (jboolean)RestoreDC((HDC)arg0, (int)arg1);
+       OS_NATIVE_EXIT(env, that, RestoreDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_RoundRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(RoundRect)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jint arg5, jint arg6)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, RoundRect_FUNC);
+       rc = (jboolean)RoundRect((HDC)arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+       OS_NATIVE_EXIT(env, that, RoundRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SAFEARRAYBOUND_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SAFEARRAYBOUND_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SAFEARRAYBOUND_1sizeof_FUNC);
+       rc = (jint)SAFEARRAYBOUND_sizeof();
+       OS_NATIVE_EXIT(env, that, SAFEARRAYBOUND_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SAFEARRAY_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SAFEARRAY_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SAFEARRAY_1sizeof_FUNC);
+       rc = (jint)SAFEARRAY_sizeof();
+       OS_NATIVE_EXIT(env, that, SAFEARRAY_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1ANALYSIS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1ANALYSIS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1ANALYSIS_1sizeof_FUNC);
+       rc = (jint)SCRIPT_ANALYSIS_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1ANALYSIS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1CONTROL_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1CONTROL_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1CONTROL_1sizeof_FUNC);
+       rc = (jint)SCRIPT_CONTROL_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1CONTROL_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1DIGITSUBSTITUTE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1DIGITSUBSTITUTE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1DIGITSUBSTITUTE_1sizeof_FUNC);
+       rc = (jint)SCRIPT_DIGITSUBSTITUTE_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1DIGITSUBSTITUTE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1FONTPROPERTIES_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1FONTPROPERTIES_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1FONTPROPERTIES_1sizeof_FUNC);
+       rc = (jint)SCRIPT_FONTPROPERTIES_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1FONTPROPERTIES_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1ITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1ITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1ITEM_1sizeof_FUNC);
+       rc = (jint)SCRIPT_ITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1ITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1LOGATTR_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1LOGATTR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1LOGATTR_1sizeof_FUNC);
+       rc = (jint)SCRIPT_LOGATTR_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1LOGATTR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1PROPERTIES_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1PROPERTIES_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1PROPERTIES_1sizeof_FUNC);
+       rc = (jint)SCRIPT_PROPERTIES_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1PROPERTIES_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1STATE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1STATE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1STATE_1sizeof_FUNC);
+       rc = (jint)SCRIPT_STATE_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1STATE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCRIPT_1STRING_1ANALYSIS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCRIPT_1STRING_1ANALYSIS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCRIPT_1STRING_1ANALYSIS_1sizeof_FUNC);
+       rc = (jint)SCRIPT_STRING_ANALYSIS_sizeof();
+       OS_NATIVE_EXIT(env, that, SCRIPT_1STRING_1ANALYSIS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCROLLBARINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCROLLBARINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCROLLBARINFO_1sizeof_FUNC);
+       rc = (jint)SCROLLBARINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, SCROLLBARINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SCROLLINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SCROLLINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SCROLLINFO_1sizeof_FUNC);
+       rc = (jint)SCROLLINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, SCROLLINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHBrowseForFolder
+JNIEXPORT jlong JNICALL OS_NATIVE(SHBrowseForFolder)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       BROWSEINFO _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SHBrowseForFolder_FUNC);
+       if (arg0) if ((lparg0 = getBROWSEINFOFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jlong)SHBrowseForFolder((LPBROWSEINFOW)lparg0);
+fail:
+       if (arg0 && lparg0) setBROWSEINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, SHBrowseForFolder_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHDRAGIMAGE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SHDRAGIMAGE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SHDRAGIMAGE_1sizeof_FUNC);
+       rc = (jint)SHDRAGIMAGE_sizeof();
+       OS_NATIVE_EXIT(env, that, SHDRAGIMAGE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHELLEXECUTEINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SHELLEXECUTEINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SHELLEXECUTEINFO_1sizeof_FUNC);
+       rc = (jint)SHELLEXECUTEINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, SHELLEXECUTEINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHFILEINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SHFILEINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SHFILEINFO_1sizeof_FUNC);
+       rc = (jint)SHFILEINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, SHFILEINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHGetFileInfo
+JNIEXPORT jlong JNICALL OS_NATIVE(SHGetFileInfo)
+       (JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jobject arg2, jint arg3, jint arg4)
+{
+       jchar *lparg0=NULL;
+       SHFILEINFO _arg2, *lparg2=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SHGetFileInfo_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getSHFILEINFOFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jlong)SHGetFileInfo((LPCWSTR)lparg0, arg1, (SHFILEINFOW *)lparg2, arg3, arg4);
+fail:
+       if (arg2 && lparg2) setSHFILEINFOFields(env, arg2, lparg2);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, SHGetFileInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHGetMalloc
+JNIEXPORT jint JNICALL OS_NATIVE(SHGetMalloc)
+       (JNIEnv *env, jclass that, jlongArray arg0)
+{
+       jlong *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SHGetMalloc_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetLongArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jint)SHGetMalloc((LPMALLOC *)lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseLongArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, SHGetMalloc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SHGetPathFromIDList
+JNIEXPORT jboolean JNICALL OS_NATIVE(SHGetPathFromIDList)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1)
+{
+       jchar *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SHGetPathFromIDList_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)SHGetPathFromIDList((LPCITEMIDLIST)arg0, (LPWSTR)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, SHGetPathFromIDList_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SIZE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SIZE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SIZE_1sizeof_FUNC);
+       rc = (jint)SIZE_sizeof();
+       OS_NATIVE_EXIT(env, that, SIZE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_STARTUPINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(STARTUPINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, STARTUPINFO_1sizeof_FUNC);
+       rc = (jint)STARTUPINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, STARTUPINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SYSTEMTIME_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(SYSTEMTIME_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SYSTEMTIME_1sizeof_FUNC);
+       rc = (jint)SYSTEMTIME_sizeof();
+       OS_NATIVE_EXIT(env, that, SYSTEMTIME_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SaveDC
+JNIEXPORT jint JNICALL OS_NATIVE(SaveDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SaveDC_FUNC);
+       rc = (jint)SaveDC((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, SaveDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScreenToClient
+JNIEXPORT jboolean JNICALL OS_NATIVE(ScreenToClient)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       POINT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ScreenToClient_FUNC);
+       if (arg1) if ((lparg1 = getPOINTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ScreenToClient((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPOINTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ScreenToClient_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptApplyDigitSubstitution
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptApplyDigitSubstitution)
+       (JNIEnv *env, jclass that, jobject arg0, jobject arg1, jobject arg2)
+{
+       SCRIPT_DIGITSUBSTITUTE _arg0, *lparg0=NULL;
+       SCRIPT_CONTROL _arg1, *lparg1=NULL;
+       SCRIPT_STATE _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptApplyDigitSubstitution_FUNC);
+       if (arg0) if ((lparg0 = getSCRIPT_DIGITSUBSTITUTEFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = getSCRIPT_CONTROLFields(env, arg1, &_arg1)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getSCRIPT_STATEFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)ScriptApplyDigitSubstitution((const SCRIPT_DIGITSUBSTITUTE*)lparg0, (SCRIPT_CONTROL*)lparg1, (SCRIPT_STATE*)lparg2);
+fail:
+       if (arg2 && lparg2) setSCRIPT_STATEFields(env, arg2, lparg2);
+       if (arg1 && lparg1) setSCRIPT_CONTROLFields(env, arg1, lparg1);
+       if (arg0 && lparg0) setSCRIPT_DIGITSUBSTITUTEFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, ScriptApplyDigitSubstitution_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptBreak
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptBreak)
+       (JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jobject arg2, jlong arg3)
+{
+       jchar *lparg0=NULL;
+       SCRIPT_ANALYSIS _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptBreak_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = getSCRIPT_ANALYSISFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)ScriptBreak((const WCHAR *)lparg0, arg1, (const SCRIPT_ANALYSIS *)lparg2, (SCRIPT_LOGATTR *)arg3);
+fail:
+       if (arg2 && lparg2) setSCRIPT_ANALYSISFields(env, arg2, lparg2);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, ScriptBreak_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptCPtoX
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptCPtoX)
+       (JNIEnv *env, jclass that, jint arg0, jboolean arg1, jint arg2, jint arg3, jlong arg4, jlong arg5, jlong arg6, jobject arg7, jintArray arg8)
+{
+       SCRIPT_ANALYSIS _arg7, *lparg7=NULL;
+       jint *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptCPtoX_FUNC);
+       if (arg7) if ((lparg7 = getSCRIPT_ANALYSISFields(env, arg7, &_arg7)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = (*env)->GetIntArrayElements(env, arg8, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptCPtoX(arg0, arg1, arg2, arg3, (const WORD *)arg4, (const SCRIPT_VISATTR *)arg5, (const int *)arg6, (const SCRIPT_ANALYSIS *)lparg7, (int *)lparg8);
+fail:
+       if (arg8 && lparg8) (*env)->ReleaseIntArrayElements(env, arg8, lparg8, 0);
+       if (arg7 && lparg7) setSCRIPT_ANALYSISFields(env, arg7, lparg7);
+       OS_NATIVE_EXIT(env, that, ScriptCPtoX_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptCacheGetHeight
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptCacheGetHeight)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jintArray arg2)
+{
+       jint *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptCacheGetHeight_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptCacheGetHeight((HDC)arg0, (SCRIPT_CACHE *)arg1, (long *)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ScriptCacheGetHeight_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptFreeCache
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptFreeCache)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptFreeCache_FUNC);
+       rc = (jint)ScriptFreeCache((SCRIPT_CACHE *)arg0);
+       OS_NATIVE_EXIT(env, that, ScriptFreeCache_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptGetCMap
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptGetCMap)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jcharArray arg2, jint arg3, jint arg4, jshortArray arg5)
+{
+       jchar *lparg2=NULL;
+       jshort *lparg5=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptGetCMap_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = (*env)->GetShortArrayElements(env, arg5, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptGetCMap((HDC)arg0, (SCRIPT_CACHE *)arg1, (const WCHAR *)lparg2, arg3, arg4, (WORD*)lparg5);
+fail:
+       if (arg5 && lparg5) (*env)->ReleaseShortArrayElements(env, arg5, lparg5, 0);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ScriptGetCMap_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptGetFontProperties
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptGetFontProperties)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2)
+{
+       SCRIPT_FONTPROPERTIES _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptGetFontProperties_FUNC);
+       if (arg2) if ((lparg2 = getSCRIPT_FONTPROPERTIESFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)ScriptGetFontProperties((HDC)arg0, (SCRIPT_CACHE *)arg1, (SCRIPT_FONTPROPERTIES *)lparg2);
+fail:
+       if (arg2 && lparg2) setSCRIPT_FONTPROPERTIESFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, ScriptGetFontProperties_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptGetLogicalWidths
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptGetLogicalWidths)
+       (JNIEnv *env, jclass that, jobject arg0, jint arg1, jint arg2, jlong arg3, jlong arg4, jlong arg5, jintArray arg6)
+{
+       SCRIPT_ANALYSIS _arg0, *lparg0=NULL;
+       jint *lparg6=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptGetLogicalWidths_FUNC);
+       if (arg0) if ((lparg0 = getSCRIPT_ANALYSISFields(env, arg0, &_arg0)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptGetLogicalWidths((const SCRIPT_ANALYSIS *)lparg0, arg1, arg2, (const int *)arg3, (const WORD *)arg4, (const SCRIPT_VISATTR *)arg5, (int *)lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
+       if (arg0 && lparg0) setSCRIPT_ANALYSISFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, ScriptGetLogicalWidths_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptGetProperties
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptGetProperties)
+       (JNIEnv *env, jclass that, jlongArray arg0, jintArray arg1)
+{
+       jlong *lparg0=NULL;
+       jint *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptGetProperties_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetLongArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptGetProperties((const SCRIPT_PROPERTIES ***)lparg0, (int *)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseLongArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, ScriptGetProperties_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptItemize
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptItemize)
+       (JNIEnv *env, jclass that, jcharArray arg0, jint arg1, jint arg2, jobject arg3, jobject arg4, jlong arg5, jintArray arg6)
+{
+       jchar *lparg0=NULL;
+       SCRIPT_CONTROL _arg3, *lparg3=NULL;
+       SCRIPT_STATE _arg4, *lparg4=NULL;
+       jint *lparg6=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptItemize_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = getSCRIPT_CONTROLFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getSCRIPT_STATEFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptItemize((const WCHAR *)lparg0, arg1, arg2, (const SCRIPT_CONTROL *)lparg3, (const SCRIPT_STATE *)lparg4, (SCRIPT_ITEM *)arg5, (int *)lparg6);
+fail:
+       if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
+       if (arg4 && lparg4) setSCRIPT_STATEFields(env, arg4, lparg4);
+       if (arg3 && lparg3) setSCRIPT_CONTROLFields(env, arg3, lparg3);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, ScriptItemize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptJustify
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptJustify)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jlong arg5)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptJustify_FUNC);
+       rc = (jint)ScriptJustify((SCRIPT_VISATTR *)arg0, (const int *)arg1, arg2, arg3, arg4, (int *)arg5);
+       OS_NATIVE_EXIT(env, that, ScriptJustify_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptLayout
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptLayout)
+       (JNIEnv *env, jclass that, jint arg0, jbyteArray arg1, jintArray arg2, jintArray arg3)
+{
+       jbyte *lparg1=NULL;
+       jint *lparg2=NULL;
+       jint *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptLayout_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptLayout(arg0, (const BYTE *)lparg1, (int *)lparg2, (int *)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, ScriptLayout_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptPlace
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptPlace)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jint arg3, jlong arg4, jobject arg5, jlong arg6, jlong arg7, jintArray arg8)
+{
+       SCRIPT_ANALYSIS _arg5, *lparg5=NULL;
+       jint *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptPlace_FUNC);
+       if (arg5) if ((lparg5 = getSCRIPT_ANALYSISFields(env, arg5, &_arg5)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = (*env)->GetIntArrayElements(env, arg8, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptPlace((HDC)arg0, (SCRIPT_CACHE *)arg1, (const WORD *)arg2, arg3, (const SCRIPT_VISATTR *)arg4, (SCRIPT_ANALYSIS *)lparg5, (int *)arg6, (GOFFSET *)arg7, (ABC *)lparg8);
+fail:
+       if (arg8 && lparg8) (*env)->ReleaseIntArrayElements(env, arg8, lparg8, 0);
+       if (arg5 && lparg5) setSCRIPT_ANALYSISFields(env, arg5, lparg5);
+       OS_NATIVE_EXIT(env, that, ScriptPlace_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptRecordDigitSubstitution
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptRecordDigitSubstitution)
+       (JNIEnv *env, jclass that, jint arg0, jobject arg1)
+{
+       SCRIPT_DIGITSUBSTITUTE _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptRecordDigitSubstitution_FUNC);
+       if (arg1) if ((lparg1 = getSCRIPT_DIGITSUBSTITUTEFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)ScriptRecordDigitSubstitution((LCID)arg0, (SCRIPT_DIGITSUBSTITUTE*)lparg1);
+fail:
+       if (arg1 && lparg1) setSCRIPT_DIGITSUBSTITUTEFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ScriptRecordDigitSubstitution_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptShape
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptShape)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jcharArray arg2, jint arg3, jint arg4, jobject arg5, jlong arg6, jlong arg7, jlong arg8, jintArray arg9)
+{
+       jchar *lparg2=NULL;
+       SCRIPT_ANALYSIS _arg5, *lparg5=NULL;
+       jint *lparg9=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptShape_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg5) if ((lparg5 = getSCRIPT_ANALYSISFields(env, arg5, &_arg5)) == NULL) goto fail;
+       if (arg9) if ((lparg9 = (*env)->GetIntArrayElements(env, arg9, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptShape((HDC)arg0, (SCRIPT_CACHE *)arg1, (const WCHAR *)lparg2, arg3, arg4, (SCRIPT_ANALYSIS *)lparg5, (WORD *)arg6, (WORD *)arg7, (SCRIPT_VISATTR *)arg8, (int *)lparg9);
+fail:
+       if (arg9 && lparg9) (*env)->ReleaseIntArrayElements(env, arg9, lparg9, 0);
+       if (arg5 && lparg5) setSCRIPT_ANALYSISFields(env, arg5, lparg5);
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ScriptShape_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptStringAnalyse
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptStringAnalyse)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jint arg6, jobject arg7, jobject arg8, jlong arg9, jlong arg10, jlong arg11, jlong arg12)
+{
+       SCRIPT_CONTROL _arg7, *lparg7=NULL;
+       SCRIPT_STATE _arg8, *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptStringAnalyse_FUNC);
+       if (arg7) if ((lparg7 = getSCRIPT_CONTROLFields(env, arg7, &_arg7)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = getSCRIPT_STATEFields(env, arg8, &_arg8)) == NULL) goto fail;
+       rc = (jint)ScriptStringAnalyse((HDC)arg0, (const void*)arg1, arg2, arg3, arg4, arg5, arg6, lparg7, lparg8, (const int*)arg9, (SCRIPT_TABDEF*)arg10, (const BYTE*)arg11, (SCRIPT_STRING_ANALYSIS*)arg12);
+fail:
+       if (arg8 && lparg8) setSCRIPT_STATEFields(env, arg8, lparg8);
+       if (arg7 && lparg7) setSCRIPT_CONTROLFields(env, arg7, lparg7);
+       OS_NATIVE_EXIT(env, that, ScriptStringAnalyse_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptStringFree
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptStringFree)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptStringFree_FUNC);
+       rc = (jint)ScriptStringFree((SCRIPT_STRING_ANALYSIS*)arg0);
+       OS_NATIVE_EXIT(env, that, ScriptStringFree_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptStringOut
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptStringOut)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jobject arg4, jint arg5, jint arg6, jboolean arg7)
+{
+       RECT _arg4, *lparg4=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptStringOut_FUNC);
+       if (arg4) if ((lparg4 = getRECTFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jint)ScriptStringOut(*(SCRIPT_STRING_ANALYSIS*)arg0, arg1, arg2, arg3, lparg4, arg5, arg6, arg7);
+fail:
+       if (arg4 && lparg4) setRECTFields(env, arg4, lparg4);
+       OS_NATIVE_EXIT(env, that, ScriptStringOut_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptTextOut
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptTextOut)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jobject arg5, jobject arg6, jlong arg7, jint arg8, jlong arg9, jint arg10, jlong arg11, jlong arg12, jlong arg13)
+{
+       RECT _arg5, *lparg5=NULL;
+       SCRIPT_ANALYSIS _arg6, *lparg6=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptTextOut_FUNC);
+       if (arg5) if ((lparg5 = getRECTFields(env, arg5, &_arg5)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = getSCRIPT_ANALYSISFields(env, arg6, &_arg6)) == NULL) goto fail;
+       rc = (jint)ScriptTextOut((const HDC)arg0, (SCRIPT_CACHE *)arg1, arg2, arg3, arg4, (const RECT *)lparg5, (const SCRIPT_ANALYSIS *)lparg6, (const WCHAR *)arg7, arg8, (const WORD *)arg9, arg10, (const int *)arg11, (const int *)arg12, (const GOFFSET *)arg13);
+fail:
+       if (arg6 && lparg6) setSCRIPT_ANALYSISFields(env, arg6, lparg6);
+       if (arg5 && lparg5) setRECTFields(env, arg5, lparg5);
+       OS_NATIVE_EXIT(env, that, ScriptTextOut_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScriptXtoCP
+JNIEXPORT jint JNICALL OS_NATIVE(ScriptXtoCP)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jint arg2, jlong arg3, jlong arg4, jlong arg5, jobject arg6, jintArray arg7, jintArray arg8)
+{
+       SCRIPT_ANALYSIS _arg6, *lparg6=NULL;
+       jint *lparg7=NULL;
+       jint *lparg8=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScriptXtoCP_FUNC);
+       if (arg6) if ((lparg6 = getSCRIPT_ANALYSISFields(env, arg6, &_arg6)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = (*env)->GetIntArrayElements(env, arg7, NULL)) == NULL) goto fail;
+       if (arg8) if ((lparg8 = (*env)->GetIntArrayElements(env, arg8, NULL)) == NULL) goto fail;
+       rc = (jint)ScriptXtoCP(arg0, arg1, arg2, (const WORD *)arg3, (const SCRIPT_VISATTR *)arg4, (const int *)arg5, (const SCRIPT_ANALYSIS *)lparg6, (int *)lparg7, (int *)lparg8);
+fail:
+       if (arg8 && lparg8) (*env)->ReleaseIntArrayElements(env, arg8, lparg8, 0);
+       if (arg7 && lparg7) (*env)->ReleaseIntArrayElements(env, arg7, lparg7, 0);
+       if (arg6 && lparg6) setSCRIPT_ANALYSISFields(env, arg6, lparg6);
+       OS_NATIVE_EXIT(env, that, ScriptXtoCP_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ScrollWindowEx
+JNIEXPORT jint JNICALL OS_NATIVE(ScrollWindowEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jobject arg3, jobject arg4, jlong arg5, jobject arg6, jint arg7)
+{
+       RECT _arg3, *lparg3=NULL;
+       RECT _arg4, *lparg4=NULL;
+       RECT _arg6, *lparg6=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ScrollWindowEx_FUNC);
+       if (arg3) if ((lparg3 = getRECTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       if (arg4) if ((lparg4 = getRECTFields(env, arg4, &_arg4)) == NULL) goto fail;
+       if (arg6) if ((lparg6 = getRECTFields(env, arg6, &_arg6)) == NULL) goto fail;
+       rc = (jint)ScrollWindowEx((HWND)arg0, arg1, arg2, lparg3, lparg4, (HRGN)arg5, lparg6, arg7);
+fail:
+       if (arg6 && lparg6) setRECTFields(env, arg6, lparg6);
+       if (arg4 && lparg4) setRECTFields(env, arg4, lparg4);
+       if (arg3 && lparg3) setRECTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, ScrollWindowEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SelectClipRgn
+JNIEXPORT jint JNICALL OS_NATIVE(SelectClipRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SelectClipRgn_FUNC);
+       rc = (jint)SelectClipRgn((HDC)arg0, (HRGN)arg1);
+       OS_NATIVE_EXIT(env, that, SelectClipRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SelectObject
+JNIEXPORT jlong JNICALL OS_NATIVE(SelectObject)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SelectObject_FUNC);
+       rc = (jlong)SelectObject((HDC)arg0, (HGDIOBJ)arg1);
+       OS_NATIVE_EXIT(env, that, SelectObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendInput
+JNIEXPORT jint JNICALL OS_NATIVE(SendInput)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SendInput_FUNC);
+       rc = (jint)SendInput(arg0, (LPINPUT)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, SendInput_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJJ
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJJ)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jlong arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJJ_FUNC);
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)arg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJJ_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_BUTTON_1IMAGELIST_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_BUTTON_1IMAGELIST_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       BUTTON_IMAGELIST _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_BUTTON_1IMAGELIST_2_FUNC);
+       if (arg3) if ((lparg3 = getBUTTON_IMAGELISTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setBUTTON_IMAGELISTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_BUTTON_1IMAGELIST_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_HDHITTESTINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_HDHITTESTINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       HDHITTESTINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_HDHITTESTINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getHDHITTESTINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setHDHITTESTINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_HDHITTESTINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_HDITEM_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_HDITEM_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       HDITEM _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_HDITEM_2_FUNC);
+       if (arg3) if ((lparg3 = getHDITEMFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setHDITEMFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_HDITEM_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_HDLAYOUT_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_HDLAYOUT_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       HDLAYOUT _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_HDLAYOUT_2_FUNC);
+       if (arg3) if ((lparg3 = getHDLAYOUTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setHDLAYOUTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_HDLAYOUT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_LITEM_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_LITEM_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       LITEM _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LITEM_2_FUNC);
+       if (arg3) if ((lparg3 = getLITEMFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setLITEMFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LITEM_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_LVCOLUMN_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_LVCOLUMN_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       LVCOLUMN _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVCOLUMN_2_FUNC);
+       if (arg3) if ((lparg3 = getLVCOLUMNFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setLVCOLUMNFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVCOLUMN_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_LVHITTESTINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_LVHITTESTINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       LVHITTESTINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVHITTESTINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getLVHITTESTINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setLVHITTESTINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVHITTESTINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_LVINSERTMARK_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_LVINSERTMARK_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       LVINSERTMARK _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVINSERTMARK_2_FUNC);
+       if (arg3) if ((lparg3 = getLVINSERTMARKFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setLVINSERTMARKFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVINSERTMARK_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_LVITEM_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_LVITEM_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       LVITEM _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVITEM_2_FUNC);
+       if (arg3) if ((lparg3 = getLVITEMFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setLVITEMFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_LVITEM_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_MARGINS_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_MARGINS_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       MARGINS _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_MARGINS_2_FUNC);
+       if (arg3) if ((lparg3 = getMARGINSFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setMARGINSFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_MARGINS_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_MCHITTESTINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_MCHITTESTINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       MCHITTESTINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_MCHITTESTINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getMCHITTESTINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setMCHITTESTINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_MCHITTESTINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_REBARBANDINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_REBARBANDINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       REBARBANDINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_REBARBANDINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getREBARBANDINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setREBARBANDINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_REBARBANDINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_RECT_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_RECT_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       RECT _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       if (arg3) if ((lparg3 = getRECTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setRECTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_RECT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       SHDRAGIMAGE _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2_FUNC);
+       if (arg3) if ((lparg3 = getSHDRAGIMAGEFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setSHDRAGIMAGEFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_SIZE_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_SIZE_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       SIZE _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_SIZE_2_FUNC);
+       if (arg3) if ((lparg3 = getSIZEFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setSIZEFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_SIZE_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_SYSTEMTIME_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_SYSTEMTIME_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       SYSTEMTIME _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_SYSTEMTIME_2_FUNC);
+       if (arg3) if ((lparg3 = getSYSTEMTIMEFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setSYSTEMTIMEFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_SYSTEMTIME_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTONINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTONINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TBBUTTONINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTONINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getTBBUTTONINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTBBUTTONINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTONINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTON_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTON_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TBBUTTON _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTON_2_FUNC);
+       if (arg3) if ((lparg3 = getTBBUTTONFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTBBUTTONFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTON_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TCHITTESTINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TCHITTESTINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TCHITTESTINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TCHITTESTINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getTCHITTESTINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTCHITTESTINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TCHITTESTINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TCITEM_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TCITEM_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TCITEM _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TCITEM_2_FUNC);
+       if (arg3) if ((lparg3 = getTCITEMFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTCITEMFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TCITEM_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TOOLINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TOOLINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TOOLINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TOOLINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getTOOLINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTOOLINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TOOLINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TVHITTESTINFO_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TVHITTESTINFO_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TVHITTESTINFO _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVHITTESTINFO_2_FUNC);
+       if (arg3) if ((lparg3 = getTVHITTESTINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTVHITTESTINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVHITTESTINFO_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TVINSERTSTRUCT_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TVINSERTSTRUCT_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TVINSERTSTRUCT _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVINSERTSTRUCT_2_FUNC);
+       if (arg3) if ((lparg3 = getTVINSERTSTRUCTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTVINSERTSTRUCTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVINSERTSTRUCT_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TVITEM_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TVITEM_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TVITEM _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVITEM_2_FUNC);
+       if (arg3) if ((lparg3 = getTVITEMFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTVITEMFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVITEM_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_TVSORTCB_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_TVSORTCB_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       TVSORTCB _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVSORTCB_2_FUNC);
+       if (arg3) if ((lparg3 = getTVSORTCBFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setTVSORTCBFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_TVSORTCB_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJLorg_eclipse_swt_internal_win32_UDACCEL_2
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJLorg_eclipse_swt_internal_win32_UDACCEL_2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jobject arg3)
+{
+       UDACCEL _arg3, *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_UDACCEL_2_FUNC);
+       if (arg3) if ((lparg3 = getUDACCELFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) setUDACCELFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJLorg_eclipse_swt_internal_win32_UDACCEL_2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJ_3C
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJ_3C)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jcharArray arg3)
+{
+       jchar *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJ_3C_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJ_3C_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JIJ_3I
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JIJ_3I)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jintArray arg3)
+{
+       jint *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JIJ_3I_FUNC);
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       OS_NATIVE_EXIT(env, that, SendMessage__JIJ_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SendMessage__JI_3I_3I
+JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JI_3I_3I)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jintArray arg2, jintArray arg3)
+{
+       jint *lparg2=NULL;
+       jint *lparg3=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SendMessage__JI_3I_3I_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)SendMessage((HWND)arg0, arg1, (WPARAM)lparg2, (LPARAM)lparg3);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, SendMessage__JI_3I_3I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetActiveWindow
+JNIEXPORT jlong JNICALL OS_NATIVE(SetActiveWindow)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetActiveWindow_FUNC);
+       rc = (jlong)SetActiveWindow((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, SetActiveWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetBkColor
+JNIEXPORT jint JNICALL OS_NATIVE(SetBkColor)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetBkColor_FUNC);
+       rc = (jint)SetBkColor((HDC)arg0, (COLORREF)arg1);
+       OS_NATIVE_EXIT(env, that, SetBkColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetBkMode
+JNIEXPORT jint JNICALL OS_NATIVE(SetBkMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetBkMode_FUNC);
+       rc = (jint)SetBkMode((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetBkMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetBrushOrgEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetBrushOrgEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jobject arg3)
+{
+       POINT _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetBrushOrgEx_FUNC);
+       if (arg3) if ((lparg3 = getPOINTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)SetBrushOrgEx((HDC)arg0, arg1, arg2, (LPPOINT)lparg3);
+fail:
+       if (arg3 && lparg3) setPOINTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SetBrushOrgEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetCapture
+JNIEXPORT jlong JNICALL OS_NATIVE(SetCapture)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetCapture_FUNC);
+       rc = (jlong)SetCapture((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, SetCapture_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetCaretPos
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetCaretPos)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetCaretPos_FUNC);
+       rc = (jboolean)SetCaretPos(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetCaretPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetCurrentProcessExplicitAppUserModelID
+JNIEXPORT jint JNICALL OS_NATIVE(SetCurrentProcessExplicitAppUserModelID)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetCurrentProcessExplicitAppUserModelID_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)SetCurrentProcessExplicitAppUserModelID(lparg0);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, SetCurrentProcessExplicitAppUserModelID)
+               if (fp) {
+                       rc = (jint)((jint (CALLING_CONVENTION*)(jchar *))fp)(lparg0);
+               }
+       }
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, SetCurrentProcessExplicitAppUserModelID_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetCursor
+JNIEXPORT jlong JNICALL OS_NATIVE(SetCursor)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetCursor_FUNC);
+       rc = (jlong)SetCursor((HCURSOR)arg0);
+       OS_NATIVE_EXIT(env, that, SetCursor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetCursorPos
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetCursorPos)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetCursorPos_FUNC);
+       rc = (jboolean)SetCursorPos(arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetCursorPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetDIBColorTable
+JNIEXPORT jint JNICALL OS_NATIVE(SetDIBColorTable)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jbyteArray arg3)
+{
+       jbyte *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetDIBColorTable_FUNC);
+               if (arg3) if ((lparg3 = (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)SetDIBColorTable((HDC)arg0, arg1, arg2, (RGBQUAD *)lparg3);
+fail:
+               if (arg3 && lparg3) (*env)->ReleasePrimitiveArrayCritical(env, arg3, lparg3, JNI_ABORT);
+       OS_NATIVE_EXIT(env, that, SetDIBColorTable_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetDllDirectory
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetDllDirectory)
+       (JNIEnv *env, jclass that, jcharArray arg0)
+{
+       jchar *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetDllDirectory_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jboolean)SetDllDirectory(lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, SetDllDirectory_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetErrorMode
+JNIEXPORT jint JNICALL OS_NATIVE(SetErrorMode)
+       (JNIEnv *env, jclass that, jint arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetErrorMode_FUNC);
+       rc = (jint)SetErrorMode(arg0);
+       OS_NATIVE_EXIT(env, that, SetErrorMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetFocus
+JNIEXPORT jlong JNICALL OS_NATIVE(SetFocus)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetFocus_FUNC);
+       rc = (jlong)SetFocus((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, SetFocus_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetForegroundWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetForegroundWindow)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetForegroundWindow_FUNC);
+       rc = (jboolean)SetForegroundWindow((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, SetForegroundWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetGestureConfig
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetGestureConfig)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jlong arg3, jint arg4)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetGestureConfig_FUNC);
+/*
+       rc = (jboolean)SetGestureConfig((HWND)arg0, arg1, arg2, (PGESTURECONFIG)arg3, arg4);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, SetGestureConfig)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HWND, jint, jint, PGESTURECONFIG, jint))fp)((HWND)arg0, arg1, arg2, (PGESTURECONFIG)arg3, arg4);
+               }
+       }
+       OS_NATIVE_EXIT(env, that, SetGestureConfig_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetGraphicsMode
+JNIEXPORT jint JNICALL OS_NATIVE(SetGraphicsMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetGraphicsMode_FUNC);
+       rc = (jint)SetGraphicsMode((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetGraphicsMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetLayeredWindowAttributes
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetLayeredWindowAttributes)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jbyte arg2, jint arg3)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetLayeredWindowAttributes_FUNC);
+       rc = (jboolean)SetLayeredWindowAttributes((HWND)arg0, arg1, arg2, arg3);
+       OS_NATIVE_EXIT(env, that, SetLayeredWindowAttributes_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetLayout
+JNIEXPORT jint JNICALL OS_NATIVE(SetLayout)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetLayout_FUNC);
+       rc = (jint)SetLayout((HDC)arg0, (DWORD)arg1);
+       OS_NATIVE_EXIT(env, that, SetLayout_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetMenu
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetMenu)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetMenu_FUNC);
+       rc = (jboolean)SetMenu((HWND)arg0, (HMENU)arg1);
+       OS_NATIVE_EXIT(env, that, SetMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetMenuDefaultItem
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetMenuDefaultItem)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetMenuDefaultItem_FUNC);
+       rc = (jboolean)SetMenuDefaultItem((HMENU)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, SetMenuDefaultItem_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetMenuInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetMenuInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       MENUINFO _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetMenuInfo_FUNC);
+       if (arg1) if ((lparg1 = getMENUINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)SetMenuInfo((HMENU)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setMENUINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, SetMenuInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetMenuItemInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetMenuItemInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jboolean arg2, jobject arg3)
+{
+       MENUITEMINFO _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetMenuItemInfo_FUNC);
+       if (arg3) if ((lparg3 = getMENUITEMINFOFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)SetMenuItemInfo((HMENU)arg0, arg1, arg2, (LPMENUITEMINFOW)lparg3);
+fail:
+       if (arg3 && lparg3) setMENUITEMINFOFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SetMenuItemInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetMetaRgn
+JNIEXPORT jint JNICALL OS_NATIVE(SetMetaRgn)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetMetaRgn_FUNC);
+       rc = (jint)SetMetaRgn((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, SetMetaRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetParent
+JNIEXPORT jlong JNICALL OS_NATIVE(SetParent)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetParent_FUNC);
+       rc = (jlong)SetParent((HWND)arg0, (HWND)arg1);
+       OS_NATIVE_EXIT(env, that, SetParent_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetPixel
+JNIEXPORT jint JNICALL OS_NATIVE(SetPixel)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetPixel_FUNC);
+       rc = (jint)SetPixel((HDC)arg0, arg1, arg2, arg3);
+       OS_NATIVE_EXIT(env, that, SetPixel_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetPolyFillMode
+JNIEXPORT jint JNICALL OS_NATIVE(SetPolyFillMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetPolyFillMode_FUNC);
+       rc = (jint)SetPolyFillMode((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetPolyFillMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetProcessDPIAware
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetProcessDPIAware)
+       (JNIEnv *env, jclass that)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetProcessDPIAware_FUNC);
+       rc = (jboolean)SetProcessDPIAware();
+       OS_NATIVE_EXIT(env, that, SetProcessDPIAware_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetProp
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetProp)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetProp_FUNC);
+       rc = (jboolean)SetProp((HWND)arg0, (LPCWSTR)arg1, (HANDLE)arg2);
+       OS_NATIVE_EXIT(env, that, SetProp_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetROP2
+JNIEXPORT jint JNICALL OS_NATIVE(SetROP2)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetROP2_FUNC);
+       rc = (jint)SetROP2((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetROP2_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetRect)
+       (JNIEnv *env, jclass that, jobject arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       RECT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetRect_FUNC);
+       if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+       rc = (jboolean)SetRect(lparg0, arg1, arg2, arg3, arg4);
+fail:
+       if (arg0 && lparg0) setRECTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, SetRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetRectRgn
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetRectRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetRectRgn_FUNC);
+       rc = (jboolean)SetRectRgn((HRGN)arg0, arg1, arg2, arg3, arg4);
+       OS_NATIVE_EXIT(env, that, SetRectRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetScrollInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetScrollInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2, jboolean arg3)
+{
+       SCROLLINFO _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetScrollInfo_FUNC);
+       if (arg2) if ((lparg2 = getSCROLLINFOFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)SetScrollInfo((HWND)arg0, arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setSCROLLINFOFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, SetScrollInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetStretchBltMode
+JNIEXPORT jint JNICALL OS_NATIVE(SetStretchBltMode)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetStretchBltMode_FUNC);
+       rc = (jint)SetStretchBltMode((HDC)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, SetStretchBltMode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetTextColor
+JNIEXPORT jint JNICALL OS_NATIVE(SetTextColor)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetTextColor_FUNC);
+       rc = (jint)SetTextColor((HDC)arg0, (COLORREF)arg1);
+       OS_NATIVE_EXIT(env, that, SetTextColor_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetTimer
+JNIEXPORT jlong JNICALL OS_NATIVE(SetTimer)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlong arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetTimer_FUNC);
+       rc = (jlong)SetTimer((HWND)arg0, arg1, arg2, (TIMERPROC)arg3);
+       OS_NATIVE_EXIT(env, that, SetTimer_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowLong
+JNIEXPORT jint JNICALL OS_NATIVE(SetWindowLong)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowLong_FUNC);
+       rc = (jint)SetWindowLong((HWND)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, SetWindowLong_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowLongPtr
+JNIEXPORT jlong JNICALL OS_NATIVE(SetWindowLongPtr)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowLongPtr_FUNC);
+       rc = (jlong)SetWindowLongPtr((HWND)arg0, arg1, (LONG_PTR)arg2);
+       OS_NATIVE_EXIT(env, that, SetWindowLongPtr_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowOrgEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetWindowOrgEx)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jobject arg3)
+{
+       POINT _arg3, *lparg3=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowOrgEx_FUNC);
+       if (arg3) if ((lparg3 = getPOINTFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jboolean)SetWindowOrgEx((HDC)arg0, arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) setPOINTFields(env, arg3, lparg3);
+       OS_NATIVE_EXIT(env, that, SetWindowOrgEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowPlacement
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetWindowPlacement)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       WINDOWPLACEMENT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowPlacement_FUNC);
+       if (arg1) if ((lparg1 = getWINDOWPLACEMENTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)SetWindowPlacement((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setWINDOWPLACEMENTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, SetWindowPlacement_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowPos
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetWindowPos)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jint arg6)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowPos_FUNC);
+       rc = (jboolean)SetWindowPos((HWND)arg0, (HWND)arg1, arg2, arg3, arg4, arg5, arg6);
+       OS_NATIVE_EXIT(env, that, SetWindowPos_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowRgn
+JNIEXPORT jint JNICALL OS_NATIVE(SetWindowRgn)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowRgn_FUNC);
+       rc = (jint)SetWindowRgn((HWND)arg0, (HRGN)arg1, arg2);
+       OS_NATIVE_EXIT(env, that, SetWindowRgn_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowText
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetWindowText)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1)
+{
+       jchar *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowText_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)SetWindowText((HWND)arg0, (LPWSTR)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, SetWindowText_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowTheme
+JNIEXPORT jint JNICALL OS_NATIVE(SetWindowTheme)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jcharArray arg2)
+{
+       jchar *lparg1=NULL;
+       jchar *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowTheme_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetCharArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)SetWindowTheme((HWND)arg0, (LPCWSTR)lparg1, (LPCWSTR)lparg2);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseCharArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, SetWindowTheme_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWindowsHookEx
+JNIEXPORT jlong JNICALL OS_NATIVE(SetWindowsHookEx)
+       (JNIEnv *env, jclass that, jint arg0, jlong arg1, jlong arg2, jint arg3)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWindowsHookEx_FUNC);
+       rc = (jlong)SetWindowsHookEx(arg0, (HOOKPROC)arg1, (HINSTANCE)arg2, arg3);
+       OS_NATIVE_EXIT(env, that, SetWindowsHookEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetWorldTransform
+JNIEXPORT jboolean JNICALL OS_NATIVE(SetWorldTransform)
+       (JNIEnv *env, jclass that, jlong arg0, jfloatArray arg1)
+{
+       jfloat *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SetWorldTransform_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetFloatArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)SetWorldTransform((HDC)arg0, (XFORM *)lparg1);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseFloatArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, SetWorldTransform_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ShellExecuteEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(ShellExecuteEx)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       SHELLEXECUTEINFO _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ShellExecuteEx_FUNC);
+       if (arg0) if ((lparg0 = getSHELLEXECUTEINFOFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)ShellExecuteEx((LPSHELLEXECUTEINFOW)lparg0);
+fail:
+       if (arg0 && lparg0) setSHELLEXECUTEINFOFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, ShellExecuteEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_Shell_1NotifyIcon
+JNIEXPORT jboolean JNICALL OS_NATIVE(Shell_1NotifyIcon)
+       (JNIEnv *env, jclass that, jint arg0, jobject arg1)
+{
+       NOTIFYICONDATA _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, Shell_1NotifyIcon_FUNC);
+       if (arg1) if ((lparg1 = getNOTIFYICONDATAFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)Shell_NotifyIcon(arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setNOTIFYICONDATAFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, Shell_1NotifyIcon_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ShowCaret
+JNIEXPORT jboolean JNICALL OS_NATIVE(ShowCaret)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ShowCaret_FUNC);
+       rc = (jboolean)ShowCaret((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, ShowCaret_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ShowOwnedPopups
+JNIEXPORT jboolean JNICALL OS_NATIVE(ShowOwnedPopups)
+       (JNIEnv *env, jclass that, jlong arg0, jboolean arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ShowOwnedPopups_FUNC);
+       rc = (jboolean)ShowOwnedPopups((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, ShowOwnedPopups_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ShowScrollBar
+JNIEXPORT jboolean JNICALL OS_NATIVE(ShowScrollBar)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jboolean arg2)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ShowScrollBar_FUNC);
+       rc = (jboolean)ShowScrollBar((HWND)arg0, arg1, arg2);
+       OS_NATIVE_EXIT(env, that, ShowScrollBar_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ShowWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(ShowWindow)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ShowWindow_FUNC);
+       rc = (jboolean)ShowWindow((HWND)arg0, arg1);
+       OS_NATIVE_EXIT(env, that, ShowWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StartDoc
+JNIEXPORT jint JNICALL OS_NATIVE(StartDoc)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       DOCINFO _arg1, *lparg1=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, StartDoc_FUNC);
+       if (arg1) if ((lparg1 = getDOCINFOFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)StartDoc((HDC)arg0, (LPDOCINFOW)lparg1);
+fail:
+       if (arg1 && lparg1) setDOCINFOFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, StartDoc_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StartPage
+JNIEXPORT jint JNICALL OS_NATIVE(StartPage)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, StartPage_FUNC);
+       rc = (jint)StartPage((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, StartPage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_StretchBlt
+JNIEXPORT jboolean JNICALL OS_NATIVE(StretchBlt)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jlong arg5, jint arg6, jint arg7, jint arg8, jint arg9, jint arg10)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, StretchBlt_FUNC);
+       rc = (jboolean)StretchBlt((HDC)arg0, arg1, arg2, arg3, arg4, (HDC)arg5, arg6, arg7, arg8, arg9, arg10);
+       OS_NATIVE_EXIT(env, that, StretchBlt_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SystemParametersInfo__IILorg_eclipse_swt_internal_win32_HIGHCONTRAST_2I
+JNIEXPORT jboolean JNICALL OS_NATIVE(SystemParametersInfo__IILorg_eclipse_swt_internal_win32_HIGHCONTRAST_2I)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jobject arg2, jint arg3)
+{
+       HIGHCONTRAST _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SystemParametersInfo__IILorg_eclipse_swt_internal_win32_HIGHCONTRAST_2I_FUNC);
+       if (arg2) if ((lparg2 = getHIGHCONTRASTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)SystemParametersInfo(arg0, arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setHIGHCONTRASTFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, SystemParametersInfo__IILorg_eclipse_swt_internal_win32_HIGHCONTRAST_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SystemParametersInfo__IILorg_eclipse_swt_internal_win32_NONCLIENTMETRICS_2I
+JNIEXPORT jboolean JNICALL OS_NATIVE(SystemParametersInfo__IILorg_eclipse_swt_internal_win32_NONCLIENTMETRICS_2I)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jobject arg2, jint arg3)
+{
+       NONCLIENTMETRICS _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SystemParametersInfo__IILorg_eclipse_swt_internal_win32_NONCLIENTMETRICS_2I_FUNC);
+       if (arg2) if ((lparg2 = getNONCLIENTMETRICSFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)SystemParametersInfo(arg0, arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setNONCLIENTMETRICSFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, SystemParametersInfo__IILorg_eclipse_swt_internal_win32_NONCLIENTMETRICS_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SystemParametersInfo__IILorg_eclipse_swt_internal_win32_RECT_2I
+JNIEXPORT jboolean JNICALL OS_NATIVE(SystemParametersInfo__IILorg_eclipse_swt_internal_win32_RECT_2I)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jobject arg2, jint arg3)
+{
+       RECT _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SystemParametersInfo__IILorg_eclipse_swt_internal_win32_RECT_2I_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)SystemParametersInfo(arg0, arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, SystemParametersInfo__IILorg_eclipse_swt_internal_win32_RECT_2I_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SystemParametersInfo__II_3II
+JNIEXPORT jboolean JNICALL OS_NATIVE(SystemParametersInfo__II_3II)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jintArray arg2, jint arg3)
+{
+       jint *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, SystemParametersInfo__II_3II_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jboolean)SystemParametersInfo(arg0, arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, SystemParametersInfo__II_3II_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TBBUTTONINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TBBUTTONINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TBBUTTONINFO_1sizeof_FUNC);
+       rc = (jint)TBBUTTONINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, TBBUTTONINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TBBUTTON_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TBBUTTON_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TBBUTTON_1sizeof_FUNC);
+       rc = (jint)TBBUTTON_sizeof();
+       OS_NATIVE_EXIT(env, that, TBBUTTON_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TCHITTESTINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TCHITTESTINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TCHITTESTINFO_1sizeof_FUNC);
+       rc = (jint)TCHITTESTINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, TCHITTESTINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TCITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TCITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TCITEM_1sizeof_FUNC);
+       rc = (jint)TCITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, TCITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TEXTMETRIC_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TEXTMETRIC_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TEXTMETRIC_1sizeof_FUNC);
+       rc = (jint)TEXTMETRIC_sizeof();
+       OS_NATIVE_EXIT(env, that, TEXTMETRIC_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TF_1DA_1COLOR_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TF_1DA_1COLOR_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TF_1DA_1COLOR_1sizeof_FUNC);
+       rc = (jint)TF_DA_COLOR_sizeof();
+       OS_NATIVE_EXIT(env, that, TF_1DA_1COLOR_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TF_1DISPLAYATTRIBUTE_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TF_1DISPLAYATTRIBUTE_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TF_1DISPLAYATTRIBUTE_1sizeof_FUNC);
+       rc = (jint)TF_DISPLAYATTRIBUTE_sizeof();
+       OS_NATIVE_EXIT(env, that, TF_1DISPLAYATTRIBUTE_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TOOLINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TOOLINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TOOLINFO_1sizeof_FUNC);
+       rc = (jint)TOOLINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, TOOLINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TOUCHINPUT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TOUCHINPUT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TOUCHINPUT_1sizeof_FUNC);
+       rc = (jint)TOUCHINPUT_sizeof();
+       OS_NATIVE_EXIT(env, that, TOUCHINPUT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TOUCH_1COORD_1TO_1PIXEL
+JNIEXPORT jlong JNICALL OS_NATIVE(TOUCH_1COORD_1TO_1PIXEL)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, TOUCH_1COORD_1TO_1PIXEL_FUNC);
+       rc = (jlong)TOUCH_COORD_TO_PIXEL(arg0);
+       OS_NATIVE_EXIT(env, that, TOUCH_1COORD_1TO_1PIXEL_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TRACKMOUSEEVENT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TRACKMOUSEEVENT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TRACKMOUSEEVENT_1sizeof_FUNC);
+       rc = (jint)TRACKMOUSEEVENT_sizeof();
+       OS_NATIVE_EXIT(env, that, TRACKMOUSEEVENT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TRIVERTEX_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TRIVERTEX_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TRIVERTEX_1sizeof_FUNC);
+       rc = (jint)TRIVERTEX_sizeof();
+       OS_NATIVE_EXIT(env, that, TRIVERTEX_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TVHITTESTINFO_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TVHITTESTINFO_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TVHITTESTINFO_1sizeof_FUNC);
+       rc = (jint)TVHITTESTINFO_sizeof();
+       OS_NATIVE_EXIT(env, that, TVHITTESTINFO_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TVINSERTSTRUCT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TVINSERTSTRUCT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TVINSERTSTRUCT_1sizeof_FUNC);
+       rc = (jint)TVINSERTSTRUCT_sizeof();
+       OS_NATIVE_EXIT(env, that, TVINSERTSTRUCT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TVITEMEX_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TVITEMEX_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TVITEMEX_1sizeof_FUNC);
+       rc = (jint)TVITEMEX_sizeof();
+       OS_NATIVE_EXIT(env, that, TVITEMEX_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TVITEM_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TVITEM_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TVITEM_1sizeof_FUNC);
+       rc = (jint)TVITEM_sizeof();
+       OS_NATIVE_EXIT(env, that, TVITEM_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TVSORTCB_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(TVSORTCB_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TVSORTCB_1sizeof_FUNC);
+       rc = (jint)TVSORTCB_sizeof();
+       OS_NATIVE_EXIT(env, that, TVSORTCB_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ToUnicode
+JNIEXPORT jint JNICALL OS_NATIVE(ToUnicode)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jbyteArray arg2, jcharArray arg3, jint arg4, jint arg5)
+{
+       jbyte *lparg2=NULL;
+       jchar *lparg3=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, ToUnicode_FUNC);
+       if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail;
+       rc = (jint)ToUnicode(arg0, arg1, (PBYTE)lparg2, (LPWSTR)lparg3, arg4, arg5);
+fail:
+       if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0);
+       if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0);
+       OS_NATIVE_EXIT(env, that, ToUnicode_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TrackMouseEvent
+JNIEXPORT jboolean JNICALL OS_NATIVE(TrackMouseEvent)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       TRACKMOUSEEVENT _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TrackMouseEvent_FUNC);
+       if (arg0) if ((lparg0 = getTRACKMOUSEEVENTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)TrackMouseEvent(lparg0);
+fail:
+       if (arg0 && lparg0) setTRACKMOUSEEVENTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, TrackMouseEvent_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TrackPopupMenu
+JNIEXPORT jboolean JNICALL OS_NATIVE(TrackPopupMenu)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jlong arg5, jobject arg6)
+{
+       RECT _arg6, *lparg6=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TrackPopupMenu_FUNC);
+       if (arg6) if ((lparg6 = getRECTFields(env, arg6, &_arg6)) == NULL) goto fail;
+       rc = (jboolean)TrackPopupMenu((HMENU)arg0, arg1, arg2, arg3, arg4, (HWND)arg5, lparg6);
+fail:
+       if (arg6 && lparg6) setRECTFields(env, arg6, lparg6);
+       OS_NATIVE_EXIT(env, that, TrackPopupMenu_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TranslateAccelerator
+JNIEXPORT jint JNICALL OS_NATIVE(TranslateAccelerator)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2)
+{
+       MSG _arg2, *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, TranslateAccelerator_FUNC);
+       if (arg2) if ((lparg2 = getMSGFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jint)TranslateAccelerator((HWND)arg0, (HACCEL)arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setMSGFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, TranslateAccelerator_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TranslateCharsetInfo
+JNIEXPORT jboolean JNICALL OS_NATIVE(TranslateCharsetInfo)
+       (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jint arg2)
+{
+       jint *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TranslateCharsetInfo_FUNC);
+       if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       rc = (jboolean)TranslateCharsetInfo((DWORD *)arg0, (LPCHARSETINFO)lparg1, arg2);
+fail:
+       if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+       OS_NATIVE_EXIT(env, that, TranslateCharsetInfo_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TranslateMDISysAccel
+JNIEXPORT jboolean JNICALL OS_NATIVE(TranslateMDISysAccel)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       MSG _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TranslateMDISysAccel_FUNC);
+       if (arg1) if ((lparg1 = getMSGFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)TranslateMDISysAccel((HWND)arg0, (LPMSG)lparg1);
+fail:
+       if (arg1 && lparg1) setMSGFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, TranslateMDISysAccel_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TranslateMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(TranslateMessage)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       MSG _arg0, *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TranslateMessage_FUNC);
+       if (arg0) if ((lparg0 = getMSGFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jboolean)TranslateMessage(lparg0);
+fail:
+       if (arg0 && lparg0) setMSGFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, TranslateMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TransparentBlt
+JNIEXPORT jboolean JNICALL OS_NATIVE(TransparentBlt)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4, jlong arg5, jint arg6, jint arg7, jint arg8, jint arg9, jint arg10)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TransparentBlt_FUNC);
+       rc = (jboolean)TransparentBlt((HDC)arg0, arg1, arg2, arg3, arg4, (HDC)arg5, arg6, arg7, arg8, arg9, arg10);
+       OS_NATIVE_EXIT(env, that, TransparentBlt_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_TreeView_1GetItemRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(TreeView_1GetItemRect)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jobject arg2, jboolean arg3)
+{
+       RECT _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, TreeView_1GetItemRect_FUNC);
+       if (arg2) if ((lparg2 = getRECTFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)TreeView_GetItemRect((HWND)arg0, (HTREEITEM)arg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) setRECTFields(env, arg2, lparg2);
+       OS_NATIVE_EXIT(env, that, TreeView_1GetItemRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UDACCEL_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(UDACCEL_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, UDACCEL_1sizeof_FUNC);
+       rc = (jint)UDACCEL_sizeof();
+       OS_NATIVE_EXIT(env, that, UDACCEL_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UnhookWindowsHookEx
+JNIEXPORT jboolean JNICALL OS_NATIVE(UnhookWindowsHookEx)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, UnhookWindowsHookEx_FUNC);
+       rc = (jboolean)UnhookWindowsHookEx((HHOOK)arg0);
+       OS_NATIVE_EXIT(env, that, UnhookWindowsHookEx_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UnmapViewOfFile
+JNIEXPORT jboolean JNICALL OS_NATIVE(UnmapViewOfFile)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, UnmapViewOfFile_FUNC);
+       rc = (jboolean)UnmapViewOfFile((LPCVOID)arg0);
+       OS_NATIVE_EXIT(env, that, UnmapViewOfFile_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UnregisterClass
+JNIEXPORT jboolean JNICALL OS_NATIVE(UnregisterClass)
+       (JNIEnv *env, jclass that, jcharArray arg0, jlong arg1)
+{
+       jchar *lparg0=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, UnregisterClass_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jboolean)UnregisterClass((LPWSTR)lparg0, (HINSTANCE)arg1);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, UnregisterClass_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UnregisterTouchWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(UnregisterTouchWindow)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, UnregisterTouchWindow_FUNC);
+/*
+       rc = (jboolean)UnregisterTouchWindow((HWND)arg0);
+*/
+       {
+               OS_LOAD_FUNCTION(fp, UnregisterTouchWindow)
+               if (fp) {
+                       rc = (jboolean)((jboolean (CALLING_CONVENTION*)(HWND))fp)((HWND)arg0);
+               }
+       }
+       OS_NATIVE_EXIT(env, that, UnregisterTouchWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UpdateWindow
+JNIEXPORT jboolean JNICALL OS_NATIVE(UpdateWindow)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, UpdateWindow_FUNC);
+       rc = (jboolean)UpdateWindow((HWND)arg0);
+       OS_NATIVE_EXIT(env, that, UpdateWindow_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_UrlCreateFromPath
+JNIEXPORT jint JNICALL OS_NATIVE(UrlCreateFromPath)
+       (JNIEnv *env, jclass that, jcharArray arg0, jcharArray arg1, jintArray arg2, jint arg3)
+{
+       jchar *lparg0=NULL;
+       jchar *lparg1=NULL;
+       jint *lparg2=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, UrlCreateFromPath_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)UrlCreateFromPath((LPCWSTR)lparg0, (LPWSTR)lparg1, lparg2, arg3);
+fail:
+       if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+       if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0);
+       if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+       OS_NATIVE_EXIT(env, that, UrlCreateFromPath_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_ValidateRect
+JNIEXPORT jboolean JNICALL OS_NATIVE(ValidateRect)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       RECT _arg1, *lparg1=NULL;
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, ValidateRect_FUNC);
+       if (arg1) if ((lparg1 = getRECTFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jboolean)ValidateRect((HWND)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setRECTFields(env, arg1, lparg1);
+       OS_NATIVE_EXIT(env, that, ValidateRect_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_VkKeyScan
+JNIEXPORT jshort JNICALL OS_NATIVE(VkKeyScan)
+       (JNIEnv *env, jclass that, jshort arg0)
+{
+       jshort rc = 0;
+       OS_NATIVE_ENTER(env, that, VkKeyScan_FUNC);
+       rc = (jshort)VkKeyScan((WCHAR)arg0);
+       OS_NATIVE_EXIT(env, that, VkKeyScan_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WINDOWPLACEMENT_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(WINDOWPLACEMENT_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, WINDOWPLACEMENT_1sizeof_FUNC);
+       rc = (jint)WINDOWPLACEMENT_sizeof();
+       OS_NATIVE_EXIT(env, that, WINDOWPLACEMENT_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WINDOWPOS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(WINDOWPOS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, WINDOWPOS_1sizeof_FUNC);
+       rc = (jint)WINDOWPOS_sizeof();
+       OS_NATIVE_EXIT(env, that, WINDOWPOS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WNDCLASS_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(WNDCLASS_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, WNDCLASS_1sizeof_FUNC);
+       rc = (jint)WNDCLASS_sizeof();
+       OS_NATIVE_EXIT(env, that, WNDCLASS_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WaitMessage
+JNIEXPORT jboolean JNICALL OS_NATIVE(WaitMessage)
+       (JNIEnv *env, jclass that)
+{
+       jboolean rc = 0;
+       OS_NATIVE_ENTER(env, that, WaitMessage_FUNC);
+       rc = (jboolean)WaitMessage();
+       OS_NATIVE_EXIT(env, that, WaitMessage_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WideCharToMultiByte__II_3CIJI_3B_3Z
+JNIEXPORT jint JNICALL OS_NATIVE(WideCharToMultiByte__II_3CIJI_3B_3Z)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jcharArray arg2, jint arg3, jlong arg4, jint arg5, jbyteArray arg6, jbooleanArray arg7)
+{
+       jchar *lparg2=NULL;
+       jbyte *lparg6=NULL;
+       jboolean *lparg7=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, WideCharToMultiByte__II_3CIJI_3B_3Z_FUNC);
+       if (arg6) if ((lparg6 = (*env)->GetByteArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = (*env)->GetBooleanArrayElements(env, arg7, NULL)) == NULL) goto fail;
+               if (arg2) if ((lparg2 = (*env)->GetPrimitiveArrayCritical(env, arg2, NULL)) == NULL) goto fail;
+       rc = (jint)WideCharToMultiByte(arg0, arg1, (LPCWSTR)lparg2, arg3, (LPSTR)arg4, arg5, (LPCSTR)lparg6, (LPBOOL)lparg7);
+fail:
+               if (arg2 && lparg2) (*env)->ReleasePrimitiveArrayCritical(env, arg2, lparg2, JNI_ABORT);
+       if (arg7 && lparg7) (*env)->ReleaseBooleanArrayElements(env, arg7, lparg7, 0);
+       if (arg6 && lparg6) (*env)->ReleaseByteArrayElements(env, arg6, lparg6, 0);
+       OS_NATIVE_EXIT(env, that, WideCharToMultiByte__II_3CIJI_3B_3Z_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WideCharToMultiByte__II_3CI_3BI_3B_3Z
+JNIEXPORT jint JNICALL OS_NATIVE(WideCharToMultiByte__II_3CI_3BI_3B_3Z)
+       (JNIEnv *env, jclass that, jint arg0, jint arg1, jcharArray arg2, jint arg3, jbyteArray arg4, jint arg5, jbyteArray arg6, jbooleanArray arg7)
+{
+       jchar *lparg2=NULL;
+       jbyte *lparg4=NULL;
+       jbyte *lparg6=NULL;
+       jboolean *lparg7=NULL;
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, WideCharToMultiByte__II_3CI_3BI_3B_3Z_FUNC);
+       if (arg6) if ((lparg6 = (*env)->GetByteArrayElements(env, arg6, NULL)) == NULL) goto fail;
+       if (arg7) if ((lparg7 = (*env)->GetBooleanArrayElements(env, arg7, NULL)) == NULL) goto fail;
+               if (arg2) if ((lparg2 = (*env)->GetPrimitiveArrayCritical(env, arg2, NULL)) == NULL) goto fail;
+               if (arg4) if ((lparg4 = (*env)->GetPrimitiveArrayCritical(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)WideCharToMultiByte(arg0, arg1, (LPCWSTR)lparg2, arg3, (LPSTR)lparg4, arg5, (LPCSTR)lparg6, (LPBOOL)lparg7);
+fail:
+               if (arg4 && lparg4) (*env)->ReleasePrimitiveArrayCritical(env, arg4, lparg4, 0);
+               if (arg2 && lparg2) (*env)->ReleasePrimitiveArrayCritical(env, arg2, lparg2, JNI_ABORT);
+       if (arg7 && lparg7) (*env)->ReleaseBooleanArrayElements(env, arg7, lparg7, 0);
+       if (arg6 && lparg6) (*env)->ReleaseByteArrayElements(env, arg6, lparg6, 0);
+       OS_NATIVE_EXIT(env, that, WideCharToMultiByte__II_3CI_3BI_3B_3Z_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WindowFromDC
+JNIEXPORT jlong JNICALL OS_NATIVE(WindowFromDC)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, WindowFromDC_FUNC);
+       rc = (jlong)WindowFromDC((HDC)arg0);
+       OS_NATIVE_EXIT(env, that, WindowFromDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_WindowFromPoint
+JNIEXPORT jlong JNICALL OS_NATIVE(WindowFromPoint)
+       (JNIEnv *env, jclass that, jobject arg0)
+{
+       POINT _arg0, *lparg0=NULL;
+       jlong rc = 0;
+       OS_NATIVE_ENTER(env, that, WindowFromPoint_FUNC);
+       if (arg0) if ((lparg0 = getPOINTFields(env, arg0, &_arg0)) == NULL) goto fail;
+       rc = (jlong)WindowFromPoint(*lparg0);
+fail:
+       if (arg0 && lparg0) setPOINTFields(env, arg0, lparg0);
+       OS_NATIVE_EXIT(env, that, WindowFromPoint_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wcslen
+JNIEXPORT jint JNICALL OS_NATIVE(wcslen)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       OS_NATIVE_ENTER(env, that, wcslen_FUNC);
+       rc = (jint)wcslen((const wchar_t *)arg0);
+       OS_NATIVE_EXIT(env, that, wcslen_FUNC);
+       return rc;
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os.h
new file mode 100644 (file)
index 0000000..6080825
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#ifndef INC_os_H
+#define INC_os_H
+
+#include <windows.h>
+#include <WindowsX.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <oaidl.h>
+#include <shlobj.h>
+#include <ole2.h>
+#include <olectl.h>
+#include <objbase.h>
+#include <shlwapi.h>
+#include <shellapi.h>
+#include <wininet.h>
+#include <mshtmhst.h>
+#include <Tabflicks.h>
+#include <initguid.h>
+#include <oleacc.h>
+#include <usp10.h>
+#include <uxtheme.h>
+#include <msctf.h>
+#include <intsafe.h>
+
+/* Optional custom definitions to exclude some types */
+#include "defines.h"
+
+#define OS_LOAD_FUNCTION LOAD_FUNCTION
+
+#include "os_custom.h"
+
+#define NATIVE_TRY(env, that, func) \
+       __try {
+#define NATIVE_CATCH(env, that, func) \
+       } __except(EXCEPTION_EXECUTE_HANDLER) { \
+               jclass expClass = (*env)->FindClass(env, "org/eclipse/swt/SWTError");  \
+               if (expClass) { \
+                       char buffer[64]; \
+                       wsprintfA(buffer, "caught native exception: 0x%x", GetExceptionCode()); \
+                       (*env)->ThrowNew(env, expClass, buffer); \
+               } \
+       }
+
+#define OS_NATIVE_ENTER_TRY(env, that, func) \
+       OS_NATIVE_ENTER(env, that, func); \
+       NATIVE_TRY(env, that, func);
+#define OS_NATIVE_EXIT_CATCH(env, that, func) \
+       NATIVE_CATCH(env, that, func); \
+       OS_NATIVE_EXIT(env, that, func);
+
+#endif /* INC_os_H */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_custom.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_custom.c
new file mode 100644 (file)
index 0000000..e9fb072
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#include "swt.h"
+#include "os_structs.h"
+#include "os_stats.h"
+
+#define OS_NATIVE(func) Java_org_eclipse_swt_internal_win32_OS_##func
+
+__declspec(dllexport) HRESULT DllGetVersion(DLLVERSIONINFO *dvi);
+HRESULT DllGetVersion(DLLVERSIONINFO *dvi)
+{
+       dvi->dwMajorVersion = SWT_VERSION / 1000;
+       dvi->dwMinorVersion = SWT_VERSION % 1000;
+    dvi->dwBuildNumber = SWT_REVISION;
+       dvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
+       return 1;
+}
+
+HINSTANCE g_hInstance = NULL;
+BOOL WINAPI DllMain(HANDLE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
+{
+       if (dwReason == DLL_PROCESS_ATTACH) {
+               if (g_hInstance == NULL) g_hInstance = hInstDLL;
+       }
+       return TRUE;
+}
+
+#ifndef NO_GetLibraryHandle
+JNIEXPORT jintLong JNICALL OS_NATIVE(GetLibraryHandle)
+       (JNIEnv *env, jclass that)
+{
+       jintLong rc;
+       OS_NATIVE_ENTER(env, that, GetLibraryHandle_FUNC)
+       rc = (jintLong)g_hInstance;
+       OS_NATIVE_EXIT(env, that, GetLibraryHandle_FUNC)
+       return rc;
+}
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_custom.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_custom.h
new file mode 100644 (file)
index 0000000..e3ad68a
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Special sizeof's */
+#define SCRIPT_STRING_ANALYSIS_sizeof() sizeof(SCRIPT_STRING_ANALYSIS)
+#define PROPVARIANT_sizeof() sizeof(PROPVARIANT)
+
+/* Libraries for dynamic loaded functions */
+#define CloseGestureInfoHandle_LIB "user32.dll"
+#define CloseTouchInputHandle_LIB "user32.dll"
+#define GetCurrentProcessExplicitAppUserModelID_LIB "shell32.dll"
+#define GetDpiForMonitor_LIB "shcore.dll"
+#define GetGestureInfo_LIB "user32.dll"
+#define GetTouchInputInfo_LIB "user32.dll"
+#define IsTouchWindow_LIB "user32.dll"
+#define RegisterTouchWindow_LIB "user32.dll"
+#define SetCurrentProcessExplicitAppUserModelID_LIB "shell32.dll"
+#define SetGestureConfig_LIB "user32.dll"
+#define UnregisterTouchWindow_LIB "user32.dll"
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_stats.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_stats.c
new file mode 100644 (file)
index 0000000..d443481
--- /dev/null
@@ -0,0 +1,796 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "os_stats.h"
+
+#ifdef NATIVE_STATS
+
+char * OS_nativeFunctionNames[] = {
+       "ACCEL_1sizeof",
+       "ACTCTX_1sizeof",
+       "AbortDoc",
+       "ActivateActCtx",
+       "ActivateKeyboardLayout",
+       "AddFontResourceEx",
+       "AdjustWindowRectEx",
+       "AllowSetForegroundWindow",
+       "AlphaBlend",
+       "Arc",
+       "AssocQueryString",
+       "BITMAPINFOHEADER_1sizeof",
+       "BITMAP_1sizeof",
+       "BLENDFUNCTION_1sizeof",
+       "BP_1PAINTPARAMS_1sizeof",
+       "BROWSEINFO_1sizeof",
+       "BUTTON_1IMAGELIST_1sizeof",
+       "BeginBufferedPaint",
+       "BeginDeferWindowPos",
+       "BeginPaint",
+       "BeginPath",
+       "BitBlt",
+       "BringWindowToTop",
+       "BufferedPaintInit",
+       "BufferedPaintUnInit",
+       "CANDIDATEFORM_1sizeof",
+       "CERT_1CONTEXT_1sizeof",
+       "CERT_1INFO_1sizeof",
+       "CERT_1NAME_1BLOB_1sizeof",
+       "CERT_1PUBLIC_1KEY_1INFO_1sizeof",
+       "CHOOSECOLOR_1sizeof",
+       "CHOOSEFONT_1sizeof",
+       "CIDA_1sizeof",
+       "COMBOBOXINFO_1sizeof",
+       "COMPOSITIONFORM_1sizeof",
+       "CREATESTRUCT_1sizeof",
+       "CRYPT_1ALGORITHM_1IDENTIFIER_1sizeof",
+       "CRYPT_1BIT_1BLOB_1sizeof",
+       "CRYPT_1INTEGER_1BLOB_1sizeof",
+       "CRYPT_1OBJID_1BLOB_1sizeof",
+       "CallNextHookEx",
+       "CallWindowProc",
+       "CertNameToStr",
+       "CharLower",
+       "CharUpper",
+       "ChildWindowFromPointEx",
+       "ChooseColor",
+       "ChooseFont",
+       "ClientToScreen",
+       "CloseClipboard",
+       "CloseEnhMetaFile",
+       "CloseGestureInfoHandle",
+       "CloseHandle",
+       "ClosePrinter",
+       "CloseThemeData",
+       "CloseTouchInputHandle",
+       "CoCreateInstance",
+       "CoInternetIsFeatureEnabled",
+       "CoInternetSetFeatureEnabled",
+       "CoTaskMemAlloc",
+       "CoTaskMemFree",
+       "CombineRgn",
+       "CommDlgExtendedError",
+       "CopyImage",
+       "CreateAcceleratorTable",
+       "CreateActCtx",
+       "CreateBitmap",
+       "CreateCaret",
+       "CreateCompatibleBitmap",
+       "CreateCompatibleDC",
+       "CreateCursor",
+       "CreateDC",
+       "CreateDIBSection__JJI_3JJI",
+       "CreateDIBSection__J_3BI_3JJI",
+       "CreateEnhMetaFile",
+       "CreateFontIndirect__J",
+       "CreateFontIndirect__Lorg_eclipse_swt_internal_win32_LOGFONT_2",
+       "CreateIconIndirect",
+       "CreateMenu",
+       "CreatePatternBrush",
+       "CreatePen",
+       "CreatePolygonRgn",
+       "CreatePopupMenu",
+       "CreateProcess",
+       "CreateRectRgn",
+       "CreateSolidBrush",
+       "CreateStreamOnHGlobal",
+       "CreateWindowEx",
+       "DEVMODE_1sizeof",
+       "DIBSECTION_1sizeof",
+       "DOCHOSTUIINFO_1sizeof",
+       "DOCINFO_1sizeof",
+       "DRAWITEMSTRUCT_1sizeof",
+       "DROPFILES_1sizeof",
+       "DTTOPTS_1sizeof",
+       "DefFrameProc",
+       "DefMDIChildProc",
+       "DefWindowProc",
+       "DeferWindowPos",
+       "DeleteDC",
+       "DeleteEnhMetaFile",
+       "DeleteMenu",
+       "DeleteObject",
+       "DestroyAcceleratorTable",
+       "DestroyCaret",
+       "DestroyCursor",
+       "DestroyIcon",
+       "DestroyMenu",
+       "DestroyWindow",
+       "DispatchMessage",
+       "DocumentProperties",
+       "DragDetect",
+       "DragFinish",
+       "DragQueryFile",
+       "DrawEdge",
+       "DrawFocusRect",
+       "DrawFrameControl",
+       "DrawIconEx",
+       "DrawMenuBar",
+       "DrawText",
+       "DrawThemeBackground",
+       "DrawThemeText",
+       "DuplicateHandle",
+       "EMREXTCREATEFONTINDIRECTW_1sizeof",
+       "EMR_1sizeof",
+       "EXTLOGFONTW_1sizeof",
+       "Ellipse",
+       "EnableMenuItem",
+       "EnableScrollBar",
+       "EnableWindow",
+       "EndBufferedPaint",
+       "EndDeferWindowPos",
+       "EndDoc",
+       "EndPage",
+       "EndPaint",
+       "EnumDisplayMonitors",
+       "EnumEnhMetaFile",
+       "EnumFontFamilies",
+       "EnumSystemLanguageGroups",
+       "EnumSystemLocales",
+       "EqualRect",
+       "ExcludeClipRect",
+       "ExpandEnvironmentStrings",
+       "ExtCreatePen",
+       "ExtCreateRegion",
+       "ExtTextOut",
+       "ExtractIconEx",
+       "FILETIME_1sizeof",
+       "FLICK_1DATA_1sizeof",
+       "FLICK_1POINT_1sizeof",
+       "FileTimeToSystemTime",
+       "FillRect",
+       "FormatMessage",
+       "GCP_1RESULTS_1sizeof",
+       "GESTURECONFIG_1sizeof",
+       "GESTUREINFO_1sizeof",
+       "GET_1WHEEL_1DELTA_1WPARAM",
+       "GET_1X_1LPARAM",
+       "GET_1Y_1LPARAM",
+       "GID_1ROTATE_1ANGLE_1FROM_1ARGUMENT",
+       "GRADIENT_1RECT_1sizeof",
+       "GUITHREADINFO_1sizeof",
+       "GdiSetBatchLimit",
+       "GetACP",
+       "GetActiveWindow",
+       "GetBkColor",
+       "GetCapture",
+       "GetCaretPos",
+       "GetCharABCWidths",
+       "GetCharWidth",
+       "GetCharacterPlacement",
+       "GetClassInfo",
+       "GetClassName",
+       "GetClientRect",
+       "GetClipBox",
+       "GetClipRgn",
+       "GetClipboardData",
+       "GetClipboardFormatName",
+       "GetComboBoxInfo",
+       "GetCurrentObject",
+       "GetCurrentProcess",
+       "GetCurrentProcessExplicitAppUserModelID",
+       "GetCurrentProcessId",
+       "GetCurrentThreadId",
+       "GetCursor",
+       "GetCursorPos",
+       "GetDC",
+       "GetDCEx",
+       "GetDIBColorTable",
+       "GetDIBits",
+       "GetDesktopWindow",
+       "GetDeviceCaps",
+       "GetDialogBaseUnits",
+       "GetDlgItem",
+       "GetDoubleClickTime",
+       "GetDpiForMonitor",
+       "GetFocus",
+       "GetFontLanguageInfo",
+       "GetForegroundWindow",
+       "GetGUIThreadInfo",
+       "GetGestureInfo",
+       "GetGlyphIndices",
+       "GetGraphicsMode",
+       "GetIconInfo",
+       "GetKeyState",
+       "GetKeyboardLayout",
+       "GetKeyboardLayoutList",
+       "GetKeyboardState",
+       "GetLastActivePopup",
+       "GetLastError",
+       "GetLayeredWindowAttributes",
+       "GetLayout",
+       "GetLibraryHandle",
+       "GetLocaleInfo",
+       "GetMenu",
+       "GetMenuBarInfo",
+       "GetMenuDefaultItem",
+       "GetMenuInfo",
+       "GetMenuItemCount",
+       "GetMenuItemInfo",
+       "GetMenuItemRect",
+       "GetMessage",
+       "GetMessagePos",
+       "GetMessageTime",
+       "GetMetaRgn",
+       "GetModuleFileName",
+       "GetModuleHandle",
+       "GetMonitorInfo",
+       "GetObject__JIJ",
+       "GetObject__JILorg_eclipse_swt_internal_win32_BITMAP_2",
+       "GetObject__JILorg_eclipse_swt_internal_win32_DIBSECTION_2",
+       "GetObject__JILorg_eclipse_swt_internal_win32_LOGBRUSH_2",
+       "GetObject__JILorg_eclipse_swt_internal_win32_LOGFONT_2",
+       "GetOpenFileName",
+       "GetOutlineTextMetrics",
+       "GetParent",
+       "GetPixel",
+       "GetPolyFillMode",
+       "GetProcessHeap",
+       "GetProfileString",
+       "GetProp",
+       "GetROP2",
+       "GetRandomRgn",
+       "GetRegionData",
+       "GetRgnBox",
+       "GetSaveFileName",
+       "GetScrollBarInfo",
+       "GetScrollInfo",
+       "GetStartupInfo",
+       "GetStockObject",
+       "GetSysColor",
+       "GetSysColorBrush",
+       "GetSystemDefaultUILanguage",
+       "GetSystemMenu",
+       "GetSystemMetrics",
+       "GetTextColor",
+       "GetTextExtentPoint32",
+       "GetTextMetrics",
+       "GetThemePartSize",
+       "GetThemeTextExtent",
+       "GetTouchInputInfo",
+       "GetUpdateRect",
+       "GetUpdateRgn",
+       "GetVersion",
+       "GetWindow",
+       "GetWindowDC",
+       "GetWindowLong",
+       "GetWindowLongPtr",
+       "GetWindowOrgEx",
+       "GetWindowPlacement",
+       "GetWindowRect",
+       "GetWindowRgn",
+       "GetWindowText",
+       "GetWindowTextLength",
+       "GetWindowThreadProcessId",
+       "GlobalAddAtom",
+       "GlobalAlloc",
+       "GlobalFree",
+       "GlobalLock",
+       "GlobalSize",
+       "GlobalUnlock",
+       "GradientFill",
+       "HDHITTESTINFO_1sizeof",
+       "HDITEM_1sizeof",
+       "HDLAYOUT_1sizeof",
+       "HELPINFO_1sizeof",
+       "HIGHCONTRAST_1sizeof",
+       "HIWORD",
+       "HeapAlloc",
+       "HeapFree",
+       "HideCaret",
+       "ICONINFO_1sizeof",
+       "IIDFromString",
+       "ILGetSize",
+       "INITCOMMONCONTROLSEX_1sizeof",
+       "INPUT_1sizeof",
+       "ImageList_1Add",
+       "ImageList_1AddMasked",
+       "ImageList_1BeginDrag",
+       "ImageList_1Create",
+       "ImageList_1Destroy",
+       "ImageList_1DragEnter",
+       "ImageList_1DragLeave",
+       "ImageList_1DragMove",
+       "ImageList_1DragShowNolock",
+       "ImageList_1EndDrag",
+       "ImageList_1GetIconSize",
+       "ImageList_1GetImageCount",
+       "ImageList_1Remove",
+       "ImageList_1Replace",
+       "ImageList_1ReplaceIcon",
+       "ImageList_1SetIconSize",
+       "ImmAssociateContext",
+       "ImmCreateContext",
+       "ImmDestroyContext",
+       "ImmEscape",
+       "ImmGetCompositionFont",
+       "ImmGetCompositionString__JI_3BI",
+       "ImmGetCompositionString__JI_3CI",
+       "ImmGetCompositionString__JI_3II",
+       "ImmGetContext",
+       "ImmGetConversionStatus",
+       "ImmGetDefaultIMEWnd",
+       "ImmGetOpenStatus",
+       "ImmNotifyIME",
+       "ImmReleaseContext",
+       "ImmSetCandidateWindow",
+       "ImmSetCompositionFont",
+       "ImmSetCompositionWindow",
+       "ImmSetConversionStatus",
+       "ImmSetOpenStatus",
+       "InitCommonControls",
+       "InitCommonControlsEx",
+       "InsertMenuItem",
+       "InternetGetCookie",
+       "InternetSetCookie",
+       "InternetSetOption",
+       "IntersectClipRect",
+       "IntersectRect",
+       "InvalidateRect",
+       "InvalidateRgn",
+       "IsAppThemed",
+       "IsHungAppWindow",
+       "IsIconic",
+       "IsTouchWindow",
+       "IsWindowEnabled",
+       "IsWindowVisible",
+       "IsZoomed",
+       "KEYBDINPUT_1sizeof",
+       "KillTimer",
+       "LITEM_1sizeof",
+       "LODWORD",
+       "LOGBRUSH_1sizeof",
+       "LOGFONT_1sizeof",
+       "LOGPEN_1sizeof",
+       "LOWORD",
+       "LPtoDP",
+       "LVCOLUMN_1sizeof",
+       "LVHITTESTINFO_1sizeof",
+       "LVINSERTMARK_1sizeof",
+       "LVITEM_1sizeof",
+       "LineTo",
+       "LoadBitmap",
+       "LoadCursor",
+       "LoadIcon",
+       "LoadIconMetric",
+       "LoadImage",
+       "LocalFree",
+       "MAKELPARAM",
+       "MAKELRESULT",
+       "MAKEWORD",
+       "MAKEWPARAM",
+       "MARGINS_1sizeof",
+       "MCHITTESTINFO_1sizeof",
+       "MEASUREITEMSTRUCT_1sizeof",
+       "MENUBARINFO_1sizeof",
+       "MENUINFO_1sizeof",
+       "MENUITEMINFO_1sizeof",
+       "MINMAXINFO_1sizeof",
+       "MONITORINFO_1sizeof",
+       "MOUSEINPUT_1sizeof",
+       "MSG_1sizeof",
+       "MapViewOfFile",
+       "MapVirtualKey",
+       "MapWindowPoints__JJLorg_eclipse_swt_internal_win32_POINT_2I",
+       "MapWindowPoints__JJLorg_eclipse_swt_internal_win32_RECT_2I",
+       "MessageBeep",
+       "MessageBox",
+       "ModifyWorldTransform",
+       "MonitorFromWindow",
+       "MoveMemory__JJI",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_GESTURECONFIG_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_GRADIENT_1RECT_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_KEYBDINPUT_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_LOGFONT_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_MINMAXINFO_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_MOUSEINPUT_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_MSG_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVDISPINFO_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_NMTTDISPINFO_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVDISPINFO_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_OPENFILENAME_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_RECT_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_SAFEARRAY_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_TRIVERTEX_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_UDACCEL_2I",
+       "MoveMemory__JLorg_eclipse_swt_internal_win32_WINDOWPOS_2I",
+       "MoveMemory__J_3BI",
+       "MoveMemory__J_3CI",
+       "MoveMemory__J_3DI",
+       "MoveMemory__J_3FI",
+       "MoveMemory__J_3II",
+       "MoveMemory__J_3JI",
+       "MoveMemory__J_3SI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_EMREXTCREATEFONTINDIRECTW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_EMR_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1DATA_2_3JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1POINT_2_3JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_HDITEM_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_HELPINFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_LOGFONT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_MINMAXINFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_MSG_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMCUSTOMDRAW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMHDR_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMHEADER_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMLINK_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMLISTVIEW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVDISPINFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVODSTATECHANGE_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHEVRON_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHILDSIZE_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBHOTITEM_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTOOLBAR_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTREEVIEW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTCUSTOMDRAW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTDISPINFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVDISPINFO_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVITEMCHANGE_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_NMUPDOWN_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_OFNOTIFY_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_OPENFILENAME_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2_3JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_SAFEARRAY_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1ITEM_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1LOGATTR_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1PROPERTIES_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_TEXTMETRIC_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_TOUCHINPUT_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_UDACCEL_2JI",
+       "MoveMemory__Lorg_eclipse_swt_internal_win32_WINDOWPOS_2JI",
+       "MoveMemory___3BJI",
+       "MoveMemory___3BLorg_eclipse_swt_internal_win32_ACCEL_2I",
+       "MoveMemory___3BLorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2I",
+       "MoveMemory___3CJI",
+       "MoveMemory___3DJI",
+       "MoveMemory___3FJI",
+       "MoveMemory___3IJI",
+       "MoveMemory___3JJI",
+       "MoveMemory___3SJI",
+       "MoveToEx",
+       "MultiByteToWideChar__IIJI_3CI",
+       "MultiByteToWideChar__II_3BI_3CI",
+       "NMCUSTOMDRAW_1sizeof",
+       "NMHDR_1sizeof",
+       "NMHEADER_1sizeof",
+       "NMLINK_1sizeof",
+       "NMLISTVIEW_1sizeof",
+       "NMLVCUSTOMDRAW_1sizeof",
+       "NMLVDISPINFO_1sizeof",
+       "NMLVFINDITEM_1sizeof",
+       "NMLVODSTATECHANGE_1sizeof",
+       "NMREBARCHEVRON_1sizeof",
+       "NMREBARCHILDSIZE_1sizeof",
+       "NMTBCUSTOMDRAW_1sizeof",
+       "NMTBHOTITEM_1sizeof",
+       "NMTOOLBAR_1sizeof",
+       "NMTREEVIEW_1sizeof",
+       "NMTTCUSTOMDRAW_1sizeof",
+       "NMTTDISPINFO_1sizeof",
+       "NMTVCUSTOMDRAW_1sizeof",
+       "NMTVDISPINFO_1sizeof",
+       "NMTVITEMCHANGE_1sizeof",
+       "NMUPDOWN_1sizeof",
+       "NONCLIENTMETRICS_1sizeof",
+       "NOTIFYICONDATA_1V2_1SIZE",
+       "NotifyWinEvent",
+       "OFNOTIFY_1sizeof",
+       "OPENFILENAME_1sizeof",
+       "OUTLINETEXTMETRIC_1sizeof",
+       "OffsetRect",
+       "OffsetRgn",
+       "OleInitialize",
+       "OleUninitialize",
+       "OpenClipboard",
+       "OpenPrinter",
+       "OpenProcess",
+       "OpenThemeData",
+       "PAINTSTRUCT_1sizeof",
+       "PANOSE_1sizeof",
+       "POINTSTOPOINT",
+       "POINT_1sizeof",
+       "PRIMARYLANGID",
+       "PRINTDLG_1sizeof",
+       "PROCESS_1INFORMATION_1sizeof",
+       "PROPERTYKEY_1sizeof",
+       "PROPVARIANT_1sizeof",
+       "PSPropertyKeyFromString",
+       "PatBlt",
+       "PathIsExe",
+       "PeekMessage",
+       "Pie",
+       "Polygon",
+       "Polyline",
+       "PostMessage",
+       "PostThreadMessage",
+       "PrintDlg",
+       "PrintWindow",
+       "PtInRect",
+       "PtInRegion",
+       "REBARBANDINFO_1sizeof",
+       "RECT_1sizeof",
+       "RectInRegion",
+       "Rectangle",
+       "RedrawWindow",
+       "RegCloseKey",
+       "RegCreateKeyEx",
+       "RegDeleteValue",
+       "RegEnumKeyEx",
+       "RegOpenKeyEx",
+       "RegQueryValueEx__J_3CJ_3I_3C_3I",
+       "RegQueryValueEx__J_3CJ_3I_3I_3I",
+       "RegSetValueEx",
+       "RegisterClass",
+       "RegisterClipboardFormat",
+       "RegisterTouchWindow",
+       "RegisterWindowMessage",
+       "ReleaseCapture",
+       "ReleaseDC",
+       "RemoveMenu",
+       "RemoveProp",
+       "ReplyMessage",
+       "RestoreDC",
+       "RoundRect",
+       "SAFEARRAYBOUND_1sizeof",
+       "SAFEARRAY_1sizeof",
+       "SCRIPT_1ANALYSIS_1sizeof",
+       "SCRIPT_1CONTROL_1sizeof",
+       "SCRIPT_1DIGITSUBSTITUTE_1sizeof",
+       "SCRIPT_1FONTPROPERTIES_1sizeof",
+       "SCRIPT_1ITEM_1sizeof",
+       "SCRIPT_1LOGATTR_1sizeof",
+       "SCRIPT_1PROPERTIES_1sizeof",
+       "SCRIPT_1STATE_1sizeof",
+       "SCRIPT_1STRING_1ANALYSIS_1sizeof",
+       "SCROLLBARINFO_1sizeof",
+       "SCROLLINFO_1sizeof",
+       "SHBrowseForFolder",
+       "SHDRAGIMAGE_1sizeof",
+       "SHELLEXECUTEINFO_1sizeof",
+       "SHFILEINFO_1sizeof",
+       "SHGetFileInfo",
+       "SHGetMalloc",
+       "SHGetPathFromIDList",
+       "SIZE_1sizeof",
+       "STARTUPINFO_1sizeof",
+       "SYSTEMTIME_1sizeof",
+       "SaveDC",
+       "ScreenToClient",
+       "ScriptApplyDigitSubstitution",
+       "ScriptBreak",
+       "ScriptCPtoX",
+       "ScriptCacheGetHeight",
+       "ScriptFreeCache",
+       "ScriptGetCMap",
+       "ScriptGetFontProperties",
+       "ScriptGetLogicalWidths",
+       "ScriptGetProperties",
+       "ScriptItemize",
+       "ScriptJustify",
+       "ScriptLayout",
+       "ScriptPlace",
+       "ScriptRecordDigitSubstitution",
+       "ScriptShape",
+       "ScriptStringAnalyse",
+       "ScriptStringFree",
+       "ScriptStringOut",
+       "ScriptTextOut",
+       "ScriptXtoCP",
+       "ScrollWindowEx",
+       "SelectClipRgn",
+       "SelectObject",
+       "SendInput",
+       "SendMessage__JIJJ",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_BUTTON_1IMAGELIST_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_HDHITTESTINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_HDITEM_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_HDLAYOUT_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_LITEM_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_LVCOLUMN_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_LVHITTESTINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_LVINSERTMARK_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_LVITEM_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_MARGINS_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_MCHITTESTINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_REBARBANDINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_RECT_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_SIZE_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_SYSTEMTIME_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTONINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTON_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TCHITTESTINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TCITEM_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TOOLINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TVHITTESTINFO_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TVINSERTSTRUCT_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TVITEM_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_TVSORTCB_2",
+       "SendMessage__JIJLorg_eclipse_swt_internal_win32_UDACCEL_2",
+       "SendMessage__JIJ_3C",
+       "SendMessage__JIJ_3I",
+       "SendMessage__JI_3I_3I",
+       "SetActiveWindow",
+       "SetBkColor",
+       "SetBkMode",
+       "SetBrushOrgEx",
+       "SetCapture",
+       "SetCaretPos",
+       "SetCurrentProcessExplicitAppUserModelID",
+       "SetCursor",
+       "SetCursorPos",
+       "SetDIBColorTable",
+       "SetDllDirectory",
+       "SetErrorMode",
+       "SetFocus",
+       "SetForegroundWindow",
+       "SetGestureConfig",
+       "SetGraphicsMode",
+       "SetLayeredWindowAttributes",
+       "SetLayout",
+       "SetMenu",
+       "SetMenuDefaultItem",
+       "SetMenuInfo",
+       "SetMenuItemInfo",
+       "SetMetaRgn",
+       "SetParent",
+       "SetPixel",
+       "SetPolyFillMode",
+       "SetProcessDPIAware",
+       "SetProp",
+       "SetROP2",
+       "SetRect",
+       "SetRectRgn",
+       "SetScrollInfo",
+       "SetStretchBltMode",
+       "SetTextColor",
+       "SetTimer",
+       "SetWindowLong",
+       "SetWindowLongPtr",
+       "SetWindowOrgEx",
+       "SetWindowPlacement",
+       "SetWindowPos",
+       "SetWindowRgn",
+       "SetWindowText",
+       "SetWindowTheme",
+       "SetWindowsHookEx",
+       "SetWorldTransform",
+       "ShellExecuteEx",
+       "Shell_1NotifyIcon",
+       "ShowCaret",
+       "ShowOwnedPopups",
+       "ShowScrollBar",
+       "ShowWindow",
+       "StartDoc",
+       "StartPage",
+       "StretchBlt",
+       "SystemParametersInfo__IILorg_eclipse_swt_internal_win32_HIGHCONTRAST_2I",
+       "SystemParametersInfo__IILorg_eclipse_swt_internal_win32_NONCLIENTMETRICS_2I",
+       "SystemParametersInfo__IILorg_eclipse_swt_internal_win32_RECT_2I",
+       "SystemParametersInfo__II_3II",
+       "TBBUTTONINFO_1sizeof",
+       "TBBUTTON_1sizeof",
+       "TCHITTESTINFO_1sizeof",
+       "TCITEM_1sizeof",
+       "TEXTMETRIC_1sizeof",
+       "TF_1DA_1COLOR_1sizeof",
+       "TF_1DISPLAYATTRIBUTE_1sizeof",
+       "TOOLINFO_1sizeof",
+       "TOUCHINPUT_1sizeof",
+       "TOUCH_1COORD_1TO_1PIXEL",
+       "TRACKMOUSEEVENT_1sizeof",
+       "TRIVERTEX_1sizeof",
+       "TVHITTESTINFO_1sizeof",
+       "TVINSERTSTRUCT_1sizeof",
+       "TVITEMEX_1sizeof",
+       "TVITEM_1sizeof",
+       "TVSORTCB_1sizeof",
+       "ToUnicode",
+       "TrackMouseEvent",
+       "TrackPopupMenu",
+       "TranslateAccelerator",
+       "TranslateCharsetInfo",
+       "TranslateMDISysAccel",
+       "TranslateMessage",
+       "TransparentBlt",
+       "TreeView_1GetItemRect",
+       "UDACCEL_1sizeof",
+       "UnhookWindowsHookEx",
+       "UnmapViewOfFile",
+       "UnregisterClass",
+       "UnregisterTouchWindow",
+       "UpdateWindow",
+       "UrlCreateFromPath",
+       "ValidateRect",
+       "VkKeyScan",
+       "WINDOWPLACEMENT_1sizeof",
+       "WINDOWPOS_1sizeof",
+       "WNDCLASS_1sizeof",
+       "WaitMessage",
+       "WideCharToMultiByte__II_3CIJI_3B_3Z",
+       "WideCharToMultiByte__II_3CI_3BI_3B_3Z",
+       "WindowFromDC",
+       "WindowFromPoint",
+       "wcslen",
+};
+#define NATIVE_FUNCTION_COUNT sizeof(OS_nativeFunctionNames) / sizeof(char*)
+int OS_nativeFunctionCount = NATIVE_FUNCTION_COUNT;
+int OS_nativeFunctionCallCount[NATIVE_FUNCTION_COUNT];
+
+#define STATS_NATIVE(func) Java_org_eclipse_swt_tools_internal_NativeStats_##func
+
+JNIEXPORT jint JNICALL STATS_NATIVE(OS_1GetFunctionCount)
+       (JNIEnv *env, jclass that)
+{
+       return OS_nativeFunctionCount;
+}
+
+JNIEXPORT jstring JNICALL STATS_NATIVE(OS_1GetFunctionName)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return (*env)->NewStringUTF(env, OS_nativeFunctionNames[index]);
+}
+
+JNIEXPORT jint JNICALL STATS_NATIVE(OS_1GetFunctionCallCount)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return OS_nativeFunctionCallCount[index];
+}
+
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_stats.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_stats.h
new file mode 100644 (file)
index 0000000..7bf2950
--- /dev/null
@@ -0,0 +1,781 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#ifdef NATIVE_STATS
+extern int OS_nativeFunctionCount;
+extern int OS_nativeFunctionCallCount[];
+extern char* OS_nativeFunctionNames[];
+#define OS_NATIVE_ENTER(env, that, func) OS_nativeFunctionCallCount[func]++;
+#define OS_NATIVE_EXIT(env, that, func) 
+#else
+#ifndef OS_NATIVE_ENTER
+#define OS_NATIVE_ENTER(env, that, func) 
+#endif
+#ifndef OS_NATIVE_EXIT
+#define OS_NATIVE_EXIT(env, that, func) 
+#endif
+#endif
+
+typedef enum {
+       ACCEL_1sizeof_FUNC,
+       ACTCTX_1sizeof_FUNC,
+       AbortDoc_FUNC,
+       ActivateActCtx_FUNC,
+       ActivateKeyboardLayout_FUNC,
+       AddFontResourceEx_FUNC,
+       AdjustWindowRectEx_FUNC,
+       AllowSetForegroundWindow_FUNC,
+       AlphaBlend_FUNC,
+       Arc_FUNC,
+       AssocQueryString_FUNC,
+       BITMAPINFOHEADER_1sizeof_FUNC,
+       BITMAP_1sizeof_FUNC,
+       BLENDFUNCTION_1sizeof_FUNC,
+       BP_1PAINTPARAMS_1sizeof_FUNC,
+       BROWSEINFO_1sizeof_FUNC,
+       BUTTON_1IMAGELIST_1sizeof_FUNC,
+       BeginBufferedPaint_FUNC,
+       BeginDeferWindowPos_FUNC,
+       BeginPaint_FUNC,
+       BeginPath_FUNC,
+       BitBlt_FUNC,
+       BringWindowToTop_FUNC,
+       BufferedPaintInit_FUNC,
+       BufferedPaintUnInit_FUNC,
+       CANDIDATEFORM_1sizeof_FUNC,
+       CERT_1CONTEXT_1sizeof_FUNC,
+       CERT_1INFO_1sizeof_FUNC,
+       CERT_1NAME_1BLOB_1sizeof_FUNC,
+       CERT_1PUBLIC_1KEY_1INFO_1sizeof_FUNC,
+       CHOOSECOLOR_1sizeof_FUNC,
+       CHOOSEFONT_1sizeof_FUNC,
+       CIDA_1sizeof_FUNC,
+       COMBOBOXINFO_1sizeof_FUNC,
+       COMPOSITIONFORM_1sizeof_FUNC,
+       CREATESTRUCT_1sizeof_FUNC,
+       CRYPT_1ALGORITHM_1IDENTIFIER_1sizeof_FUNC,
+       CRYPT_1BIT_1BLOB_1sizeof_FUNC,
+       CRYPT_1INTEGER_1BLOB_1sizeof_FUNC,
+       CRYPT_1OBJID_1BLOB_1sizeof_FUNC,
+       CallNextHookEx_FUNC,
+       CallWindowProc_FUNC,
+       CertNameToStr_FUNC,
+       CharLower_FUNC,
+       CharUpper_FUNC,
+       ChildWindowFromPointEx_FUNC,
+       ChooseColor_FUNC,
+       ChooseFont_FUNC,
+       ClientToScreen_FUNC,
+       CloseClipboard_FUNC,
+       CloseEnhMetaFile_FUNC,
+       CloseGestureInfoHandle_FUNC,
+       CloseHandle_FUNC,
+       ClosePrinter_FUNC,
+       CloseThemeData_FUNC,
+       CloseTouchInputHandle_FUNC,
+       CoCreateInstance_FUNC,
+       CoInternetIsFeatureEnabled_FUNC,
+       CoInternetSetFeatureEnabled_FUNC,
+       CoTaskMemAlloc_FUNC,
+       CoTaskMemFree_FUNC,
+       CombineRgn_FUNC,
+       CommDlgExtendedError_FUNC,
+       CopyImage_FUNC,
+       CreateAcceleratorTable_FUNC,
+       CreateActCtx_FUNC,
+       CreateBitmap_FUNC,
+       CreateCaret_FUNC,
+       CreateCompatibleBitmap_FUNC,
+       CreateCompatibleDC_FUNC,
+       CreateCursor_FUNC,
+       CreateDC_FUNC,
+       CreateDIBSection__JJI_3JJI_FUNC,
+       CreateDIBSection__J_3BI_3JJI_FUNC,
+       CreateEnhMetaFile_FUNC,
+       CreateFontIndirect__J_FUNC,
+       CreateFontIndirect__Lorg_eclipse_swt_internal_win32_LOGFONT_2_FUNC,
+       CreateIconIndirect_FUNC,
+       CreateMenu_FUNC,
+       CreatePatternBrush_FUNC,
+       CreatePen_FUNC,
+       CreatePolygonRgn_FUNC,
+       CreatePopupMenu_FUNC,
+       CreateProcess_FUNC,
+       CreateRectRgn_FUNC,
+       CreateSolidBrush_FUNC,
+       CreateStreamOnHGlobal_FUNC,
+       CreateWindowEx_FUNC,
+       DEVMODE_1sizeof_FUNC,
+       DIBSECTION_1sizeof_FUNC,
+       DOCHOSTUIINFO_1sizeof_FUNC,
+       DOCINFO_1sizeof_FUNC,
+       DRAWITEMSTRUCT_1sizeof_FUNC,
+       DROPFILES_1sizeof_FUNC,
+       DTTOPTS_1sizeof_FUNC,
+       DefFrameProc_FUNC,
+       DefMDIChildProc_FUNC,
+       DefWindowProc_FUNC,
+       DeferWindowPos_FUNC,
+       DeleteDC_FUNC,
+       DeleteEnhMetaFile_FUNC,
+       DeleteMenu_FUNC,
+       DeleteObject_FUNC,
+       DestroyAcceleratorTable_FUNC,
+       DestroyCaret_FUNC,
+       DestroyCursor_FUNC,
+       DestroyIcon_FUNC,
+       DestroyMenu_FUNC,
+       DestroyWindow_FUNC,
+       DispatchMessage_FUNC,
+       DocumentProperties_FUNC,
+       DragDetect_FUNC,
+       DragFinish_FUNC,
+       DragQueryFile_FUNC,
+       DrawEdge_FUNC,
+       DrawFocusRect_FUNC,
+       DrawFrameControl_FUNC,
+       DrawIconEx_FUNC,
+       DrawMenuBar_FUNC,
+       DrawText_FUNC,
+       DrawThemeBackground_FUNC,
+       DrawThemeText_FUNC,
+       DuplicateHandle_FUNC,
+       EMREXTCREATEFONTINDIRECTW_1sizeof_FUNC,
+       EMR_1sizeof_FUNC,
+       EXTLOGFONTW_1sizeof_FUNC,
+       Ellipse_FUNC,
+       EnableMenuItem_FUNC,
+       EnableScrollBar_FUNC,
+       EnableWindow_FUNC,
+       EndBufferedPaint_FUNC,
+       EndDeferWindowPos_FUNC,
+       EndDoc_FUNC,
+       EndPage_FUNC,
+       EndPaint_FUNC,
+       EnumDisplayMonitors_FUNC,
+       EnumEnhMetaFile_FUNC,
+       EnumFontFamilies_FUNC,
+       EnumSystemLanguageGroups_FUNC,
+       EnumSystemLocales_FUNC,
+       EqualRect_FUNC,
+       ExcludeClipRect_FUNC,
+       ExpandEnvironmentStrings_FUNC,
+       ExtCreatePen_FUNC,
+       ExtCreateRegion_FUNC,
+       ExtTextOut_FUNC,
+       ExtractIconEx_FUNC,
+       FILETIME_1sizeof_FUNC,
+       FLICK_1DATA_1sizeof_FUNC,
+       FLICK_1POINT_1sizeof_FUNC,
+       FileTimeToSystemTime_FUNC,
+       FillRect_FUNC,
+       FormatMessage_FUNC,
+       GCP_1RESULTS_1sizeof_FUNC,
+       GESTURECONFIG_1sizeof_FUNC,
+       GESTUREINFO_1sizeof_FUNC,
+       GET_1WHEEL_1DELTA_1WPARAM_FUNC,
+       GET_1X_1LPARAM_FUNC,
+       GET_1Y_1LPARAM_FUNC,
+       GID_1ROTATE_1ANGLE_1FROM_1ARGUMENT_FUNC,
+       GRADIENT_1RECT_1sizeof_FUNC,
+       GUITHREADINFO_1sizeof_FUNC,
+       GdiSetBatchLimit_FUNC,
+       GetACP_FUNC,
+       GetActiveWindow_FUNC,
+       GetBkColor_FUNC,
+       GetCapture_FUNC,
+       GetCaretPos_FUNC,
+       GetCharABCWidths_FUNC,
+       GetCharWidth_FUNC,
+       GetCharacterPlacement_FUNC,
+       GetClassInfo_FUNC,
+       GetClassName_FUNC,
+       GetClientRect_FUNC,
+       GetClipBox_FUNC,
+       GetClipRgn_FUNC,
+       GetClipboardData_FUNC,
+       GetClipboardFormatName_FUNC,
+       GetComboBoxInfo_FUNC,
+       GetCurrentObject_FUNC,
+       GetCurrentProcess_FUNC,
+       GetCurrentProcessExplicitAppUserModelID_FUNC,
+       GetCurrentProcessId_FUNC,
+       GetCurrentThreadId_FUNC,
+       GetCursor_FUNC,
+       GetCursorPos_FUNC,
+       GetDC_FUNC,
+       GetDCEx_FUNC,
+       GetDIBColorTable_FUNC,
+       GetDIBits_FUNC,
+       GetDesktopWindow_FUNC,
+       GetDeviceCaps_FUNC,
+       GetDialogBaseUnits_FUNC,
+       GetDlgItem_FUNC,
+       GetDoubleClickTime_FUNC,
+       GetDpiForMonitor_FUNC,
+       GetFocus_FUNC,
+       GetFontLanguageInfo_FUNC,
+       GetForegroundWindow_FUNC,
+       GetGUIThreadInfo_FUNC,
+       GetGestureInfo_FUNC,
+       GetGlyphIndices_FUNC,
+       GetGraphicsMode_FUNC,
+       GetIconInfo_FUNC,
+       GetKeyState_FUNC,
+       GetKeyboardLayout_FUNC,
+       GetKeyboardLayoutList_FUNC,
+       GetKeyboardState_FUNC,
+       GetLastActivePopup_FUNC,
+       GetLastError_FUNC,
+       GetLayeredWindowAttributes_FUNC,
+       GetLayout_FUNC,
+       GetLibraryHandle_FUNC,
+       GetLocaleInfo_FUNC,
+       GetMenu_FUNC,
+       GetMenuBarInfo_FUNC,
+       GetMenuDefaultItem_FUNC,
+       GetMenuInfo_FUNC,
+       GetMenuItemCount_FUNC,
+       GetMenuItemInfo_FUNC,
+       GetMenuItemRect_FUNC,
+       GetMessage_FUNC,
+       GetMessagePos_FUNC,
+       GetMessageTime_FUNC,
+       GetMetaRgn_FUNC,
+       GetModuleFileName_FUNC,
+       GetModuleHandle_FUNC,
+       GetMonitorInfo_FUNC,
+       GetObject__JIJ_FUNC,
+       GetObject__JILorg_eclipse_swt_internal_win32_BITMAP_2_FUNC,
+       GetObject__JILorg_eclipse_swt_internal_win32_DIBSECTION_2_FUNC,
+       GetObject__JILorg_eclipse_swt_internal_win32_LOGBRUSH_2_FUNC,
+       GetObject__JILorg_eclipse_swt_internal_win32_LOGFONT_2_FUNC,
+       GetOpenFileName_FUNC,
+       GetOutlineTextMetrics_FUNC,
+       GetParent_FUNC,
+       GetPixel_FUNC,
+       GetPolyFillMode_FUNC,
+       GetProcessHeap_FUNC,
+       GetProfileString_FUNC,
+       GetProp_FUNC,
+       GetROP2_FUNC,
+       GetRandomRgn_FUNC,
+       GetRegionData_FUNC,
+       GetRgnBox_FUNC,
+       GetSaveFileName_FUNC,
+       GetScrollBarInfo_FUNC,
+       GetScrollInfo_FUNC,
+       GetStartupInfo_FUNC,
+       GetStockObject_FUNC,
+       GetSysColor_FUNC,
+       GetSysColorBrush_FUNC,
+       GetSystemDefaultUILanguage_FUNC,
+       GetSystemMenu_FUNC,
+       GetSystemMetrics_FUNC,
+       GetTextColor_FUNC,
+       GetTextExtentPoint32_FUNC,
+       GetTextMetrics_FUNC,
+       GetThemePartSize_FUNC,
+       GetThemeTextExtent_FUNC,
+       GetTouchInputInfo_FUNC,
+       GetUpdateRect_FUNC,
+       GetUpdateRgn_FUNC,
+       GetVersion_FUNC,
+       GetWindow_FUNC,
+       GetWindowDC_FUNC,
+       GetWindowLong_FUNC,
+       GetWindowLongPtr_FUNC,
+       GetWindowOrgEx_FUNC,
+       GetWindowPlacement_FUNC,
+       GetWindowRect_FUNC,
+       GetWindowRgn_FUNC,
+       GetWindowText_FUNC,
+       GetWindowTextLength_FUNC,
+       GetWindowThreadProcessId_FUNC,
+       GlobalAddAtom_FUNC,
+       GlobalAlloc_FUNC,
+       GlobalFree_FUNC,
+       GlobalLock_FUNC,
+       GlobalSize_FUNC,
+       GlobalUnlock_FUNC,
+       GradientFill_FUNC,
+       HDHITTESTINFO_1sizeof_FUNC,
+       HDITEM_1sizeof_FUNC,
+       HDLAYOUT_1sizeof_FUNC,
+       HELPINFO_1sizeof_FUNC,
+       HIGHCONTRAST_1sizeof_FUNC,
+       HIWORD_FUNC,
+       HeapAlloc_FUNC,
+       HeapFree_FUNC,
+       HideCaret_FUNC,
+       ICONINFO_1sizeof_FUNC,
+       IIDFromString_FUNC,
+       ILGetSize_FUNC,
+       INITCOMMONCONTROLSEX_1sizeof_FUNC,
+       INPUT_1sizeof_FUNC,
+       ImageList_1Add_FUNC,
+       ImageList_1AddMasked_FUNC,
+       ImageList_1BeginDrag_FUNC,
+       ImageList_1Create_FUNC,
+       ImageList_1Destroy_FUNC,
+       ImageList_1DragEnter_FUNC,
+       ImageList_1DragLeave_FUNC,
+       ImageList_1DragMove_FUNC,
+       ImageList_1DragShowNolock_FUNC,
+       ImageList_1EndDrag_FUNC,
+       ImageList_1GetIconSize_FUNC,
+       ImageList_1GetImageCount_FUNC,
+       ImageList_1Remove_FUNC,
+       ImageList_1Replace_FUNC,
+       ImageList_1ReplaceIcon_FUNC,
+       ImageList_1SetIconSize_FUNC,
+       ImmAssociateContext_FUNC,
+       ImmCreateContext_FUNC,
+       ImmDestroyContext_FUNC,
+       ImmEscape_FUNC,
+       ImmGetCompositionFont_FUNC,
+       ImmGetCompositionString__JI_3BI_FUNC,
+       ImmGetCompositionString__JI_3CI_FUNC,
+       ImmGetCompositionString__JI_3II_FUNC,
+       ImmGetContext_FUNC,
+       ImmGetConversionStatus_FUNC,
+       ImmGetDefaultIMEWnd_FUNC,
+       ImmGetOpenStatus_FUNC,
+       ImmNotifyIME_FUNC,
+       ImmReleaseContext_FUNC,
+       ImmSetCandidateWindow_FUNC,
+       ImmSetCompositionFont_FUNC,
+       ImmSetCompositionWindow_FUNC,
+       ImmSetConversionStatus_FUNC,
+       ImmSetOpenStatus_FUNC,
+       InitCommonControls_FUNC,
+       InitCommonControlsEx_FUNC,
+       InsertMenuItem_FUNC,
+       InternetGetCookie_FUNC,
+       InternetSetCookie_FUNC,
+       InternetSetOption_FUNC,
+       IntersectClipRect_FUNC,
+       IntersectRect_FUNC,
+       InvalidateRect_FUNC,
+       InvalidateRgn_FUNC,
+       IsAppThemed_FUNC,
+       IsHungAppWindow_FUNC,
+       IsIconic_FUNC,
+       IsTouchWindow_FUNC,
+       IsWindowEnabled_FUNC,
+       IsWindowVisible_FUNC,
+       IsZoomed_FUNC,
+       KEYBDINPUT_1sizeof_FUNC,
+       KillTimer_FUNC,
+       LITEM_1sizeof_FUNC,
+       LODWORD_FUNC,
+       LOGBRUSH_1sizeof_FUNC,
+       LOGFONT_1sizeof_FUNC,
+       LOGPEN_1sizeof_FUNC,
+       LOWORD_FUNC,
+       LPtoDP_FUNC,
+       LVCOLUMN_1sizeof_FUNC,
+       LVHITTESTINFO_1sizeof_FUNC,
+       LVINSERTMARK_1sizeof_FUNC,
+       LVITEM_1sizeof_FUNC,
+       LineTo_FUNC,
+       LoadBitmap_FUNC,
+       LoadCursor_FUNC,
+       LoadIcon_FUNC,
+       LoadIconMetric_FUNC,
+       LoadImage_FUNC,
+       LocalFree_FUNC,
+       MAKELPARAM_FUNC,
+       MAKELRESULT_FUNC,
+       MAKEWORD_FUNC,
+       MAKEWPARAM_FUNC,
+       MARGINS_1sizeof_FUNC,
+       MCHITTESTINFO_1sizeof_FUNC,
+       MEASUREITEMSTRUCT_1sizeof_FUNC,
+       MENUBARINFO_1sizeof_FUNC,
+       MENUINFO_1sizeof_FUNC,
+       MENUITEMINFO_1sizeof_FUNC,
+       MINMAXINFO_1sizeof_FUNC,
+       MONITORINFO_1sizeof_FUNC,
+       MOUSEINPUT_1sizeof_FUNC,
+       MSG_1sizeof_FUNC,
+       MapViewOfFile_FUNC,
+       MapVirtualKey_FUNC,
+       MapWindowPoints__JJLorg_eclipse_swt_internal_win32_POINT_2I_FUNC,
+       MapWindowPoints__JJLorg_eclipse_swt_internal_win32_RECT_2I_FUNC,
+       MessageBeep_FUNC,
+       MessageBox_FUNC,
+       ModifyWorldTransform_FUNC,
+       MonitorFromWindow_FUNC,
+       MoveMemory__JJI_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_GESTURECONFIG_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_GRADIENT_1RECT_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_KEYBDINPUT_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_LOGFONT_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_MINMAXINFO_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_MOUSEINPUT_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_MSG_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_NMLVDISPINFO_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_NMTTDISPINFO_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_NMTVDISPINFO_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_OPENFILENAME_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_RECT_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_SAFEARRAY_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_TRIVERTEX_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_UDACCEL_2I_FUNC,
+       MoveMemory__JLorg_eclipse_swt_internal_win32_WINDOWPOS_2I_FUNC,
+       MoveMemory__J_3BI_FUNC,
+       MoveMemory__J_3CI_FUNC,
+       MoveMemory__J_3DI_FUNC,
+       MoveMemory__J_3FI_FUNC,
+       MoveMemory__J_3II_FUNC,
+       MoveMemory__J_3JI_FUNC,
+       MoveMemory__J_3SI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_EMREXTCREATEFONTINDIRECTW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_EMR_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1DATA_2_3JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_FLICK_1POINT_2_3JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_HDITEM_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_HELPINFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_LOGFONT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_MEASUREITEMSTRUCT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_MINMAXINFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_MSG_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMCUSTOMDRAW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMHDR_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMHEADER_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMLINK_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMLISTVIEW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVCUSTOMDRAW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVDISPINFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMLVODSTATECHANGE_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHEVRON_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMREBARCHILDSIZE_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBCUSTOMDRAW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTBHOTITEM_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTOOLBAR_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTREEVIEW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTCUSTOMDRAW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTTDISPINFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVCUSTOMDRAW_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVDISPINFO_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMTVITEMCHANGE_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_NMUPDOWN_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_OFNOTIFY_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_OPENFILENAME_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_POINT_2_3JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_SAFEARRAY_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1ITEM_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1LOGATTR_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_SCRIPT_1PROPERTIES_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_TEXTMETRIC_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_TOUCHINPUT_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_UDACCEL_2JI_FUNC,
+       MoveMemory__Lorg_eclipse_swt_internal_win32_WINDOWPOS_2JI_FUNC,
+       MoveMemory___3BJI_FUNC,
+       MoveMemory___3BLorg_eclipse_swt_internal_win32_ACCEL_2I_FUNC,
+       MoveMemory___3BLorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2I_FUNC,
+       MoveMemory___3CJI_FUNC,
+       MoveMemory___3DJI_FUNC,
+       MoveMemory___3FJI_FUNC,
+       MoveMemory___3IJI_FUNC,
+       MoveMemory___3JJI_FUNC,
+       MoveMemory___3SJI_FUNC,
+       MoveToEx_FUNC,
+       MultiByteToWideChar__IIJI_3CI_FUNC,
+       MultiByteToWideChar__II_3BI_3CI_FUNC,
+       NMCUSTOMDRAW_1sizeof_FUNC,
+       NMHDR_1sizeof_FUNC,
+       NMHEADER_1sizeof_FUNC,
+       NMLINK_1sizeof_FUNC,
+       NMLISTVIEW_1sizeof_FUNC,
+       NMLVCUSTOMDRAW_1sizeof_FUNC,
+       NMLVDISPINFO_1sizeof_FUNC,
+       NMLVFINDITEM_1sizeof_FUNC,
+       NMLVODSTATECHANGE_1sizeof_FUNC,
+       NMREBARCHEVRON_1sizeof_FUNC,
+       NMREBARCHILDSIZE_1sizeof_FUNC,
+       NMTBCUSTOMDRAW_1sizeof_FUNC,
+       NMTBHOTITEM_1sizeof_FUNC,
+       NMTOOLBAR_1sizeof_FUNC,
+       NMTREEVIEW_1sizeof_FUNC,
+       NMTTCUSTOMDRAW_1sizeof_FUNC,
+       NMTTDISPINFO_1sizeof_FUNC,
+       NMTVCUSTOMDRAW_1sizeof_FUNC,
+       NMTVDISPINFO_1sizeof_FUNC,
+       NMTVITEMCHANGE_1sizeof_FUNC,
+       NMUPDOWN_1sizeof_FUNC,
+       NONCLIENTMETRICS_1sizeof_FUNC,
+       NOTIFYICONDATA_1V2_1SIZE_FUNC,
+       NotifyWinEvent_FUNC,
+       OFNOTIFY_1sizeof_FUNC,
+       OPENFILENAME_1sizeof_FUNC,
+       OUTLINETEXTMETRIC_1sizeof_FUNC,
+       OffsetRect_FUNC,
+       OffsetRgn_FUNC,
+       OleInitialize_FUNC,
+       OleUninitialize_FUNC,
+       OpenClipboard_FUNC,
+       OpenPrinter_FUNC,
+       OpenProcess_FUNC,
+       OpenThemeData_FUNC,
+       PAINTSTRUCT_1sizeof_FUNC,
+       PANOSE_1sizeof_FUNC,
+       POINTSTOPOINT_FUNC,
+       POINT_1sizeof_FUNC,
+       PRIMARYLANGID_FUNC,
+       PRINTDLG_1sizeof_FUNC,
+       PROCESS_1INFORMATION_1sizeof_FUNC,
+       PROPERTYKEY_1sizeof_FUNC,
+       PROPVARIANT_1sizeof_FUNC,
+       PSPropertyKeyFromString_FUNC,
+       PatBlt_FUNC,
+       PathIsExe_FUNC,
+       PeekMessage_FUNC,
+       Pie_FUNC,
+       Polygon_FUNC,
+       Polyline_FUNC,
+       PostMessage_FUNC,
+       PostThreadMessage_FUNC,
+       PrintDlg_FUNC,
+       PrintWindow_FUNC,
+       PtInRect_FUNC,
+       PtInRegion_FUNC,
+       REBARBANDINFO_1sizeof_FUNC,
+       RECT_1sizeof_FUNC,
+       RectInRegion_FUNC,
+       Rectangle_FUNC,
+       RedrawWindow_FUNC,
+       RegCloseKey_FUNC,
+       RegCreateKeyEx_FUNC,
+       RegDeleteValue_FUNC,
+       RegEnumKeyEx_FUNC,
+       RegOpenKeyEx_FUNC,
+       RegQueryValueEx__J_3CJ_3I_3C_3I_FUNC,
+       RegQueryValueEx__J_3CJ_3I_3I_3I_FUNC,
+       RegSetValueEx_FUNC,
+       RegisterClass_FUNC,
+       RegisterClipboardFormat_FUNC,
+       RegisterTouchWindow_FUNC,
+       RegisterWindowMessage_FUNC,
+       ReleaseCapture_FUNC,
+       ReleaseDC_FUNC,
+       RemoveMenu_FUNC,
+       RemoveProp_FUNC,
+       ReplyMessage_FUNC,
+       RestoreDC_FUNC,
+       RoundRect_FUNC,
+       SAFEARRAYBOUND_1sizeof_FUNC,
+       SAFEARRAY_1sizeof_FUNC,
+       SCRIPT_1ANALYSIS_1sizeof_FUNC,
+       SCRIPT_1CONTROL_1sizeof_FUNC,
+       SCRIPT_1DIGITSUBSTITUTE_1sizeof_FUNC,
+       SCRIPT_1FONTPROPERTIES_1sizeof_FUNC,
+       SCRIPT_1ITEM_1sizeof_FUNC,
+       SCRIPT_1LOGATTR_1sizeof_FUNC,
+       SCRIPT_1PROPERTIES_1sizeof_FUNC,
+       SCRIPT_1STATE_1sizeof_FUNC,
+       SCRIPT_1STRING_1ANALYSIS_1sizeof_FUNC,
+       SCROLLBARINFO_1sizeof_FUNC,
+       SCROLLINFO_1sizeof_FUNC,
+       SHBrowseForFolder_FUNC,
+       SHDRAGIMAGE_1sizeof_FUNC,
+       SHELLEXECUTEINFO_1sizeof_FUNC,
+       SHFILEINFO_1sizeof_FUNC,
+       SHGetFileInfo_FUNC,
+       SHGetMalloc_FUNC,
+       SHGetPathFromIDList_FUNC,
+       SIZE_1sizeof_FUNC,
+       STARTUPINFO_1sizeof_FUNC,
+       SYSTEMTIME_1sizeof_FUNC,
+       SaveDC_FUNC,
+       ScreenToClient_FUNC,
+       ScriptApplyDigitSubstitution_FUNC,
+       ScriptBreak_FUNC,
+       ScriptCPtoX_FUNC,
+       ScriptCacheGetHeight_FUNC,
+       ScriptFreeCache_FUNC,
+       ScriptGetCMap_FUNC,
+       ScriptGetFontProperties_FUNC,
+       ScriptGetLogicalWidths_FUNC,
+       ScriptGetProperties_FUNC,
+       ScriptItemize_FUNC,
+       ScriptJustify_FUNC,
+       ScriptLayout_FUNC,
+       ScriptPlace_FUNC,
+       ScriptRecordDigitSubstitution_FUNC,
+       ScriptShape_FUNC,
+       ScriptStringAnalyse_FUNC,
+       ScriptStringFree_FUNC,
+       ScriptStringOut_FUNC,
+       ScriptTextOut_FUNC,
+       ScriptXtoCP_FUNC,
+       ScrollWindowEx_FUNC,
+       SelectClipRgn_FUNC,
+       SelectObject_FUNC,
+       SendInput_FUNC,
+       SendMessage__JIJJ_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_BUTTON_1IMAGELIST_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_HDHITTESTINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_HDITEM_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_HDLAYOUT_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_LITEM_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_LVCOLUMN_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_LVHITTESTINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_LVINSERTMARK_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_LVITEM_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_MARGINS_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_MCHITTESTINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_REBARBANDINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_RECT_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_SHDRAGIMAGE_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_SIZE_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_SYSTEMTIME_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTONINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TBBUTTON_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TCHITTESTINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TCITEM_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TOOLINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TVHITTESTINFO_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TVINSERTSTRUCT_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TVITEM_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_TVSORTCB_2_FUNC,
+       SendMessage__JIJLorg_eclipse_swt_internal_win32_UDACCEL_2_FUNC,
+       SendMessage__JIJ_3C_FUNC,
+       SendMessage__JIJ_3I_FUNC,
+       SendMessage__JI_3I_3I_FUNC,
+       SetActiveWindow_FUNC,
+       SetBkColor_FUNC,
+       SetBkMode_FUNC,
+       SetBrushOrgEx_FUNC,
+       SetCapture_FUNC,
+       SetCaretPos_FUNC,
+       SetCurrentProcessExplicitAppUserModelID_FUNC,
+       SetCursor_FUNC,
+       SetCursorPos_FUNC,
+       SetDIBColorTable_FUNC,
+       SetDllDirectory_FUNC,
+       SetErrorMode_FUNC,
+       SetFocus_FUNC,
+       SetForegroundWindow_FUNC,
+       SetGestureConfig_FUNC,
+       SetGraphicsMode_FUNC,
+       SetLayeredWindowAttributes_FUNC,
+       SetLayout_FUNC,
+       SetMenu_FUNC,
+       SetMenuDefaultItem_FUNC,
+       SetMenuInfo_FUNC,
+       SetMenuItemInfo_FUNC,
+       SetMetaRgn_FUNC,
+       SetParent_FUNC,
+       SetPixel_FUNC,
+       SetPolyFillMode_FUNC,
+       SetProcessDPIAware_FUNC,
+       SetProp_FUNC,
+       SetROP2_FUNC,
+       SetRect_FUNC,
+       SetRectRgn_FUNC,
+       SetScrollInfo_FUNC,
+       SetStretchBltMode_FUNC,
+       SetTextColor_FUNC,
+       SetTimer_FUNC,
+       SetWindowLong_FUNC,
+       SetWindowLongPtr_FUNC,
+       SetWindowOrgEx_FUNC,
+       SetWindowPlacement_FUNC,
+       SetWindowPos_FUNC,
+       SetWindowRgn_FUNC,
+       SetWindowText_FUNC,
+       SetWindowTheme_FUNC,
+       SetWindowsHookEx_FUNC,
+       SetWorldTransform_FUNC,
+       ShellExecuteEx_FUNC,
+       Shell_1NotifyIcon_FUNC,
+       ShowCaret_FUNC,
+       ShowOwnedPopups_FUNC,
+       ShowScrollBar_FUNC,
+       ShowWindow_FUNC,
+       StartDoc_FUNC,
+       StartPage_FUNC,
+       StretchBlt_FUNC,
+       SystemParametersInfo__IILorg_eclipse_swt_internal_win32_HIGHCONTRAST_2I_FUNC,
+       SystemParametersInfo__IILorg_eclipse_swt_internal_win32_NONCLIENTMETRICS_2I_FUNC,
+       SystemParametersInfo__IILorg_eclipse_swt_internal_win32_RECT_2I_FUNC,
+       SystemParametersInfo__II_3II_FUNC,
+       TBBUTTONINFO_1sizeof_FUNC,
+       TBBUTTON_1sizeof_FUNC,
+       TCHITTESTINFO_1sizeof_FUNC,
+       TCITEM_1sizeof_FUNC,
+       TEXTMETRIC_1sizeof_FUNC,
+       TF_1DA_1COLOR_1sizeof_FUNC,
+       TF_1DISPLAYATTRIBUTE_1sizeof_FUNC,
+       TOOLINFO_1sizeof_FUNC,
+       TOUCHINPUT_1sizeof_FUNC,
+       TOUCH_1COORD_1TO_1PIXEL_FUNC,
+       TRACKMOUSEEVENT_1sizeof_FUNC,
+       TRIVERTEX_1sizeof_FUNC,
+       TVHITTESTINFO_1sizeof_FUNC,
+       TVINSERTSTRUCT_1sizeof_FUNC,
+       TVITEMEX_1sizeof_FUNC,
+       TVITEM_1sizeof_FUNC,
+       TVSORTCB_1sizeof_FUNC,
+       ToUnicode_FUNC,
+       TrackMouseEvent_FUNC,
+       TrackPopupMenu_FUNC,
+       TranslateAccelerator_FUNC,
+       TranslateCharsetInfo_FUNC,
+       TranslateMDISysAccel_FUNC,
+       TranslateMessage_FUNC,
+       TransparentBlt_FUNC,
+       TreeView_1GetItemRect_FUNC,
+       UDACCEL_1sizeof_FUNC,
+       UnhookWindowsHookEx_FUNC,
+       UnmapViewOfFile_FUNC,
+       UnregisterClass_FUNC,
+       UnregisterTouchWindow_FUNC,
+       UpdateWindow_FUNC,
+       UrlCreateFromPath_FUNC,
+       ValidateRect_FUNC,
+       VkKeyScan_FUNC,
+       WINDOWPLACEMENT_1sizeof_FUNC,
+       WINDOWPOS_1sizeof_FUNC,
+       WNDCLASS_1sizeof_FUNC,
+       WaitMessage_FUNC,
+       WideCharToMultiByte__II_3CIJI_3B_3Z_FUNC,
+       WideCharToMultiByte__II_3CI_3BI_3B_3Z_FUNC,
+       WindowFromDC_FUNC,
+       WindowFromPoint_FUNC,
+       wcslen_FUNC,
+} OS_FUNCS;
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_structs.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_structs.c
new file mode 100644 (file)
index 0000000..3bb1523
--- /dev/null
@@ -0,0 +1,7609 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "os_structs.h"
+
+#ifndef NO_ACCEL
+typedef struct ACCEL_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID fVirt, key, cmd;
+} ACCEL_FID_CACHE;
+
+ACCEL_FID_CACHE ACCELFc;
+
+void cacheACCELFields(JNIEnv *env, jobject lpObject)
+{
+       if (ACCELFc.cached) return;
+       ACCELFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       ACCELFc.fVirt = (*env)->GetFieldID(env, ACCELFc.clazz, "fVirt", "B");
+       ACCELFc.key = (*env)->GetFieldID(env, ACCELFc.clazz, "key", "S");
+       ACCELFc.cmd = (*env)->GetFieldID(env, ACCELFc.clazz, "cmd", "S");
+       ACCELFc.cached = 1;
+}
+
+ACCEL *getACCELFields(JNIEnv *env, jobject lpObject, ACCEL *lpStruct)
+{
+       if (!ACCELFc.cached) cacheACCELFields(env, lpObject);
+       lpStruct->fVirt = (*env)->GetByteField(env, lpObject, ACCELFc.fVirt);
+       lpStruct->key = (*env)->GetShortField(env, lpObject, ACCELFc.key);
+       lpStruct->cmd = (*env)->GetShortField(env, lpObject, ACCELFc.cmd);
+       return lpStruct;
+}
+
+void setACCELFields(JNIEnv *env, jobject lpObject, ACCEL *lpStruct)
+{
+       if (!ACCELFc.cached) cacheACCELFields(env, lpObject);
+       (*env)->SetByteField(env, lpObject, ACCELFc.fVirt, (jbyte)lpStruct->fVirt);
+       (*env)->SetShortField(env, lpObject, ACCELFc.key, (jshort)lpStruct->key);
+       (*env)->SetShortField(env, lpObject, ACCELFc.cmd, (jshort)lpStruct->cmd);
+}
+#endif
+
+#ifndef NO_ACTCTX
+typedef struct ACTCTX_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, lpSource, wProcessorArchitecture, wLangId, lpAssemblyDirectory, lpResourceName, lpApplicationName, hModule;
+} ACTCTX_FID_CACHE;
+
+ACTCTX_FID_CACHE ACTCTXFc;
+
+void cacheACTCTXFields(JNIEnv *env, jobject lpObject)
+{
+       if (ACTCTXFc.cached) return;
+       ACTCTXFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       ACTCTXFc.cbSize = (*env)->GetFieldID(env, ACTCTXFc.clazz, "cbSize", "I");
+       ACTCTXFc.dwFlags = (*env)->GetFieldID(env, ACTCTXFc.clazz, "dwFlags", "I");
+       ACTCTXFc.lpSource = (*env)->GetFieldID(env, ACTCTXFc.clazz, "lpSource", "J");
+       ACTCTXFc.wProcessorArchitecture = (*env)->GetFieldID(env, ACTCTXFc.clazz, "wProcessorArchitecture", "S");
+       ACTCTXFc.wLangId = (*env)->GetFieldID(env, ACTCTXFc.clazz, "wLangId", "S");
+       ACTCTXFc.lpAssemblyDirectory = (*env)->GetFieldID(env, ACTCTXFc.clazz, "lpAssemblyDirectory", "J");
+       ACTCTXFc.lpResourceName = (*env)->GetFieldID(env, ACTCTXFc.clazz, "lpResourceName", "J");
+       ACTCTXFc.lpApplicationName = (*env)->GetFieldID(env, ACTCTXFc.clazz, "lpApplicationName", "J");
+       ACTCTXFc.hModule = (*env)->GetFieldID(env, ACTCTXFc.clazz, "hModule", "J");
+       ACTCTXFc.cached = 1;
+}
+
+ACTCTX *getACTCTXFields(JNIEnv *env, jobject lpObject, ACTCTX *lpStruct)
+{
+       if (!ACTCTXFc.cached) cacheACTCTXFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, ACTCTXFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, ACTCTXFc.dwFlags);
+       lpStruct->lpSource = (LPCTSTR)(*env)->GetLongField(env, lpObject, ACTCTXFc.lpSource);
+       lpStruct->wProcessorArchitecture = (*env)->GetShortField(env, lpObject, ACTCTXFc.wProcessorArchitecture);
+       lpStruct->wLangId = (*env)->GetShortField(env, lpObject, ACTCTXFc.wLangId);
+       lpStruct->lpAssemblyDirectory = (LPCTSTR)(*env)->GetLongField(env, lpObject, ACTCTXFc.lpAssemblyDirectory);
+       lpStruct->lpResourceName = (LPCTSTR)(*env)->GetLongField(env, lpObject, ACTCTXFc.lpResourceName);
+       lpStruct->lpApplicationName = (LPCTSTR)(*env)->GetLongField(env, lpObject, ACTCTXFc.lpApplicationName);
+       lpStruct->hModule = (HMODULE)(*env)->GetLongField(env, lpObject, ACTCTXFc.hModule);
+       return lpStruct;
+}
+
+void setACTCTXFields(JNIEnv *env, jobject lpObject, ACTCTX *lpStruct)
+{
+       if (!ACTCTXFc.cached) cacheACTCTXFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, ACTCTXFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, ACTCTXFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetLongField(env, lpObject, ACTCTXFc.lpSource, (jlong)lpStruct->lpSource);
+       (*env)->SetShortField(env, lpObject, ACTCTXFc.wProcessorArchitecture, (jshort)lpStruct->wProcessorArchitecture);
+       (*env)->SetShortField(env, lpObject, ACTCTXFc.wLangId, (jshort)lpStruct->wLangId);
+       (*env)->SetLongField(env, lpObject, ACTCTXFc.lpAssemblyDirectory, (jlong)lpStruct->lpAssemblyDirectory);
+       (*env)->SetLongField(env, lpObject, ACTCTXFc.lpResourceName, (jlong)lpStruct->lpResourceName);
+       (*env)->SetLongField(env, lpObject, ACTCTXFc.lpApplicationName, (jlong)lpStruct->lpApplicationName);
+       (*env)->SetLongField(env, lpObject, ACTCTXFc.hModule, (jlong)lpStruct->hModule);
+}
+#endif
+
+#ifndef NO_BITMAP
+typedef struct BITMAP_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID bmType, bmWidth, bmHeight, bmWidthBytes, bmPlanes, bmBitsPixel, bmBits;
+} BITMAP_FID_CACHE;
+
+BITMAP_FID_CACHE BITMAPFc;
+
+void cacheBITMAPFields(JNIEnv *env, jobject lpObject)
+{
+       if (BITMAPFc.cached) return;
+       BITMAPFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       BITMAPFc.bmType = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmType", "I");
+       BITMAPFc.bmWidth = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmWidth", "I");
+       BITMAPFc.bmHeight = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmHeight", "I");
+       BITMAPFc.bmWidthBytes = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmWidthBytes", "I");
+       BITMAPFc.bmPlanes = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmPlanes", "S");
+       BITMAPFc.bmBitsPixel = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmBitsPixel", "S");
+       BITMAPFc.bmBits = (*env)->GetFieldID(env, BITMAPFc.clazz, "bmBits", "J");
+       BITMAPFc.cached = 1;
+}
+
+BITMAP *getBITMAPFields(JNIEnv *env, jobject lpObject, BITMAP *lpStruct)
+{
+       if (!BITMAPFc.cached) cacheBITMAPFields(env, lpObject);
+       lpStruct->bmType = (*env)->GetIntField(env, lpObject, BITMAPFc.bmType);
+       lpStruct->bmWidth = (*env)->GetIntField(env, lpObject, BITMAPFc.bmWidth);
+       lpStruct->bmHeight = (*env)->GetIntField(env, lpObject, BITMAPFc.bmHeight);
+       lpStruct->bmWidthBytes = (*env)->GetIntField(env, lpObject, BITMAPFc.bmWidthBytes);
+       lpStruct->bmPlanes = (*env)->GetShortField(env, lpObject, BITMAPFc.bmPlanes);
+       lpStruct->bmBitsPixel = (*env)->GetShortField(env, lpObject, BITMAPFc.bmBitsPixel);
+       lpStruct->bmBits = (LPVOID)(*env)->GetLongField(env, lpObject, BITMAPFc.bmBits);
+       return lpStruct;
+}
+
+void setBITMAPFields(JNIEnv *env, jobject lpObject, BITMAP *lpStruct)
+{
+       if (!BITMAPFc.cached) cacheBITMAPFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, BITMAPFc.bmType, (jint)lpStruct->bmType);
+       (*env)->SetIntField(env, lpObject, BITMAPFc.bmWidth, (jint)lpStruct->bmWidth);
+       (*env)->SetIntField(env, lpObject, BITMAPFc.bmHeight, (jint)lpStruct->bmHeight);
+       (*env)->SetIntField(env, lpObject, BITMAPFc.bmWidthBytes, (jint)lpStruct->bmWidthBytes);
+       (*env)->SetShortField(env, lpObject, BITMAPFc.bmPlanes, (jshort)lpStruct->bmPlanes);
+       (*env)->SetShortField(env, lpObject, BITMAPFc.bmBitsPixel, (jshort)lpStruct->bmBitsPixel);
+       (*env)->SetLongField(env, lpObject, BITMAPFc.bmBits, (jlong)lpStruct->bmBits);
+}
+#endif
+
+#ifndef NO_BITMAPINFOHEADER
+typedef struct BITMAPINFOHEADER_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID biSize, biWidth, biHeight, biPlanes, biBitCount, biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant;
+} BITMAPINFOHEADER_FID_CACHE;
+
+BITMAPINFOHEADER_FID_CACHE BITMAPINFOHEADERFc;
+
+void cacheBITMAPINFOHEADERFields(JNIEnv *env, jobject lpObject)
+{
+       if (BITMAPINFOHEADERFc.cached) return;
+       BITMAPINFOHEADERFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       BITMAPINFOHEADERFc.biSize = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biSize", "I");
+       BITMAPINFOHEADERFc.biWidth = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biWidth", "I");
+       BITMAPINFOHEADERFc.biHeight = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biHeight", "I");
+       BITMAPINFOHEADERFc.biPlanes = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biPlanes", "S");
+       BITMAPINFOHEADERFc.biBitCount = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biBitCount", "S");
+       BITMAPINFOHEADERFc.biCompression = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biCompression", "I");
+       BITMAPINFOHEADERFc.biSizeImage = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biSizeImage", "I");
+       BITMAPINFOHEADERFc.biXPelsPerMeter = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biXPelsPerMeter", "I");
+       BITMAPINFOHEADERFc.biYPelsPerMeter = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biYPelsPerMeter", "I");
+       BITMAPINFOHEADERFc.biClrUsed = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biClrUsed", "I");
+       BITMAPINFOHEADERFc.biClrImportant = (*env)->GetFieldID(env, BITMAPINFOHEADERFc.clazz, "biClrImportant", "I");
+       BITMAPINFOHEADERFc.cached = 1;
+}
+
+BITMAPINFOHEADER *getBITMAPINFOHEADERFields(JNIEnv *env, jobject lpObject, BITMAPINFOHEADER *lpStruct)
+{
+       if (!BITMAPINFOHEADERFc.cached) cacheBITMAPINFOHEADERFields(env, lpObject);
+       lpStruct->biSize = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biSize);
+       lpStruct->biWidth = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biWidth);
+       lpStruct->biHeight = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biHeight);
+       lpStruct->biPlanes = (*env)->GetShortField(env, lpObject, BITMAPINFOHEADERFc.biPlanes);
+       lpStruct->biBitCount = (*env)->GetShortField(env, lpObject, BITMAPINFOHEADERFc.biBitCount);
+       lpStruct->biCompression = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biCompression);
+       lpStruct->biSizeImage = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biSizeImage);
+       lpStruct->biXPelsPerMeter = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biXPelsPerMeter);
+       lpStruct->biYPelsPerMeter = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biYPelsPerMeter);
+       lpStruct->biClrUsed = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biClrUsed);
+       lpStruct->biClrImportant = (*env)->GetIntField(env, lpObject, BITMAPINFOHEADERFc.biClrImportant);
+       return lpStruct;
+}
+
+void setBITMAPINFOHEADERFields(JNIEnv *env, jobject lpObject, BITMAPINFOHEADER *lpStruct)
+{
+       if (!BITMAPINFOHEADERFc.cached) cacheBITMAPINFOHEADERFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biSize, (jint)lpStruct->biSize);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biWidth, (jint)lpStruct->biWidth);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biHeight, (jint)lpStruct->biHeight);
+       (*env)->SetShortField(env, lpObject, BITMAPINFOHEADERFc.biPlanes, (jshort)lpStruct->biPlanes);
+       (*env)->SetShortField(env, lpObject, BITMAPINFOHEADERFc.biBitCount, (jshort)lpStruct->biBitCount);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biCompression, (jint)lpStruct->biCompression);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biSizeImage, (jint)lpStruct->biSizeImage);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biXPelsPerMeter, (jint)lpStruct->biXPelsPerMeter);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biYPelsPerMeter, (jint)lpStruct->biYPelsPerMeter);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biClrUsed, (jint)lpStruct->biClrUsed);
+       (*env)->SetIntField(env, lpObject, BITMAPINFOHEADERFc.biClrImportant, (jint)lpStruct->biClrImportant);
+}
+#endif
+
+#ifndef NO_BLENDFUNCTION
+typedef struct BLENDFUNCTION_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID BlendOp, BlendFlags, SourceConstantAlpha, AlphaFormat;
+} BLENDFUNCTION_FID_CACHE;
+
+BLENDFUNCTION_FID_CACHE BLENDFUNCTIONFc;
+
+void cacheBLENDFUNCTIONFields(JNIEnv *env, jobject lpObject)
+{
+       if (BLENDFUNCTIONFc.cached) return;
+       BLENDFUNCTIONFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       BLENDFUNCTIONFc.BlendOp = (*env)->GetFieldID(env, BLENDFUNCTIONFc.clazz, "BlendOp", "B");
+       BLENDFUNCTIONFc.BlendFlags = (*env)->GetFieldID(env, BLENDFUNCTIONFc.clazz, "BlendFlags", "B");
+       BLENDFUNCTIONFc.SourceConstantAlpha = (*env)->GetFieldID(env, BLENDFUNCTIONFc.clazz, "SourceConstantAlpha", "B");
+       BLENDFUNCTIONFc.AlphaFormat = (*env)->GetFieldID(env, BLENDFUNCTIONFc.clazz, "AlphaFormat", "B");
+       BLENDFUNCTIONFc.cached = 1;
+}
+
+BLENDFUNCTION *getBLENDFUNCTIONFields(JNIEnv *env, jobject lpObject, BLENDFUNCTION *lpStruct)
+{
+       if (!BLENDFUNCTIONFc.cached) cacheBLENDFUNCTIONFields(env, lpObject);
+       lpStruct->BlendOp = (*env)->GetByteField(env, lpObject, BLENDFUNCTIONFc.BlendOp);
+       lpStruct->BlendFlags = (*env)->GetByteField(env, lpObject, BLENDFUNCTIONFc.BlendFlags);
+       lpStruct->SourceConstantAlpha = (*env)->GetByteField(env, lpObject, BLENDFUNCTIONFc.SourceConstantAlpha);
+       lpStruct->AlphaFormat = (*env)->GetByteField(env, lpObject, BLENDFUNCTIONFc.AlphaFormat);
+       return lpStruct;
+}
+
+void setBLENDFUNCTIONFields(JNIEnv *env, jobject lpObject, BLENDFUNCTION *lpStruct)
+{
+       if (!BLENDFUNCTIONFc.cached) cacheBLENDFUNCTIONFields(env, lpObject);
+       (*env)->SetByteField(env, lpObject, BLENDFUNCTIONFc.BlendOp, (jbyte)lpStruct->BlendOp);
+       (*env)->SetByteField(env, lpObject, BLENDFUNCTIONFc.BlendFlags, (jbyte)lpStruct->BlendFlags);
+       (*env)->SetByteField(env, lpObject, BLENDFUNCTIONFc.SourceConstantAlpha, (jbyte)lpStruct->SourceConstantAlpha);
+       (*env)->SetByteField(env, lpObject, BLENDFUNCTIONFc.AlphaFormat, (jbyte)lpStruct->AlphaFormat);
+}
+#endif
+
+#ifndef NO_BP_PAINTPARAMS
+typedef struct BP_PAINTPARAMS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, prcExclude, pBlendFunction;
+} BP_PAINTPARAMS_FID_CACHE;
+
+BP_PAINTPARAMS_FID_CACHE BP_PAINTPARAMSFc;
+
+void cacheBP_PAINTPARAMSFields(JNIEnv *env, jobject lpObject)
+{
+       if (BP_PAINTPARAMSFc.cached) return;
+       BP_PAINTPARAMSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       BP_PAINTPARAMSFc.cbSize = (*env)->GetFieldID(env, BP_PAINTPARAMSFc.clazz, "cbSize", "I");
+       BP_PAINTPARAMSFc.dwFlags = (*env)->GetFieldID(env, BP_PAINTPARAMSFc.clazz, "dwFlags", "I");
+       BP_PAINTPARAMSFc.prcExclude = (*env)->GetFieldID(env, BP_PAINTPARAMSFc.clazz, "prcExclude", "J");
+       BP_PAINTPARAMSFc.pBlendFunction = (*env)->GetFieldID(env, BP_PAINTPARAMSFc.clazz, "pBlendFunction", "J");
+       BP_PAINTPARAMSFc.cached = 1;
+}
+
+BP_PAINTPARAMS *getBP_PAINTPARAMSFields(JNIEnv *env, jobject lpObject, BP_PAINTPARAMS *lpStruct)
+{
+       if (!BP_PAINTPARAMSFc.cached) cacheBP_PAINTPARAMSFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, BP_PAINTPARAMSFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, BP_PAINTPARAMSFc.dwFlags);
+       lpStruct->prcExclude = (RECT*)(*env)->GetLongField(env, lpObject, BP_PAINTPARAMSFc.prcExclude);
+       lpStruct->pBlendFunction = (BLENDFUNCTION*)(*env)->GetLongField(env, lpObject, BP_PAINTPARAMSFc.pBlendFunction);
+       return lpStruct;
+}
+
+void setBP_PAINTPARAMSFields(JNIEnv *env, jobject lpObject, BP_PAINTPARAMS *lpStruct)
+{
+       if (!BP_PAINTPARAMSFc.cached) cacheBP_PAINTPARAMSFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, BP_PAINTPARAMSFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, BP_PAINTPARAMSFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetLongField(env, lpObject, BP_PAINTPARAMSFc.prcExclude, (jlong)lpStruct->prcExclude);
+       (*env)->SetLongField(env, lpObject, BP_PAINTPARAMSFc.pBlendFunction, (jlong)lpStruct->pBlendFunction);
+}
+#endif
+
+#ifndef NO_BROWSEINFO
+typedef struct BROWSEINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hwndOwner, pidlRoot, pszDisplayName, lpszTitle, ulFlags, lpfn, lParam, iImage;
+} BROWSEINFO_FID_CACHE;
+
+BROWSEINFO_FID_CACHE BROWSEINFOFc;
+
+void cacheBROWSEINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (BROWSEINFOFc.cached) return;
+       BROWSEINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       BROWSEINFOFc.hwndOwner = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "hwndOwner", "J");
+       BROWSEINFOFc.pidlRoot = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "pidlRoot", "J");
+       BROWSEINFOFc.pszDisplayName = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "pszDisplayName", "J");
+       BROWSEINFOFc.lpszTitle = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "lpszTitle", "J");
+       BROWSEINFOFc.ulFlags = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "ulFlags", "I");
+       BROWSEINFOFc.lpfn = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "lpfn", "J");
+       BROWSEINFOFc.lParam = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "lParam", "J");
+       BROWSEINFOFc.iImage = (*env)->GetFieldID(env, BROWSEINFOFc.clazz, "iImage", "I");
+       BROWSEINFOFc.cached = 1;
+}
+
+BROWSEINFO *getBROWSEINFOFields(JNIEnv *env, jobject lpObject, BROWSEINFO *lpStruct)
+{
+       if (!BROWSEINFOFc.cached) cacheBROWSEINFOFields(env, lpObject);
+       lpStruct->hwndOwner = (HWND)(*env)->GetLongField(env, lpObject, BROWSEINFOFc.hwndOwner);
+       lpStruct->pidlRoot = (LPCITEMIDLIST)(*env)->GetLongField(env, lpObject, BROWSEINFOFc.pidlRoot);
+       lpStruct->pszDisplayName = (LPTSTR)(*env)->GetLongField(env, lpObject, BROWSEINFOFc.pszDisplayName);
+       lpStruct->lpszTitle = (LPCTSTR)(*env)->GetLongField(env, lpObject, BROWSEINFOFc.lpszTitle);
+       lpStruct->ulFlags = (*env)->GetIntField(env, lpObject, BROWSEINFOFc.ulFlags);
+       lpStruct->lpfn = (BFFCALLBACK)(*env)->GetLongField(env, lpObject, BROWSEINFOFc.lpfn);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, BROWSEINFOFc.lParam);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, BROWSEINFOFc.iImage);
+       return lpStruct;
+}
+
+void setBROWSEINFOFields(JNIEnv *env, jobject lpObject, BROWSEINFO *lpStruct)
+{
+       if (!BROWSEINFOFc.cached) cacheBROWSEINFOFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, BROWSEINFOFc.hwndOwner, (jlong)lpStruct->hwndOwner);
+       (*env)->SetLongField(env, lpObject, BROWSEINFOFc.pidlRoot, (jlong)lpStruct->pidlRoot);
+       (*env)->SetLongField(env, lpObject, BROWSEINFOFc.pszDisplayName, (jlong)lpStruct->pszDisplayName);
+       (*env)->SetLongField(env, lpObject, BROWSEINFOFc.lpszTitle, (jlong)lpStruct->lpszTitle);
+       (*env)->SetIntField(env, lpObject, BROWSEINFOFc.ulFlags, (jint)lpStruct->ulFlags);
+       (*env)->SetLongField(env, lpObject, BROWSEINFOFc.lpfn, (jlong)lpStruct->lpfn);
+       (*env)->SetLongField(env, lpObject, BROWSEINFOFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetIntField(env, lpObject, BROWSEINFOFc.iImage, (jint)lpStruct->iImage);
+}
+#endif
+
+#ifndef NO_BUTTON_IMAGELIST
+typedef struct BUTTON_IMAGELIST_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID himl, margin_left, margin_top, margin_right, margin_bottom, uAlign;
+} BUTTON_IMAGELIST_FID_CACHE;
+
+BUTTON_IMAGELIST_FID_CACHE BUTTON_IMAGELISTFc;
+
+void cacheBUTTON_IMAGELISTFields(JNIEnv *env, jobject lpObject)
+{
+       if (BUTTON_IMAGELISTFc.cached) return;
+       BUTTON_IMAGELISTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       BUTTON_IMAGELISTFc.himl = (*env)->GetFieldID(env, BUTTON_IMAGELISTFc.clazz, "himl", "J");
+       BUTTON_IMAGELISTFc.margin_left = (*env)->GetFieldID(env, BUTTON_IMAGELISTFc.clazz, "margin_left", "I");
+       BUTTON_IMAGELISTFc.margin_top = (*env)->GetFieldID(env, BUTTON_IMAGELISTFc.clazz, "margin_top", "I");
+       BUTTON_IMAGELISTFc.margin_right = (*env)->GetFieldID(env, BUTTON_IMAGELISTFc.clazz, "margin_right", "I");
+       BUTTON_IMAGELISTFc.margin_bottom = (*env)->GetFieldID(env, BUTTON_IMAGELISTFc.clazz, "margin_bottom", "I");
+       BUTTON_IMAGELISTFc.uAlign = (*env)->GetFieldID(env, BUTTON_IMAGELISTFc.clazz, "uAlign", "I");
+       BUTTON_IMAGELISTFc.cached = 1;
+}
+
+BUTTON_IMAGELIST *getBUTTON_IMAGELISTFields(JNIEnv *env, jobject lpObject, BUTTON_IMAGELIST *lpStruct)
+{
+       if (!BUTTON_IMAGELISTFc.cached) cacheBUTTON_IMAGELISTFields(env, lpObject);
+       lpStruct->himl = (HIMAGELIST)(*env)->GetLongField(env, lpObject, BUTTON_IMAGELISTFc.himl);
+       lpStruct->margin.left = (LONG)(*env)->GetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_left);
+       lpStruct->margin.top = (LONG)(*env)->GetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_top);
+       lpStruct->margin.right = (LONG)(*env)->GetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_right);
+       lpStruct->margin.bottom = (LONG)(*env)->GetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_bottom);
+       lpStruct->uAlign = (UINT)(*env)->GetIntField(env, lpObject, BUTTON_IMAGELISTFc.uAlign);
+       return lpStruct;
+}
+
+void setBUTTON_IMAGELISTFields(JNIEnv *env, jobject lpObject, BUTTON_IMAGELIST *lpStruct)
+{
+       if (!BUTTON_IMAGELISTFc.cached) cacheBUTTON_IMAGELISTFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, BUTTON_IMAGELISTFc.himl, (jlong)lpStruct->himl);
+       (*env)->SetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_left, (jint)lpStruct->margin.left);
+       (*env)->SetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_top, (jint)lpStruct->margin.top);
+       (*env)->SetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_right, (jint)lpStruct->margin.right);
+       (*env)->SetIntField(env, lpObject, BUTTON_IMAGELISTFc.margin_bottom, (jint)lpStruct->margin.bottom);
+       (*env)->SetIntField(env, lpObject, BUTTON_IMAGELISTFc.uAlign, (jint)lpStruct->uAlign);
+}
+#endif
+
+#ifndef NO_CANDIDATEFORM
+typedef struct CANDIDATEFORM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwIndex, dwStyle, ptCurrentPos, rcArea;
+} CANDIDATEFORM_FID_CACHE;
+
+CANDIDATEFORM_FID_CACHE CANDIDATEFORMFc;
+
+void cacheCANDIDATEFORMFields(JNIEnv *env, jobject lpObject)
+{
+       if (CANDIDATEFORMFc.cached) return;
+       CANDIDATEFORMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CANDIDATEFORMFc.dwIndex = (*env)->GetFieldID(env, CANDIDATEFORMFc.clazz, "dwIndex", "I");
+       CANDIDATEFORMFc.dwStyle = (*env)->GetFieldID(env, CANDIDATEFORMFc.clazz, "dwStyle", "I");
+       CANDIDATEFORMFc.ptCurrentPos = (*env)->GetFieldID(env, CANDIDATEFORMFc.clazz, "ptCurrentPos", "Lorg/eclipse/swt/internal/win32/POINT;");
+       CANDIDATEFORMFc.rcArea = (*env)->GetFieldID(env, CANDIDATEFORMFc.clazz, "rcArea", "Lorg/eclipse/swt/internal/win32/RECT;");
+       CANDIDATEFORMFc.cached = 1;
+}
+
+CANDIDATEFORM *getCANDIDATEFORMFields(JNIEnv *env, jobject lpObject, CANDIDATEFORM *lpStruct)
+{
+       if (!CANDIDATEFORMFc.cached) cacheCANDIDATEFORMFields(env, lpObject);
+       lpStruct->dwIndex = (*env)->GetIntField(env, lpObject, CANDIDATEFORMFc.dwIndex);
+       lpStruct->dwStyle = (*env)->GetIntField(env, lpObject, CANDIDATEFORMFc.dwStyle);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CANDIDATEFORMFc.ptCurrentPos);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->ptCurrentPos);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CANDIDATEFORMFc.rcArea);
+       if (lpObject1 != NULL) getRECTFields(env, lpObject1, &lpStruct->rcArea);
+       }
+       return lpStruct;
+}
+
+void setCANDIDATEFORMFields(JNIEnv *env, jobject lpObject, CANDIDATEFORM *lpStruct)
+{
+       if (!CANDIDATEFORMFc.cached) cacheCANDIDATEFORMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CANDIDATEFORMFc.dwIndex, (jint)lpStruct->dwIndex);
+       (*env)->SetIntField(env, lpObject, CANDIDATEFORMFc.dwStyle, (jint)lpStruct->dwStyle);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CANDIDATEFORMFc.ptCurrentPos);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->ptCurrentPos);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CANDIDATEFORMFc.rcArea);
+       if (lpObject1 != NULL) setRECTFields(env, lpObject1, &lpStruct->rcArea);
+       }
+}
+#endif
+
+#ifndef NO_CERT_CONTEXT
+typedef struct CERT_CONTEXT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwCertEncodingType, pbCertEncoded, cbCertEncoded, pCertInfo, hCertStore;
+} CERT_CONTEXT_FID_CACHE;
+
+CERT_CONTEXT_FID_CACHE CERT_CONTEXTFc;
+
+void cacheCERT_CONTEXTFields(JNIEnv *env, jobject lpObject)
+{
+       if (CERT_CONTEXTFc.cached) return;
+       CERT_CONTEXTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CERT_CONTEXTFc.dwCertEncodingType = (*env)->GetFieldID(env, CERT_CONTEXTFc.clazz, "dwCertEncodingType", "I");
+       CERT_CONTEXTFc.pbCertEncoded = (*env)->GetFieldID(env, CERT_CONTEXTFc.clazz, "pbCertEncoded", "J");
+       CERT_CONTEXTFc.cbCertEncoded = (*env)->GetFieldID(env, CERT_CONTEXTFc.clazz, "cbCertEncoded", "I");
+       CERT_CONTEXTFc.pCertInfo = (*env)->GetFieldID(env, CERT_CONTEXTFc.clazz, "pCertInfo", "J");
+       CERT_CONTEXTFc.hCertStore = (*env)->GetFieldID(env, CERT_CONTEXTFc.clazz, "hCertStore", "J");
+       CERT_CONTEXTFc.cached = 1;
+}
+
+CERT_CONTEXT *getCERT_CONTEXTFields(JNIEnv *env, jobject lpObject, CERT_CONTEXT *lpStruct)
+{
+       if (!CERT_CONTEXTFc.cached) cacheCERT_CONTEXTFields(env, lpObject);
+       lpStruct->dwCertEncodingType = (*env)->GetIntField(env, lpObject, CERT_CONTEXTFc.dwCertEncodingType);
+       lpStruct->pbCertEncoded = (BYTE *)(*env)->GetLongField(env, lpObject, CERT_CONTEXTFc.pbCertEncoded);
+       lpStruct->cbCertEncoded = (*env)->GetIntField(env, lpObject, CERT_CONTEXTFc.cbCertEncoded);
+       lpStruct->pCertInfo = (PCERT_INFO)(*env)->GetLongField(env, lpObject, CERT_CONTEXTFc.pCertInfo);
+       lpStruct->hCertStore = (HCERTSTORE)(*env)->GetLongField(env, lpObject, CERT_CONTEXTFc.hCertStore);
+       return lpStruct;
+}
+
+void setCERT_CONTEXTFields(JNIEnv *env, jobject lpObject, CERT_CONTEXT *lpStruct)
+{
+       if (!CERT_CONTEXTFc.cached) cacheCERT_CONTEXTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CERT_CONTEXTFc.dwCertEncodingType, (jint)lpStruct->dwCertEncodingType);
+       (*env)->SetLongField(env, lpObject, CERT_CONTEXTFc.pbCertEncoded, (jlong)lpStruct->pbCertEncoded);
+       (*env)->SetIntField(env, lpObject, CERT_CONTEXTFc.cbCertEncoded, (jint)lpStruct->cbCertEncoded);
+       (*env)->SetLongField(env, lpObject, CERT_CONTEXTFc.pCertInfo, (jlong)lpStruct->pCertInfo);
+       (*env)->SetLongField(env, lpObject, CERT_CONTEXTFc.hCertStore, (jlong)lpStruct->hCertStore);
+}
+#endif
+
+#ifndef NO_CERT_INFO
+typedef struct CERT_INFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwVersion, SerialNumber, SignatureAlgorithm, Issuer, NotBefore, NotAfter, Subject, SubjectPublicKeyInfo, IssuerUniqueId, SubjectUniqueId, cExtension, rgExtension;
+} CERT_INFO_FID_CACHE;
+
+CERT_INFO_FID_CACHE CERT_INFOFc;
+
+void cacheCERT_INFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (CERT_INFOFc.cached) return;
+       CERT_INFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CERT_INFOFc.dwVersion = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "dwVersion", "I");
+       CERT_INFOFc.SerialNumber = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "SerialNumber", "Lorg/eclipse/swt/internal/win32/CRYPT_INTEGER_BLOB;");
+       CERT_INFOFc.SignatureAlgorithm = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "SignatureAlgorithm", "Lorg/eclipse/swt/internal/win32/CRYPT_ALGORITHM_IDENTIFIER;");
+       CERT_INFOFc.Issuer = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "Issuer", "Lorg/eclipse/swt/internal/win32/CERT_NAME_BLOB;");
+       CERT_INFOFc.NotBefore = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "NotBefore", "Lorg/eclipse/swt/internal/win32/FILETIME;");
+       CERT_INFOFc.NotAfter = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "NotAfter", "Lorg/eclipse/swt/internal/win32/FILETIME;");
+       CERT_INFOFc.Subject = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "Subject", "Lorg/eclipse/swt/internal/win32/CERT_NAME_BLOB;");
+       CERT_INFOFc.SubjectPublicKeyInfo = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "SubjectPublicKeyInfo", "Lorg/eclipse/swt/internal/win32/CERT_PUBLIC_KEY_INFO;");
+       CERT_INFOFc.IssuerUniqueId = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "IssuerUniqueId", "Lorg/eclipse/swt/internal/win32/CRYPT_BIT_BLOB;");
+       CERT_INFOFc.SubjectUniqueId = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "SubjectUniqueId", "Lorg/eclipse/swt/internal/win32/CRYPT_BIT_BLOB;");
+       CERT_INFOFc.cExtension = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "cExtension", "I");
+       CERT_INFOFc.rgExtension = (*env)->GetFieldID(env, CERT_INFOFc.clazz, "rgExtension", "J");
+       CERT_INFOFc.cached = 1;
+}
+
+CERT_INFO *getCERT_INFOFields(JNIEnv *env, jobject lpObject, CERT_INFO *lpStruct)
+{
+       if (!CERT_INFOFc.cached) cacheCERT_INFOFields(env, lpObject);
+       lpStruct->dwVersion = (*env)->GetIntField(env, lpObject, CERT_INFOFc.dwVersion);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SerialNumber);
+       if (lpObject1 != NULL) getCRYPT_INTEGER_BLOBFields(env, lpObject1, &lpStruct->SerialNumber);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SignatureAlgorithm);
+       if (lpObject1 != NULL) getCRYPT_ALGORITHM_IDENTIFIERFields(env, lpObject1, &lpStruct->SignatureAlgorithm);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.Issuer);
+       if (lpObject1 != NULL) getCERT_NAME_BLOBFields(env, lpObject1, &lpStruct->Issuer);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.NotBefore);
+       if (lpObject1 != NULL) getFILETIMEFields(env, lpObject1, &lpStruct->NotBefore);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.NotAfter);
+       if (lpObject1 != NULL) getFILETIMEFields(env, lpObject1, &lpStruct->NotAfter);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.Subject);
+       if (lpObject1 != NULL) getCERT_NAME_BLOBFields(env, lpObject1, &lpStruct->Subject);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SubjectPublicKeyInfo);
+       if (lpObject1 != NULL) getCERT_PUBLIC_KEY_INFOFields(env, lpObject1, &lpStruct->SubjectPublicKeyInfo);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.IssuerUniqueId);
+       if (lpObject1 != NULL) getCRYPT_BIT_BLOBFields(env, lpObject1, &lpStruct->IssuerUniqueId);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SubjectUniqueId);
+       if (lpObject1 != NULL) getCRYPT_BIT_BLOBFields(env, lpObject1, &lpStruct->SubjectUniqueId);
+       }
+       lpStruct->cExtension = (*env)->GetIntField(env, lpObject, CERT_INFOFc.cExtension);
+       lpStruct->rgExtension = (PCERT_EXTENSION)(*env)->GetLongField(env, lpObject, CERT_INFOFc.rgExtension);
+       return lpStruct;
+}
+
+void setCERT_INFOFields(JNIEnv *env, jobject lpObject, CERT_INFO *lpStruct)
+{
+       if (!CERT_INFOFc.cached) cacheCERT_INFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CERT_INFOFc.dwVersion, (jint)lpStruct->dwVersion);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SerialNumber);
+       if (lpObject1 != NULL) setCRYPT_INTEGER_BLOBFields(env, lpObject1, &lpStruct->SerialNumber);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SignatureAlgorithm);
+       if (lpObject1 != NULL) setCRYPT_ALGORITHM_IDENTIFIERFields(env, lpObject1, &lpStruct->SignatureAlgorithm);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.Issuer);
+       if (lpObject1 != NULL) setCERT_NAME_BLOBFields(env, lpObject1, &lpStruct->Issuer);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.NotBefore);
+       if (lpObject1 != NULL) setFILETIMEFields(env, lpObject1, &lpStruct->NotBefore);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.NotAfter);
+       if (lpObject1 != NULL) setFILETIMEFields(env, lpObject1, &lpStruct->NotAfter);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.Subject);
+       if (lpObject1 != NULL) setCERT_NAME_BLOBFields(env, lpObject1, &lpStruct->Subject);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SubjectPublicKeyInfo);
+       if (lpObject1 != NULL) setCERT_PUBLIC_KEY_INFOFields(env, lpObject1, &lpStruct->SubjectPublicKeyInfo);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.IssuerUniqueId);
+       if (lpObject1 != NULL) setCRYPT_BIT_BLOBFields(env, lpObject1, &lpStruct->IssuerUniqueId);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_INFOFc.SubjectUniqueId);
+       if (lpObject1 != NULL) setCRYPT_BIT_BLOBFields(env, lpObject1, &lpStruct->SubjectUniqueId);
+       }
+       (*env)->SetIntField(env, lpObject, CERT_INFOFc.cExtension, (jint)lpStruct->cExtension);
+       (*env)->SetLongField(env, lpObject, CERT_INFOFc.rgExtension, (jlong)lpStruct->rgExtension);
+}
+#endif
+
+#ifndef NO_CERT_NAME_BLOB
+typedef struct CERT_NAME_BLOB_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbData, pbData;
+} CERT_NAME_BLOB_FID_CACHE;
+
+CERT_NAME_BLOB_FID_CACHE CERT_NAME_BLOBFc;
+
+void cacheCERT_NAME_BLOBFields(JNIEnv *env, jobject lpObject)
+{
+       if (CERT_NAME_BLOBFc.cached) return;
+       CERT_NAME_BLOBFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CERT_NAME_BLOBFc.cbData = (*env)->GetFieldID(env, CERT_NAME_BLOBFc.clazz, "cbData", "I");
+       CERT_NAME_BLOBFc.pbData = (*env)->GetFieldID(env, CERT_NAME_BLOBFc.clazz, "pbData", "J");
+       CERT_NAME_BLOBFc.cached = 1;
+}
+
+CERT_NAME_BLOB *getCERT_NAME_BLOBFields(JNIEnv *env, jobject lpObject, CERT_NAME_BLOB *lpStruct)
+{
+       if (!CERT_NAME_BLOBFc.cached) cacheCERT_NAME_BLOBFields(env, lpObject);
+       lpStruct->cbData = (*env)->GetIntField(env, lpObject, CERT_NAME_BLOBFc.cbData);
+       lpStruct->pbData = (BYTE *)(*env)->GetLongField(env, lpObject, CERT_NAME_BLOBFc.pbData);
+       return lpStruct;
+}
+
+void setCERT_NAME_BLOBFields(JNIEnv *env, jobject lpObject, CERT_NAME_BLOB *lpStruct)
+{
+       if (!CERT_NAME_BLOBFc.cached) cacheCERT_NAME_BLOBFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CERT_NAME_BLOBFc.cbData, (jint)lpStruct->cbData);
+       (*env)->SetLongField(env, lpObject, CERT_NAME_BLOBFc.pbData, (jlong)lpStruct->pbData);
+}
+#endif
+
+#ifndef NO_CERT_PUBLIC_KEY_INFO
+typedef struct CERT_PUBLIC_KEY_INFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID Algorithm, PublicKey;
+} CERT_PUBLIC_KEY_INFO_FID_CACHE;
+
+CERT_PUBLIC_KEY_INFO_FID_CACHE CERT_PUBLIC_KEY_INFOFc;
+
+void cacheCERT_PUBLIC_KEY_INFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (CERT_PUBLIC_KEY_INFOFc.cached) return;
+       CERT_PUBLIC_KEY_INFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CERT_PUBLIC_KEY_INFOFc.Algorithm = (*env)->GetFieldID(env, CERT_PUBLIC_KEY_INFOFc.clazz, "Algorithm", "Lorg/eclipse/swt/internal/win32/CRYPT_ALGORITHM_IDENTIFIER;");
+       CERT_PUBLIC_KEY_INFOFc.PublicKey = (*env)->GetFieldID(env, CERT_PUBLIC_KEY_INFOFc.clazz, "PublicKey", "Lorg/eclipse/swt/internal/win32/CRYPT_BIT_BLOB;");
+       CERT_PUBLIC_KEY_INFOFc.cached = 1;
+}
+
+CERT_PUBLIC_KEY_INFO *getCERT_PUBLIC_KEY_INFOFields(JNIEnv *env, jobject lpObject, CERT_PUBLIC_KEY_INFO *lpStruct)
+{
+       if (!CERT_PUBLIC_KEY_INFOFc.cached) cacheCERT_PUBLIC_KEY_INFOFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_PUBLIC_KEY_INFOFc.Algorithm);
+       if (lpObject1 != NULL) getCRYPT_ALGORITHM_IDENTIFIERFields(env, lpObject1, &lpStruct->Algorithm);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_PUBLIC_KEY_INFOFc.PublicKey);
+       if (lpObject1 != NULL) getCRYPT_BIT_BLOBFields(env, lpObject1, &lpStruct->PublicKey);
+       }
+       return lpStruct;
+}
+
+void setCERT_PUBLIC_KEY_INFOFields(JNIEnv *env, jobject lpObject, CERT_PUBLIC_KEY_INFO *lpStruct)
+{
+       if (!CERT_PUBLIC_KEY_INFOFc.cached) cacheCERT_PUBLIC_KEY_INFOFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_PUBLIC_KEY_INFOFc.Algorithm);
+       if (lpObject1 != NULL) setCRYPT_ALGORITHM_IDENTIFIERFields(env, lpObject1, &lpStruct->Algorithm);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CERT_PUBLIC_KEY_INFOFc.PublicKey);
+       if (lpObject1 != NULL) setCRYPT_BIT_BLOBFields(env, lpObject1, &lpStruct->PublicKey);
+       }
+}
+#endif
+
+#ifndef NO_CHOOSECOLOR
+typedef struct CHOOSECOLOR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lStructSize, hwndOwner, hInstance, rgbResult, lpCustColors, Flags, lCustData, lpfnHook, lpTemplateName;
+} CHOOSECOLOR_FID_CACHE;
+
+CHOOSECOLOR_FID_CACHE CHOOSECOLORFc;
+
+void cacheCHOOSECOLORFields(JNIEnv *env, jobject lpObject)
+{
+       if (CHOOSECOLORFc.cached) return;
+       CHOOSECOLORFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CHOOSECOLORFc.lStructSize = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "lStructSize", "I");
+       CHOOSECOLORFc.hwndOwner = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "hwndOwner", "J");
+       CHOOSECOLORFc.hInstance = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "hInstance", "J");
+       CHOOSECOLORFc.rgbResult = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "rgbResult", "I");
+       CHOOSECOLORFc.lpCustColors = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "lpCustColors", "J");
+       CHOOSECOLORFc.Flags = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "Flags", "I");
+       CHOOSECOLORFc.lCustData = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "lCustData", "J");
+       CHOOSECOLORFc.lpfnHook = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "lpfnHook", "J");
+       CHOOSECOLORFc.lpTemplateName = (*env)->GetFieldID(env, CHOOSECOLORFc.clazz, "lpTemplateName", "J");
+       CHOOSECOLORFc.cached = 1;
+}
+
+CHOOSECOLOR *getCHOOSECOLORFields(JNIEnv *env, jobject lpObject, CHOOSECOLOR *lpStruct)
+{
+       if (!CHOOSECOLORFc.cached) cacheCHOOSECOLORFields(env, lpObject);
+       lpStruct->lStructSize = (*env)->GetIntField(env, lpObject, CHOOSECOLORFc.lStructSize);
+       lpStruct->hwndOwner = (HWND)(*env)->GetLongField(env, lpObject, CHOOSECOLORFc.hwndOwner);
+       lpStruct->hInstance = (HANDLE)(*env)->GetLongField(env, lpObject, CHOOSECOLORFc.hInstance);
+       lpStruct->rgbResult = (*env)->GetIntField(env, lpObject, CHOOSECOLORFc.rgbResult);
+       lpStruct->lpCustColors = (COLORREF *)(*env)->GetLongField(env, lpObject, CHOOSECOLORFc.lpCustColors);
+       lpStruct->Flags = (*env)->GetIntField(env, lpObject, CHOOSECOLORFc.Flags);
+       lpStruct->lCustData = (*env)->GetLongField(env, lpObject, CHOOSECOLORFc.lCustData);
+       lpStruct->lpfnHook = (LPCCHOOKPROC)(*env)->GetLongField(env, lpObject, CHOOSECOLORFc.lpfnHook);
+       lpStruct->lpTemplateName = (LPCTSTR)(*env)->GetLongField(env, lpObject, CHOOSECOLORFc.lpTemplateName);
+       return lpStruct;
+}
+
+void setCHOOSECOLORFields(JNIEnv *env, jobject lpObject, CHOOSECOLOR *lpStruct)
+{
+       if (!CHOOSECOLORFc.cached) cacheCHOOSECOLORFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CHOOSECOLORFc.lStructSize, (jint)lpStruct->lStructSize);
+       (*env)->SetLongField(env, lpObject, CHOOSECOLORFc.hwndOwner, (jlong)lpStruct->hwndOwner);
+       (*env)->SetLongField(env, lpObject, CHOOSECOLORFc.hInstance, (jlong)lpStruct->hInstance);
+       (*env)->SetIntField(env, lpObject, CHOOSECOLORFc.rgbResult, (jint)lpStruct->rgbResult);
+       (*env)->SetLongField(env, lpObject, CHOOSECOLORFc.lpCustColors, (jlong)lpStruct->lpCustColors);
+       (*env)->SetIntField(env, lpObject, CHOOSECOLORFc.Flags, (jint)lpStruct->Flags);
+       (*env)->SetLongField(env, lpObject, CHOOSECOLORFc.lCustData, (jlong)lpStruct->lCustData);
+       (*env)->SetLongField(env, lpObject, CHOOSECOLORFc.lpfnHook, (jlong)lpStruct->lpfnHook);
+       (*env)->SetLongField(env, lpObject, CHOOSECOLORFc.lpTemplateName, (jlong)lpStruct->lpTemplateName);
+}
+#endif
+
+#ifndef NO_CHOOSEFONT
+typedef struct CHOOSEFONT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lStructSize, hwndOwner, hDC, lpLogFont, iPointSize, Flags, rgbColors, lCustData, lpfnHook, lpTemplateName, hInstance, lpszStyle, nFontType, nSizeMin, nSizeMax;
+} CHOOSEFONT_FID_CACHE;
+
+CHOOSEFONT_FID_CACHE CHOOSEFONTFc;
+
+void cacheCHOOSEFONTFields(JNIEnv *env, jobject lpObject)
+{
+       if (CHOOSEFONTFc.cached) return;
+       CHOOSEFONTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CHOOSEFONTFc.lStructSize = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "lStructSize", "I");
+       CHOOSEFONTFc.hwndOwner = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "hwndOwner", "J");
+       CHOOSEFONTFc.hDC = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "hDC", "J");
+       CHOOSEFONTFc.lpLogFont = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "lpLogFont", "J");
+       CHOOSEFONTFc.iPointSize = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "iPointSize", "I");
+       CHOOSEFONTFc.Flags = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "Flags", "I");
+       CHOOSEFONTFc.rgbColors = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "rgbColors", "I");
+       CHOOSEFONTFc.lCustData = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "lCustData", "J");
+       CHOOSEFONTFc.lpfnHook = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "lpfnHook", "J");
+       CHOOSEFONTFc.lpTemplateName = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "lpTemplateName", "J");
+       CHOOSEFONTFc.hInstance = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "hInstance", "J");
+       CHOOSEFONTFc.lpszStyle = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "lpszStyle", "J");
+       CHOOSEFONTFc.nFontType = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "nFontType", "S");
+       CHOOSEFONTFc.nSizeMin = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "nSizeMin", "I");
+       CHOOSEFONTFc.nSizeMax = (*env)->GetFieldID(env, CHOOSEFONTFc.clazz, "nSizeMax", "I");
+       CHOOSEFONTFc.cached = 1;
+}
+
+CHOOSEFONT *getCHOOSEFONTFields(JNIEnv *env, jobject lpObject, CHOOSEFONT *lpStruct)
+{
+       if (!CHOOSEFONTFc.cached) cacheCHOOSEFONTFields(env, lpObject);
+       lpStruct->lStructSize = (*env)->GetIntField(env, lpObject, CHOOSEFONTFc.lStructSize);
+       lpStruct->hwndOwner = (HWND)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.hwndOwner);
+       lpStruct->hDC = (HDC)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.hDC);
+       lpStruct->lpLogFont = (LPLOGFONT)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.lpLogFont);
+       lpStruct->iPointSize = (*env)->GetIntField(env, lpObject, CHOOSEFONTFc.iPointSize);
+       lpStruct->Flags = (*env)->GetIntField(env, lpObject, CHOOSEFONTFc.Flags);
+       lpStruct->rgbColors = (*env)->GetIntField(env, lpObject, CHOOSEFONTFc.rgbColors);
+       lpStruct->lCustData = (*env)->GetLongField(env, lpObject, CHOOSEFONTFc.lCustData);
+       lpStruct->lpfnHook = (LPCFHOOKPROC)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.lpfnHook);
+       lpStruct->lpTemplateName = (LPCTSTR)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.lpTemplateName);
+       lpStruct->hInstance = (HINSTANCE)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.hInstance);
+       lpStruct->lpszStyle = (LPTSTR)(*env)->GetLongField(env, lpObject, CHOOSEFONTFc.lpszStyle);
+       lpStruct->nFontType = (*env)->GetShortField(env, lpObject, CHOOSEFONTFc.nFontType);
+       lpStruct->nSizeMin = (*env)->GetIntField(env, lpObject, CHOOSEFONTFc.nSizeMin);
+       lpStruct->nSizeMax = (*env)->GetIntField(env, lpObject, CHOOSEFONTFc.nSizeMax);
+       return lpStruct;
+}
+
+void setCHOOSEFONTFields(JNIEnv *env, jobject lpObject, CHOOSEFONT *lpStruct)
+{
+       if (!CHOOSEFONTFc.cached) cacheCHOOSEFONTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CHOOSEFONTFc.lStructSize, (jint)lpStruct->lStructSize);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.hwndOwner, (jlong)lpStruct->hwndOwner);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.hDC, (jlong)lpStruct->hDC);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.lpLogFont, (jlong)lpStruct->lpLogFont);
+       (*env)->SetIntField(env, lpObject, CHOOSEFONTFc.iPointSize, (jint)lpStruct->iPointSize);
+       (*env)->SetIntField(env, lpObject, CHOOSEFONTFc.Flags, (jint)lpStruct->Flags);
+       (*env)->SetIntField(env, lpObject, CHOOSEFONTFc.rgbColors, (jint)lpStruct->rgbColors);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.lCustData, (jlong)lpStruct->lCustData);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.lpfnHook, (jlong)lpStruct->lpfnHook);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.lpTemplateName, (jlong)lpStruct->lpTemplateName);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.hInstance, (jlong)lpStruct->hInstance);
+       (*env)->SetLongField(env, lpObject, CHOOSEFONTFc.lpszStyle, (jlong)lpStruct->lpszStyle);
+       (*env)->SetShortField(env, lpObject, CHOOSEFONTFc.nFontType, (jshort)lpStruct->nFontType);
+       (*env)->SetIntField(env, lpObject, CHOOSEFONTFc.nSizeMin, (jint)lpStruct->nSizeMin);
+       (*env)->SetIntField(env, lpObject, CHOOSEFONTFc.nSizeMax, (jint)lpStruct->nSizeMax);
+}
+#endif
+
+#ifndef NO_CIDA
+typedef struct CIDA_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cidl, aoffset;
+} CIDA_FID_CACHE;
+
+CIDA_FID_CACHE CIDAFc;
+
+void cacheCIDAFields(JNIEnv *env, jobject lpObject)
+{
+       if (CIDAFc.cached) return;
+       CIDAFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CIDAFc.cidl = (*env)->GetFieldID(env, CIDAFc.clazz, "cidl", "I");
+       CIDAFc.aoffset = (*env)->GetFieldID(env, CIDAFc.clazz, "aoffset", "I");
+       CIDAFc.cached = 1;
+}
+
+CIDA *getCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct)
+{
+       if (!CIDAFc.cached) cacheCIDAFields(env, lpObject);
+       lpStruct->cidl = (*env)->GetIntField(env, lpObject, CIDAFc.cidl);
+       lpStruct->aoffset[0] = (*env)->GetIntField(env, lpObject, CIDAFc.aoffset);
+       return lpStruct;
+}
+
+void setCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct)
+{
+       if (!CIDAFc.cached) cacheCIDAFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CIDAFc.cidl, (jint)lpStruct->cidl);
+       (*env)->SetIntField(env, lpObject, CIDAFc.aoffset, (jint)lpStruct->aoffset[0]);
+}
+#endif
+
+#ifndef NO_COMBOBOXINFO
+typedef struct COMBOBOXINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, itemLeft, itemTop, itemRight, itemBottom, buttonLeft, buttonTop, buttonRight, buttonBottom, stateButton, hwndCombo, hwndItem, hwndList;
+} COMBOBOXINFO_FID_CACHE;
+
+COMBOBOXINFO_FID_CACHE COMBOBOXINFOFc;
+
+void cacheCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (COMBOBOXINFOFc.cached) return;
+       COMBOBOXINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       COMBOBOXINFOFc.cbSize = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "cbSize", "I");
+       COMBOBOXINFOFc.itemLeft = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "itemLeft", "I");
+       COMBOBOXINFOFc.itemTop = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "itemTop", "I");
+       COMBOBOXINFOFc.itemRight = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "itemRight", "I");
+       COMBOBOXINFOFc.itemBottom = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "itemBottom", "I");
+       COMBOBOXINFOFc.buttonLeft = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "buttonLeft", "I");
+       COMBOBOXINFOFc.buttonTop = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "buttonTop", "I");
+       COMBOBOXINFOFc.buttonRight = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "buttonRight", "I");
+       COMBOBOXINFOFc.buttonBottom = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "buttonBottom", "I");
+       COMBOBOXINFOFc.stateButton = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "stateButton", "I");
+       COMBOBOXINFOFc.hwndCombo = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "hwndCombo", "J");
+       COMBOBOXINFOFc.hwndItem = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "hwndItem", "J");
+       COMBOBOXINFOFc.hwndList = (*env)->GetFieldID(env, COMBOBOXINFOFc.clazz, "hwndList", "J");
+       COMBOBOXINFOFc.cached = 1;
+}
+
+COMBOBOXINFO *getCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject, COMBOBOXINFO *lpStruct)
+{
+       if (!COMBOBOXINFOFc.cached) cacheCOMBOBOXINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.cbSize);
+       lpStruct->rcItem.left = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.itemLeft);
+       lpStruct->rcItem.top = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.itemTop);
+       lpStruct->rcItem.right = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.itemRight);
+       lpStruct->rcItem.bottom = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.itemBottom);
+       lpStruct->rcButton.left = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.buttonLeft);
+       lpStruct->rcButton.top = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.buttonTop);
+       lpStruct->rcButton.right = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.buttonRight);
+       lpStruct->rcButton.bottom = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.buttonBottom);
+       lpStruct->stateButton = (*env)->GetIntField(env, lpObject, COMBOBOXINFOFc.stateButton);
+       lpStruct->hwndCombo = (HWND)(*env)->GetLongField(env, lpObject, COMBOBOXINFOFc.hwndCombo);
+       lpStruct->hwndItem = (HWND)(*env)->GetLongField(env, lpObject, COMBOBOXINFOFc.hwndItem);
+       lpStruct->hwndList = (HWND)(*env)->GetLongField(env, lpObject, COMBOBOXINFOFc.hwndList);
+       return lpStruct;
+}
+
+void setCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject, COMBOBOXINFO *lpStruct)
+{
+       if (!COMBOBOXINFOFc.cached) cacheCOMBOBOXINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.itemLeft, (jint)lpStruct->rcItem.left);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.itemTop, (jint)lpStruct->rcItem.top);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.itemRight, (jint)lpStruct->rcItem.right);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.itemBottom, (jint)lpStruct->rcItem.bottom);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.buttonLeft, (jint)lpStruct->rcButton.left);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.buttonTop, (jint)lpStruct->rcButton.top);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.buttonRight, (jint)lpStruct->rcButton.right);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.buttonBottom, (jint)lpStruct->rcButton.bottom);
+       (*env)->SetIntField(env, lpObject, COMBOBOXINFOFc.stateButton, (jint)lpStruct->stateButton);
+       (*env)->SetLongField(env, lpObject, COMBOBOXINFOFc.hwndCombo, (jlong)lpStruct->hwndCombo);
+       (*env)->SetLongField(env, lpObject, COMBOBOXINFOFc.hwndItem, (jlong)lpStruct->hwndItem);
+       (*env)->SetLongField(env, lpObject, COMBOBOXINFOFc.hwndList, (jlong)lpStruct->hwndList);
+}
+#endif
+
+#ifndef NO_COMPOSITIONFORM
+typedef struct COMPOSITIONFORM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwStyle, x, y, left, top, right, bottom;
+} COMPOSITIONFORM_FID_CACHE;
+
+COMPOSITIONFORM_FID_CACHE COMPOSITIONFORMFc;
+
+void cacheCOMPOSITIONFORMFields(JNIEnv *env, jobject lpObject)
+{
+       if (COMPOSITIONFORMFc.cached) return;
+       COMPOSITIONFORMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       COMPOSITIONFORMFc.dwStyle = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "dwStyle", "I");
+       COMPOSITIONFORMFc.x = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "x", "I");
+       COMPOSITIONFORMFc.y = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "y", "I");
+       COMPOSITIONFORMFc.left = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "left", "I");
+       COMPOSITIONFORMFc.top = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "top", "I");
+       COMPOSITIONFORMFc.right = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "right", "I");
+       COMPOSITIONFORMFc.bottom = (*env)->GetFieldID(env, COMPOSITIONFORMFc.clazz, "bottom", "I");
+       COMPOSITIONFORMFc.cached = 1;
+}
+
+COMPOSITIONFORM *getCOMPOSITIONFORMFields(JNIEnv *env, jobject lpObject, COMPOSITIONFORM *lpStruct)
+{
+       if (!COMPOSITIONFORMFc.cached) cacheCOMPOSITIONFORMFields(env, lpObject);
+       lpStruct->dwStyle = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.dwStyle);
+       lpStruct->ptCurrentPos.x = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.x);
+       lpStruct->ptCurrentPos.y = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.y);
+       lpStruct->rcArea.left = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.left);
+       lpStruct->rcArea.top = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.top);
+       lpStruct->rcArea.right = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.right);
+       lpStruct->rcArea.bottom = (*env)->GetIntField(env, lpObject, COMPOSITIONFORMFc.bottom);
+       return lpStruct;
+}
+
+void setCOMPOSITIONFORMFields(JNIEnv *env, jobject lpObject, COMPOSITIONFORM *lpStruct)
+{
+       if (!COMPOSITIONFORMFc.cached) cacheCOMPOSITIONFORMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.dwStyle, (jint)lpStruct->dwStyle);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.x, (jint)lpStruct->ptCurrentPos.x);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.y, (jint)lpStruct->ptCurrentPos.y);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.left, (jint)lpStruct->rcArea.left);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.top, (jint)lpStruct->rcArea.top);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.right, (jint)lpStruct->rcArea.right);
+       (*env)->SetIntField(env, lpObject, COMPOSITIONFORMFc.bottom, (jint)lpStruct->rcArea.bottom);
+}
+#endif
+
+#ifndef NO_CREATESTRUCT
+typedef struct CREATESTRUCT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lpCreateParams, hInstance, hMenu, hwndParent, cy, cx, y, x, style, lpszName, lpszClass, dwExStyle;
+} CREATESTRUCT_FID_CACHE;
+
+CREATESTRUCT_FID_CACHE CREATESTRUCTFc;
+
+void cacheCREATESTRUCTFields(JNIEnv *env, jobject lpObject)
+{
+       if (CREATESTRUCTFc.cached) return;
+       CREATESTRUCTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CREATESTRUCTFc.lpCreateParams = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "lpCreateParams", "J");
+       CREATESTRUCTFc.hInstance = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "hInstance", "J");
+       CREATESTRUCTFc.hMenu = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "hMenu", "J");
+       CREATESTRUCTFc.hwndParent = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "hwndParent", "J");
+       CREATESTRUCTFc.cy = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "cy", "I");
+       CREATESTRUCTFc.cx = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "cx", "I");
+       CREATESTRUCTFc.y = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "y", "I");
+       CREATESTRUCTFc.x = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "x", "I");
+       CREATESTRUCTFc.style = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "style", "I");
+       CREATESTRUCTFc.lpszName = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "lpszName", "J");
+       CREATESTRUCTFc.lpszClass = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "lpszClass", "J");
+       CREATESTRUCTFc.dwExStyle = (*env)->GetFieldID(env, CREATESTRUCTFc.clazz, "dwExStyle", "I");
+       CREATESTRUCTFc.cached = 1;
+}
+
+CREATESTRUCT *getCREATESTRUCTFields(JNIEnv *env, jobject lpObject, CREATESTRUCT *lpStruct)
+{
+       if (!CREATESTRUCTFc.cached) cacheCREATESTRUCTFields(env, lpObject);
+       lpStruct->lpCreateParams = (LPVOID)(*env)->GetLongField(env, lpObject, CREATESTRUCTFc.lpCreateParams);
+       lpStruct->hInstance = (HINSTANCE)(*env)->GetLongField(env, lpObject, CREATESTRUCTFc.hInstance);
+       lpStruct->hMenu = (HMENU)(*env)->GetLongField(env, lpObject, CREATESTRUCTFc.hMenu);
+       lpStruct->hwndParent = (HWND)(*env)->GetLongField(env, lpObject, CREATESTRUCTFc.hwndParent);
+       lpStruct->cy = (*env)->GetIntField(env, lpObject, CREATESTRUCTFc.cy);
+       lpStruct->cx = (*env)->GetIntField(env, lpObject, CREATESTRUCTFc.cx);
+       lpStruct->y = (*env)->GetIntField(env, lpObject, CREATESTRUCTFc.y);
+       lpStruct->x = (*env)->GetIntField(env, lpObject, CREATESTRUCTFc.x);
+       lpStruct->style = (*env)->GetIntField(env, lpObject, CREATESTRUCTFc.style);
+       lpStruct->lpszName = (LPCTSTR)(*env)->GetLongField(env, lpObject, CREATESTRUCTFc.lpszName);
+       lpStruct->lpszClass = (LPCTSTR)(*env)->GetLongField(env, lpObject, CREATESTRUCTFc.lpszClass);
+       lpStruct->dwExStyle = (*env)->GetIntField(env, lpObject, CREATESTRUCTFc.dwExStyle);
+       return lpStruct;
+}
+
+void setCREATESTRUCTFields(JNIEnv *env, jobject lpObject, CREATESTRUCT *lpStruct)
+{
+       if (!CREATESTRUCTFc.cached) cacheCREATESTRUCTFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, CREATESTRUCTFc.lpCreateParams, (jlong)lpStruct->lpCreateParams);
+       (*env)->SetLongField(env, lpObject, CREATESTRUCTFc.hInstance, (jlong)lpStruct->hInstance);
+       (*env)->SetLongField(env, lpObject, CREATESTRUCTFc.hMenu, (jlong)lpStruct->hMenu);
+       (*env)->SetLongField(env, lpObject, CREATESTRUCTFc.hwndParent, (jlong)lpStruct->hwndParent);
+       (*env)->SetIntField(env, lpObject, CREATESTRUCTFc.cy, (jint)lpStruct->cy);
+       (*env)->SetIntField(env, lpObject, CREATESTRUCTFc.cx, (jint)lpStruct->cx);
+       (*env)->SetIntField(env, lpObject, CREATESTRUCTFc.y, (jint)lpStruct->y);
+       (*env)->SetIntField(env, lpObject, CREATESTRUCTFc.x, (jint)lpStruct->x);
+       (*env)->SetIntField(env, lpObject, CREATESTRUCTFc.style, (jint)lpStruct->style);
+       (*env)->SetLongField(env, lpObject, CREATESTRUCTFc.lpszName, (jlong)lpStruct->lpszName);
+       (*env)->SetLongField(env, lpObject, CREATESTRUCTFc.lpszClass, (jlong)lpStruct->lpszClass);
+       (*env)->SetIntField(env, lpObject, CREATESTRUCTFc.dwExStyle, (jint)lpStruct->dwExStyle);
+}
+#endif
+
+#ifndef NO_CRYPT_ALGORITHM_IDENTIFIER
+typedef struct CRYPT_ALGORITHM_IDENTIFIER_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID pszObjId, Parameters;
+} CRYPT_ALGORITHM_IDENTIFIER_FID_CACHE;
+
+CRYPT_ALGORITHM_IDENTIFIER_FID_CACHE CRYPT_ALGORITHM_IDENTIFIERFc;
+
+void cacheCRYPT_ALGORITHM_IDENTIFIERFields(JNIEnv *env, jobject lpObject)
+{
+       if (CRYPT_ALGORITHM_IDENTIFIERFc.cached) return;
+       CRYPT_ALGORITHM_IDENTIFIERFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CRYPT_ALGORITHM_IDENTIFIERFc.pszObjId = (*env)->GetFieldID(env, CRYPT_ALGORITHM_IDENTIFIERFc.clazz, "pszObjId", "J");
+       CRYPT_ALGORITHM_IDENTIFIERFc.Parameters = (*env)->GetFieldID(env, CRYPT_ALGORITHM_IDENTIFIERFc.clazz, "Parameters", "Lorg/eclipse/swt/internal/win32/CRYPT_OBJID_BLOB;");
+       CRYPT_ALGORITHM_IDENTIFIERFc.cached = 1;
+}
+
+CRYPT_ALGORITHM_IDENTIFIER *getCRYPT_ALGORITHM_IDENTIFIERFields(JNIEnv *env, jobject lpObject, CRYPT_ALGORITHM_IDENTIFIER *lpStruct)
+{
+       if (!CRYPT_ALGORITHM_IDENTIFIERFc.cached) cacheCRYPT_ALGORITHM_IDENTIFIERFields(env, lpObject);
+       lpStruct->pszObjId = (LPSTR)(*env)->GetLongField(env, lpObject, CRYPT_ALGORITHM_IDENTIFIERFc.pszObjId);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CRYPT_ALGORITHM_IDENTIFIERFc.Parameters);
+       if (lpObject1 != NULL) getCRYPT_OBJID_BLOBFields(env, lpObject1, &lpStruct->Parameters);
+       }
+       return lpStruct;
+}
+
+void setCRYPT_ALGORITHM_IDENTIFIERFields(JNIEnv *env, jobject lpObject, CRYPT_ALGORITHM_IDENTIFIER *lpStruct)
+{
+       if (!CRYPT_ALGORITHM_IDENTIFIERFc.cached) cacheCRYPT_ALGORITHM_IDENTIFIERFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, CRYPT_ALGORITHM_IDENTIFIERFc.pszObjId, (jlong)lpStruct->pszObjId);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CRYPT_ALGORITHM_IDENTIFIERFc.Parameters);
+       if (lpObject1 != NULL) setCRYPT_OBJID_BLOBFields(env, lpObject1, &lpStruct->Parameters);
+       }
+}
+#endif
+
+#ifndef NO_CRYPT_BIT_BLOB
+typedef struct CRYPT_BIT_BLOB_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbData, pbData, cUnusedBits;
+} CRYPT_BIT_BLOB_FID_CACHE;
+
+CRYPT_BIT_BLOB_FID_CACHE CRYPT_BIT_BLOBFc;
+
+void cacheCRYPT_BIT_BLOBFields(JNIEnv *env, jobject lpObject)
+{
+       if (CRYPT_BIT_BLOBFc.cached) return;
+       CRYPT_BIT_BLOBFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CRYPT_BIT_BLOBFc.cbData = (*env)->GetFieldID(env, CRYPT_BIT_BLOBFc.clazz, "cbData", "I");
+       CRYPT_BIT_BLOBFc.pbData = (*env)->GetFieldID(env, CRYPT_BIT_BLOBFc.clazz, "pbData", "J");
+       CRYPT_BIT_BLOBFc.cUnusedBits = (*env)->GetFieldID(env, CRYPT_BIT_BLOBFc.clazz, "cUnusedBits", "I");
+       CRYPT_BIT_BLOBFc.cached = 1;
+}
+
+CRYPT_BIT_BLOB *getCRYPT_BIT_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_BIT_BLOB *lpStruct)
+{
+       if (!CRYPT_BIT_BLOBFc.cached) cacheCRYPT_BIT_BLOBFields(env, lpObject);
+       lpStruct->cbData = (*env)->GetIntField(env, lpObject, CRYPT_BIT_BLOBFc.cbData);
+       lpStruct->pbData = (BYTE *)(*env)->GetLongField(env, lpObject, CRYPT_BIT_BLOBFc.pbData);
+       lpStruct->cUnusedBits = (*env)->GetIntField(env, lpObject, CRYPT_BIT_BLOBFc.cUnusedBits);
+       return lpStruct;
+}
+
+void setCRYPT_BIT_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_BIT_BLOB *lpStruct)
+{
+       if (!CRYPT_BIT_BLOBFc.cached) cacheCRYPT_BIT_BLOBFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CRYPT_BIT_BLOBFc.cbData, (jint)lpStruct->cbData);
+       (*env)->SetLongField(env, lpObject, CRYPT_BIT_BLOBFc.pbData, (jlong)lpStruct->pbData);
+       (*env)->SetIntField(env, lpObject, CRYPT_BIT_BLOBFc.cUnusedBits, (jint)lpStruct->cUnusedBits);
+}
+#endif
+
+#ifndef NO_CRYPT_INTEGER_BLOB
+typedef struct CRYPT_INTEGER_BLOB_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbData, pbData;
+} CRYPT_INTEGER_BLOB_FID_CACHE;
+
+CRYPT_INTEGER_BLOB_FID_CACHE CRYPT_INTEGER_BLOBFc;
+
+void cacheCRYPT_INTEGER_BLOBFields(JNIEnv *env, jobject lpObject)
+{
+       if (CRYPT_INTEGER_BLOBFc.cached) return;
+       CRYPT_INTEGER_BLOBFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CRYPT_INTEGER_BLOBFc.cbData = (*env)->GetFieldID(env, CRYPT_INTEGER_BLOBFc.clazz, "cbData", "I");
+       CRYPT_INTEGER_BLOBFc.pbData = (*env)->GetFieldID(env, CRYPT_INTEGER_BLOBFc.clazz, "pbData", "J");
+       CRYPT_INTEGER_BLOBFc.cached = 1;
+}
+
+CRYPT_INTEGER_BLOB *getCRYPT_INTEGER_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_INTEGER_BLOB *lpStruct)
+{
+       if (!CRYPT_INTEGER_BLOBFc.cached) cacheCRYPT_INTEGER_BLOBFields(env, lpObject);
+       lpStruct->cbData = (*env)->GetIntField(env, lpObject, CRYPT_INTEGER_BLOBFc.cbData);
+       lpStruct->pbData = (BYTE *)(*env)->GetLongField(env, lpObject, CRYPT_INTEGER_BLOBFc.pbData);
+       return lpStruct;
+}
+
+void setCRYPT_INTEGER_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_INTEGER_BLOB *lpStruct)
+{
+       if (!CRYPT_INTEGER_BLOBFc.cached) cacheCRYPT_INTEGER_BLOBFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CRYPT_INTEGER_BLOBFc.cbData, (jint)lpStruct->cbData);
+       (*env)->SetLongField(env, lpObject, CRYPT_INTEGER_BLOBFc.pbData, (jlong)lpStruct->pbData);
+}
+#endif
+
+#ifndef NO_CRYPT_OBJID_BLOB
+typedef struct CRYPT_OBJID_BLOB_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbData, pbData;
+} CRYPT_OBJID_BLOB_FID_CACHE;
+
+CRYPT_OBJID_BLOB_FID_CACHE CRYPT_OBJID_BLOBFc;
+
+void cacheCRYPT_OBJID_BLOBFields(JNIEnv *env, jobject lpObject)
+{
+       if (CRYPT_OBJID_BLOBFc.cached) return;
+       CRYPT_OBJID_BLOBFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       CRYPT_OBJID_BLOBFc.cbData = (*env)->GetFieldID(env, CRYPT_OBJID_BLOBFc.clazz, "cbData", "I");
+       CRYPT_OBJID_BLOBFc.pbData = (*env)->GetFieldID(env, CRYPT_OBJID_BLOBFc.clazz, "pbData", "J");
+       CRYPT_OBJID_BLOBFc.cached = 1;
+}
+
+CRYPT_OBJID_BLOB *getCRYPT_OBJID_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_OBJID_BLOB *lpStruct)
+{
+       if (!CRYPT_OBJID_BLOBFc.cached) cacheCRYPT_OBJID_BLOBFields(env, lpObject);
+       lpStruct->cbData = (*env)->GetIntField(env, lpObject, CRYPT_OBJID_BLOBFc.cbData);
+       lpStruct->pbData = (BYTE *)(*env)->GetLongField(env, lpObject, CRYPT_OBJID_BLOBFc.pbData);
+       return lpStruct;
+}
+
+void setCRYPT_OBJID_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_OBJID_BLOB *lpStruct)
+{
+       if (!CRYPT_OBJID_BLOBFc.cached) cacheCRYPT_OBJID_BLOBFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, CRYPT_OBJID_BLOBFc.cbData, (jint)lpStruct->cbData);
+       (*env)->SetLongField(env, lpObject, CRYPT_OBJID_BLOBFc.pbData, (jlong)lpStruct->pbData);
+}
+#endif
+
+#ifndef NO_DEVMODE
+typedef struct DEVMODE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dmDeviceName, dmSpecVersion, dmDriverVersion, dmSize, dmDriverExtra, dmFields, dmOrientation, dmPaperSize, dmPaperLength, dmPaperWidth, dmScale, dmCopies, dmDefaultSource, dmPrintQuality, dmColor, dmDuplex, dmYResolution, dmTTOption, dmCollate, dmFormName, dmLogPixels, dmBitsPerPel, dmPelsWidth, dmPelsHeight, dmNup, dmDisplayFrequency, dmICMMethod, dmICMIntent, dmMediaType, dmDitherType, dmReserved1, dmReserved2, dmPanningWidth, dmPanningHeight;
+} DEVMODE_FID_CACHE;
+
+DEVMODE_FID_CACHE DEVMODEFc;
+
+void cacheDEVMODEFields(JNIEnv *env, jobject lpObject)
+{
+       if (DEVMODEFc.cached) return;
+       DEVMODEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DEVMODEFc.dmDeviceName = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDeviceName", "[C");
+       DEVMODEFc.dmSpecVersion = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmSpecVersion", "S");
+       DEVMODEFc.dmDriverVersion = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDriverVersion", "S");
+       DEVMODEFc.dmSize = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmSize", "S");
+       DEVMODEFc.dmDriverExtra = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDriverExtra", "S");
+       DEVMODEFc.dmFields = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmFields", "I");
+       DEVMODEFc.dmOrientation = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmOrientation", "S");
+       DEVMODEFc.dmPaperSize = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPaperSize", "S");
+       DEVMODEFc.dmPaperLength = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPaperLength", "S");
+       DEVMODEFc.dmPaperWidth = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPaperWidth", "S");
+       DEVMODEFc.dmScale = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmScale", "S");
+       DEVMODEFc.dmCopies = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmCopies", "S");
+       DEVMODEFc.dmDefaultSource = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDefaultSource", "S");
+       DEVMODEFc.dmPrintQuality = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPrintQuality", "S");
+       DEVMODEFc.dmColor = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmColor", "S");
+       DEVMODEFc.dmDuplex = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDuplex", "S");
+       DEVMODEFc.dmYResolution = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmYResolution", "S");
+       DEVMODEFc.dmTTOption = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmTTOption", "S");
+       DEVMODEFc.dmCollate = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmCollate", "S");
+       DEVMODEFc.dmFormName = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmFormName", "[C");
+       DEVMODEFc.dmLogPixels = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmLogPixels", "S");
+       DEVMODEFc.dmBitsPerPel = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmBitsPerPel", "I");
+       DEVMODEFc.dmPelsWidth = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPelsWidth", "I");
+       DEVMODEFc.dmPelsHeight = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPelsHeight", "I");
+       DEVMODEFc.dmNup = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmNup", "I");
+       DEVMODEFc.dmDisplayFrequency = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDisplayFrequency", "I");
+       DEVMODEFc.dmICMMethod = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmICMMethod", "I");
+       DEVMODEFc.dmICMIntent = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmICMIntent", "I");
+       DEVMODEFc.dmMediaType = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmMediaType", "I");
+       DEVMODEFc.dmDitherType = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmDitherType", "I");
+       DEVMODEFc.dmReserved1 = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmReserved1", "I");
+       DEVMODEFc.dmReserved2 = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmReserved2", "I");
+       DEVMODEFc.dmPanningWidth = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPanningWidth", "I");
+       DEVMODEFc.dmPanningHeight = (*env)->GetFieldID(env, DEVMODEFc.clazz, "dmPanningHeight", "I");
+       DEVMODEFc.cached = 1;
+}
+
+DEVMODE *getDEVMODEFields(JNIEnv *env, jobject lpObject, DEVMODE *lpStruct)
+{
+       if (!DEVMODEFc.cached) cacheDEVMODEFields(env, lpObject);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, DEVMODEFc.dmDeviceName);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->dmDeviceName) / sizeof(jchar), (jchar *)lpStruct->dmDeviceName);
+       }
+       lpStruct->dmSpecVersion = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmSpecVersion);
+       lpStruct->dmDriverVersion = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmDriverVersion);
+       lpStruct->dmSize = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmSize);
+       lpStruct->dmDriverExtra = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmDriverExtra);
+       lpStruct->dmFields = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmFields);
+       lpStruct->dmOrientation = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmOrientation);
+       lpStruct->dmPaperSize = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmPaperSize);
+       lpStruct->dmPaperLength = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmPaperLength);
+       lpStruct->dmPaperWidth = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmPaperWidth);
+       lpStruct->dmScale = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmScale);
+       lpStruct->dmCopies = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmCopies);
+       lpStruct->dmDefaultSource = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmDefaultSource);
+       lpStruct->dmPrintQuality = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmPrintQuality);
+       lpStruct->dmColor = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmColor);
+       lpStruct->dmDuplex = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmDuplex);
+       lpStruct->dmYResolution = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmYResolution);
+       lpStruct->dmTTOption = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmTTOption);
+       lpStruct->dmCollate = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmCollate);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, DEVMODEFc.dmFormName);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->dmFormName) / sizeof(jchar), (jchar *)lpStruct->dmFormName);
+       }
+       lpStruct->dmLogPixels = (*env)->GetShortField(env, lpObject, DEVMODEFc.dmLogPixels);
+       lpStruct->dmBitsPerPel = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmBitsPerPel);
+       lpStruct->dmPelsWidth = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmPelsWidth);
+       lpStruct->dmPelsHeight = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmPelsHeight);
+       lpStruct->dmNup = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmNup);
+       lpStruct->dmDisplayFrequency = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmDisplayFrequency);
+       lpStruct->dmICMMethod = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmICMMethod);
+       lpStruct->dmICMIntent = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmICMIntent);
+       lpStruct->dmMediaType = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmMediaType);
+       lpStruct->dmDitherType = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmDitherType);
+       lpStruct->dmReserved1 = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmReserved1);
+       lpStruct->dmReserved2 = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmReserved2);
+       lpStruct->dmPanningWidth = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmPanningWidth);
+       lpStruct->dmPanningHeight = (*env)->GetIntField(env, lpObject, DEVMODEFc.dmPanningHeight);
+       return lpStruct;
+}
+
+void setDEVMODEFields(JNIEnv *env, jobject lpObject, DEVMODE *lpStruct)
+{
+       if (!DEVMODEFc.cached) cacheDEVMODEFields(env, lpObject);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, DEVMODEFc.dmDeviceName);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->dmDeviceName) / sizeof(jchar), (jchar *)lpStruct->dmDeviceName);
+       }
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmSpecVersion, (jshort)lpStruct->dmSpecVersion);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmDriverVersion, (jshort)lpStruct->dmDriverVersion);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmSize, (jshort)lpStruct->dmSize);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmDriverExtra, (jshort)lpStruct->dmDriverExtra);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmFields, (jint)lpStruct->dmFields);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmOrientation, (jshort)lpStruct->dmOrientation);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmPaperSize, (jshort)lpStruct->dmPaperSize);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmPaperLength, (jshort)lpStruct->dmPaperLength);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmPaperWidth, (jshort)lpStruct->dmPaperWidth);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmScale, (jshort)lpStruct->dmScale);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmCopies, (jshort)lpStruct->dmCopies);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmDefaultSource, (jshort)lpStruct->dmDefaultSource);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmPrintQuality, (jshort)lpStruct->dmPrintQuality);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmColor, (jshort)lpStruct->dmColor);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmDuplex, (jshort)lpStruct->dmDuplex);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmYResolution, (jshort)lpStruct->dmYResolution);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmTTOption, (jshort)lpStruct->dmTTOption);
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmCollate, (jshort)lpStruct->dmCollate);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, DEVMODEFc.dmFormName);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->dmFormName) / sizeof(jchar), (jchar *)lpStruct->dmFormName);
+       }
+       (*env)->SetShortField(env, lpObject, DEVMODEFc.dmLogPixels, (jshort)lpStruct->dmLogPixels);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmBitsPerPel, (jint)lpStruct->dmBitsPerPel);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmPelsWidth, (jint)lpStruct->dmPelsWidth);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmPelsHeight, (jint)lpStruct->dmPelsHeight);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmNup, (jint)lpStruct->dmNup);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmDisplayFrequency, (jint)lpStruct->dmDisplayFrequency);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmICMMethod, (jint)lpStruct->dmICMMethod);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmICMIntent, (jint)lpStruct->dmICMIntent);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmMediaType, (jint)lpStruct->dmMediaType);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmDitherType, (jint)lpStruct->dmDitherType);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmReserved1, (jint)lpStruct->dmReserved1);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmReserved2, (jint)lpStruct->dmReserved2);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmPanningWidth, (jint)lpStruct->dmPanningWidth);
+       (*env)->SetIntField(env, lpObject, DEVMODEFc.dmPanningHeight, (jint)lpStruct->dmPanningHeight);
+}
+#endif
+
+#ifndef NO_DIBSECTION
+typedef struct DIBSECTION_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID biSize, biWidth, biHeight, biPlanes, biBitCount, biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant, dsBitfields0, dsBitfields1, dsBitfields2, dshSection, dsOffset;
+} DIBSECTION_FID_CACHE;
+
+DIBSECTION_FID_CACHE DIBSECTIONFc;
+
+void cacheDIBSECTIONFields(JNIEnv *env, jobject lpObject)
+{
+       if (DIBSECTIONFc.cached) return;
+       cacheBITMAPFields(env, lpObject);
+       DIBSECTIONFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DIBSECTIONFc.biSize = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biSize", "I");
+       DIBSECTIONFc.biWidth = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biWidth", "I");
+       DIBSECTIONFc.biHeight = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biHeight", "I");
+       DIBSECTIONFc.biPlanes = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biPlanes", "S");
+       DIBSECTIONFc.biBitCount = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biBitCount", "S");
+       DIBSECTIONFc.biCompression = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biCompression", "I");
+       DIBSECTIONFc.biSizeImage = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biSizeImage", "I");
+       DIBSECTIONFc.biXPelsPerMeter = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biXPelsPerMeter", "I");
+       DIBSECTIONFc.biYPelsPerMeter = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biYPelsPerMeter", "I");
+       DIBSECTIONFc.biClrUsed = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biClrUsed", "I");
+       DIBSECTIONFc.biClrImportant = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "biClrImportant", "I");
+       DIBSECTIONFc.dsBitfields0 = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "dsBitfields0", "I");
+       DIBSECTIONFc.dsBitfields1 = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "dsBitfields1", "I");
+       DIBSECTIONFc.dsBitfields2 = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "dsBitfields2", "I");
+       DIBSECTIONFc.dshSection = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "dshSection", "J");
+       DIBSECTIONFc.dsOffset = (*env)->GetFieldID(env, DIBSECTIONFc.clazz, "dsOffset", "I");
+       DIBSECTIONFc.cached = 1;
+}
+
+DIBSECTION *getDIBSECTIONFields(JNIEnv *env, jobject lpObject, DIBSECTION *lpStruct)
+{
+       if (!DIBSECTIONFc.cached) cacheDIBSECTIONFields(env, lpObject);
+       getBITMAPFields(env, lpObject, (BITMAP *)lpStruct);
+       lpStruct->dsBmih.biSize = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biSize);
+       lpStruct->dsBmih.biWidth = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biWidth);
+       lpStruct->dsBmih.biHeight = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biHeight);
+       lpStruct->dsBmih.biPlanes = (*env)->GetShortField(env, lpObject, DIBSECTIONFc.biPlanes);
+       lpStruct->dsBmih.biBitCount = (*env)->GetShortField(env, lpObject, DIBSECTIONFc.biBitCount);
+       lpStruct->dsBmih.biCompression = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biCompression);
+       lpStruct->dsBmih.biSizeImage = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biSizeImage);
+       lpStruct->dsBmih.biXPelsPerMeter = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biXPelsPerMeter);
+       lpStruct->dsBmih.biYPelsPerMeter = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biYPelsPerMeter);
+       lpStruct->dsBmih.biClrUsed = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biClrUsed);
+       lpStruct->dsBmih.biClrImportant = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.biClrImportant);
+       lpStruct->dsBitfields[0] = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.dsBitfields0);
+       lpStruct->dsBitfields[1] = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.dsBitfields1);
+       lpStruct->dsBitfields[2] = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.dsBitfields2);
+       lpStruct->dshSection = (HANDLE)(*env)->GetLongField(env, lpObject, DIBSECTIONFc.dshSection);
+       lpStruct->dsOffset = (*env)->GetIntField(env, lpObject, DIBSECTIONFc.dsOffset);
+       return lpStruct;
+}
+
+void setDIBSECTIONFields(JNIEnv *env, jobject lpObject, DIBSECTION *lpStruct)
+{
+       if (!DIBSECTIONFc.cached) cacheDIBSECTIONFields(env, lpObject);
+       setBITMAPFields(env, lpObject, (BITMAP *)lpStruct);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biSize, (jint)lpStruct->dsBmih.biSize);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biWidth, (jint)lpStruct->dsBmih.biWidth);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biHeight, (jint)lpStruct->dsBmih.biHeight);
+       (*env)->SetShortField(env, lpObject, DIBSECTIONFc.biPlanes, (jshort)lpStruct->dsBmih.biPlanes);
+       (*env)->SetShortField(env, lpObject, DIBSECTIONFc.biBitCount, (jshort)lpStruct->dsBmih.biBitCount);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biCompression, (jint)lpStruct->dsBmih.biCompression);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biSizeImage, (jint)lpStruct->dsBmih.biSizeImage);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biXPelsPerMeter, (jint)lpStruct->dsBmih.biXPelsPerMeter);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biYPelsPerMeter, (jint)lpStruct->dsBmih.biYPelsPerMeter);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biClrUsed, (jint)lpStruct->dsBmih.biClrUsed);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.biClrImportant, (jint)lpStruct->dsBmih.biClrImportant);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.dsBitfields0, (jint)lpStruct->dsBitfields[0]);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.dsBitfields1, (jint)lpStruct->dsBitfields[1]);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.dsBitfields2, (jint)lpStruct->dsBitfields[2]);
+       (*env)->SetLongField(env, lpObject, DIBSECTIONFc.dshSection, (jlong)lpStruct->dshSection);
+       (*env)->SetIntField(env, lpObject, DIBSECTIONFc.dsOffset, (jint)lpStruct->dsOffset);
+}
+#endif
+
+#ifndef NO_DOCHOSTUIINFO
+typedef struct DOCHOSTUIINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, dwDoubleClick, pchHostCss, pchHostNS;
+} DOCHOSTUIINFO_FID_CACHE;
+
+DOCHOSTUIINFO_FID_CACHE DOCHOSTUIINFOFc;
+
+void cacheDOCHOSTUIINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (DOCHOSTUIINFOFc.cached) return;
+       DOCHOSTUIINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DOCHOSTUIINFOFc.cbSize = (*env)->GetFieldID(env, DOCHOSTUIINFOFc.clazz, "cbSize", "I");
+       DOCHOSTUIINFOFc.dwFlags = (*env)->GetFieldID(env, DOCHOSTUIINFOFc.clazz, "dwFlags", "I");
+       DOCHOSTUIINFOFc.dwDoubleClick = (*env)->GetFieldID(env, DOCHOSTUIINFOFc.clazz, "dwDoubleClick", "I");
+       DOCHOSTUIINFOFc.pchHostCss = (*env)->GetFieldID(env, DOCHOSTUIINFOFc.clazz, "pchHostCss", "J");
+       DOCHOSTUIINFOFc.pchHostNS = (*env)->GetFieldID(env, DOCHOSTUIINFOFc.clazz, "pchHostNS", "J");
+       DOCHOSTUIINFOFc.cached = 1;
+}
+
+DOCHOSTUIINFO *getDOCHOSTUIINFOFields(JNIEnv *env, jobject lpObject, DOCHOSTUIINFO *lpStruct)
+{
+       if (!DOCHOSTUIINFOFc.cached) cacheDOCHOSTUIINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, DOCHOSTUIINFOFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, DOCHOSTUIINFOFc.dwFlags);
+       lpStruct->dwDoubleClick = (*env)->GetIntField(env, lpObject, DOCHOSTUIINFOFc.dwDoubleClick);
+       lpStruct->pchHostCss = (OLECHAR *)(*env)->GetLongField(env, lpObject, DOCHOSTUIINFOFc.pchHostCss);
+       lpStruct->pchHostNS = (OLECHAR *)(*env)->GetLongField(env, lpObject, DOCHOSTUIINFOFc.pchHostNS);
+       return lpStruct;
+}
+
+void setDOCHOSTUIINFOFields(JNIEnv *env, jobject lpObject, DOCHOSTUIINFO *lpStruct)
+{
+       if (!DOCHOSTUIINFOFc.cached) cacheDOCHOSTUIINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, DOCHOSTUIINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, DOCHOSTUIINFOFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, DOCHOSTUIINFOFc.dwDoubleClick, (jint)lpStruct->dwDoubleClick);
+       (*env)->SetLongField(env, lpObject, DOCHOSTUIINFOFc.pchHostCss, (jlong)lpStruct->pchHostCss);
+       (*env)->SetLongField(env, lpObject, DOCHOSTUIINFOFc.pchHostNS, (jlong)lpStruct->pchHostNS);
+}
+#endif
+
+#ifndef NO_DOCINFO
+typedef struct DOCINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, lpszDocName, lpszOutput, lpszDatatype, fwType;
+} DOCINFO_FID_CACHE;
+
+DOCINFO_FID_CACHE DOCINFOFc;
+
+void cacheDOCINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (DOCINFOFc.cached) return;
+       DOCINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DOCINFOFc.cbSize = (*env)->GetFieldID(env, DOCINFOFc.clazz, "cbSize", "I");
+       DOCINFOFc.lpszDocName = (*env)->GetFieldID(env, DOCINFOFc.clazz, "lpszDocName", "J");
+       DOCINFOFc.lpszOutput = (*env)->GetFieldID(env, DOCINFOFc.clazz, "lpszOutput", "J");
+       DOCINFOFc.lpszDatatype = (*env)->GetFieldID(env, DOCINFOFc.clazz, "lpszDatatype", "J");
+       DOCINFOFc.fwType = (*env)->GetFieldID(env, DOCINFOFc.clazz, "fwType", "I");
+       DOCINFOFc.cached = 1;
+}
+
+DOCINFO *getDOCINFOFields(JNIEnv *env, jobject lpObject, DOCINFO *lpStruct)
+{
+       if (!DOCINFOFc.cached) cacheDOCINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, DOCINFOFc.cbSize);
+       lpStruct->lpszDocName = (LPCTSTR)(*env)->GetLongField(env, lpObject, DOCINFOFc.lpszDocName);
+       lpStruct->lpszOutput = (LPCTSTR)(*env)->GetLongField(env, lpObject, DOCINFOFc.lpszOutput);
+       lpStruct->lpszDatatype = (LPCTSTR)(*env)->GetLongField(env, lpObject, DOCINFOFc.lpszDatatype);
+       lpStruct->fwType = (*env)->GetIntField(env, lpObject, DOCINFOFc.fwType);
+       return lpStruct;
+}
+
+void setDOCINFOFields(JNIEnv *env, jobject lpObject, DOCINFO *lpStruct)
+{
+       if (!DOCINFOFc.cached) cacheDOCINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, DOCINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetLongField(env, lpObject, DOCINFOFc.lpszDocName, (jlong)lpStruct->lpszDocName);
+       (*env)->SetLongField(env, lpObject, DOCINFOFc.lpszOutput, (jlong)lpStruct->lpszOutput);
+       (*env)->SetLongField(env, lpObject, DOCINFOFc.lpszDatatype, (jlong)lpStruct->lpszDatatype);
+       (*env)->SetIntField(env, lpObject, DOCINFOFc.fwType, (jint)lpStruct->fwType);
+}
+#endif
+
+#ifndef NO_DRAWITEMSTRUCT
+typedef struct DRAWITEMSTRUCT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID CtlType, CtlID, itemID, itemAction, itemState, hwndItem, hDC, left, top, bottom, right, itemData;
+} DRAWITEMSTRUCT_FID_CACHE;
+
+DRAWITEMSTRUCT_FID_CACHE DRAWITEMSTRUCTFc;
+
+void cacheDRAWITEMSTRUCTFields(JNIEnv *env, jobject lpObject)
+{
+       if (DRAWITEMSTRUCTFc.cached) return;
+       DRAWITEMSTRUCTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DRAWITEMSTRUCTFc.CtlType = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "CtlType", "I");
+       DRAWITEMSTRUCTFc.CtlID = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "CtlID", "I");
+       DRAWITEMSTRUCTFc.itemID = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "itemID", "I");
+       DRAWITEMSTRUCTFc.itemAction = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "itemAction", "I");
+       DRAWITEMSTRUCTFc.itemState = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "itemState", "I");
+       DRAWITEMSTRUCTFc.hwndItem = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "hwndItem", "J");
+       DRAWITEMSTRUCTFc.hDC = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "hDC", "J");
+       DRAWITEMSTRUCTFc.left = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "left", "I");
+       DRAWITEMSTRUCTFc.top = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "top", "I");
+       DRAWITEMSTRUCTFc.bottom = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "bottom", "I");
+       DRAWITEMSTRUCTFc.right = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "right", "I");
+       DRAWITEMSTRUCTFc.itemData = (*env)->GetFieldID(env, DRAWITEMSTRUCTFc.clazz, "itemData", "J");
+       DRAWITEMSTRUCTFc.cached = 1;
+}
+
+DRAWITEMSTRUCT *getDRAWITEMSTRUCTFields(JNIEnv *env, jobject lpObject, DRAWITEMSTRUCT *lpStruct)
+{
+       if (!DRAWITEMSTRUCTFc.cached) cacheDRAWITEMSTRUCTFields(env, lpObject);
+       lpStruct->CtlType = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.CtlType);
+       lpStruct->CtlID = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.CtlID);
+       lpStruct->itemID = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.itemID);
+       lpStruct->itemAction = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.itemAction);
+       lpStruct->itemState = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.itemState);
+       lpStruct->hwndItem = (HWND)(*env)->GetLongField(env, lpObject, DRAWITEMSTRUCTFc.hwndItem);
+       lpStruct->hDC = (HDC)(*env)->GetLongField(env, lpObject, DRAWITEMSTRUCTFc.hDC);
+       lpStruct->rcItem.left = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.left);
+       lpStruct->rcItem.top = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.top);
+       lpStruct->rcItem.bottom = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.bottom);
+       lpStruct->rcItem.right = (*env)->GetIntField(env, lpObject, DRAWITEMSTRUCTFc.right);
+       lpStruct->itemData = (*env)->GetLongField(env, lpObject, DRAWITEMSTRUCTFc.itemData);
+       return lpStruct;
+}
+
+void setDRAWITEMSTRUCTFields(JNIEnv *env, jobject lpObject, DRAWITEMSTRUCT *lpStruct)
+{
+       if (!DRAWITEMSTRUCTFc.cached) cacheDRAWITEMSTRUCTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.CtlType, (jint)lpStruct->CtlType);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.CtlID, (jint)lpStruct->CtlID);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.itemID, (jint)lpStruct->itemID);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.itemAction, (jint)lpStruct->itemAction);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.itemState, (jint)lpStruct->itemState);
+       (*env)->SetLongField(env, lpObject, DRAWITEMSTRUCTFc.hwndItem, (jlong)lpStruct->hwndItem);
+       (*env)->SetLongField(env, lpObject, DRAWITEMSTRUCTFc.hDC, (jlong)lpStruct->hDC);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.left, (jint)lpStruct->rcItem.left);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.top, (jint)lpStruct->rcItem.top);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.bottom, (jint)lpStruct->rcItem.bottom);
+       (*env)->SetIntField(env, lpObject, DRAWITEMSTRUCTFc.right, (jint)lpStruct->rcItem.right);
+       (*env)->SetLongField(env, lpObject, DRAWITEMSTRUCTFc.itemData, (jlong)lpStruct->itemData);
+}
+#endif
+
+#ifndef NO_DROPFILES
+typedef struct DROPFILES_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID pFiles, pt_x, pt_y, fNC, fWide;
+} DROPFILES_FID_CACHE;
+
+DROPFILES_FID_CACHE DROPFILESFc;
+
+void cacheDROPFILESFields(JNIEnv *env, jobject lpObject)
+{
+       if (DROPFILESFc.cached) return;
+       DROPFILESFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DROPFILESFc.pFiles = (*env)->GetFieldID(env, DROPFILESFc.clazz, "pFiles", "I");
+       DROPFILESFc.pt_x = (*env)->GetFieldID(env, DROPFILESFc.clazz, "pt_x", "I");
+       DROPFILESFc.pt_y = (*env)->GetFieldID(env, DROPFILESFc.clazz, "pt_y", "I");
+       DROPFILESFc.fNC = (*env)->GetFieldID(env, DROPFILESFc.clazz, "fNC", "I");
+       DROPFILESFc.fWide = (*env)->GetFieldID(env, DROPFILESFc.clazz, "fWide", "I");
+       DROPFILESFc.cached = 1;
+}
+
+DROPFILES *getDROPFILESFields(JNIEnv *env, jobject lpObject, DROPFILES *lpStruct)
+{
+       if (!DROPFILESFc.cached) cacheDROPFILESFields(env, lpObject);
+       lpStruct->pFiles = (*env)->GetIntField(env, lpObject, DROPFILESFc.pFiles);
+       lpStruct->pt.x = (*env)->GetIntField(env, lpObject, DROPFILESFc.pt_x);
+       lpStruct->pt.y = (*env)->GetIntField(env, lpObject, DROPFILESFc.pt_y);
+       lpStruct->fNC = (*env)->GetIntField(env, lpObject, DROPFILESFc.fNC);
+       lpStruct->fWide = (*env)->GetIntField(env, lpObject, DROPFILESFc.fWide);
+       return lpStruct;
+}
+
+void setDROPFILESFields(JNIEnv *env, jobject lpObject, DROPFILES *lpStruct)
+{
+       if (!DROPFILESFc.cached) cacheDROPFILESFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, DROPFILESFc.pFiles, (jint)lpStruct->pFiles);
+       (*env)->SetIntField(env, lpObject, DROPFILESFc.pt_x, (jint)lpStruct->pt.x);
+       (*env)->SetIntField(env, lpObject, DROPFILESFc.pt_y, (jint)lpStruct->pt.y);
+       (*env)->SetIntField(env, lpObject, DROPFILESFc.fNC, (jint)lpStruct->fNC);
+       (*env)->SetIntField(env, lpObject, DROPFILESFc.fWide, (jint)lpStruct->fWide);
+}
+#endif
+
+#ifndef NO_DTTOPTS
+typedef struct DTTOPTS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwSize, dwFlags, crText, crBorder, crShadow, iTextShadowType, ptShadowOffset, iBorderSize, iFontPropId, iColorPropId, iStateId, fApplyOverlay, iGlowSize, pfnDrawTextCallback, lParam;
+} DTTOPTS_FID_CACHE;
+
+DTTOPTS_FID_CACHE DTTOPTSFc;
+
+void cacheDTTOPTSFields(JNIEnv *env, jobject lpObject)
+{
+       if (DTTOPTSFc.cached) return;
+       DTTOPTSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       DTTOPTSFc.dwSize = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "dwSize", "I");
+       DTTOPTSFc.dwFlags = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "dwFlags", "I");
+       DTTOPTSFc.crText = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "crText", "I");
+       DTTOPTSFc.crBorder = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "crBorder", "I");
+       DTTOPTSFc.crShadow = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "crShadow", "I");
+       DTTOPTSFc.iTextShadowType = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "iTextShadowType", "I");
+       DTTOPTSFc.ptShadowOffset = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "ptShadowOffset", "Lorg/eclipse/swt/internal/win32/POINT;");
+       DTTOPTSFc.iBorderSize = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "iBorderSize", "I");
+       DTTOPTSFc.iFontPropId = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "iFontPropId", "I");
+       DTTOPTSFc.iColorPropId = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "iColorPropId", "I");
+       DTTOPTSFc.iStateId = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "iStateId", "I");
+       DTTOPTSFc.fApplyOverlay = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "fApplyOverlay", "Z");
+       DTTOPTSFc.iGlowSize = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "iGlowSize", "I");
+       DTTOPTSFc.pfnDrawTextCallback = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "pfnDrawTextCallback", "J");
+       DTTOPTSFc.lParam = (*env)->GetFieldID(env, DTTOPTSFc.clazz, "lParam", "J");
+       DTTOPTSFc.cached = 1;
+}
+
+DTTOPTS *getDTTOPTSFields(JNIEnv *env, jobject lpObject, DTTOPTS *lpStruct)
+{
+       if (!DTTOPTSFc.cached) cacheDTTOPTSFields(env, lpObject);
+       lpStruct->dwSize = (*env)->GetIntField(env, lpObject, DTTOPTSFc.dwSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, DTTOPTSFc.dwFlags);
+       lpStruct->crText = (*env)->GetIntField(env, lpObject, DTTOPTSFc.crText);
+       lpStruct->crBorder = (*env)->GetIntField(env, lpObject, DTTOPTSFc.crBorder);
+       lpStruct->crShadow = (*env)->GetIntField(env, lpObject, DTTOPTSFc.crShadow);
+       lpStruct->iTextShadowType = (*env)->GetIntField(env, lpObject, DTTOPTSFc.iTextShadowType);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, DTTOPTSFc.ptShadowOffset);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->ptShadowOffset);
+       }
+       lpStruct->iBorderSize = (*env)->GetIntField(env, lpObject, DTTOPTSFc.iBorderSize);
+       lpStruct->iFontPropId = (*env)->GetIntField(env, lpObject, DTTOPTSFc.iFontPropId);
+       lpStruct->iColorPropId = (*env)->GetIntField(env, lpObject, DTTOPTSFc.iColorPropId);
+       lpStruct->iStateId = (*env)->GetIntField(env, lpObject, DTTOPTSFc.iStateId);
+       lpStruct->fApplyOverlay = (*env)->GetBooleanField(env, lpObject, DTTOPTSFc.fApplyOverlay);
+       lpStruct->iGlowSize = (*env)->GetIntField(env, lpObject, DTTOPTSFc.iGlowSize);
+       lpStruct->pfnDrawTextCallback = (DTT_CALLBACK_PROC)(*env)->GetLongField(env, lpObject, DTTOPTSFc.pfnDrawTextCallback);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, DTTOPTSFc.lParam);
+       return lpStruct;
+}
+
+void setDTTOPTSFields(JNIEnv *env, jobject lpObject, DTTOPTS *lpStruct)
+{
+       if (!DTTOPTSFc.cached) cacheDTTOPTSFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.dwSize, (jint)lpStruct->dwSize);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.crText, (jint)lpStruct->crText);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.crBorder, (jint)lpStruct->crBorder);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.crShadow, (jint)lpStruct->crShadow);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.iTextShadowType, (jint)lpStruct->iTextShadowType);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, DTTOPTSFc.ptShadowOffset);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->ptShadowOffset);
+       }
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.iBorderSize, (jint)lpStruct->iBorderSize);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.iFontPropId, (jint)lpStruct->iFontPropId);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.iColorPropId, (jint)lpStruct->iColorPropId);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.iStateId, (jint)lpStruct->iStateId);
+       (*env)->SetBooleanField(env, lpObject, DTTOPTSFc.fApplyOverlay, (jboolean)lpStruct->fApplyOverlay);
+       (*env)->SetIntField(env, lpObject, DTTOPTSFc.iGlowSize, (jint)lpStruct->iGlowSize);
+       (*env)->SetLongField(env, lpObject, DTTOPTSFc.pfnDrawTextCallback, (jlong)lpStruct->pfnDrawTextCallback);
+       (*env)->SetLongField(env, lpObject, DTTOPTSFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_EMR
+typedef struct EMR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iType, nSize;
+} EMR_FID_CACHE;
+
+EMR_FID_CACHE EMRFc;
+
+void cacheEMRFields(JNIEnv *env, jobject lpObject)
+{
+       if (EMRFc.cached) return;
+       EMRFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       EMRFc.iType = (*env)->GetFieldID(env, EMRFc.clazz, "iType", "I");
+       EMRFc.nSize = (*env)->GetFieldID(env, EMRFc.clazz, "nSize", "I");
+       EMRFc.cached = 1;
+}
+
+EMR *getEMRFields(JNIEnv *env, jobject lpObject, EMR *lpStruct)
+{
+       if (!EMRFc.cached) cacheEMRFields(env, lpObject);
+       lpStruct->iType = (*env)->GetIntField(env, lpObject, EMRFc.iType);
+       lpStruct->nSize = (*env)->GetIntField(env, lpObject, EMRFc.nSize);
+       return lpStruct;
+}
+
+void setEMRFields(JNIEnv *env, jobject lpObject, EMR *lpStruct)
+{
+       if (!EMRFc.cached) cacheEMRFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, EMRFc.iType, (jint)lpStruct->iType);
+       (*env)->SetIntField(env, lpObject, EMRFc.nSize, (jint)lpStruct->nSize);
+}
+#endif
+
+#ifndef NO_EMREXTCREATEFONTINDIRECTW
+typedef struct EMREXTCREATEFONTINDIRECTW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID emr, ihFont, elfw;
+} EMREXTCREATEFONTINDIRECTW_FID_CACHE;
+
+EMREXTCREATEFONTINDIRECTW_FID_CACHE EMREXTCREATEFONTINDIRECTWFc;
+
+void cacheEMREXTCREATEFONTINDIRECTWFields(JNIEnv *env, jobject lpObject)
+{
+       if (EMREXTCREATEFONTINDIRECTWFc.cached) return;
+       EMREXTCREATEFONTINDIRECTWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       EMREXTCREATEFONTINDIRECTWFc.emr = (*env)->GetFieldID(env, EMREXTCREATEFONTINDIRECTWFc.clazz, "emr", "Lorg/eclipse/swt/internal/win32/EMR;");
+       EMREXTCREATEFONTINDIRECTWFc.ihFont = (*env)->GetFieldID(env, EMREXTCREATEFONTINDIRECTWFc.clazz, "ihFont", "I");
+       EMREXTCREATEFONTINDIRECTWFc.elfw = (*env)->GetFieldID(env, EMREXTCREATEFONTINDIRECTWFc.clazz, "elfw", "Lorg/eclipse/swt/internal/win32/EXTLOGFONTW;");
+       EMREXTCREATEFONTINDIRECTWFc.cached = 1;
+}
+
+EMREXTCREATEFONTINDIRECTW *getEMREXTCREATEFONTINDIRECTWFields(JNIEnv *env, jobject lpObject, EMREXTCREATEFONTINDIRECTW *lpStruct)
+{
+       if (!EMREXTCREATEFONTINDIRECTWFc.cached) cacheEMREXTCREATEFONTINDIRECTWFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EMREXTCREATEFONTINDIRECTWFc.emr);
+       if (lpObject1 != NULL) getEMRFields(env, lpObject1, &lpStruct->emr);
+       }
+       lpStruct->ihFont = (*env)->GetIntField(env, lpObject, EMREXTCREATEFONTINDIRECTWFc.ihFont);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EMREXTCREATEFONTINDIRECTWFc.elfw);
+       if (lpObject1 != NULL) getEXTLOGFONTWFields(env, lpObject1, &lpStruct->elfw);
+       }
+       return lpStruct;
+}
+
+void setEMREXTCREATEFONTINDIRECTWFields(JNIEnv *env, jobject lpObject, EMREXTCREATEFONTINDIRECTW *lpStruct)
+{
+       if (!EMREXTCREATEFONTINDIRECTWFc.cached) cacheEMREXTCREATEFONTINDIRECTWFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EMREXTCREATEFONTINDIRECTWFc.emr);
+       if (lpObject1 != NULL) setEMRFields(env, lpObject1, &lpStruct->emr);
+       }
+       (*env)->SetIntField(env, lpObject, EMREXTCREATEFONTINDIRECTWFc.ihFont, (jint)lpStruct->ihFont);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EMREXTCREATEFONTINDIRECTWFc.elfw);
+       if (lpObject1 != NULL) setEXTLOGFONTWFields(env, lpObject1, &lpStruct->elfw);
+       }
+}
+#endif
+
+#ifndef NO_EXTLOGFONTW
+typedef struct EXTLOGFONTW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID elfLogFont, elfFullName, elfStyle, elfVersion, elfStyleSize, elfMatch, elfReserved, elfVendorId, elfCulture, elfPanose;
+} EXTLOGFONTW_FID_CACHE;
+
+EXTLOGFONTW_FID_CACHE EXTLOGFONTWFc;
+
+void cacheEXTLOGFONTWFields(JNIEnv *env, jobject lpObject)
+{
+       if (EXTLOGFONTWFc.cached) return;
+       EXTLOGFONTWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       EXTLOGFONTWFc.elfLogFont = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfLogFont", "Lorg/eclipse/swt/internal/win32/LOGFONT;");
+       EXTLOGFONTWFc.elfFullName = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfFullName", "[C");
+       EXTLOGFONTWFc.elfStyle = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfStyle", "[C");
+       EXTLOGFONTWFc.elfVersion = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfVersion", "I");
+       EXTLOGFONTWFc.elfStyleSize = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfStyleSize", "I");
+       EXTLOGFONTWFc.elfMatch = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfMatch", "I");
+       EXTLOGFONTWFc.elfReserved = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfReserved", "I");
+       EXTLOGFONTWFc.elfVendorId = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfVendorId", "[B");
+       EXTLOGFONTWFc.elfCulture = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfCulture", "I");
+       EXTLOGFONTWFc.elfPanose = (*env)->GetFieldID(env, EXTLOGFONTWFc.clazz, "elfPanose", "Lorg/eclipse/swt/internal/win32/PANOSE;");
+       EXTLOGFONTWFc.cached = 1;
+}
+
+EXTLOGFONTW *getEXTLOGFONTWFields(JNIEnv *env, jobject lpObject, EXTLOGFONTW *lpStruct)
+{
+       if (!EXTLOGFONTWFc.cached) cacheEXTLOGFONTWFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfLogFont);
+       if (lpObject1 != NULL) getLOGFONTFields(env, lpObject1, &lpStruct->elfLogFont);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfFullName);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->elfFullName) / sizeof(jchar), (jchar *)lpStruct->elfFullName);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfStyle);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->elfStyle) / sizeof(jchar), (jchar *)lpStruct->elfStyle);
+       }
+       lpStruct->elfVersion = (*env)->GetIntField(env, lpObject, EXTLOGFONTWFc.elfVersion);
+       lpStruct->elfStyleSize = (*env)->GetIntField(env, lpObject, EXTLOGFONTWFc.elfStyleSize);
+       lpStruct->elfMatch = (*env)->GetIntField(env, lpObject, EXTLOGFONTWFc.elfMatch);
+       lpStruct->elfReserved = (*env)->GetIntField(env, lpObject, EXTLOGFONTWFc.elfReserved);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfVendorId);
+       (*env)->GetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->elfVendorId), (jbyte *)lpStruct->elfVendorId);
+       }
+       lpStruct->elfCulture = (*env)->GetIntField(env, lpObject, EXTLOGFONTWFc.elfCulture);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfPanose);
+       if (lpObject1 != NULL) getPANOSEFields(env, lpObject1, &lpStruct->elfPanose);
+       }
+       return lpStruct;
+}
+
+void setEXTLOGFONTWFields(JNIEnv *env, jobject lpObject, EXTLOGFONTW *lpStruct)
+{
+       if (!EXTLOGFONTWFc.cached) cacheEXTLOGFONTWFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfLogFont);
+       if (lpObject1 != NULL) setLOGFONTFields(env, lpObject1, &lpStruct->elfLogFont);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfFullName);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->elfFullName) / sizeof(jchar), (jchar *)lpStruct->elfFullName);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfStyle);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->elfStyle) / sizeof(jchar), (jchar *)lpStruct->elfStyle);
+       }
+       (*env)->SetIntField(env, lpObject, EXTLOGFONTWFc.elfVersion, (jint)lpStruct->elfVersion);
+       (*env)->SetIntField(env, lpObject, EXTLOGFONTWFc.elfStyleSize, (jint)lpStruct->elfStyleSize);
+       (*env)->SetIntField(env, lpObject, EXTLOGFONTWFc.elfMatch, (jint)lpStruct->elfMatch);
+       (*env)->SetIntField(env, lpObject, EXTLOGFONTWFc.elfReserved, (jint)lpStruct->elfReserved);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfVendorId);
+       (*env)->SetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->elfVendorId), (jbyte *)lpStruct->elfVendorId);
+       }
+       (*env)->SetIntField(env, lpObject, EXTLOGFONTWFc.elfCulture, (jint)lpStruct->elfCulture);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, EXTLOGFONTWFc.elfPanose);
+       if (lpObject1 != NULL) setPANOSEFields(env, lpObject1, &lpStruct->elfPanose);
+       }
+}
+#endif
+
+#ifndef NO_FILETIME
+typedef struct FILETIME_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwLowDateTime, dwHighDateTime;
+} FILETIME_FID_CACHE;
+
+FILETIME_FID_CACHE FILETIMEFc;
+
+void cacheFILETIMEFields(JNIEnv *env, jobject lpObject)
+{
+       if (FILETIMEFc.cached) return;
+       FILETIMEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       FILETIMEFc.dwLowDateTime = (*env)->GetFieldID(env, FILETIMEFc.clazz, "dwLowDateTime", "I");
+       FILETIMEFc.dwHighDateTime = (*env)->GetFieldID(env, FILETIMEFc.clazz, "dwHighDateTime", "I");
+       FILETIMEFc.cached = 1;
+}
+
+FILETIME *getFILETIMEFields(JNIEnv *env, jobject lpObject, FILETIME *lpStruct)
+{
+       if (!FILETIMEFc.cached) cacheFILETIMEFields(env, lpObject);
+       lpStruct->dwLowDateTime = (*env)->GetIntField(env, lpObject, FILETIMEFc.dwLowDateTime);
+       lpStruct->dwHighDateTime = (*env)->GetIntField(env, lpObject, FILETIMEFc.dwHighDateTime);
+       return lpStruct;
+}
+
+void setFILETIMEFields(JNIEnv *env, jobject lpObject, FILETIME *lpStruct)
+{
+       if (!FILETIMEFc.cached) cacheFILETIMEFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, FILETIMEFc.dwLowDateTime, (jint)lpStruct->dwLowDateTime);
+       (*env)->SetIntField(env, lpObject, FILETIMEFc.dwHighDateTime, (jint)lpStruct->dwHighDateTime);
+}
+#endif
+
+#ifndef NO_FLICK_DATA
+typedef struct FLICK_DATA_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iFlickActionCommandCode, iFlickDirection, fControlModifier, fMenuModifier, fAltGRModifier, fWinModifier, fShiftModifier, iReserved, fOnInkingSurface, iActionArgument;
+} FLICK_DATA_FID_CACHE;
+
+FLICK_DATA_FID_CACHE FLICK_DATAFc;
+
+void cacheFLICK_DATAFields(JNIEnv *env, jobject lpObject)
+{
+       if (FLICK_DATAFc.cached) return;
+       FLICK_DATAFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       FLICK_DATAFc.iFlickActionCommandCode = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "iFlickActionCommandCode", "I");
+       FLICK_DATAFc.iFlickDirection = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "iFlickDirection", "B");
+       FLICK_DATAFc.fControlModifier = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "fControlModifier", "Z");
+       FLICK_DATAFc.fMenuModifier = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "fMenuModifier", "Z");
+       FLICK_DATAFc.fAltGRModifier = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "fAltGRModifier", "Z");
+       FLICK_DATAFc.fWinModifier = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "fWinModifier", "Z");
+       FLICK_DATAFc.fShiftModifier = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "fShiftModifier", "Z");
+       FLICK_DATAFc.iReserved = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "iReserved", "I");
+       FLICK_DATAFc.fOnInkingSurface = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "fOnInkingSurface", "Z");
+       FLICK_DATAFc.iActionArgument = (*env)->GetFieldID(env, FLICK_DATAFc.clazz, "iActionArgument", "I");
+       FLICK_DATAFc.cached = 1;
+}
+
+FLICK_DATA *getFLICK_DATAFields(JNIEnv *env, jobject lpObject, FLICK_DATA *lpStruct)
+{
+       if (!FLICK_DATAFc.cached) cacheFLICK_DATAFields(env, lpObject);
+       lpStruct->iFlickActionCommandCode = (*env)->GetIntField(env, lpObject, FLICK_DATAFc.iFlickActionCommandCode);
+       lpStruct->iFlickDirection = (*env)->GetByteField(env, lpObject, FLICK_DATAFc.iFlickDirection);
+       lpStruct->fControlModifier = (*env)->GetBooleanField(env, lpObject, FLICK_DATAFc.fControlModifier);
+       lpStruct->fMenuModifier = (*env)->GetBooleanField(env, lpObject, FLICK_DATAFc.fMenuModifier);
+       lpStruct->fAltGRModifier = (*env)->GetBooleanField(env, lpObject, FLICK_DATAFc.fAltGRModifier);
+       lpStruct->fWinModifier = (*env)->GetBooleanField(env, lpObject, FLICK_DATAFc.fWinModifier);
+       lpStruct->fShiftModifier = (*env)->GetBooleanField(env, lpObject, FLICK_DATAFc.fShiftModifier);
+       lpStruct->iReserved = (*env)->GetIntField(env, lpObject, FLICK_DATAFc.iReserved);
+       lpStruct->fOnInkingSurface = (*env)->GetBooleanField(env, lpObject, FLICK_DATAFc.fOnInkingSurface);
+       lpStruct->iActionArgument = (*env)->GetIntField(env, lpObject, FLICK_DATAFc.iActionArgument);
+       return lpStruct;
+}
+
+void setFLICK_DATAFields(JNIEnv *env, jobject lpObject, FLICK_DATA *lpStruct)
+{
+       if (!FLICK_DATAFc.cached) cacheFLICK_DATAFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, FLICK_DATAFc.iFlickActionCommandCode, (jint)lpStruct->iFlickActionCommandCode);
+       (*env)->SetByteField(env, lpObject, FLICK_DATAFc.iFlickDirection, (jbyte)lpStruct->iFlickDirection);
+       (*env)->SetBooleanField(env, lpObject, FLICK_DATAFc.fControlModifier, (jboolean)lpStruct->fControlModifier);
+       (*env)->SetBooleanField(env, lpObject, FLICK_DATAFc.fMenuModifier, (jboolean)lpStruct->fMenuModifier);
+       (*env)->SetBooleanField(env, lpObject, FLICK_DATAFc.fAltGRModifier, (jboolean)lpStruct->fAltGRModifier);
+       (*env)->SetBooleanField(env, lpObject, FLICK_DATAFc.fWinModifier, (jboolean)lpStruct->fWinModifier);
+       (*env)->SetBooleanField(env, lpObject, FLICK_DATAFc.fShiftModifier, (jboolean)lpStruct->fShiftModifier);
+       (*env)->SetIntField(env, lpObject, FLICK_DATAFc.iReserved, (jint)lpStruct->iReserved);
+       (*env)->SetBooleanField(env, lpObject, FLICK_DATAFc.fOnInkingSurface, (jboolean)lpStruct->fOnInkingSurface);
+       (*env)->SetIntField(env, lpObject, FLICK_DATAFc.iActionArgument, (jint)lpStruct->iActionArgument);
+}
+#endif
+
+#ifndef NO_FLICK_POINT
+typedef struct FLICK_POINT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y;
+} FLICK_POINT_FID_CACHE;
+
+FLICK_POINT_FID_CACHE FLICK_POINTFc;
+
+void cacheFLICK_POINTFields(JNIEnv *env, jobject lpObject)
+{
+       if (FLICK_POINTFc.cached) return;
+       FLICK_POINTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       FLICK_POINTFc.x = (*env)->GetFieldID(env, FLICK_POINTFc.clazz, "x", "I");
+       FLICK_POINTFc.y = (*env)->GetFieldID(env, FLICK_POINTFc.clazz, "y", "I");
+       FLICK_POINTFc.cached = 1;
+}
+
+FLICK_POINT *getFLICK_POINTFields(JNIEnv *env, jobject lpObject, FLICK_POINT *lpStruct)
+{
+       if (!FLICK_POINTFc.cached) cacheFLICK_POINTFields(env, lpObject);
+       lpStruct->x = (*env)->GetIntField(env, lpObject, FLICK_POINTFc.x);
+       lpStruct->y = (*env)->GetIntField(env, lpObject, FLICK_POINTFc.y);
+       return lpStruct;
+}
+
+void setFLICK_POINTFields(JNIEnv *env, jobject lpObject, FLICK_POINT *lpStruct)
+{
+       if (!FLICK_POINTFc.cached) cacheFLICK_POINTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, FLICK_POINTFc.x, (jint)lpStruct->x);
+       (*env)->SetIntField(env, lpObject, FLICK_POINTFc.y, (jint)lpStruct->y);
+}
+#endif
+
+#ifndef NO_GCP_RESULTS
+typedef struct GCP_RESULTS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lStructSize, lpOutString, lpOrder, lpDx, lpCaretPos, lpClass, lpGlyphs, nGlyphs, nMaxFit;
+} GCP_RESULTS_FID_CACHE;
+
+GCP_RESULTS_FID_CACHE GCP_RESULTSFc;
+
+void cacheGCP_RESULTSFields(JNIEnv *env, jobject lpObject)
+{
+       if (GCP_RESULTSFc.cached) return;
+       GCP_RESULTSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       GCP_RESULTSFc.lStructSize = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lStructSize", "I");
+       GCP_RESULTSFc.lpOutString = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lpOutString", "J");
+       GCP_RESULTSFc.lpOrder = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lpOrder", "J");
+       GCP_RESULTSFc.lpDx = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lpDx", "J");
+       GCP_RESULTSFc.lpCaretPos = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lpCaretPos", "J");
+       GCP_RESULTSFc.lpClass = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lpClass", "J");
+       GCP_RESULTSFc.lpGlyphs = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "lpGlyphs", "J");
+       GCP_RESULTSFc.nGlyphs = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "nGlyphs", "I");
+       GCP_RESULTSFc.nMaxFit = (*env)->GetFieldID(env, GCP_RESULTSFc.clazz, "nMaxFit", "I");
+       GCP_RESULTSFc.cached = 1;
+}
+
+GCP_RESULTS *getGCP_RESULTSFields(JNIEnv *env, jobject lpObject, GCP_RESULTS *lpStruct)
+{
+       if (!GCP_RESULTSFc.cached) cacheGCP_RESULTSFields(env, lpObject);
+       lpStruct->lStructSize = (*env)->GetIntField(env, lpObject, GCP_RESULTSFc.lStructSize);
+       lpStruct->lpOutString = (LPTSTR)(*env)->GetLongField(env, lpObject, GCP_RESULTSFc.lpOutString);
+       lpStruct->lpOrder = (UINT  *)(*env)->GetLongField(env, lpObject, GCP_RESULTSFc.lpOrder);
+       lpStruct->lpDx = (int  *)(*env)->GetLongField(env, lpObject, GCP_RESULTSFc.lpDx);
+       lpStruct->lpCaretPos = (int  *)(*env)->GetLongField(env, lpObject, GCP_RESULTSFc.lpCaretPos);
+       lpStruct->lpClass = (LPSTR)(*env)->GetLongField(env, lpObject, GCP_RESULTSFc.lpClass);
+       lpStruct->lpGlyphs = (LPWSTR)(*env)->GetLongField(env, lpObject, GCP_RESULTSFc.lpGlyphs);
+       lpStruct->nGlyphs = (*env)->GetIntField(env, lpObject, GCP_RESULTSFc.nGlyphs);
+       lpStruct->nMaxFit = (*env)->GetIntField(env, lpObject, GCP_RESULTSFc.nMaxFit);
+       return lpStruct;
+}
+
+void setGCP_RESULTSFields(JNIEnv *env, jobject lpObject, GCP_RESULTS *lpStruct)
+{
+       if (!GCP_RESULTSFc.cached) cacheGCP_RESULTSFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, GCP_RESULTSFc.lStructSize, (jint)lpStruct->lStructSize);
+       (*env)->SetLongField(env, lpObject, GCP_RESULTSFc.lpOutString, (jlong)lpStruct->lpOutString);
+       (*env)->SetLongField(env, lpObject, GCP_RESULTSFc.lpOrder, (jlong)lpStruct->lpOrder);
+       (*env)->SetLongField(env, lpObject, GCP_RESULTSFc.lpDx, (jlong)lpStruct->lpDx);
+       (*env)->SetLongField(env, lpObject, GCP_RESULTSFc.lpCaretPos, (jlong)lpStruct->lpCaretPos);
+       (*env)->SetLongField(env, lpObject, GCP_RESULTSFc.lpClass, (jlong)lpStruct->lpClass);
+       (*env)->SetLongField(env, lpObject, GCP_RESULTSFc.lpGlyphs, (jlong)lpStruct->lpGlyphs);
+       (*env)->SetIntField(env, lpObject, GCP_RESULTSFc.nGlyphs, (jint)lpStruct->nGlyphs);
+       (*env)->SetIntField(env, lpObject, GCP_RESULTSFc.nMaxFit, (jint)lpStruct->nMaxFit);
+}
+#endif
+
+#ifndef NO_GESTURECONFIG
+typedef struct GESTURECONFIG_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwID, dwWant, dwBlock;
+} GESTURECONFIG_FID_CACHE;
+
+GESTURECONFIG_FID_CACHE GESTURECONFIGFc;
+
+void cacheGESTURECONFIGFields(JNIEnv *env, jobject lpObject)
+{
+       if (GESTURECONFIGFc.cached) return;
+       GESTURECONFIGFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       GESTURECONFIGFc.dwID = (*env)->GetFieldID(env, GESTURECONFIGFc.clazz, "dwID", "I");
+       GESTURECONFIGFc.dwWant = (*env)->GetFieldID(env, GESTURECONFIGFc.clazz, "dwWant", "I");
+       GESTURECONFIGFc.dwBlock = (*env)->GetFieldID(env, GESTURECONFIGFc.clazz, "dwBlock", "I");
+       GESTURECONFIGFc.cached = 1;
+}
+
+GESTURECONFIG *getGESTURECONFIGFields(JNIEnv *env, jobject lpObject, GESTURECONFIG *lpStruct)
+{
+       if (!GESTURECONFIGFc.cached) cacheGESTURECONFIGFields(env, lpObject);
+       lpStruct->dwID = (*env)->GetIntField(env, lpObject, GESTURECONFIGFc.dwID);
+       lpStruct->dwWant = (*env)->GetIntField(env, lpObject, GESTURECONFIGFc.dwWant);
+       lpStruct->dwBlock = (*env)->GetIntField(env, lpObject, GESTURECONFIGFc.dwBlock);
+       return lpStruct;
+}
+
+void setGESTURECONFIGFields(JNIEnv *env, jobject lpObject, GESTURECONFIG *lpStruct)
+{
+       if (!GESTURECONFIGFc.cached) cacheGESTURECONFIGFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, GESTURECONFIGFc.dwID, (jint)lpStruct->dwID);
+       (*env)->SetIntField(env, lpObject, GESTURECONFIGFc.dwWant, (jint)lpStruct->dwWant);
+       (*env)->SetIntField(env, lpObject, GESTURECONFIGFc.dwBlock, (jint)lpStruct->dwBlock);
+}
+#endif
+
+#ifndef NO_GESTUREINFO
+typedef struct GESTUREINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, dwID, hwndTarget, x, y, dwInstanceID, dwSequenceID, ullArguments, cbExtraArgs;
+} GESTUREINFO_FID_CACHE;
+
+GESTUREINFO_FID_CACHE GESTUREINFOFc;
+
+void cacheGESTUREINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (GESTUREINFOFc.cached) return;
+       GESTUREINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       GESTUREINFOFc.cbSize = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "cbSize", "I");
+       GESTUREINFOFc.dwFlags = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "dwFlags", "I");
+       GESTUREINFOFc.dwID = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "dwID", "I");
+       GESTUREINFOFc.hwndTarget = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "hwndTarget", "J");
+       GESTUREINFOFc.x = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "x", "S");
+       GESTUREINFOFc.y = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "y", "S");
+       GESTUREINFOFc.dwInstanceID = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "dwInstanceID", "I");
+       GESTUREINFOFc.dwSequenceID = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "dwSequenceID", "I");
+       GESTUREINFOFc.ullArguments = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "ullArguments", "J");
+       GESTUREINFOFc.cbExtraArgs = (*env)->GetFieldID(env, GESTUREINFOFc.clazz, "cbExtraArgs", "I");
+       GESTUREINFOFc.cached = 1;
+}
+
+GESTUREINFO *getGESTUREINFOFields(JNIEnv *env, jobject lpObject, GESTUREINFO *lpStruct)
+{
+       if (!GESTUREINFOFc.cached) cacheGESTUREINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, GESTUREINFOFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, GESTUREINFOFc.dwFlags);
+       lpStruct->dwID = (*env)->GetIntField(env, lpObject, GESTUREINFOFc.dwID);
+       lpStruct->hwndTarget = (HWND)(*env)->GetLongField(env, lpObject, GESTUREINFOFc.hwndTarget);
+       lpStruct->ptsLocation.x = (*env)->GetShortField(env, lpObject, GESTUREINFOFc.x);
+       lpStruct->ptsLocation.y = (*env)->GetShortField(env, lpObject, GESTUREINFOFc.y);
+       lpStruct->dwInstanceID = (*env)->GetIntField(env, lpObject, GESTUREINFOFc.dwInstanceID);
+       lpStruct->dwSequenceID = (*env)->GetIntField(env, lpObject, GESTUREINFOFc.dwSequenceID);
+       lpStruct->ullArguments = (*env)->GetLongField(env, lpObject, GESTUREINFOFc.ullArguments);
+       lpStruct->cbExtraArgs = (*env)->GetIntField(env, lpObject, GESTUREINFOFc.cbExtraArgs);
+       return lpStruct;
+}
+
+void setGESTUREINFOFields(JNIEnv *env, jobject lpObject, GESTUREINFO *lpStruct)
+{
+       if (!GESTUREINFOFc.cached) cacheGESTUREINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, GESTUREINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, GESTUREINFOFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, GESTUREINFOFc.dwID, (jint)lpStruct->dwID);
+       (*env)->SetLongField(env, lpObject, GESTUREINFOFc.hwndTarget, (jlong)lpStruct->hwndTarget);
+       (*env)->SetShortField(env, lpObject, GESTUREINFOFc.x, (jshort)lpStruct->ptsLocation.x);
+       (*env)->SetShortField(env, lpObject, GESTUREINFOFc.y, (jshort)lpStruct->ptsLocation.y);
+       (*env)->SetIntField(env, lpObject, GESTUREINFOFc.dwInstanceID, (jint)lpStruct->dwInstanceID);
+       (*env)->SetIntField(env, lpObject, GESTUREINFOFc.dwSequenceID, (jint)lpStruct->dwSequenceID);
+       (*env)->SetLongField(env, lpObject, GESTUREINFOFc.ullArguments, (jlong)lpStruct->ullArguments);
+       (*env)->SetIntField(env, lpObject, GESTUREINFOFc.cbExtraArgs, (jint)lpStruct->cbExtraArgs);
+}
+#endif
+
+#ifndef NO_GRADIENT_RECT
+typedef struct GRADIENT_RECT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID UpperLeft, LowerRight;
+} GRADIENT_RECT_FID_CACHE;
+
+GRADIENT_RECT_FID_CACHE GRADIENT_RECTFc;
+
+void cacheGRADIENT_RECTFields(JNIEnv *env, jobject lpObject)
+{
+       if (GRADIENT_RECTFc.cached) return;
+       GRADIENT_RECTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       GRADIENT_RECTFc.UpperLeft = (*env)->GetFieldID(env, GRADIENT_RECTFc.clazz, "UpperLeft", "I");
+       GRADIENT_RECTFc.LowerRight = (*env)->GetFieldID(env, GRADIENT_RECTFc.clazz, "LowerRight", "I");
+       GRADIENT_RECTFc.cached = 1;
+}
+
+GRADIENT_RECT *getGRADIENT_RECTFields(JNIEnv *env, jobject lpObject, GRADIENT_RECT *lpStruct)
+{
+       if (!GRADIENT_RECTFc.cached) cacheGRADIENT_RECTFields(env, lpObject);
+       lpStruct->UpperLeft = (*env)->GetIntField(env, lpObject, GRADIENT_RECTFc.UpperLeft);
+       lpStruct->LowerRight = (*env)->GetIntField(env, lpObject, GRADIENT_RECTFc.LowerRight);
+       return lpStruct;
+}
+
+void setGRADIENT_RECTFields(JNIEnv *env, jobject lpObject, GRADIENT_RECT *lpStruct)
+{
+       if (!GRADIENT_RECTFc.cached) cacheGRADIENT_RECTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, GRADIENT_RECTFc.UpperLeft, (jint)lpStruct->UpperLeft);
+       (*env)->SetIntField(env, lpObject, GRADIENT_RECTFc.LowerRight, (jint)lpStruct->LowerRight);
+}
+#endif
+
+#ifndef NO_GUITHREADINFO
+typedef struct GUITHREADINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, flags, hwndActive, hwndFocus, hwndCapture, hwndMenuOwner, hwndMoveSize, hwndCaret, left, top, right, bottom;
+} GUITHREADINFO_FID_CACHE;
+
+GUITHREADINFO_FID_CACHE GUITHREADINFOFc;
+
+void cacheGUITHREADINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (GUITHREADINFOFc.cached) return;
+       GUITHREADINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       GUITHREADINFOFc.cbSize = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "cbSize", "I");
+       GUITHREADINFOFc.flags = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "flags", "I");
+       GUITHREADINFOFc.hwndActive = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "hwndActive", "J");
+       GUITHREADINFOFc.hwndFocus = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "hwndFocus", "J");
+       GUITHREADINFOFc.hwndCapture = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "hwndCapture", "J");
+       GUITHREADINFOFc.hwndMenuOwner = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "hwndMenuOwner", "J");
+       GUITHREADINFOFc.hwndMoveSize = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "hwndMoveSize", "J");
+       GUITHREADINFOFc.hwndCaret = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "hwndCaret", "J");
+       GUITHREADINFOFc.left = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "left", "I");
+       GUITHREADINFOFc.top = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "top", "I");
+       GUITHREADINFOFc.right = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "right", "I");
+       GUITHREADINFOFc.bottom = (*env)->GetFieldID(env, GUITHREADINFOFc.clazz, "bottom", "I");
+       GUITHREADINFOFc.cached = 1;
+}
+
+GUITHREADINFO *getGUITHREADINFOFields(JNIEnv *env, jobject lpObject, GUITHREADINFO *lpStruct)
+{
+       if (!GUITHREADINFOFc.cached) cacheGUITHREADINFOFields(env, lpObject);
+       lpStruct->cbSize = (DWORD)(*env)->GetIntField(env, lpObject, GUITHREADINFOFc.cbSize);
+       lpStruct->flags = (DWORD)(*env)->GetIntField(env, lpObject, GUITHREADINFOFc.flags);
+       lpStruct->hwndActive = (HWND)(*env)->GetLongField(env, lpObject, GUITHREADINFOFc.hwndActive);
+       lpStruct->hwndFocus = (HWND)(*env)->GetLongField(env, lpObject, GUITHREADINFOFc.hwndFocus);
+       lpStruct->hwndCapture = (HWND)(*env)->GetLongField(env, lpObject, GUITHREADINFOFc.hwndCapture);
+       lpStruct->hwndMenuOwner = (HWND)(*env)->GetLongField(env, lpObject, GUITHREADINFOFc.hwndMenuOwner);
+       lpStruct->hwndMoveSize = (HWND)(*env)->GetLongField(env, lpObject, GUITHREADINFOFc.hwndMoveSize);
+       lpStruct->hwndCaret = (HWND)(*env)->GetLongField(env, lpObject, GUITHREADINFOFc.hwndCaret);
+       lpStruct->rcCaret.left = (*env)->GetIntField(env, lpObject, GUITHREADINFOFc.left);
+       lpStruct->rcCaret.top = (*env)->GetIntField(env, lpObject, GUITHREADINFOFc.top);
+       lpStruct->rcCaret.right = (*env)->GetIntField(env, lpObject, GUITHREADINFOFc.right);
+       lpStruct->rcCaret.bottom = (*env)->GetIntField(env, lpObject, GUITHREADINFOFc.bottom);
+       return lpStruct;
+}
+
+void setGUITHREADINFOFields(JNIEnv *env, jobject lpObject, GUITHREADINFO *lpStruct)
+{
+       if (!GUITHREADINFOFc.cached) cacheGUITHREADINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, GUITHREADINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, GUITHREADINFOFc.flags, (jint)lpStruct->flags);
+       (*env)->SetLongField(env, lpObject, GUITHREADINFOFc.hwndActive, (jlong)lpStruct->hwndActive);
+       (*env)->SetLongField(env, lpObject, GUITHREADINFOFc.hwndFocus, (jlong)lpStruct->hwndFocus);
+       (*env)->SetLongField(env, lpObject, GUITHREADINFOFc.hwndCapture, (jlong)lpStruct->hwndCapture);
+       (*env)->SetLongField(env, lpObject, GUITHREADINFOFc.hwndMenuOwner, (jlong)lpStruct->hwndMenuOwner);
+       (*env)->SetLongField(env, lpObject, GUITHREADINFOFc.hwndMoveSize, (jlong)lpStruct->hwndMoveSize);
+       (*env)->SetLongField(env, lpObject, GUITHREADINFOFc.hwndCaret, (jlong)lpStruct->hwndCaret);
+       (*env)->SetIntField(env, lpObject, GUITHREADINFOFc.left, (jint)lpStruct->rcCaret.left);
+       (*env)->SetIntField(env, lpObject, GUITHREADINFOFc.top, (jint)lpStruct->rcCaret.top);
+       (*env)->SetIntField(env, lpObject, GUITHREADINFOFc.right, (jint)lpStruct->rcCaret.right);
+       (*env)->SetIntField(env, lpObject, GUITHREADINFOFc.bottom, (jint)lpStruct->rcCaret.bottom);
+}
+#endif
+
+#ifndef NO_HDHITTESTINFO
+typedef struct HDHITTESTINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y, flags, iItem;
+} HDHITTESTINFO_FID_CACHE;
+
+HDHITTESTINFO_FID_CACHE HDHITTESTINFOFc;
+
+void cacheHDHITTESTINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (HDHITTESTINFOFc.cached) return;
+       HDHITTESTINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       HDHITTESTINFOFc.x = (*env)->GetFieldID(env, HDHITTESTINFOFc.clazz, "x", "I");
+       HDHITTESTINFOFc.y = (*env)->GetFieldID(env, HDHITTESTINFOFc.clazz, "y", "I");
+       HDHITTESTINFOFc.flags = (*env)->GetFieldID(env, HDHITTESTINFOFc.clazz, "flags", "I");
+       HDHITTESTINFOFc.iItem = (*env)->GetFieldID(env, HDHITTESTINFOFc.clazz, "iItem", "I");
+       HDHITTESTINFOFc.cached = 1;
+}
+
+HDHITTESTINFO *getHDHITTESTINFOFields(JNIEnv *env, jobject lpObject, HDHITTESTINFO *lpStruct)
+{
+       if (!HDHITTESTINFOFc.cached) cacheHDHITTESTINFOFields(env, lpObject);
+       lpStruct->pt.x = (*env)->GetIntField(env, lpObject, HDHITTESTINFOFc.x);
+       lpStruct->pt.y = (*env)->GetIntField(env, lpObject, HDHITTESTINFOFc.y);
+       lpStruct->flags = (*env)->GetIntField(env, lpObject, HDHITTESTINFOFc.flags);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, HDHITTESTINFOFc.iItem);
+       return lpStruct;
+}
+
+void setHDHITTESTINFOFields(JNIEnv *env, jobject lpObject, HDHITTESTINFO *lpStruct)
+{
+       if (!HDHITTESTINFOFc.cached) cacheHDHITTESTINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, HDHITTESTINFOFc.x, (jint)lpStruct->pt.x);
+       (*env)->SetIntField(env, lpObject, HDHITTESTINFOFc.y, (jint)lpStruct->pt.y);
+       (*env)->SetIntField(env, lpObject, HDHITTESTINFOFc.flags, (jint)lpStruct->flags);
+       (*env)->SetIntField(env, lpObject, HDHITTESTINFOFc.iItem, (jint)lpStruct->iItem);
+}
+#endif
+
+#ifndef NO_HDITEM
+typedef struct HDITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, cxy, pszText, hbm, cchTextMax, fmt, lParam, iImage, iOrder, type, pvFilter;
+} HDITEM_FID_CACHE;
+
+HDITEM_FID_CACHE HDITEMFc;
+
+void cacheHDITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (HDITEMFc.cached) return;
+       HDITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       HDITEMFc.mask = (*env)->GetFieldID(env, HDITEMFc.clazz, "mask", "I");
+       HDITEMFc.cxy = (*env)->GetFieldID(env, HDITEMFc.clazz, "cxy", "I");
+       HDITEMFc.pszText = (*env)->GetFieldID(env, HDITEMFc.clazz, "pszText", "J");
+       HDITEMFc.hbm = (*env)->GetFieldID(env, HDITEMFc.clazz, "hbm", "J");
+       HDITEMFc.cchTextMax = (*env)->GetFieldID(env, HDITEMFc.clazz, "cchTextMax", "I");
+       HDITEMFc.fmt = (*env)->GetFieldID(env, HDITEMFc.clazz, "fmt", "I");
+       HDITEMFc.lParam = (*env)->GetFieldID(env, HDITEMFc.clazz, "lParam", "J");
+       HDITEMFc.iImage = (*env)->GetFieldID(env, HDITEMFc.clazz, "iImage", "I");
+       HDITEMFc.iOrder = (*env)->GetFieldID(env, HDITEMFc.clazz, "iOrder", "I");
+       HDITEMFc.type = (*env)->GetFieldID(env, HDITEMFc.clazz, "type", "I");
+       HDITEMFc.pvFilter = (*env)->GetFieldID(env, HDITEMFc.clazz, "pvFilter", "J");
+       HDITEMFc.cached = 1;
+}
+
+HDITEM *getHDITEMFields(JNIEnv *env, jobject lpObject, HDITEM *lpStruct)
+{
+       if (!HDITEMFc.cached) cacheHDITEMFields(env, lpObject);
+       lpStruct->mask = (*env)->GetIntField(env, lpObject, HDITEMFc.mask);
+       lpStruct->cxy = (*env)->GetIntField(env, lpObject, HDITEMFc.cxy);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, HDITEMFc.pszText);
+       lpStruct->hbm = (HBITMAP)(*env)->GetLongField(env, lpObject, HDITEMFc.hbm);
+       lpStruct->cchTextMax = (*env)->GetIntField(env, lpObject, HDITEMFc.cchTextMax);
+       lpStruct->fmt = (*env)->GetIntField(env, lpObject, HDITEMFc.fmt);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, HDITEMFc.lParam);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, HDITEMFc.iImage);
+       lpStruct->iOrder = (*env)->GetIntField(env, lpObject, HDITEMFc.iOrder);
+       lpStruct->type = (*env)->GetIntField(env, lpObject, HDITEMFc.type);
+       lpStruct->pvFilter = (void *)(*env)->GetLongField(env, lpObject, HDITEMFc.pvFilter);
+       return lpStruct;
+}
+
+void setHDITEMFields(JNIEnv *env, jobject lpObject, HDITEM *lpStruct)
+{
+       if (!HDITEMFc.cached) cacheHDITEMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.mask, (jint)lpStruct->mask);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.cxy, (jint)lpStruct->cxy);
+       (*env)->SetLongField(env, lpObject, HDITEMFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetLongField(env, lpObject, HDITEMFc.hbm, (jlong)lpStruct->hbm);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.cchTextMax, (jint)lpStruct->cchTextMax);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.fmt, (jint)lpStruct->fmt);
+       (*env)->SetLongField(env, lpObject, HDITEMFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.iOrder, (jint)lpStruct->iOrder);
+       (*env)->SetIntField(env, lpObject, HDITEMFc.type, (jint)lpStruct->type);
+       (*env)->SetLongField(env, lpObject, HDITEMFc.pvFilter, (jlong)lpStruct->pvFilter);
+}
+#endif
+
+#ifndef NO_HDLAYOUT
+typedef struct HDLAYOUT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID prc, pwpos;
+} HDLAYOUT_FID_CACHE;
+
+HDLAYOUT_FID_CACHE HDLAYOUTFc;
+
+void cacheHDLAYOUTFields(JNIEnv *env, jobject lpObject)
+{
+       if (HDLAYOUTFc.cached) return;
+       HDLAYOUTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       HDLAYOUTFc.prc = (*env)->GetFieldID(env, HDLAYOUTFc.clazz, "prc", "J");
+       HDLAYOUTFc.pwpos = (*env)->GetFieldID(env, HDLAYOUTFc.clazz, "pwpos", "J");
+       HDLAYOUTFc.cached = 1;
+}
+
+HDLAYOUT *getHDLAYOUTFields(JNIEnv *env, jobject lpObject, HDLAYOUT *lpStruct)
+{
+       if (!HDLAYOUTFc.cached) cacheHDLAYOUTFields(env, lpObject);
+       lpStruct->prc = (RECT *)(*env)->GetLongField(env, lpObject, HDLAYOUTFc.prc);
+       lpStruct->pwpos = (WINDOWPOS *)(*env)->GetLongField(env, lpObject, HDLAYOUTFc.pwpos);
+       return lpStruct;
+}
+
+void setHDLAYOUTFields(JNIEnv *env, jobject lpObject, HDLAYOUT *lpStruct)
+{
+       if (!HDLAYOUTFc.cached) cacheHDLAYOUTFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, HDLAYOUTFc.prc, (jlong)lpStruct->prc);
+       (*env)->SetLongField(env, lpObject, HDLAYOUTFc.pwpos, (jlong)lpStruct->pwpos);
+}
+#endif
+
+#ifndef NO_HELPINFO
+typedef struct HELPINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, iContextType, iCtrlId, hItemHandle, dwContextId, x, y;
+} HELPINFO_FID_CACHE;
+
+HELPINFO_FID_CACHE HELPINFOFc;
+
+void cacheHELPINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (HELPINFOFc.cached) return;
+       HELPINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       HELPINFOFc.cbSize = (*env)->GetFieldID(env, HELPINFOFc.clazz, "cbSize", "I");
+       HELPINFOFc.iContextType = (*env)->GetFieldID(env, HELPINFOFc.clazz, "iContextType", "I");
+       HELPINFOFc.iCtrlId = (*env)->GetFieldID(env, HELPINFOFc.clazz, "iCtrlId", "I");
+       HELPINFOFc.hItemHandle = (*env)->GetFieldID(env, HELPINFOFc.clazz, "hItemHandle", "J");
+       HELPINFOFc.dwContextId = (*env)->GetFieldID(env, HELPINFOFc.clazz, "dwContextId", "I");
+       HELPINFOFc.x = (*env)->GetFieldID(env, HELPINFOFc.clazz, "x", "I");
+       HELPINFOFc.y = (*env)->GetFieldID(env, HELPINFOFc.clazz, "y", "I");
+       HELPINFOFc.cached = 1;
+}
+
+HELPINFO *getHELPINFOFields(JNIEnv *env, jobject lpObject, HELPINFO *lpStruct)
+{
+       if (!HELPINFOFc.cached) cacheHELPINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, HELPINFOFc.cbSize);
+       lpStruct->iContextType = (*env)->GetIntField(env, lpObject, HELPINFOFc.iContextType);
+       lpStruct->iCtrlId = (*env)->GetIntField(env, lpObject, HELPINFOFc.iCtrlId);
+       lpStruct->hItemHandle = (HANDLE)(*env)->GetLongField(env, lpObject, HELPINFOFc.hItemHandle);
+       lpStruct->dwContextId = (*env)->GetIntField(env, lpObject, HELPINFOFc.dwContextId);
+       lpStruct->MousePos.x = (*env)->GetIntField(env, lpObject, HELPINFOFc.x);
+       lpStruct->MousePos.y = (*env)->GetIntField(env, lpObject, HELPINFOFc.y);
+       return lpStruct;
+}
+
+void setHELPINFOFields(JNIEnv *env, jobject lpObject, HELPINFO *lpStruct)
+{
+       if (!HELPINFOFc.cached) cacheHELPINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, HELPINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, HELPINFOFc.iContextType, (jint)lpStruct->iContextType);
+       (*env)->SetIntField(env, lpObject, HELPINFOFc.iCtrlId, (jint)lpStruct->iCtrlId);
+       (*env)->SetLongField(env, lpObject, HELPINFOFc.hItemHandle, (jlong)lpStruct->hItemHandle);
+       (*env)->SetIntField(env, lpObject, HELPINFOFc.dwContextId, (jint)lpStruct->dwContextId);
+       (*env)->SetIntField(env, lpObject, HELPINFOFc.x, (jint)lpStruct->MousePos.x);
+       (*env)->SetIntField(env, lpObject, HELPINFOFc.y, (jint)lpStruct->MousePos.y);
+}
+#endif
+
+#ifndef NO_HIGHCONTRAST
+typedef struct HIGHCONTRAST_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, lpszDefaultScheme;
+} HIGHCONTRAST_FID_CACHE;
+
+HIGHCONTRAST_FID_CACHE HIGHCONTRASTFc;
+
+void cacheHIGHCONTRASTFields(JNIEnv *env, jobject lpObject)
+{
+       if (HIGHCONTRASTFc.cached) return;
+       HIGHCONTRASTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       HIGHCONTRASTFc.cbSize = (*env)->GetFieldID(env, HIGHCONTRASTFc.clazz, "cbSize", "I");
+       HIGHCONTRASTFc.dwFlags = (*env)->GetFieldID(env, HIGHCONTRASTFc.clazz, "dwFlags", "I");
+       HIGHCONTRASTFc.lpszDefaultScheme = (*env)->GetFieldID(env, HIGHCONTRASTFc.clazz, "lpszDefaultScheme", "J");
+       HIGHCONTRASTFc.cached = 1;
+}
+
+HIGHCONTRAST *getHIGHCONTRASTFields(JNIEnv *env, jobject lpObject, HIGHCONTRAST *lpStruct)
+{
+       if (!HIGHCONTRASTFc.cached) cacheHIGHCONTRASTFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, HIGHCONTRASTFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, HIGHCONTRASTFc.dwFlags);
+       lpStruct->lpszDefaultScheme = (LPTSTR)(*env)->GetLongField(env, lpObject, HIGHCONTRASTFc.lpszDefaultScheme);
+       return lpStruct;
+}
+
+void setHIGHCONTRASTFields(JNIEnv *env, jobject lpObject, HIGHCONTRAST *lpStruct)
+{
+       if (!HIGHCONTRASTFc.cached) cacheHIGHCONTRASTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, HIGHCONTRASTFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, HIGHCONTRASTFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetLongField(env, lpObject, HIGHCONTRASTFc.lpszDefaultScheme, (jlong)lpStruct->lpszDefaultScheme);
+}
+#endif
+
+#ifndef NO_ICONINFO
+typedef struct ICONINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID fIcon, xHotspot, yHotspot, hbmMask, hbmColor;
+} ICONINFO_FID_CACHE;
+
+ICONINFO_FID_CACHE ICONINFOFc;
+
+void cacheICONINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (ICONINFOFc.cached) return;
+       ICONINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       ICONINFOFc.fIcon = (*env)->GetFieldID(env, ICONINFOFc.clazz, "fIcon", "Z");
+       ICONINFOFc.xHotspot = (*env)->GetFieldID(env, ICONINFOFc.clazz, "xHotspot", "I");
+       ICONINFOFc.yHotspot = (*env)->GetFieldID(env, ICONINFOFc.clazz, "yHotspot", "I");
+       ICONINFOFc.hbmMask = (*env)->GetFieldID(env, ICONINFOFc.clazz, "hbmMask", "J");
+       ICONINFOFc.hbmColor = (*env)->GetFieldID(env, ICONINFOFc.clazz, "hbmColor", "J");
+       ICONINFOFc.cached = 1;
+}
+
+ICONINFO *getICONINFOFields(JNIEnv *env, jobject lpObject, ICONINFO *lpStruct)
+{
+       if (!ICONINFOFc.cached) cacheICONINFOFields(env, lpObject);
+       lpStruct->fIcon = (*env)->GetBooleanField(env, lpObject, ICONINFOFc.fIcon);
+       lpStruct->xHotspot = (*env)->GetIntField(env, lpObject, ICONINFOFc.xHotspot);
+       lpStruct->yHotspot = (*env)->GetIntField(env, lpObject, ICONINFOFc.yHotspot);
+       lpStruct->hbmMask = (HBITMAP)(*env)->GetLongField(env, lpObject, ICONINFOFc.hbmMask);
+       lpStruct->hbmColor = (HBITMAP)(*env)->GetLongField(env, lpObject, ICONINFOFc.hbmColor);
+       return lpStruct;
+}
+
+void setICONINFOFields(JNIEnv *env, jobject lpObject, ICONINFO *lpStruct)
+{
+       if (!ICONINFOFc.cached) cacheICONINFOFields(env, lpObject);
+       (*env)->SetBooleanField(env, lpObject, ICONINFOFc.fIcon, (jboolean)lpStruct->fIcon);
+       (*env)->SetIntField(env, lpObject, ICONINFOFc.xHotspot, (jint)lpStruct->xHotspot);
+       (*env)->SetIntField(env, lpObject, ICONINFOFc.yHotspot, (jint)lpStruct->yHotspot);
+       (*env)->SetLongField(env, lpObject, ICONINFOFc.hbmMask, (jlong)lpStruct->hbmMask);
+       (*env)->SetLongField(env, lpObject, ICONINFOFc.hbmColor, (jlong)lpStruct->hbmColor);
+}
+#endif
+
+#ifndef NO_INITCOMMONCONTROLSEX
+typedef struct INITCOMMONCONTROLSEX_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwSize, dwICC;
+} INITCOMMONCONTROLSEX_FID_CACHE;
+
+INITCOMMONCONTROLSEX_FID_CACHE INITCOMMONCONTROLSEXFc;
+
+void cacheINITCOMMONCONTROLSEXFields(JNIEnv *env, jobject lpObject)
+{
+       if (INITCOMMONCONTROLSEXFc.cached) return;
+       INITCOMMONCONTROLSEXFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       INITCOMMONCONTROLSEXFc.dwSize = (*env)->GetFieldID(env, INITCOMMONCONTROLSEXFc.clazz, "dwSize", "I");
+       INITCOMMONCONTROLSEXFc.dwICC = (*env)->GetFieldID(env, INITCOMMONCONTROLSEXFc.clazz, "dwICC", "I");
+       INITCOMMONCONTROLSEXFc.cached = 1;
+}
+
+INITCOMMONCONTROLSEX *getINITCOMMONCONTROLSEXFields(JNIEnv *env, jobject lpObject, INITCOMMONCONTROLSEX *lpStruct)
+{
+       if (!INITCOMMONCONTROLSEXFc.cached) cacheINITCOMMONCONTROLSEXFields(env, lpObject);
+       lpStruct->dwSize = (*env)->GetIntField(env, lpObject, INITCOMMONCONTROLSEXFc.dwSize);
+       lpStruct->dwICC = (*env)->GetIntField(env, lpObject, INITCOMMONCONTROLSEXFc.dwICC);
+       return lpStruct;
+}
+
+void setINITCOMMONCONTROLSEXFields(JNIEnv *env, jobject lpObject, INITCOMMONCONTROLSEX *lpStruct)
+{
+       if (!INITCOMMONCONTROLSEXFc.cached) cacheINITCOMMONCONTROLSEXFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, INITCOMMONCONTROLSEXFc.dwSize, (jint)lpStruct->dwSize);
+       (*env)->SetIntField(env, lpObject, INITCOMMONCONTROLSEXFc.dwICC, (jint)lpStruct->dwICC);
+}
+#endif
+
+#ifndef NO_INPUT
+typedef struct INPUT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID type;
+} INPUT_FID_CACHE;
+
+INPUT_FID_CACHE INPUTFc;
+
+void cacheINPUTFields(JNIEnv *env, jobject lpObject)
+{
+       if (INPUTFc.cached) return;
+       INPUTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       INPUTFc.type = (*env)->GetFieldID(env, INPUTFc.clazz, "type", "I");
+       INPUTFc.cached = 1;
+}
+
+INPUT *getINPUTFields(JNIEnv *env, jobject lpObject, INPUT *lpStruct)
+{
+       if (!INPUTFc.cached) cacheINPUTFields(env, lpObject);
+       lpStruct->type = (*env)->GetIntField(env, lpObject, INPUTFc.type);
+       return lpStruct;
+}
+
+void setINPUTFields(JNIEnv *env, jobject lpObject, INPUT *lpStruct)
+{
+       if (!INPUTFc.cached) cacheINPUTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, INPUTFc.type, (jint)lpStruct->type);
+}
+#endif
+
+#ifndef NO_KEYBDINPUT
+typedef struct KEYBDINPUT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID wVk, wScan, dwFlags, time, dwExtraInfo;
+} KEYBDINPUT_FID_CACHE;
+
+KEYBDINPUT_FID_CACHE KEYBDINPUTFc;
+
+void cacheKEYBDINPUTFields(JNIEnv *env, jobject lpObject)
+{
+       if (KEYBDINPUTFc.cached) return;
+       KEYBDINPUTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       KEYBDINPUTFc.wVk = (*env)->GetFieldID(env, KEYBDINPUTFc.clazz, "wVk", "S");
+       KEYBDINPUTFc.wScan = (*env)->GetFieldID(env, KEYBDINPUTFc.clazz, "wScan", "S");
+       KEYBDINPUTFc.dwFlags = (*env)->GetFieldID(env, KEYBDINPUTFc.clazz, "dwFlags", "I");
+       KEYBDINPUTFc.time = (*env)->GetFieldID(env, KEYBDINPUTFc.clazz, "time", "I");
+       KEYBDINPUTFc.dwExtraInfo = (*env)->GetFieldID(env, KEYBDINPUTFc.clazz, "dwExtraInfo", "J");
+       KEYBDINPUTFc.cached = 1;
+}
+
+KEYBDINPUT *getKEYBDINPUTFields(JNIEnv *env, jobject lpObject, KEYBDINPUT *lpStruct)
+{
+       if (!KEYBDINPUTFc.cached) cacheKEYBDINPUTFields(env, lpObject);
+       lpStruct->wVk = (*env)->GetShortField(env, lpObject, KEYBDINPUTFc.wVk);
+       lpStruct->wScan = (*env)->GetShortField(env, lpObject, KEYBDINPUTFc.wScan);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, KEYBDINPUTFc.dwFlags);
+       lpStruct->time = (*env)->GetIntField(env, lpObject, KEYBDINPUTFc.time);
+       lpStruct->dwExtraInfo = (*env)->GetLongField(env, lpObject, KEYBDINPUTFc.dwExtraInfo);
+       return lpStruct;
+}
+
+void setKEYBDINPUTFields(JNIEnv *env, jobject lpObject, KEYBDINPUT *lpStruct)
+{
+       if (!KEYBDINPUTFc.cached) cacheKEYBDINPUTFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, KEYBDINPUTFc.wVk, (jshort)lpStruct->wVk);
+       (*env)->SetShortField(env, lpObject, KEYBDINPUTFc.wScan, (jshort)lpStruct->wScan);
+       (*env)->SetIntField(env, lpObject, KEYBDINPUTFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, KEYBDINPUTFc.time, (jint)lpStruct->time);
+       (*env)->SetLongField(env, lpObject, KEYBDINPUTFc.dwExtraInfo, (jlong)lpStruct->dwExtraInfo);
+}
+#endif
+
+#ifndef NO_LITEM
+typedef struct LITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, iLink, state, stateMask, szID, szUrl;
+} LITEM_FID_CACHE;
+
+LITEM_FID_CACHE LITEMFc;
+
+void cacheLITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (LITEMFc.cached) return;
+       LITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LITEMFc.mask = (*env)->GetFieldID(env, LITEMFc.clazz, "mask", "I");
+       LITEMFc.iLink = (*env)->GetFieldID(env, LITEMFc.clazz, "iLink", "I");
+       LITEMFc.state = (*env)->GetFieldID(env, LITEMFc.clazz, "state", "I");
+       LITEMFc.stateMask = (*env)->GetFieldID(env, LITEMFc.clazz, "stateMask", "I");
+       LITEMFc.szID = (*env)->GetFieldID(env, LITEMFc.clazz, "szID", "[C");
+       LITEMFc.szUrl = (*env)->GetFieldID(env, LITEMFc.clazz, "szUrl", "[C");
+       LITEMFc.cached = 1;
+}
+
+LITEM *getLITEMFields(JNIEnv *env, jobject lpObject, LITEM *lpStruct)
+{
+       if (!LITEMFc.cached) cacheLITEMFields(env, lpObject);
+       lpStruct->mask = (*env)->GetIntField(env, lpObject, LITEMFc.mask);
+       lpStruct->iLink = (*env)->GetIntField(env, lpObject, LITEMFc.iLink);
+       lpStruct->state = (*env)->GetIntField(env, lpObject, LITEMFc.state);
+       lpStruct->stateMask = (*env)->GetIntField(env, lpObject, LITEMFc.stateMask);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, LITEMFc.szID);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szID) / sizeof(jchar), (jchar *)lpStruct->szID);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, LITEMFc.szUrl);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szUrl) / sizeof(jchar), (jchar *)lpStruct->szUrl);
+       }
+       return lpStruct;
+}
+
+void setLITEMFields(JNIEnv *env, jobject lpObject, LITEM *lpStruct)
+{
+       if (!LITEMFc.cached) cacheLITEMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LITEMFc.mask, (jint)lpStruct->mask);
+       (*env)->SetIntField(env, lpObject, LITEMFc.iLink, (jint)lpStruct->iLink);
+       (*env)->SetIntField(env, lpObject, LITEMFc.state, (jint)lpStruct->state);
+       (*env)->SetIntField(env, lpObject, LITEMFc.stateMask, (jint)lpStruct->stateMask);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, LITEMFc.szID);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szID) / sizeof(jchar), (jchar *)lpStruct->szID);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, LITEMFc.szUrl);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szUrl) / sizeof(jchar), (jchar *)lpStruct->szUrl);
+       }
+}
+#endif
+
+#ifndef NO_LOGBRUSH
+typedef struct LOGBRUSH_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lbStyle, lbColor, lbHatch;
+} LOGBRUSH_FID_CACHE;
+
+LOGBRUSH_FID_CACHE LOGBRUSHFc;
+
+void cacheLOGBRUSHFields(JNIEnv *env, jobject lpObject)
+{
+       if (LOGBRUSHFc.cached) return;
+       LOGBRUSHFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LOGBRUSHFc.lbStyle = (*env)->GetFieldID(env, LOGBRUSHFc.clazz, "lbStyle", "I");
+       LOGBRUSHFc.lbColor = (*env)->GetFieldID(env, LOGBRUSHFc.clazz, "lbColor", "I");
+       LOGBRUSHFc.lbHatch = (*env)->GetFieldID(env, LOGBRUSHFc.clazz, "lbHatch", "J");
+       LOGBRUSHFc.cached = 1;
+}
+
+LOGBRUSH *getLOGBRUSHFields(JNIEnv *env, jobject lpObject, LOGBRUSH *lpStruct)
+{
+       if (!LOGBRUSHFc.cached) cacheLOGBRUSHFields(env, lpObject);
+       lpStruct->lbStyle = (*env)->GetIntField(env, lpObject, LOGBRUSHFc.lbStyle);
+       lpStruct->lbColor = (*env)->GetIntField(env, lpObject, LOGBRUSHFc.lbColor);
+       lpStruct->lbHatch = (*env)->GetLongField(env, lpObject, LOGBRUSHFc.lbHatch);
+       return lpStruct;
+}
+
+void setLOGBRUSHFields(JNIEnv *env, jobject lpObject, LOGBRUSH *lpStruct)
+{
+       if (!LOGBRUSHFc.cached) cacheLOGBRUSHFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LOGBRUSHFc.lbStyle, (jint)lpStruct->lbStyle);
+       (*env)->SetIntField(env, lpObject, LOGBRUSHFc.lbColor, (jint)lpStruct->lbColor);
+       (*env)->SetLongField(env, lpObject, LOGBRUSHFc.lbHatch, (jlong)lpStruct->lbHatch);
+}
+#endif
+
+#ifndef NO_LOGFONT
+typedef struct LOGFONT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lfHeight, lfWidth, lfEscapement, lfOrientation, lfWeight, lfItalic, lfUnderline, lfStrikeOut, lfCharSet, lfOutPrecision, lfClipPrecision, lfQuality, lfPitchAndFamily, lfFaceName;
+} LOGFONT_FID_CACHE;
+
+LOGFONT_FID_CACHE LOGFONTFc;
+
+void cacheLOGFONTFields(JNIEnv *env, jobject lpObject)
+{
+       if (LOGFONTFc.cached) return;
+       LOGFONTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LOGFONTFc.lfHeight = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfHeight", "I");
+       LOGFONTFc.lfWidth = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfWidth", "I");
+       LOGFONTFc.lfEscapement = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfEscapement", "I");
+       LOGFONTFc.lfOrientation = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfOrientation", "I");
+       LOGFONTFc.lfWeight = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfWeight", "I");
+       LOGFONTFc.lfItalic = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfItalic", "B");
+       LOGFONTFc.lfUnderline = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfUnderline", "B");
+       LOGFONTFc.lfStrikeOut = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfStrikeOut", "B");
+       LOGFONTFc.lfCharSet = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfCharSet", "B");
+       LOGFONTFc.lfOutPrecision = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfOutPrecision", "B");
+       LOGFONTFc.lfClipPrecision = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfClipPrecision", "B");
+       LOGFONTFc.lfQuality = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfQuality", "B");
+       LOGFONTFc.lfPitchAndFamily = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfPitchAndFamily", "B");
+       LOGFONTFc.lfFaceName = (*env)->GetFieldID(env, LOGFONTFc.clazz, "lfFaceName", "[C");
+       LOGFONTFc.cached = 1;
+}
+
+LOGFONT *getLOGFONTFields(JNIEnv *env, jobject lpObject, LOGFONT *lpStruct)
+{
+       if (!LOGFONTFc.cached) cacheLOGFONTFields(env, lpObject);
+       lpStruct->lfHeight = (*env)->GetIntField(env, lpObject, LOGFONTFc.lfHeight);
+       lpStruct->lfWidth = (*env)->GetIntField(env, lpObject, LOGFONTFc.lfWidth);
+       lpStruct->lfEscapement = (*env)->GetIntField(env, lpObject, LOGFONTFc.lfEscapement);
+       lpStruct->lfOrientation = (*env)->GetIntField(env, lpObject, LOGFONTFc.lfOrientation);
+       lpStruct->lfWeight = (*env)->GetIntField(env, lpObject, LOGFONTFc.lfWeight);
+       lpStruct->lfItalic = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfItalic);
+       lpStruct->lfUnderline = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfUnderline);
+       lpStruct->lfStrikeOut = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfStrikeOut);
+       lpStruct->lfCharSet = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfCharSet);
+       lpStruct->lfOutPrecision = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfOutPrecision);
+       lpStruct->lfClipPrecision = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfClipPrecision);
+       lpStruct->lfQuality = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfQuality);
+       lpStruct->lfPitchAndFamily = (*env)->GetByteField(env, lpObject, LOGFONTFc.lfPitchAndFamily);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, LOGFONTFc.lfFaceName);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->lfFaceName) / sizeof(jchar), (jchar *)lpStruct->lfFaceName);
+       }
+       return lpStruct;
+}
+
+void setLOGFONTFields(JNIEnv *env, jobject lpObject, LOGFONT *lpStruct)
+{
+       if (!LOGFONTFc.cached) cacheLOGFONTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LOGFONTFc.lfHeight, (jint)lpStruct->lfHeight);
+       (*env)->SetIntField(env, lpObject, LOGFONTFc.lfWidth, (jint)lpStruct->lfWidth);
+       (*env)->SetIntField(env, lpObject, LOGFONTFc.lfEscapement, (jint)lpStruct->lfEscapement);
+       (*env)->SetIntField(env, lpObject, LOGFONTFc.lfOrientation, (jint)lpStruct->lfOrientation);
+       (*env)->SetIntField(env, lpObject, LOGFONTFc.lfWeight, (jint)lpStruct->lfWeight);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfItalic, (jbyte)lpStruct->lfItalic);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfUnderline, (jbyte)lpStruct->lfUnderline);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfStrikeOut, (jbyte)lpStruct->lfStrikeOut);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfCharSet, (jbyte)lpStruct->lfCharSet);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfOutPrecision, (jbyte)lpStruct->lfOutPrecision);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfClipPrecision, (jbyte)lpStruct->lfClipPrecision);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfQuality, (jbyte)lpStruct->lfQuality);
+       (*env)->SetByteField(env, lpObject, LOGFONTFc.lfPitchAndFamily, (jbyte)lpStruct->lfPitchAndFamily);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, LOGFONTFc.lfFaceName);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->lfFaceName) / sizeof(jchar), (jchar *)lpStruct->lfFaceName);
+       }
+}
+#endif
+
+#ifndef NO_LOGPEN
+typedef struct LOGPEN_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lopnStyle, x, y, lopnColor;
+} LOGPEN_FID_CACHE;
+
+LOGPEN_FID_CACHE LOGPENFc;
+
+void cacheLOGPENFields(JNIEnv *env, jobject lpObject)
+{
+       if (LOGPENFc.cached) return;
+       LOGPENFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LOGPENFc.lopnStyle = (*env)->GetFieldID(env, LOGPENFc.clazz, "lopnStyle", "I");
+       LOGPENFc.x = (*env)->GetFieldID(env, LOGPENFc.clazz, "x", "I");
+       LOGPENFc.y = (*env)->GetFieldID(env, LOGPENFc.clazz, "y", "I");
+       LOGPENFc.lopnColor = (*env)->GetFieldID(env, LOGPENFc.clazz, "lopnColor", "I");
+       LOGPENFc.cached = 1;
+}
+
+LOGPEN *getLOGPENFields(JNIEnv *env, jobject lpObject, LOGPEN *lpStruct)
+{
+       if (!LOGPENFc.cached) cacheLOGPENFields(env, lpObject);
+       lpStruct->lopnStyle = (*env)->GetIntField(env, lpObject, LOGPENFc.lopnStyle);
+       lpStruct->lopnWidth.x = (*env)->GetIntField(env, lpObject, LOGPENFc.x);
+       lpStruct->lopnWidth.y = (*env)->GetIntField(env, lpObject, LOGPENFc.y);
+       lpStruct->lopnColor = (*env)->GetIntField(env, lpObject, LOGPENFc.lopnColor);
+       return lpStruct;
+}
+
+void setLOGPENFields(JNIEnv *env, jobject lpObject, LOGPEN *lpStruct)
+{
+       if (!LOGPENFc.cached) cacheLOGPENFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LOGPENFc.lopnStyle, (jint)lpStruct->lopnStyle);
+       (*env)->SetIntField(env, lpObject, LOGPENFc.x, (jint)lpStruct->lopnWidth.x);
+       (*env)->SetIntField(env, lpObject, LOGPENFc.y, (jint)lpStruct->lopnWidth.y);
+       (*env)->SetIntField(env, lpObject, LOGPENFc.lopnColor, (jint)lpStruct->lopnColor);
+}
+#endif
+
+#ifndef NO_LVCOLUMN
+typedef struct LVCOLUMN_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, fmt, cx, pszText, cchTextMax, iSubItem, iImage, iOrder;
+} LVCOLUMN_FID_CACHE;
+
+LVCOLUMN_FID_CACHE LVCOLUMNFc;
+
+void cacheLVCOLUMNFields(JNIEnv *env, jobject lpObject)
+{
+       if (LVCOLUMNFc.cached) return;
+       LVCOLUMNFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LVCOLUMNFc.mask = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "mask", "I");
+       LVCOLUMNFc.fmt = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "fmt", "I");
+       LVCOLUMNFc.cx = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "cx", "I");
+       LVCOLUMNFc.pszText = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "pszText", "J");
+       LVCOLUMNFc.cchTextMax = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "cchTextMax", "I");
+       LVCOLUMNFc.iSubItem = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "iSubItem", "I");
+       LVCOLUMNFc.iImage = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "iImage", "I");
+       LVCOLUMNFc.iOrder = (*env)->GetFieldID(env, LVCOLUMNFc.clazz, "iOrder", "I");
+       LVCOLUMNFc.cached = 1;
+}
+
+LVCOLUMN *getLVCOLUMNFields(JNIEnv *env, jobject lpObject, LVCOLUMN *lpStruct)
+{
+       if (!LVCOLUMNFc.cached) cacheLVCOLUMNFields(env, lpObject);
+       lpStruct->mask = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.mask);
+       lpStruct->fmt = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.fmt);
+       lpStruct->cx = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.cx);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, LVCOLUMNFc.pszText);
+       lpStruct->cchTextMax = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.cchTextMax);
+       lpStruct->iSubItem = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.iSubItem);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.iImage);
+       lpStruct->iOrder = (*env)->GetIntField(env, lpObject, LVCOLUMNFc.iOrder);
+       return lpStruct;
+}
+
+void setLVCOLUMNFields(JNIEnv *env, jobject lpObject, LVCOLUMN *lpStruct)
+{
+       if (!LVCOLUMNFc.cached) cacheLVCOLUMNFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.mask, (jint)lpStruct->mask);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.fmt, (jint)lpStruct->fmt);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.cx, (jint)lpStruct->cx);
+       (*env)->SetLongField(env, lpObject, LVCOLUMNFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.cchTextMax, (jint)lpStruct->cchTextMax);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.iSubItem, (jint)lpStruct->iSubItem);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetIntField(env, lpObject, LVCOLUMNFc.iOrder, (jint)lpStruct->iOrder);
+}
+#endif
+
+#ifndef NO_LVHITTESTINFO
+typedef struct LVHITTESTINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y, flags, iItem, iSubItem;
+} LVHITTESTINFO_FID_CACHE;
+
+LVHITTESTINFO_FID_CACHE LVHITTESTINFOFc;
+
+void cacheLVHITTESTINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (LVHITTESTINFOFc.cached) return;
+       LVHITTESTINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LVHITTESTINFOFc.x = (*env)->GetFieldID(env, LVHITTESTINFOFc.clazz, "x", "I");
+       LVHITTESTINFOFc.y = (*env)->GetFieldID(env, LVHITTESTINFOFc.clazz, "y", "I");
+       LVHITTESTINFOFc.flags = (*env)->GetFieldID(env, LVHITTESTINFOFc.clazz, "flags", "I");
+       LVHITTESTINFOFc.iItem = (*env)->GetFieldID(env, LVHITTESTINFOFc.clazz, "iItem", "I");
+       LVHITTESTINFOFc.iSubItem = (*env)->GetFieldID(env, LVHITTESTINFOFc.clazz, "iSubItem", "I");
+       LVHITTESTINFOFc.cached = 1;
+}
+
+LVHITTESTINFO *getLVHITTESTINFOFields(JNIEnv *env, jobject lpObject, LVHITTESTINFO *lpStruct)
+{
+       if (!LVHITTESTINFOFc.cached) cacheLVHITTESTINFOFields(env, lpObject);
+       lpStruct->pt.x = (*env)->GetIntField(env, lpObject, LVHITTESTINFOFc.x);
+       lpStruct->pt.y = (*env)->GetIntField(env, lpObject, LVHITTESTINFOFc.y);
+       lpStruct->flags = (*env)->GetIntField(env, lpObject, LVHITTESTINFOFc.flags);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, LVHITTESTINFOFc.iItem);
+       lpStruct->iSubItem = (*env)->GetIntField(env, lpObject, LVHITTESTINFOFc.iSubItem);
+       return lpStruct;
+}
+
+void setLVHITTESTINFOFields(JNIEnv *env, jobject lpObject, LVHITTESTINFO *lpStruct)
+{
+       if (!LVHITTESTINFOFc.cached) cacheLVHITTESTINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LVHITTESTINFOFc.x, (jint)lpStruct->pt.x);
+       (*env)->SetIntField(env, lpObject, LVHITTESTINFOFc.y, (jint)lpStruct->pt.y);
+       (*env)->SetIntField(env, lpObject, LVHITTESTINFOFc.flags, (jint)lpStruct->flags);
+       (*env)->SetIntField(env, lpObject, LVHITTESTINFOFc.iItem, (jint)lpStruct->iItem);
+       (*env)->SetIntField(env, lpObject, LVHITTESTINFOFc.iSubItem, (jint)lpStruct->iSubItem);
+}
+#endif
+
+#ifndef NO_LVINSERTMARK
+typedef struct LVINSERTMARK_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, iItem, dwReserved;
+} LVINSERTMARK_FID_CACHE;
+
+LVINSERTMARK_FID_CACHE LVINSERTMARKFc;
+
+void cacheLVINSERTMARKFields(JNIEnv *env, jobject lpObject)
+{
+       if (LVINSERTMARKFc.cached) return;
+       LVINSERTMARKFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LVINSERTMARKFc.cbSize = (*env)->GetFieldID(env, LVINSERTMARKFc.clazz, "cbSize", "I");
+       LVINSERTMARKFc.dwFlags = (*env)->GetFieldID(env, LVINSERTMARKFc.clazz, "dwFlags", "I");
+       LVINSERTMARKFc.iItem = (*env)->GetFieldID(env, LVINSERTMARKFc.clazz, "iItem", "I");
+       LVINSERTMARKFc.dwReserved = (*env)->GetFieldID(env, LVINSERTMARKFc.clazz, "dwReserved", "I");
+       LVINSERTMARKFc.cached = 1;
+}
+
+LVINSERTMARK *getLVINSERTMARKFields(JNIEnv *env, jobject lpObject, LVINSERTMARK *lpStruct)
+{
+       if (!LVINSERTMARKFc.cached) cacheLVINSERTMARKFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, LVINSERTMARKFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, LVINSERTMARKFc.dwFlags);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, LVINSERTMARKFc.iItem);
+       lpStruct->dwReserved = (*env)->GetIntField(env, lpObject, LVINSERTMARKFc.dwReserved);
+       return lpStruct;
+}
+
+void setLVINSERTMARKFields(JNIEnv *env, jobject lpObject, LVINSERTMARK *lpStruct)
+{
+       if (!LVINSERTMARKFc.cached) cacheLVINSERTMARKFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LVINSERTMARKFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, LVINSERTMARKFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, LVINSERTMARKFc.iItem, (jint)lpStruct->iItem);
+       (*env)->SetIntField(env, lpObject, LVINSERTMARKFc.dwReserved, (jint)lpStruct->dwReserved);
+}
+#endif
+
+#ifndef NO_LVITEM
+typedef struct LVITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, iItem, iSubItem, state, stateMask, pszText, cchTextMax, iImage, lParam, iIndent, iGroupId, cColumns, puColumns;
+} LVITEM_FID_CACHE;
+
+LVITEM_FID_CACHE LVITEMFc;
+
+void cacheLVITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (LVITEMFc.cached) return;
+       LVITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LVITEMFc.mask = (*env)->GetFieldID(env, LVITEMFc.clazz, "mask", "I");
+       LVITEMFc.iItem = (*env)->GetFieldID(env, LVITEMFc.clazz, "iItem", "I");
+       LVITEMFc.iSubItem = (*env)->GetFieldID(env, LVITEMFc.clazz, "iSubItem", "I");
+       LVITEMFc.state = (*env)->GetFieldID(env, LVITEMFc.clazz, "state", "I");
+       LVITEMFc.stateMask = (*env)->GetFieldID(env, LVITEMFc.clazz, "stateMask", "I");
+       LVITEMFc.pszText = (*env)->GetFieldID(env, LVITEMFc.clazz, "pszText", "J");
+       LVITEMFc.cchTextMax = (*env)->GetFieldID(env, LVITEMFc.clazz, "cchTextMax", "I");
+       LVITEMFc.iImage = (*env)->GetFieldID(env, LVITEMFc.clazz, "iImage", "I");
+       LVITEMFc.lParam = (*env)->GetFieldID(env, LVITEMFc.clazz, "lParam", "J");
+       LVITEMFc.iIndent = (*env)->GetFieldID(env, LVITEMFc.clazz, "iIndent", "I");
+       LVITEMFc.iGroupId = (*env)->GetFieldID(env, LVITEMFc.clazz, "iGroupId", "I");
+       LVITEMFc.cColumns = (*env)->GetFieldID(env, LVITEMFc.clazz, "cColumns", "I");
+       LVITEMFc.puColumns = (*env)->GetFieldID(env, LVITEMFc.clazz, "puColumns", "J");
+       LVITEMFc.cached = 1;
+}
+
+LVITEM *getLVITEMFields(JNIEnv *env, jobject lpObject, LVITEM *lpStruct)
+{
+       if (!LVITEMFc.cached) cacheLVITEMFields(env, lpObject);
+       lpStruct->mask = (*env)->GetIntField(env, lpObject, LVITEMFc.mask);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, LVITEMFc.iItem);
+       lpStruct->iSubItem = (*env)->GetIntField(env, lpObject, LVITEMFc.iSubItem);
+       lpStruct->state = (*env)->GetIntField(env, lpObject, LVITEMFc.state);
+       lpStruct->stateMask = (*env)->GetIntField(env, lpObject, LVITEMFc.stateMask);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, LVITEMFc.pszText);
+       lpStruct->cchTextMax = (*env)->GetIntField(env, lpObject, LVITEMFc.cchTextMax);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, LVITEMFc.iImage);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, LVITEMFc.lParam);
+       lpStruct->iIndent = (*env)->GetIntField(env, lpObject, LVITEMFc.iIndent);
+       lpStruct->iGroupId = (*env)->GetIntField(env, lpObject, LVITEMFc.iGroupId);
+       lpStruct->cColumns = (*env)->GetIntField(env, lpObject, LVITEMFc.cColumns);
+       lpStruct->puColumns = (PUINT)(*env)->GetLongField(env, lpObject, LVITEMFc.puColumns);
+       return lpStruct;
+}
+
+void setLVITEMFields(JNIEnv *env, jobject lpObject, LVITEM *lpStruct)
+{
+       if (!LVITEMFc.cached) cacheLVITEMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.mask, (jint)lpStruct->mask);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.iItem, (jint)lpStruct->iItem);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.iSubItem, (jint)lpStruct->iSubItem);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.state, (jint)lpStruct->state);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.stateMask, (jint)lpStruct->stateMask);
+       (*env)->SetLongField(env, lpObject, LVITEMFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.cchTextMax, (jint)lpStruct->cchTextMax);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetLongField(env, lpObject, LVITEMFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.iIndent, (jint)lpStruct->iIndent);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.iGroupId, (jint)lpStruct->iGroupId);
+       (*env)->SetIntField(env, lpObject, LVITEMFc.cColumns, (jint)lpStruct->cColumns);
+       (*env)->SetLongField(env, lpObject, LVITEMFc.puColumns, (jlong)lpStruct->puColumns);
+}
+#endif
+
+#ifndef NO_MARGINS
+typedef struct MARGINS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight;
+} MARGINS_FID_CACHE;
+
+MARGINS_FID_CACHE MARGINSFc;
+
+void cacheMARGINSFields(JNIEnv *env, jobject lpObject)
+{
+       if (MARGINSFc.cached) return;
+       MARGINSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MARGINSFc.cxLeftWidth = (*env)->GetFieldID(env, MARGINSFc.clazz, "cxLeftWidth", "I");
+       MARGINSFc.cxRightWidth = (*env)->GetFieldID(env, MARGINSFc.clazz, "cxRightWidth", "I");
+       MARGINSFc.cyTopHeight = (*env)->GetFieldID(env, MARGINSFc.clazz, "cyTopHeight", "I");
+       MARGINSFc.cyBottomHeight = (*env)->GetFieldID(env, MARGINSFc.clazz, "cyBottomHeight", "I");
+       MARGINSFc.cached = 1;
+}
+
+MARGINS *getMARGINSFields(JNIEnv *env, jobject lpObject, MARGINS *lpStruct)
+{
+       if (!MARGINSFc.cached) cacheMARGINSFields(env, lpObject);
+       lpStruct->cxLeftWidth = (*env)->GetIntField(env, lpObject, MARGINSFc.cxLeftWidth);
+       lpStruct->cxRightWidth = (*env)->GetIntField(env, lpObject, MARGINSFc.cxRightWidth);
+       lpStruct->cyTopHeight = (*env)->GetIntField(env, lpObject, MARGINSFc.cyTopHeight);
+       lpStruct->cyBottomHeight = (*env)->GetIntField(env, lpObject, MARGINSFc.cyBottomHeight);
+       return lpStruct;
+}
+
+void setMARGINSFields(JNIEnv *env, jobject lpObject, MARGINS *lpStruct)
+{
+       if (!MARGINSFc.cached) cacheMARGINSFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MARGINSFc.cxLeftWidth, (jint)lpStruct->cxLeftWidth);
+       (*env)->SetIntField(env, lpObject, MARGINSFc.cxRightWidth, (jint)lpStruct->cxRightWidth);
+       (*env)->SetIntField(env, lpObject, MARGINSFc.cyTopHeight, (jint)lpStruct->cyTopHeight);
+       (*env)->SetIntField(env, lpObject, MARGINSFc.cyBottomHeight, (jint)lpStruct->cyBottomHeight);
+}
+#endif
+
+#ifndef NO_MCHITTESTINFO
+typedef struct MCHITTESTINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, pt, uHit, st;
+} MCHITTESTINFO_FID_CACHE;
+
+MCHITTESTINFO_FID_CACHE MCHITTESTINFOFc;
+
+void cacheMCHITTESTINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (MCHITTESTINFOFc.cached) return;
+       MCHITTESTINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MCHITTESTINFOFc.cbSize = (*env)->GetFieldID(env, MCHITTESTINFOFc.clazz, "cbSize", "I");
+       MCHITTESTINFOFc.pt = (*env)->GetFieldID(env, MCHITTESTINFOFc.clazz, "pt", "Lorg/eclipse/swt/internal/win32/POINT;");
+       MCHITTESTINFOFc.uHit = (*env)->GetFieldID(env, MCHITTESTINFOFc.clazz, "uHit", "I");
+       MCHITTESTINFOFc.st = (*env)->GetFieldID(env, MCHITTESTINFOFc.clazz, "st", "Lorg/eclipse/swt/internal/win32/SYSTEMTIME;");
+       MCHITTESTINFOFc.cached = 1;
+}
+
+MCHITTESTINFO *getMCHITTESTINFOFields(JNIEnv *env, jobject lpObject, MCHITTESTINFO *lpStruct)
+{
+       if (!MCHITTESTINFOFc.cached) cacheMCHITTESTINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, MCHITTESTINFOFc.cbSize);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, MCHITTESTINFOFc.pt);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->pt);
+       }
+       lpStruct->uHit = (*env)->GetIntField(env, lpObject, MCHITTESTINFOFc.uHit);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, MCHITTESTINFOFc.st);
+       if (lpObject1 != NULL) getSYSTEMTIMEFields(env, lpObject1, &lpStruct->st);
+       }
+       return lpStruct;
+}
+
+void setMCHITTESTINFOFields(JNIEnv *env, jobject lpObject, MCHITTESTINFO *lpStruct)
+{
+       if (!MCHITTESTINFOFc.cached) cacheMCHITTESTINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MCHITTESTINFOFc.cbSize, (jint)lpStruct->cbSize);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, MCHITTESTINFOFc.pt);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->pt);
+       }
+       (*env)->SetIntField(env, lpObject, MCHITTESTINFOFc.uHit, (jint)lpStruct->uHit);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, MCHITTESTINFOFc.st);
+       if (lpObject1 != NULL) setSYSTEMTIMEFields(env, lpObject1, &lpStruct->st);
+       }
+}
+#endif
+
+#ifndef NO_MEASUREITEMSTRUCT
+typedef struct MEASUREITEMSTRUCT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID CtlType, CtlID, itemID, itemWidth, itemHeight, itemData;
+} MEASUREITEMSTRUCT_FID_CACHE;
+
+MEASUREITEMSTRUCT_FID_CACHE MEASUREITEMSTRUCTFc;
+
+void cacheMEASUREITEMSTRUCTFields(JNIEnv *env, jobject lpObject)
+{
+       if (MEASUREITEMSTRUCTFc.cached) return;
+       MEASUREITEMSTRUCTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MEASUREITEMSTRUCTFc.CtlType = (*env)->GetFieldID(env, MEASUREITEMSTRUCTFc.clazz, "CtlType", "I");
+       MEASUREITEMSTRUCTFc.CtlID = (*env)->GetFieldID(env, MEASUREITEMSTRUCTFc.clazz, "CtlID", "I");
+       MEASUREITEMSTRUCTFc.itemID = (*env)->GetFieldID(env, MEASUREITEMSTRUCTFc.clazz, "itemID", "I");
+       MEASUREITEMSTRUCTFc.itemWidth = (*env)->GetFieldID(env, MEASUREITEMSTRUCTFc.clazz, "itemWidth", "I");
+       MEASUREITEMSTRUCTFc.itemHeight = (*env)->GetFieldID(env, MEASUREITEMSTRUCTFc.clazz, "itemHeight", "I");
+       MEASUREITEMSTRUCTFc.itemData = (*env)->GetFieldID(env, MEASUREITEMSTRUCTFc.clazz, "itemData", "J");
+       MEASUREITEMSTRUCTFc.cached = 1;
+}
+
+MEASUREITEMSTRUCT *getMEASUREITEMSTRUCTFields(JNIEnv *env, jobject lpObject, MEASUREITEMSTRUCT *lpStruct)
+{
+       if (!MEASUREITEMSTRUCTFc.cached) cacheMEASUREITEMSTRUCTFields(env, lpObject);
+       lpStruct->CtlType = (*env)->GetIntField(env, lpObject, MEASUREITEMSTRUCTFc.CtlType);
+       lpStruct->CtlID = (*env)->GetIntField(env, lpObject, MEASUREITEMSTRUCTFc.CtlID);
+       lpStruct->itemID = (*env)->GetIntField(env, lpObject, MEASUREITEMSTRUCTFc.itemID);
+       lpStruct->itemWidth = (*env)->GetIntField(env, lpObject, MEASUREITEMSTRUCTFc.itemWidth);
+       lpStruct->itemHeight = (*env)->GetIntField(env, lpObject, MEASUREITEMSTRUCTFc.itemHeight);
+       lpStruct->itemData = (*env)->GetLongField(env, lpObject, MEASUREITEMSTRUCTFc.itemData);
+       return lpStruct;
+}
+
+void setMEASUREITEMSTRUCTFields(JNIEnv *env, jobject lpObject, MEASUREITEMSTRUCT *lpStruct)
+{
+       if (!MEASUREITEMSTRUCTFc.cached) cacheMEASUREITEMSTRUCTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MEASUREITEMSTRUCTFc.CtlType, (jint)lpStruct->CtlType);
+       (*env)->SetIntField(env, lpObject, MEASUREITEMSTRUCTFc.CtlID, (jint)lpStruct->CtlID);
+       (*env)->SetIntField(env, lpObject, MEASUREITEMSTRUCTFc.itemID, (jint)lpStruct->itemID);
+       (*env)->SetIntField(env, lpObject, MEASUREITEMSTRUCTFc.itemWidth, (jint)lpStruct->itemWidth);
+       (*env)->SetIntField(env, lpObject, MEASUREITEMSTRUCTFc.itemHeight, (jint)lpStruct->itemHeight);
+       (*env)->SetLongField(env, lpObject, MEASUREITEMSTRUCTFc.itemData, (jlong)lpStruct->itemData);
+}
+#endif
+
+#ifndef NO_MENUBARINFO
+typedef struct MENUBARINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, left, top, right, bottom, hMenu, hwndMenu, fBarFocused, fFocused;
+} MENUBARINFO_FID_CACHE;
+
+MENUBARINFO_FID_CACHE MENUBARINFOFc;
+
+void cacheMENUBARINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (MENUBARINFOFc.cached) return;
+       MENUBARINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MENUBARINFOFc.cbSize = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "cbSize", "I");
+       MENUBARINFOFc.left = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "left", "I");
+       MENUBARINFOFc.top = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "top", "I");
+       MENUBARINFOFc.right = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "right", "I");
+       MENUBARINFOFc.bottom = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "bottom", "I");
+       MENUBARINFOFc.hMenu = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "hMenu", "J");
+       MENUBARINFOFc.hwndMenu = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "hwndMenu", "J");
+       MENUBARINFOFc.fBarFocused = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "fBarFocused", "Z");
+       MENUBARINFOFc.fFocused = (*env)->GetFieldID(env, MENUBARINFOFc.clazz, "fFocused", "Z");
+       MENUBARINFOFc.cached = 1;
+}
+
+MENUBARINFO *getMENUBARINFOFields(JNIEnv *env, jobject lpObject, MENUBARINFO *lpStruct)
+{
+       if (!MENUBARINFOFc.cached) cacheMENUBARINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, MENUBARINFOFc.cbSize);
+       lpStruct->rcBar.left = (*env)->GetIntField(env, lpObject, MENUBARINFOFc.left);
+       lpStruct->rcBar.top = (*env)->GetIntField(env, lpObject, MENUBARINFOFc.top);
+       lpStruct->rcBar.right = (*env)->GetIntField(env, lpObject, MENUBARINFOFc.right);
+       lpStruct->rcBar.bottom = (*env)->GetIntField(env, lpObject, MENUBARINFOFc.bottom);
+       lpStruct->hMenu = (HMENU)(*env)->GetLongField(env, lpObject, MENUBARINFOFc.hMenu);
+       lpStruct->hwndMenu = (HWND)(*env)->GetLongField(env, lpObject, MENUBARINFOFc.hwndMenu);
+       lpStruct->fBarFocused = (*env)->GetBooleanField(env, lpObject, MENUBARINFOFc.fBarFocused);
+       lpStruct->fFocused = (*env)->GetBooleanField(env, lpObject, MENUBARINFOFc.fFocused);
+       return lpStruct;
+}
+
+void setMENUBARINFOFields(JNIEnv *env, jobject lpObject, MENUBARINFO *lpStruct)
+{
+       if (!MENUBARINFOFc.cached) cacheMENUBARINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MENUBARINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, MENUBARINFOFc.left, (jint)lpStruct->rcBar.left);
+       (*env)->SetIntField(env, lpObject, MENUBARINFOFc.top, (jint)lpStruct->rcBar.top);
+       (*env)->SetIntField(env, lpObject, MENUBARINFOFc.right, (jint)lpStruct->rcBar.right);
+       (*env)->SetIntField(env, lpObject, MENUBARINFOFc.bottom, (jint)lpStruct->rcBar.bottom);
+       (*env)->SetLongField(env, lpObject, MENUBARINFOFc.hMenu, (jlong)lpStruct->hMenu);
+       (*env)->SetLongField(env, lpObject, MENUBARINFOFc.hwndMenu, (jlong)lpStruct->hwndMenu);
+       (*env)->SetBooleanField(env, lpObject, MENUBARINFOFc.fBarFocused, (jboolean)lpStruct->fBarFocused);
+       (*env)->SetBooleanField(env, lpObject, MENUBARINFOFc.fFocused, (jboolean)lpStruct->fFocused);
+}
+#endif
+
+#ifndef NO_MENUINFO
+typedef struct MENUINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, fMask, dwStyle, cyMax, hbrBack, dwContextHelpID, dwMenuData;
+} MENUINFO_FID_CACHE;
+
+MENUINFO_FID_CACHE MENUINFOFc;
+
+void cacheMENUINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (MENUINFOFc.cached) return;
+       MENUINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MENUINFOFc.cbSize = (*env)->GetFieldID(env, MENUINFOFc.clazz, "cbSize", "I");
+       MENUINFOFc.fMask = (*env)->GetFieldID(env, MENUINFOFc.clazz, "fMask", "I");
+       MENUINFOFc.dwStyle = (*env)->GetFieldID(env, MENUINFOFc.clazz, "dwStyle", "I");
+       MENUINFOFc.cyMax = (*env)->GetFieldID(env, MENUINFOFc.clazz, "cyMax", "I");
+       MENUINFOFc.hbrBack = (*env)->GetFieldID(env, MENUINFOFc.clazz, "hbrBack", "J");
+       MENUINFOFc.dwContextHelpID = (*env)->GetFieldID(env, MENUINFOFc.clazz, "dwContextHelpID", "I");
+       MENUINFOFc.dwMenuData = (*env)->GetFieldID(env, MENUINFOFc.clazz, "dwMenuData", "J");
+       MENUINFOFc.cached = 1;
+}
+
+MENUINFO *getMENUINFOFields(JNIEnv *env, jobject lpObject, MENUINFO *lpStruct)
+{
+       if (!MENUINFOFc.cached) cacheMENUINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, MENUINFOFc.cbSize);
+       lpStruct->fMask = (*env)->GetIntField(env, lpObject, MENUINFOFc.fMask);
+       lpStruct->dwStyle = (*env)->GetIntField(env, lpObject, MENUINFOFc.dwStyle);
+       lpStruct->cyMax = (*env)->GetIntField(env, lpObject, MENUINFOFc.cyMax);
+       lpStruct->hbrBack = (HBRUSH)(*env)->GetLongField(env, lpObject, MENUINFOFc.hbrBack);
+       lpStruct->dwContextHelpID = (*env)->GetIntField(env, lpObject, MENUINFOFc.dwContextHelpID);
+       lpStruct->dwMenuData = (*env)->GetLongField(env, lpObject, MENUINFOFc.dwMenuData);
+       return lpStruct;
+}
+
+void setMENUINFOFields(JNIEnv *env, jobject lpObject, MENUINFO *lpStruct)
+{
+       if (!MENUINFOFc.cached) cacheMENUINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MENUINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, MENUINFOFc.fMask, (jint)lpStruct->fMask);
+       (*env)->SetIntField(env, lpObject, MENUINFOFc.dwStyle, (jint)lpStruct->dwStyle);
+       (*env)->SetIntField(env, lpObject, MENUINFOFc.cyMax, (jint)lpStruct->cyMax);
+       (*env)->SetLongField(env, lpObject, MENUINFOFc.hbrBack, (jlong)lpStruct->hbrBack);
+       (*env)->SetIntField(env, lpObject, MENUINFOFc.dwContextHelpID, (jint)lpStruct->dwContextHelpID);
+       (*env)->SetLongField(env, lpObject, MENUINFOFc.dwMenuData, (jlong)lpStruct->dwMenuData);
+}
+#endif
+
+#ifndef NO_MENUITEMINFO
+typedef struct MENUITEMINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, fMask, fType, fState, wID, hSubMenu, hbmpChecked, hbmpUnchecked, dwItemData, dwTypeData, cch, hbmpItem;
+} MENUITEMINFO_FID_CACHE;
+
+MENUITEMINFO_FID_CACHE MENUITEMINFOFc;
+
+void cacheMENUITEMINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (MENUITEMINFOFc.cached) return;
+       MENUITEMINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MENUITEMINFOFc.cbSize = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "cbSize", "I");
+       MENUITEMINFOFc.fMask = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "fMask", "I");
+       MENUITEMINFOFc.fType = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "fType", "I");
+       MENUITEMINFOFc.fState = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "fState", "I");
+       MENUITEMINFOFc.wID = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "wID", "I");
+       MENUITEMINFOFc.hSubMenu = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "hSubMenu", "J");
+       MENUITEMINFOFc.hbmpChecked = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "hbmpChecked", "J");
+       MENUITEMINFOFc.hbmpUnchecked = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "hbmpUnchecked", "J");
+       MENUITEMINFOFc.dwItemData = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "dwItemData", "J");
+       MENUITEMINFOFc.dwTypeData = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "dwTypeData", "J");
+       MENUITEMINFOFc.cch = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "cch", "I");
+       MENUITEMINFOFc.hbmpItem = (*env)->GetFieldID(env, MENUITEMINFOFc.clazz, "hbmpItem", "J");
+       MENUITEMINFOFc.cached = 1;
+}
+
+MENUITEMINFO *getMENUITEMINFOFields(JNIEnv *env, jobject lpObject, MENUITEMINFO *lpStruct)
+{
+       if (!MENUITEMINFOFc.cached) cacheMENUITEMINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, MENUITEMINFOFc.cbSize);
+       lpStruct->fMask = (*env)->GetIntField(env, lpObject, MENUITEMINFOFc.fMask);
+       lpStruct->fType = (*env)->GetIntField(env, lpObject, MENUITEMINFOFc.fType);
+       lpStruct->fState = (*env)->GetIntField(env, lpObject, MENUITEMINFOFc.fState);
+       lpStruct->wID = (*env)->GetIntField(env, lpObject, MENUITEMINFOFc.wID);
+       lpStruct->hSubMenu = (HMENU)(*env)->GetLongField(env, lpObject, MENUITEMINFOFc.hSubMenu);
+       lpStruct->hbmpChecked = (HBITMAP)(*env)->GetLongField(env, lpObject, MENUITEMINFOFc.hbmpChecked);
+       lpStruct->hbmpUnchecked = (HBITMAP)(*env)->GetLongField(env, lpObject, MENUITEMINFOFc.hbmpUnchecked);
+       lpStruct->dwItemData = (*env)->GetLongField(env, lpObject, MENUITEMINFOFc.dwItemData);
+       lpStruct->dwTypeData = (LPTSTR)(*env)->GetLongField(env, lpObject, MENUITEMINFOFc.dwTypeData);
+       lpStruct->cch = (*env)->GetIntField(env, lpObject, MENUITEMINFOFc.cch);
+       lpStruct->hbmpItem = (HBITMAP)(*env)->GetLongField(env, lpObject, MENUITEMINFOFc.hbmpItem);
+       return lpStruct;
+}
+
+void setMENUITEMINFOFields(JNIEnv *env, jobject lpObject, MENUITEMINFO *lpStruct)
+{
+       if (!MENUITEMINFOFc.cached) cacheMENUITEMINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MENUITEMINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, MENUITEMINFOFc.fMask, (jint)lpStruct->fMask);
+       (*env)->SetIntField(env, lpObject, MENUITEMINFOFc.fType, (jint)lpStruct->fType);
+       (*env)->SetIntField(env, lpObject, MENUITEMINFOFc.fState, (jint)lpStruct->fState);
+       (*env)->SetIntField(env, lpObject, MENUITEMINFOFc.wID, (jint)lpStruct->wID);
+       (*env)->SetLongField(env, lpObject, MENUITEMINFOFc.hSubMenu, (jlong)lpStruct->hSubMenu);
+       (*env)->SetLongField(env, lpObject, MENUITEMINFOFc.hbmpChecked, (jlong)lpStruct->hbmpChecked);
+       (*env)->SetLongField(env, lpObject, MENUITEMINFOFc.hbmpUnchecked, (jlong)lpStruct->hbmpUnchecked);
+       (*env)->SetLongField(env, lpObject, MENUITEMINFOFc.dwItemData, (jlong)lpStruct->dwItemData);
+       (*env)->SetLongField(env, lpObject, MENUITEMINFOFc.dwTypeData, (jlong)lpStruct->dwTypeData);
+       (*env)->SetIntField(env, lpObject, MENUITEMINFOFc.cch, (jint)lpStruct->cch);
+       (*env)->SetLongField(env, lpObject, MENUITEMINFOFc.hbmpItem, (jlong)lpStruct->hbmpItem);
+}
+#endif
+
+#ifndef NO_MINMAXINFO
+typedef struct MINMAXINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID ptReserved_x, ptReserved_y, ptMaxSize_x, ptMaxSize_y, ptMaxPosition_x, ptMaxPosition_y, ptMinTrackSize_x, ptMinTrackSize_y, ptMaxTrackSize_x, ptMaxTrackSize_y;
+} MINMAXINFO_FID_CACHE;
+
+MINMAXINFO_FID_CACHE MINMAXINFOFc;
+
+void cacheMINMAXINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (MINMAXINFOFc.cached) return;
+       MINMAXINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MINMAXINFOFc.ptReserved_x = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptReserved_x", "I");
+       MINMAXINFOFc.ptReserved_y = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptReserved_y", "I");
+       MINMAXINFOFc.ptMaxSize_x = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMaxSize_x", "I");
+       MINMAXINFOFc.ptMaxSize_y = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMaxSize_y", "I");
+       MINMAXINFOFc.ptMaxPosition_x = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMaxPosition_x", "I");
+       MINMAXINFOFc.ptMaxPosition_y = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMaxPosition_y", "I");
+       MINMAXINFOFc.ptMinTrackSize_x = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMinTrackSize_x", "I");
+       MINMAXINFOFc.ptMinTrackSize_y = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMinTrackSize_y", "I");
+       MINMAXINFOFc.ptMaxTrackSize_x = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMaxTrackSize_x", "I");
+       MINMAXINFOFc.ptMaxTrackSize_y = (*env)->GetFieldID(env, MINMAXINFOFc.clazz, "ptMaxTrackSize_y", "I");
+       MINMAXINFOFc.cached = 1;
+}
+
+MINMAXINFO *getMINMAXINFOFields(JNIEnv *env, jobject lpObject, MINMAXINFO *lpStruct)
+{
+       if (!MINMAXINFOFc.cached) cacheMINMAXINFOFields(env, lpObject);
+       lpStruct->ptReserved.x = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptReserved_x);
+       lpStruct->ptReserved.y = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptReserved_y);
+       lpStruct->ptMaxSize.x = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMaxSize_x);
+       lpStruct->ptMaxSize.y = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMaxSize_y);
+       lpStruct->ptMaxPosition.x = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMaxPosition_x);
+       lpStruct->ptMaxPosition.y = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMaxPosition_y);
+       lpStruct->ptMinTrackSize.x = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMinTrackSize_x);
+       lpStruct->ptMinTrackSize.y = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMinTrackSize_y);
+       lpStruct->ptMaxTrackSize.x = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMaxTrackSize_x);
+       lpStruct->ptMaxTrackSize.y = (*env)->GetIntField(env, lpObject, MINMAXINFOFc.ptMaxTrackSize_y);
+       return lpStruct;
+}
+
+void setMINMAXINFOFields(JNIEnv *env, jobject lpObject, MINMAXINFO *lpStruct)
+{
+       if (!MINMAXINFOFc.cached) cacheMINMAXINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptReserved_x, (jint)lpStruct->ptReserved.x);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptReserved_y, (jint)lpStruct->ptReserved.y);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMaxSize_x, (jint)lpStruct->ptMaxSize.x);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMaxSize_y, (jint)lpStruct->ptMaxSize.y);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMaxPosition_x, (jint)lpStruct->ptMaxPosition.x);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMaxPosition_y, (jint)lpStruct->ptMaxPosition.y);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMinTrackSize_x, (jint)lpStruct->ptMinTrackSize.x);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMinTrackSize_y, (jint)lpStruct->ptMinTrackSize.y);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMaxTrackSize_x, (jint)lpStruct->ptMaxTrackSize.x);
+       (*env)->SetIntField(env, lpObject, MINMAXINFOFc.ptMaxTrackSize_y, (jint)lpStruct->ptMaxTrackSize.y);
+}
+#endif
+
+#ifndef NO_MONITORINFO
+typedef struct MONITORINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, rcMonitor_left, rcMonitor_top, rcMonitor_right, rcMonitor_bottom, rcWork_left, rcWork_top, rcWork_right, rcWork_bottom, dwFlags;
+} MONITORINFO_FID_CACHE;
+
+MONITORINFO_FID_CACHE MONITORINFOFc;
+
+void cacheMONITORINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (MONITORINFOFc.cached) return;
+       MONITORINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MONITORINFOFc.cbSize = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "cbSize", "I");
+       MONITORINFOFc.rcMonitor_left = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcMonitor_left", "I");
+       MONITORINFOFc.rcMonitor_top = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcMonitor_top", "I");
+       MONITORINFOFc.rcMonitor_right = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcMonitor_right", "I");
+       MONITORINFOFc.rcMonitor_bottom = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcMonitor_bottom", "I");
+       MONITORINFOFc.rcWork_left = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcWork_left", "I");
+       MONITORINFOFc.rcWork_top = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcWork_top", "I");
+       MONITORINFOFc.rcWork_right = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcWork_right", "I");
+       MONITORINFOFc.rcWork_bottom = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "rcWork_bottom", "I");
+       MONITORINFOFc.dwFlags = (*env)->GetFieldID(env, MONITORINFOFc.clazz, "dwFlags", "I");
+       MONITORINFOFc.cached = 1;
+}
+
+MONITORINFO *getMONITORINFOFields(JNIEnv *env, jobject lpObject, MONITORINFO *lpStruct)
+{
+       if (!MONITORINFOFc.cached) cacheMONITORINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, MONITORINFOFc.cbSize);
+       lpStruct->rcMonitor.left = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcMonitor_left);
+       lpStruct->rcMonitor.top = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcMonitor_top);
+       lpStruct->rcMonitor.right = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcMonitor_right);
+       lpStruct->rcMonitor.bottom = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcMonitor_bottom);
+       lpStruct->rcWork.left = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcWork_left);
+       lpStruct->rcWork.top = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcWork_top);
+       lpStruct->rcWork.right = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcWork_right);
+       lpStruct->rcWork.bottom = (*env)->GetIntField(env, lpObject, MONITORINFOFc.rcWork_bottom);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, MONITORINFOFc.dwFlags);
+       return lpStruct;
+}
+
+void setMONITORINFOFields(JNIEnv *env, jobject lpObject, MONITORINFO *lpStruct)
+{
+       if (!MONITORINFOFc.cached) cacheMONITORINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcMonitor_left, (jint)lpStruct->rcMonitor.left);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcMonitor_top, (jint)lpStruct->rcMonitor.top);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcMonitor_right, (jint)lpStruct->rcMonitor.right);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcMonitor_bottom, (jint)lpStruct->rcMonitor.bottom);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcWork_left, (jint)lpStruct->rcWork.left);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcWork_top, (jint)lpStruct->rcWork.top);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcWork_right, (jint)lpStruct->rcWork.right);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.rcWork_bottom, (jint)lpStruct->rcWork.bottom);
+       (*env)->SetIntField(env, lpObject, MONITORINFOFc.dwFlags, (jint)lpStruct->dwFlags);
+}
+#endif
+
+#ifndef NO_MOUSEINPUT
+typedef struct MOUSEINPUT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dx, dy, mouseData, dwFlags, time, dwExtraInfo;
+} MOUSEINPUT_FID_CACHE;
+
+MOUSEINPUT_FID_CACHE MOUSEINPUTFc;
+
+void cacheMOUSEINPUTFields(JNIEnv *env, jobject lpObject)
+{
+       if (MOUSEINPUTFc.cached) return;
+       MOUSEINPUTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MOUSEINPUTFc.dx = (*env)->GetFieldID(env, MOUSEINPUTFc.clazz, "dx", "I");
+       MOUSEINPUTFc.dy = (*env)->GetFieldID(env, MOUSEINPUTFc.clazz, "dy", "I");
+       MOUSEINPUTFc.mouseData = (*env)->GetFieldID(env, MOUSEINPUTFc.clazz, "mouseData", "I");
+       MOUSEINPUTFc.dwFlags = (*env)->GetFieldID(env, MOUSEINPUTFc.clazz, "dwFlags", "I");
+       MOUSEINPUTFc.time = (*env)->GetFieldID(env, MOUSEINPUTFc.clazz, "time", "I");
+       MOUSEINPUTFc.dwExtraInfo = (*env)->GetFieldID(env, MOUSEINPUTFc.clazz, "dwExtraInfo", "J");
+       MOUSEINPUTFc.cached = 1;
+}
+
+MOUSEINPUT *getMOUSEINPUTFields(JNIEnv *env, jobject lpObject, MOUSEINPUT *lpStruct)
+{
+       if (!MOUSEINPUTFc.cached) cacheMOUSEINPUTFields(env, lpObject);
+       lpStruct->dx = (*env)->GetIntField(env, lpObject, MOUSEINPUTFc.dx);
+       lpStruct->dy = (*env)->GetIntField(env, lpObject, MOUSEINPUTFc.dy);
+       lpStruct->mouseData = (*env)->GetIntField(env, lpObject, MOUSEINPUTFc.mouseData);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, MOUSEINPUTFc.dwFlags);
+       lpStruct->time = (*env)->GetIntField(env, lpObject, MOUSEINPUTFc.time);
+       lpStruct->dwExtraInfo = (*env)->GetLongField(env, lpObject, MOUSEINPUTFc.dwExtraInfo);
+       return lpStruct;
+}
+
+void setMOUSEINPUTFields(JNIEnv *env, jobject lpObject, MOUSEINPUT *lpStruct)
+{
+       if (!MOUSEINPUTFc.cached) cacheMOUSEINPUTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, MOUSEINPUTFc.dx, (jint)lpStruct->dx);
+       (*env)->SetIntField(env, lpObject, MOUSEINPUTFc.dy, (jint)lpStruct->dy);
+       (*env)->SetIntField(env, lpObject, MOUSEINPUTFc.mouseData, (jint)lpStruct->mouseData);
+       (*env)->SetIntField(env, lpObject, MOUSEINPUTFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, MOUSEINPUTFc.time, (jint)lpStruct->time);
+       (*env)->SetLongField(env, lpObject, MOUSEINPUTFc.dwExtraInfo, (jlong)lpStruct->dwExtraInfo);
+}
+#endif
+
+#ifndef NO_MSG
+typedef struct MSG_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hwnd, message, wParam, lParam, time, x, y;
+} MSG_FID_CACHE;
+
+MSG_FID_CACHE MSGFc;
+
+void cacheMSGFields(JNIEnv *env, jobject lpObject)
+{
+       if (MSGFc.cached) return;
+       MSGFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       MSGFc.hwnd = (*env)->GetFieldID(env, MSGFc.clazz, "hwnd", "J");
+       MSGFc.message = (*env)->GetFieldID(env, MSGFc.clazz, "message", "I");
+       MSGFc.wParam = (*env)->GetFieldID(env, MSGFc.clazz, "wParam", "J");
+       MSGFc.lParam = (*env)->GetFieldID(env, MSGFc.clazz, "lParam", "J");
+       MSGFc.time = (*env)->GetFieldID(env, MSGFc.clazz, "time", "I");
+       MSGFc.x = (*env)->GetFieldID(env, MSGFc.clazz, "x", "I");
+       MSGFc.y = (*env)->GetFieldID(env, MSGFc.clazz, "y", "I");
+       MSGFc.cached = 1;
+}
+
+MSG *getMSGFields(JNIEnv *env, jobject lpObject, MSG *lpStruct)
+{
+       if (!MSGFc.cached) cacheMSGFields(env, lpObject);
+       lpStruct->hwnd = (HWND)(*env)->GetLongField(env, lpObject, MSGFc.hwnd);
+       lpStruct->message = (*env)->GetIntField(env, lpObject, MSGFc.message);
+       lpStruct->wParam = (*env)->GetLongField(env, lpObject, MSGFc.wParam);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, MSGFc.lParam);
+       lpStruct->time = (*env)->GetIntField(env, lpObject, MSGFc.time);
+       lpStruct->pt.x = (*env)->GetIntField(env, lpObject, MSGFc.x);
+       lpStruct->pt.y = (*env)->GetIntField(env, lpObject, MSGFc.y);
+       return lpStruct;
+}
+
+void setMSGFields(JNIEnv *env, jobject lpObject, MSG *lpStruct)
+{
+       if (!MSGFc.cached) cacheMSGFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, MSGFc.hwnd, (jlong)lpStruct->hwnd);
+       (*env)->SetIntField(env, lpObject, MSGFc.message, (jint)lpStruct->message);
+       (*env)->SetLongField(env, lpObject, MSGFc.wParam, (jlong)lpStruct->wParam);
+       (*env)->SetLongField(env, lpObject, MSGFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetIntField(env, lpObject, MSGFc.time, (jint)lpStruct->time);
+       (*env)->SetIntField(env, lpObject, MSGFc.x, (jint)lpStruct->pt.x);
+       (*env)->SetIntField(env, lpObject, MSGFc.y, (jint)lpStruct->pt.y);
+}
+#endif
+
+#ifndef NO_NMCUSTOMDRAW
+typedef struct NMCUSTOMDRAW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID dwDrawStage, hdc, left, top, right, bottom, dwItemSpec, uItemState, lItemlParam;
+} NMCUSTOMDRAW_FID_CACHE;
+
+NMCUSTOMDRAW_FID_CACHE NMCUSTOMDRAWFc;
+
+void cacheNMCUSTOMDRAWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMCUSTOMDRAWFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMCUSTOMDRAWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMCUSTOMDRAWFc.dwDrawStage = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "dwDrawStage", "I");
+       NMCUSTOMDRAWFc.hdc = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "hdc", "J");
+       NMCUSTOMDRAWFc.left = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "left", "I");
+       NMCUSTOMDRAWFc.top = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "top", "I");
+       NMCUSTOMDRAWFc.right = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "right", "I");
+       NMCUSTOMDRAWFc.bottom = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "bottom", "I");
+       NMCUSTOMDRAWFc.dwItemSpec = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "dwItemSpec", "J");
+       NMCUSTOMDRAWFc.uItemState = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "uItemState", "I");
+       NMCUSTOMDRAWFc.lItemlParam = (*env)->GetFieldID(env, NMCUSTOMDRAWFc.clazz, "lItemlParam", "J");
+       NMCUSTOMDRAWFc.cached = 1;
+}
+
+NMCUSTOMDRAW *getNMCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMCUSTOMDRAW *lpStruct)
+{
+       if (!NMCUSTOMDRAWFc.cached) cacheNMCUSTOMDRAWFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->dwDrawStage = (*env)->GetIntField(env, lpObject, NMCUSTOMDRAWFc.dwDrawStage);
+       lpStruct->hdc = (HDC)(*env)->GetLongField(env, lpObject, NMCUSTOMDRAWFc.hdc);
+       lpStruct->rc.left = (*env)->GetIntField(env, lpObject, NMCUSTOMDRAWFc.left);
+       lpStruct->rc.top = (*env)->GetIntField(env, lpObject, NMCUSTOMDRAWFc.top);
+       lpStruct->rc.right = (*env)->GetIntField(env, lpObject, NMCUSTOMDRAWFc.right);
+       lpStruct->rc.bottom = (*env)->GetIntField(env, lpObject, NMCUSTOMDRAWFc.bottom);
+       lpStruct->dwItemSpec = (*env)->GetLongField(env, lpObject, NMCUSTOMDRAWFc.dwItemSpec);
+       lpStruct->uItemState = (*env)->GetIntField(env, lpObject, NMCUSTOMDRAWFc.uItemState);
+       lpStruct->lItemlParam = (*env)->GetLongField(env, lpObject, NMCUSTOMDRAWFc.lItemlParam);
+       return lpStruct;
+}
+
+void setNMCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMCUSTOMDRAW *lpStruct)
+{
+       if (!NMCUSTOMDRAWFc.cached) cacheNMCUSTOMDRAWFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMCUSTOMDRAWFc.dwDrawStage, (jint)lpStruct->dwDrawStage);
+       (*env)->SetLongField(env, lpObject, NMCUSTOMDRAWFc.hdc, (jlong)lpStruct->hdc);
+       (*env)->SetIntField(env, lpObject, NMCUSTOMDRAWFc.left, (jint)lpStruct->rc.left);
+       (*env)->SetIntField(env, lpObject, NMCUSTOMDRAWFc.top, (jint)lpStruct->rc.top);
+       (*env)->SetIntField(env, lpObject, NMCUSTOMDRAWFc.right, (jint)lpStruct->rc.right);
+       (*env)->SetIntField(env, lpObject, NMCUSTOMDRAWFc.bottom, (jint)lpStruct->rc.bottom);
+       (*env)->SetLongField(env, lpObject, NMCUSTOMDRAWFc.dwItemSpec, (jlong)lpStruct->dwItemSpec);
+       (*env)->SetIntField(env, lpObject, NMCUSTOMDRAWFc.uItemState, (jint)lpStruct->uItemState);
+       (*env)->SetLongField(env, lpObject, NMCUSTOMDRAWFc.lItemlParam, (jlong)lpStruct->lItemlParam);
+}
+#endif
+
+#ifndef NO_NMHDR
+typedef struct NMHDR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hwndFrom, idFrom, code;
+} NMHDR_FID_CACHE;
+
+NMHDR_FID_CACHE NMHDRFc;
+
+void cacheNMHDRFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMHDRFc.cached) return;
+       NMHDRFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMHDRFc.hwndFrom = (*env)->GetFieldID(env, NMHDRFc.clazz, "hwndFrom", "J");
+       NMHDRFc.idFrom = (*env)->GetFieldID(env, NMHDRFc.clazz, "idFrom", "J");
+       NMHDRFc.code = (*env)->GetFieldID(env, NMHDRFc.clazz, "code", "I");
+       NMHDRFc.cached = 1;
+}
+
+NMHDR *getNMHDRFields(JNIEnv *env, jobject lpObject, NMHDR *lpStruct)
+{
+       if (!NMHDRFc.cached) cacheNMHDRFields(env, lpObject);
+       lpStruct->hwndFrom = (HWND)(*env)->GetLongField(env, lpObject, NMHDRFc.hwndFrom);
+       lpStruct->idFrom = (*env)->GetLongField(env, lpObject, NMHDRFc.idFrom);
+       lpStruct->code = (*env)->GetIntField(env, lpObject, NMHDRFc.code);
+       return lpStruct;
+}
+
+void setNMHDRFields(JNIEnv *env, jobject lpObject, NMHDR *lpStruct)
+{
+       if (!NMHDRFc.cached) cacheNMHDRFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, NMHDRFc.hwndFrom, (jlong)lpStruct->hwndFrom);
+       (*env)->SetLongField(env, lpObject, NMHDRFc.idFrom, (jlong)lpStruct->idFrom);
+       (*env)->SetIntField(env, lpObject, NMHDRFc.code, (jint)lpStruct->code);
+}
+#endif
+
+#ifndef NO_NMHEADER
+typedef struct NMHEADER_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iItem, iButton, pitem;
+} NMHEADER_FID_CACHE;
+
+NMHEADER_FID_CACHE NMHEADERFc;
+
+void cacheNMHEADERFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMHEADERFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMHEADERFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMHEADERFc.iItem = (*env)->GetFieldID(env, NMHEADERFc.clazz, "iItem", "I");
+       NMHEADERFc.iButton = (*env)->GetFieldID(env, NMHEADERFc.clazz, "iButton", "I");
+       NMHEADERFc.pitem = (*env)->GetFieldID(env, NMHEADERFc.clazz, "pitem", "J");
+       NMHEADERFc.cached = 1;
+}
+
+NMHEADER *getNMHEADERFields(JNIEnv *env, jobject lpObject, NMHEADER *lpStruct)
+{
+       if (!NMHEADERFc.cached) cacheNMHEADERFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, NMHEADERFc.iItem);
+       lpStruct->iButton = (*env)->GetIntField(env, lpObject, NMHEADERFc.iButton);
+       lpStruct->pitem = (HDITEM FAR *)(*env)->GetLongField(env, lpObject, NMHEADERFc.pitem);
+       return lpStruct;
+}
+
+void setNMHEADERFields(JNIEnv *env, jobject lpObject, NMHEADER *lpStruct)
+{
+       if (!NMHEADERFc.cached) cacheNMHEADERFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMHEADERFc.iItem, (jint)lpStruct->iItem);
+       (*env)->SetIntField(env, lpObject, NMHEADERFc.iButton, (jint)lpStruct->iButton);
+       (*env)->SetLongField(env, lpObject, NMHEADERFc.pitem, (jlong)lpStruct->pitem);
+}
+#endif
+
+#ifndef NO_NMLINK
+typedef struct NMLINK_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, iLink, state, stateMask, szID, szUrl;
+} NMLINK_FID_CACHE;
+
+NMLINK_FID_CACHE NMLINKFc;
+
+void cacheNMLINKFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMLINKFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMLINKFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMLINKFc.mask = (*env)->GetFieldID(env, NMLINKFc.clazz, "mask", "I");
+       NMLINKFc.iLink = (*env)->GetFieldID(env, NMLINKFc.clazz, "iLink", "I");
+       NMLINKFc.state = (*env)->GetFieldID(env, NMLINKFc.clazz, "state", "I");
+       NMLINKFc.stateMask = (*env)->GetFieldID(env, NMLINKFc.clazz, "stateMask", "I");
+       NMLINKFc.szID = (*env)->GetFieldID(env, NMLINKFc.clazz, "szID", "[C");
+       NMLINKFc.szUrl = (*env)->GetFieldID(env, NMLINKFc.clazz, "szUrl", "[C");
+       NMLINKFc.cached = 1;
+}
+
+NMLINK *getNMLINKFields(JNIEnv *env, jobject lpObject, NMLINK *lpStruct)
+{
+       if (!NMLINKFc.cached) cacheNMLINKFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->item.mask = (*env)->GetIntField(env, lpObject, NMLINKFc.mask);
+       lpStruct->item.iLink = (*env)->GetIntField(env, lpObject, NMLINKFc.iLink);
+       lpStruct->item.state = (*env)->GetIntField(env, lpObject, NMLINKFc.state);
+       lpStruct->item.stateMask = (*env)->GetIntField(env, lpObject, NMLINKFc.stateMask);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NMLINKFc.szID);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->item.szID) / sizeof(jchar), (jchar *)lpStruct->item.szID);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NMLINKFc.szUrl);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->item.szUrl) / sizeof(jchar), (jchar *)lpStruct->item.szUrl);
+       }
+       return lpStruct;
+}
+
+void setNMLINKFields(JNIEnv *env, jobject lpObject, NMLINK *lpStruct)
+{
+       if (!NMLINKFc.cached) cacheNMLINKFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMLINKFc.mask, (jint)lpStruct->item.mask);
+       (*env)->SetIntField(env, lpObject, NMLINKFc.iLink, (jint)lpStruct->item.iLink);
+       (*env)->SetIntField(env, lpObject, NMLINKFc.state, (jint)lpStruct->item.state);
+       (*env)->SetIntField(env, lpObject, NMLINKFc.stateMask, (jint)lpStruct->item.stateMask);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NMLINKFc.szID);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->item.szID) / sizeof(jchar), (jchar *)lpStruct->item.szID);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NMLINKFc.szUrl);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->item.szUrl) / sizeof(jchar), (jchar *)lpStruct->item.szUrl);
+       }
+}
+#endif
+
+#ifndef NO_NMLISTVIEW
+typedef struct NMLISTVIEW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iItem, iSubItem, uNewState, uOldState, uChanged, x, y, lParam;
+} NMLISTVIEW_FID_CACHE;
+
+NMLISTVIEW_FID_CACHE NMLISTVIEWFc;
+
+void cacheNMLISTVIEWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMLISTVIEWFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMLISTVIEWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMLISTVIEWFc.iItem = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "iItem", "I");
+       NMLISTVIEWFc.iSubItem = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "iSubItem", "I");
+       NMLISTVIEWFc.uNewState = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "uNewState", "I");
+       NMLISTVIEWFc.uOldState = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "uOldState", "I");
+       NMLISTVIEWFc.uChanged = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "uChanged", "I");
+       NMLISTVIEWFc.x = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "x", "I");
+       NMLISTVIEWFc.y = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "y", "I");
+       NMLISTVIEWFc.lParam = (*env)->GetFieldID(env, NMLISTVIEWFc.clazz, "lParam", "J");
+       NMLISTVIEWFc.cached = 1;
+}
+
+NMLISTVIEW *getNMLISTVIEWFields(JNIEnv *env, jobject lpObject, NMLISTVIEW *lpStruct)
+{
+       if (!NMLISTVIEWFc.cached) cacheNMLISTVIEWFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.iItem);
+       lpStruct->iSubItem = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.iSubItem);
+       lpStruct->uNewState = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.uNewState);
+       lpStruct->uOldState = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.uOldState);
+       lpStruct->uChanged = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.uChanged);
+       lpStruct->ptAction.x = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.x);
+       lpStruct->ptAction.y = (*env)->GetIntField(env, lpObject, NMLISTVIEWFc.y);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, NMLISTVIEWFc.lParam);
+       return lpStruct;
+}
+
+void setNMLISTVIEWFields(JNIEnv *env, jobject lpObject, NMLISTVIEW *lpStruct)
+{
+       if (!NMLISTVIEWFc.cached) cacheNMLISTVIEWFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.iItem, (jint)lpStruct->iItem);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.iSubItem, (jint)lpStruct->iSubItem);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.uNewState, (jint)lpStruct->uNewState);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.uOldState, (jint)lpStruct->uOldState);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.uChanged, (jint)lpStruct->uChanged);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.x, (jint)lpStruct->ptAction.x);
+       (*env)->SetIntField(env, lpObject, NMLISTVIEWFc.y, (jint)lpStruct->ptAction.y);
+       (*env)->SetLongField(env, lpObject, NMLISTVIEWFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_NMLVCUSTOMDRAW
+typedef struct NMLVCUSTOMDRAW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID clrText, clrTextBk, iSubItem, dwItemType, clrFace, iIconEffect, iIconPhase, iPartId, iStateId, rcText_left, rcText_top, rcText_right, rcText_bottom, uAlign;
+} NMLVCUSTOMDRAW_FID_CACHE;
+
+NMLVCUSTOMDRAW_FID_CACHE NMLVCUSTOMDRAWFc;
+
+void cacheNMLVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMLVCUSTOMDRAWFc.cached) return;
+       cacheNMCUSTOMDRAWFields(env, lpObject);
+       NMLVCUSTOMDRAWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMLVCUSTOMDRAWFc.clrText = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "clrText", "I");
+       NMLVCUSTOMDRAWFc.clrTextBk = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "clrTextBk", "I");
+       NMLVCUSTOMDRAWFc.iSubItem = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "iSubItem", "I");
+       NMLVCUSTOMDRAWFc.dwItemType = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "dwItemType", "I");
+       NMLVCUSTOMDRAWFc.clrFace = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "clrFace", "I");
+       NMLVCUSTOMDRAWFc.iIconEffect = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "iIconEffect", "I");
+       NMLVCUSTOMDRAWFc.iIconPhase = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "iIconPhase", "I");
+       NMLVCUSTOMDRAWFc.iPartId = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "iPartId", "I");
+       NMLVCUSTOMDRAWFc.iStateId = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "iStateId", "I");
+       NMLVCUSTOMDRAWFc.rcText_left = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "rcText_left", "I");
+       NMLVCUSTOMDRAWFc.rcText_top = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "rcText_top", "I");
+       NMLVCUSTOMDRAWFc.rcText_right = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "rcText_right", "I");
+       NMLVCUSTOMDRAWFc.rcText_bottom = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "rcText_bottom", "I");
+       NMLVCUSTOMDRAWFc.uAlign = (*env)->GetFieldID(env, NMLVCUSTOMDRAWFc.clazz, "uAlign", "I");
+       NMLVCUSTOMDRAWFc.cached = 1;
+}
+
+NMLVCUSTOMDRAW *getNMLVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMLVCUSTOMDRAW *lpStruct)
+{
+       if (!NMLVCUSTOMDRAWFc.cached) cacheNMLVCUSTOMDRAWFields(env, lpObject);
+       getNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       lpStruct->clrText = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.clrText);
+       lpStruct->clrTextBk = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.clrTextBk);
+       lpStruct->iSubItem = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iSubItem);
+       lpStruct->dwItemType = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.dwItemType);
+       lpStruct->clrFace = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.clrFace);
+       lpStruct->iIconEffect = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iIconEffect);
+       lpStruct->iIconPhase = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iIconPhase);
+       lpStruct->iPartId = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iPartId);
+       lpStruct->iStateId = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iStateId);
+       lpStruct->rcText.left = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_left);
+       lpStruct->rcText.top = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_top);
+       lpStruct->rcText.right = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_right);
+       lpStruct->rcText.bottom = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_bottom);
+       lpStruct->uAlign = (*env)->GetIntField(env, lpObject, NMLVCUSTOMDRAWFc.uAlign);
+       return lpStruct;
+}
+
+void setNMLVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMLVCUSTOMDRAW *lpStruct)
+{
+       if (!NMLVCUSTOMDRAWFc.cached) cacheNMLVCUSTOMDRAWFields(env, lpObject);
+       setNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.clrText, (jint)lpStruct->clrText);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.clrTextBk, (jint)lpStruct->clrTextBk);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iSubItem, (jint)lpStruct->iSubItem);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.dwItemType, (jint)lpStruct->dwItemType);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.clrFace, (jint)lpStruct->clrFace);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iIconEffect, (jint)lpStruct->iIconEffect);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iIconPhase, (jint)lpStruct->iIconPhase);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iPartId, (jint)lpStruct->iPartId);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.iStateId, (jint)lpStruct->iStateId);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_left, (jint)lpStruct->rcText.left);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_top, (jint)lpStruct->rcText.top);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_right, (jint)lpStruct->rcText.right);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.rcText_bottom, (jint)lpStruct->rcText.bottom);
+       (*env)->SetIntField(env, lpObject, NMLVCUSTOMDRAWFc.uAlign, (jint)lpStruct->uAlign);
+}
+#endif
+
+#ifndef NO_NMLVDISPINFO
+typedef struct NMLVDISPINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, iItem, iSubItem, state, stateMask, pszText, cchTextMax, iImage, lParam, iIndent, iGroupId, cColumns, puColumns;
+} NMLVDISPINFO_FID_CACHE;
+
+NMLVDISPINFO_FID_CACHE NMLVDISPINFOFc;
+
+void cacheNMLVDISPINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMLVDISPINFOFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMLVDISPINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMLVDISPINFOFc.mask = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "mask", "I");
+       NMLVDISPINFOFc.iItem = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "iItem", "I");
+       NMLVDISPINFOFc.iSubItem = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "iSubItem", "I");
+       NMLVDISPINFOFc.state = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "state", "I");
+       NMLVDISPINFOFc.stateMask = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "stateMask", "I");
+       NMLVDISPINFOFc.pszText = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "pszText", "J");
+       NMLVDISPINFOFc.cchTextMax = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "cchTextMax", "I");
+       NMLVDISPINFOFc.iImage = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "iImage", "I");
+       NMLVDISPINFOFc.lParam = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "lParam", "J");
+       NMLVDISPINFOFc.iIndent = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "iIndent", "I");
+       NMLVDISPINFOFc.iGroupId = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "iGroupId", "I");
+       NMLVDISPINFOFc.cColumns = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "cColumns", "I");
+       NMLVDISPINFOFc.puColumns = (*env)->GetFieldID(env, NMLVDISPINFOFc.clazz, "puColumns", "J");
+       NMLVDISPINFOFc.cached = 1;
+}
+
+NMLVDISPINFO *getNMLVDISPINFOFields(JNIEnv *env, jobject lpObject, NMLVDISPINFO *lpStruct)
+{
+       if (!NMLVDISPINFOFc.cached) cacheNMLVDISPINFOFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->item.mask = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.mask);
+       lpStruct->item.iItem = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.iItem);
+       lpStruct->item.iSubItem = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.iSubItem);
+       lpStruct->item.state = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.state);
+       lpStruct->item.stateMask = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.stateMask);
+       lpStruct->item.pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, NMLVDISPINFOFc.pszText);
+       lpStruct->item.cchTextMax = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.cchTextMax);
+       lpStruct->item.iImage = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.iImage);
+       lpStruct->item.lParam = (*env)->GetLongField(env, lpObject, NMLVDISPINFOFc.lParam);
+       lpStruct->item.iIndent = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.iIndent);
+       lpStruct->item.iGroupId = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.iGroupId);
+       lpStruct->item.cColumns = (*env)->GetIntField(env, lpObject, NMLVDISPINFOFc.cColumns);
+       lpStruct->item.puColumns = (PUINT)(*env)->GetLongField(env, lpObject, NMLVDISPINFOFc.puColumns);
+       return lpStruct;
+}
+
+void setNMLVDISPINFOFields(JNIEnv *env, jobject lpObject, NMLVDISPINFO *lpStruct)
+{
+       if (!NMLVDISPINFOFc.cached) cacheNMLVDISPINFOFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.mask, (jint)lpStruct->item.mask);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.iItem, (jint)lpStruct->item.iItem);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.iSubItem, (jint)lpStruct->item.iSubItem);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.state, (jint)lpStruct->item.state);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.stateMask, (jint)lpStruct->item.stateMask);
+       (*env)->SetLongField(env, lpObject, NMLVDISPINFOFc.pszText, (jlong)lpStruct->item.pszText);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.cchTextMax, (jint)lpStruct->item.cchTextMax);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.iImage, (jint)lpStruct->item.iImage);
+       (*env)->SetLongField(env, lpObject, NMLVDISPINFOFc.lParam, (jlong)lpStruct->item.lParam);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.iIndent, (jint)lpStruct->item.iIndent);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.iGroupId, (jint)lpStruct->item.iGroupId);
+       (*env)->SetIntField(env, lpObject, NMLVDISPINFOFc.cColumns, (jint)lpStruct->item.cColumns);
+       (*env)->SetLongField(env, lpObject, NMLVDISPINFOFc.puColumns, (jlong)lpStruct->item.puColumns);
+}
+#endif
+
+#ifndef NO_NMLVFINDITEM
+typedef struct NMLVFINDITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iStart, flags, psz, lParam, x, y, vkDirection;
+} NMLVFINDITEM_FID_CACHE;
+
+NMLVFINDITEM_FID_CACHE NMLVFINDITEMFc;
+
+void cacheNMLVFINDITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMLVFINDITEMFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMLVFINDITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMLVFINDITEMFc.iStart = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "iStart", "I");
+       NMLVFINDITEMFc.flags = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "flags", "I");
+       NMLVFINDITEMFc.psz = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "psz", "J");
+       NMLVFINDITEMFc.lParam = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "lParam", "J");
+       NMLVFINDITEMFc.x = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "x", "I");
+       NMLVFINDITEMFc.y = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "y", "I");
+       NMLVFINDITEMFc.vkDirection = (*env)->GetFieldID(env, NMLVFINDITEMFc.clazz, "vkDirection", "I");
+       NMLVFINDITEMFc.cached = 1;
+}
+
+NMLVFINDITEM *getNMLVFINDITEMFields(JNIEnv *env, jobject lpObject, NMLVFINDITEM *lpStruct)
+{
+       if (!NMLVFINDITEMFc.cached) cacheNMLVFINDITEMFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->iStart = (*env)->GetIntField(env, lpObject, NMLVFINDITEMFc.iStart);
+       lpStruct->lvfi.flags = (*env)->GetIntField(env, lpObject, NMLVFINDITEMFc.flags);
+       lpStruct->lvfi.psz = (LPCTSTR)(*env)->GetLongField(env, lpObject, NMLVFINDITEMFc.psz);
+       lpStruct->lvfi.lParam = (*env)->GetLongField(env, lpObject, NMLVFINDITEMFc.lParam);
+       lpStruct->lvfi.pt.x = (*env)->GetIntField(env, lpObject, NMLVFINDITEMFc.x);
+       lpStruct->lvfi.pt.y = (*env)->GetIntField(env, lpObject, NMLVFINDITEMFc.y);
+       lpStruct->lvfi.vkDirection = (*env)->GetIntField(env, lpObject, NMLVFINDITEMFc.vkDirection);
+       return lpStruct;
+}
+
+void setNMLVFINDITEMFields(JNIEnv *env, jobject lpObject, NMLVFINDITEM *lpStruct)
+{
+       if (!NMLVFINDITEMFc.cached) cacheNMLVFINDITEMFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMLVFINDITEMFc.iStart, (jint)lpStruct->iStart);
+       (*env)->SetIntField(env, lpObject, NMLVFINDITEMFc.flags, (jint)lpStruct->lvfi.flags);
+       (*env)->SetLongField(env, lpObject, NMLVFINDITEMFc.psz, (jlong)lpStruct->lvfi.psz);
+       (*env)->SetLongField(env, lpObject, NMLVFINDITEMFc.lParam, (jlong)lpStruct->lvfi.lParam);
+       (*env)->SetIntField(env, lpObject, NMLVFINDITEMFc.x, (jint)lpStruct->lvfi.pt.x);
+       (*env)->SetIntField(env, lpObject, NMLVFINDITEMFc.y, (jint)lpStruct->lvfi.pt.y);
+       (*env)->SetIntField(env, lpObject, NMLVFINDITEMFc.vkDirection, (jint)lpStruct->lvfi.vkDirection);
+}
+#endif
+
+#ifndef NO_NMLVODSTATECHANGE
+typedef struct NMLVODSTATECHANGE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iFrom, iTo, uNewState, uOldState;
+} NMLVODSTATECHANGE_FID_CACHE;
+
+NMLVODSTATECHANGE_FID_CACHE NMLVODSTATECHANGEFc;
+
+void cacheNMLVODSTATECHANGEFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMLVODSTATECHANGEFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMLVODSTATECHANGEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMLVODSTATECHANGEFc.iFrom = (*env)->GetFieldID(env, NMLVODSTATECHANGEFc.clazz, "iFrom", "I");
+       NMLVODSTATECHANGEFc.iTo = (*env)->GetFieldID(env, NMLVODSTATECHANGEFc.clazz, "iTo", "I");
+       NMLVODSTATECHANGEFc.uNewState = (*env)->GetFieldID(env, NMLVODSTATECHANGEFc.clazz, "uNewState", "I");
+       NMLVODSTATECHANGEFc.uOldState = (*env)->GetFieldID(env, NMLVODSTATECHANGEFc.clazz, "uOldState", "I");
+       NMLVODSTATECHANGEFc.cached = 1;
+}
+
+NMLVODSTATECHANGE *getNMLVODSTATECHANGEFields(JNIEnv *env, jobject lpObject, NMLVODSTATECHANGE *lpStruct)
+{
+       if (!NMLVODSTATECHANGEFc.cached) cacheNMLVODSTATECHANGEFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->iFrom = (*env)->GetIntField(env, lpObject, NMLVODSTATECHANGEFc.iFrom);
+       lpStruct->iTo = (*env)->GetIntField(env, lpObject, NMLVODSTATECHANGEFc.iTo);
+       lpStruct->uNewState = (*env)->GetIntField(env, lpObject, NMLVODSTATECHANGEFc.uNewState);
+       lpStruct->uOldState = (*env)->GetIntField(env, lpObject, NMLVODSTATECHANGEFc.uOldState);
+       return lpStruct;
+}
+
+void setNMLVODSTATECHANGEFields(JNIEnv *env, jobject lpObject, NMLVODSTATECHANGE *lpStruct)
+{
+       if (!NMLVODSTATECHANGEFc.cached) cacheNMLVODSTATECHANGEFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMLVODSTATECHANGEFc.iFrom, (jint)lpStruct->iFrom);
+       (*env)->SetIntField(env, lpObject, NMLVODSTATECHANGEFc.iTo, (jint)lpStruct->iTo);
+       (*env)->SetIntField(env, lpObject, NMLVODSTATECHANGEFc.uNewState, (jint)lpStruct->uNewState);
+       (*env)->SetIntField(env, lpObject, NMLVODSTATECHANGEFc.uOldState, (jint)lpStruct->uOldState);
+}
+#endif
+
+#ifndef NO_NMREBARCHEVRON
+typedef struct NMREBARCHEVRON_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID uBand, wID, lParam, left, top, right, bottom, lParamNM;
+} NMREBARCHEVRON_FID_CACHE;
+
+NMREBARCHEVRON_FID_CACHE NMREBARCHEVRONFc;
+
+void cacheNMREBARCHEVRONFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMREBARCHEVRONFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMREBARCHEVRONFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMREBARCHEVRONFc.uBand = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "uBand", "I");
+       NMREBARCHEVRONFc.wID = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "wID", "I");
+       NMREBARCHEVRONFc.lParam = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "lParam", "J");
+       NMREBARCHEVRONFc.left = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "left", "I");
+       NMREBARCHEVRONFc.top = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "top", "I");
+       NMREBARCHEVRONFc.right = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "right", "I");
+       NMREBARCHEVRONFc.bottom = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "bottom", "I");
+       NMREBARCHEVRONFc.lParamNM = (*env)->GetFieldID(env, NMREBARCHEVRONFc.clazz, "lParamNM", "J");
+       NMREBARCHEVRONFc.cached = 1;
+}
+
+NMREBARCHEVRON *getNMREBARCHEVRONFields(JNIEnv *env, jobject lpObject, NMREBARCHEVRON *lpStruct)
+{
+       if (!NMREBARCHEVRONFc.cached) cacheNMREBARCHEVRONFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->uBand = (*env)->GetIntField(env, lpObject, NMREBARCHEVRONFc.uBand);
+       lpStruct->wID = (*env)->GetIntField(env, lpObject, NMREBARCHEVRONFc.wID);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, NMREBARCHEVRONFc.lParam);
+       lpStruct->rc.left = (*env)->GetIntField(env, lpObject, NMREBARCHEVRONFc.left);
+       lpStruct->rc.top = (*env)->GetIntField(env, lpObject, NMREBARCHEVRONFc.top);
+       lpStruct->rc.right = (*env)->GetIntField(env, lpObject, NMREBARCHEVRONFc.right);
+       lpStruct->rc.bottom = (*env)->GetIntField(env, lpObject, NMREBARCHEVRONFc.bottom);
+       lpStruct->lParamNM = (*env)->GetLongField(env, lpObject, NMREBARCHEVRONFc.lParamNM);
+       return lpStruct;
+}
+
+void setNMREBARCHEVRONFields(JNIEnv *env, jobject lpObject, NMREBARCHEVRON *lpStruct)
+{
+       if (!NMREBARCHEVRONFc.cached) cacheNMREBARCHEVRONFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMREBARCHEVRONFc.uBand, (jint)lpStruct->uBand);
+       (*env)->SetIntField(env, lpObject, NMREBARCHEVRONFc.wID, (jint)lpStruct->wID);
+       (*env)->SetLongField(env, lpObject, NMREBARCHEVRONFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetIntField(env, lpObject, NMREBARCHEVRONFc.left, (jint)lpStruct->rc.left);
+       (*env)->SetIntField(env, lpObject, NMREBARCHEVRONFc.top, (jint)lpStruct->rc.top);
+       (*env)->SetIntField(env, lpObject, NMREBARCHEVRONFc.right, (jint)lpStruct->rc.right);
+       (*env)->SetIntField(env, lpObject, NMREBARCHEVRONFc.bottom, (jint)lpStruct->rc.bottom);
+       (*env)->SetLongField(env, lpObject, NMREBARCHEVRONFc.lParamNM, (jlong)lpStruct->lParamNM);
+}
+#endif
+
+#ifndef NO_NMREBARCHILDSIZE
+typedef struct NMREBARCHILDSIZE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID uBand, wID, rcChild_left, rcChild_top, rcChild_right, rcChild_bottom, rcBand_left, rcBand_top, rcBand_right, rcBand_bottom;
+} NMREBARCHILDSIZE_FID_CACHE;
+
+NMREBARCHILDSIZE_FID_CACHE NMREBARCHILDSIZEFc;
+
+void cacheNMREBARCHILDSIZEFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMREBARCHILDSIZEFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMREBARCHILDSIZEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMREBARCHILDSIZEFc.uBand = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "uBand", "I");
+       NMREBARCHILDSIZEFc.wID = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "wID", "I");
+       NMREBARCHILDSIZEFc.rcChild_left = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcChild_left", "I");
+       NMREBARCHILDSIZEFc.rcChild_top = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcChild_top", "I");
+       NMREBARCHILDSIZEFc.rcChild_right = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcChild_right", "I");
+       NMREBARCHILDSIZEFc.rcChild_bottom = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcChild_bottom", "I");
+       NMREBARCHILDSIZEFc.rcBand_left = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcBand_left", "I");
+       NMREBARCHILDSIZEFc.rcBand_top = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcBand_top", "I");
+       NMREBARCHILDSIZEFc.rcBand_right = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcBand_right", "I");
+       NMREBARCHILDSIZEFc.rcBand_bottom = (*env)->GetFieldID(env, NMREBARCHILDSIZEFc.clazz, "rcBand_bottom", "I");
+       NMREBARCHILDSIZEFc.cached = 1;
+}
+
+NMREBARCHILDSIZE *getNMREBARCHILDSIZEFields(JNIEnv *env, jobject lpObject, NMREBARCHILDSIZE *lpStruct)
+{
+       if (!NMREBARCHILDSIZEFc.cached) cacheNMREBARCHILDSIZEFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->uBand = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.uBand);
+       lpStruct->wID = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.wID);
+       lpStruct->rcChild.left = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_left);
+       lpStruct->rcChild.top = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_top);
+       lpStruct->rcChild.right = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_right);
+       lpStruct->rcChild.bottom = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_bottom);
+       lpStruct->rcBand.left = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_left);
+       lpStruct->rcBand.top = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_top);
+       lpStruct->rcBand.right = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_right);
+       lpStruct->rcBand.bottom = (*env)->GetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_bottom);
+       return lpStruct;
+}
+
+void setNMREBARCHILDSIZEFields(JNIEnv *env, jobject lpObject, NMREBARCHILDSIZE *lpStruct)
+{
+       if (!NMREBARCHILDSIZEFc.cached) cacheNMREBARCHILDSIZEFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.uBand, (jint)lpStruct->uBand);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.wID, (jint)lpStruct->wID);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_left, (jint)lpStruct->rcChild.left);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_top, (jint)lpStruct->rcChild.top);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_right, (jint)lpStruct->rcChild.right);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcChild_bottom, (jint)lpStruct->rcChild.bottom);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_left, (jint)lpStruct->rcBand.left);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_top, (jint)lpStruct->rcBand.top);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_right, (jint)lpStruct->rcBand.right);
+       (*env)->SetIntField(env, lpObject, NMREBARCHILDSIZEFc.rcBand_bottom, (jint)lpStruct->rcBand.bottom);
+}
+#endif
+
+#ifndef NO_NMTBCUSTOMDRAW
+typedef struct NMTBCUSTOMDRAW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID nmcd, hbrMonoDither, hbrLines, hpenLines, clrText, clrMark, clrTextHighlight, clrBtnFace, clrBtnHighlight, clrHighlightHotTrack, rcText_left, rcText_top, rcText_right, rcText_bottom, nStringBkMode, nHLStringBkMode, iListGap;
+} NMTBCUSTOMDRAW_FID_CACHE;
+
+NMTBCUSTOMDRAW_FID_CACHE NMTBCUSTOMDRAWFc;
+
+void cacheNMTBCUSTOMDRAWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTBCUSTOMDRAWFc.cached) return;
+       cacheNMCUSTOMDRAWFields(env, lpObject);
+       NMTBCUSTOMDRAWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTBCUSTOMDRAWFc.nmcd = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "nmcd", "Lorg/eclipse/swt/internal/win32/NMCUSTOMDRAW;");
+       NMTBCUSTOMDRAWFc.hbrMonoDither = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "hbrMonoDither", "J");
+       NMTBCUSTOMDRAWFc.hbrLines = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "hbrLines", "J");
+       NMTBCUSTOMDRAWFc.hpenLines = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "hpenLines", "J");
+       NMTBCUSTOMDRAWFc.clrText = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "clrText", "I");
+       NMTBCUSTOMDRAWFc.clrMark = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "clrMark", "I");
+       NMTBCUSTOMDRAWFc.clrTextHighlight = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "clrTextHighlight", "I");
+       NMTBCUSTOMDRAWFc.clrBtnFace = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "clrBtnFace", "I");
+       NMTBCUSTOMDRAWFc.clrBtnHighlight = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "clrBtnHighlight", "I");
+       NMTBCUSTOMDRAWFc.clrHighlightHotTrack = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "clrHighlightHotTrack", "I");
+       NMTBCUSTOMDRAWFc.rcText_left = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "rcText_left", "I");
+       NMTBCUSTOMDRAWFc.rcText_top = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "rcText_top", "I");
+       NMTBCUSTOMDRAWFc.rcText_right = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "rcText_right", "I");
+       NMTBCUSTOMDRAWFc.rcText_bottom = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "rcText_bottom", "I");
+       NMTBCUSTOMDRAWFc.nStringBkMode = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "nStringBkMode", "I");
+       NMTBCUSTOMDRAWFc.nHLStringBkMode = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "nHLStringBkMode", "I");
+       NMTBCUSTOMDRAWFc.iListGap = (*env)->GetFieldID(env, NMTBCUSTOMDRAWFc.clazz, "iListGap", "I");
+       NMTBCUSTOMDRAWFc.cached = 1;
+}
+
+NMTBCUSTOMDRAW *getNMTBCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTBCUSTOMDRAW *lpStruct)
+{
+       if (!NMTBCUSTOMDRAWFc.cached) cacheNMTBCUSTOMDRAWFields(env, lpObject);
+       getNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTBCUSTOMDRAWFc.nmcd);
+       if (lpObject1 != NULL) getNMCUSTOMDRAWFields(env, lpObject1, &lpStruct->nmcd);
+       }
+       lpStruct->hbrMonoDither = (HBRUSH)(*env)->GetLongField(env, lpObject, NMTBCUSTOMDRAWFc.hbrMonoDither);
+       lpStruct->hbrLines = (HBRUSH)(*env)->GetLongField(env, lpObject, NMTBCUSTOMDRAWFc.hbrLines);
+       lpStruct->hpenLines = (HPEN)(*env)->GetLongField(env, lpObject, NMTBCUSTOMDRAWFc.hpenLines);
+       lpStruct->clrText = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrText);
+       lpStruct->clrMark = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrMark);
+       lpStruct->clrTextHighlight = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrTextHighlight);
+       lpStruct->clrBtnFace = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrBtnFace);
+       lpStruct->clrBtnHighlight = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrBtnHighlight);
+       lpStruct->clrHighlightHotTrack = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrHighlightHotTrack);
+       lpStruct->rcText.left = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_left);
+       lpStruct->rcText.top = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_top);
+       lpStruct->rcText.right = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_right);
+       lpStruct->rcText.bottom = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_bottom);
+       lpStruct->nStringBkMode = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.nStringBkMode);
+       lpStruct->nHLStringBkMode = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.nHLStringBkMode);
+       lpStruct->iListGap = (*env)->GetIntField(env, lpObject, NMTBCUSTOMDRAWFc.iListGap);
+       return lpStruct;
+}
+
+void setNMTBCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTBCUSTOMDRAW *lpStruct)
+{
+       if (!NMTBCUSTOMDRAWFc.cached) cacheNMTBCUSTOMDRAWFields(env, lpObject);
+       setNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTBCUSTOMDRAWFc.nmcd);
+       if (lpObject1 != NULL) setNMCUSTOMDRAWFields(env, lpObject1, &lpStruct->nmcd);
+       }
+       (*env)->SetLongField(env, lpObject, NMTBCUSTOMDRAWFc.hbrMonoDither, (jlong)lpStruct->hbrMonoDither);
+       (*env)->SetLongField(env, lpObject, NMTBCUSTOMDRAWFc.hbrLines, (jlong)lpStruct->hbrLines);
+       (*env)->SetLongField(env, lpObject, NMTBCUSTOMDRAWFc.hpenLines, (jlong)lpStruct->hpenLines);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrText, (jint)lpStruct->clrText);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrMark, (jint)lpStruct->clrMark);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrTextHighlight, (jint)lpStruct->clrTextHighlight);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrBtnFace, (jint)lpStruct->clrBtnFace);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrBtnHighlight, (jint)lpStruct->clrBtnHighlight);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.clrHighlightHotTrack, (jint)lpStruct->clrHighlightHotTrack);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_left, (jint)lpStruct->rcText.left);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_top, (jint)lpStruct->rcText.top);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_right, (jint)lpStruct->rcText.right);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.rcText_bottom, (jint)lpStruct->rcText.bottom);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.nStringBkMode, (jint)lpStruct->nStringBkMode);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.nHLStringBkMode, (jint)lpStruct->nHLStringBkMode);
+       (*env)->SetIntField(env, lpObject, NMTBCUSTOMDRAWFc.iListGap, (jint)lpStruct->iListGap);
+}
+#endif
+
+#ifndef NO_NMTBHOTITEM
+typedef struct NMTBHOTITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID idOld, idNew, dwFlags;
+} NMTBHOTITEM_FID_CACHE;
+
+NMTBHOTITEM_FID_CACHE NMTBHOTITEMFc;
+
+void cacheNMTBHOTITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTBHOTITEMFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMTBHOTITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTBHOTITEMFc.idOld = (*env)->GetFieldID(env, NMTBHOTITEMFc.clazz, "idOld", "I");
+       NMTBHOTITEMFc.idNew = (*env)->GetFieldID(env, NMTBHOTITEMFc.clazz, "idNew", "I");
+       NMTBHOTITEMFc.dwFlags = (*env)->GetFieldID(env, NMTBHOTITEMFc.clazz, "dwFlags", "I");
+       NMTBHOTITEMFc.cached = 1;
+}
+
+NMTBHOTITEM *getNMTBHOTITEMFields(JNIEnv *env, jobject lpObject, NMTBHOTITEM *lpStruct)
+{
+       if (!NMTBHOTITEMFc.cached) cacheNMTBHOTITEMFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->idOld = (*env)->GetIntField(env, lpObject, NMTBHOTITEMFc.idOld);
+       lpStruct->idNew = (*env)->GetIntField(env, lpObject, NMTBHOTITEMFc.idNew);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, NMTBHOTITEMFc.dwFlags);
+       return lpStruct;
+}
+
+void setNMTBHOTITEMFields(JNIEnv *env, jobject lpObject, NMTBHOTITEM *lpStruct)
+{
+       if (!NMTBHOTITEMFc.cached) cacheNMTBHOTITEMFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMTBHOTITEMFc.idOld, (jint)lpStruct->idOld);
+       (*env)->SetIntField(env, lpObject, NMTBHOTITEMFc.idNew, (jint)lpStruct->idNew);
+       (*env)->SetIntField(env, lpObject, NMTBHOTITEMFc.dwFlags, (jint)lpStruct->dwFlags);
+}
+#endif
+
+#ifndef NO_NMTOOLBAR
+typedef struct NMTOOLBAR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iItem, iBitmap, idCommand, fsState, fsStyle, dwData, iString, cchText, pszText, left, top, right, bottom;
+} NMTOOLBAR_FID_CACHE;
+
+NMTOOLBAR_FID_CACHE NMTOOLBARFc;
+
+void cacheNMTOOLBARFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTOOLBARFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMTOOLBARFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTOOLBARFc.iItem = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "iItem", "I");
+       NMTOOLBARFc.iBitmap = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "iBitmap", "I");
+       NMTOOLBARFc.idCommand = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "idCommand", "I");
+       NMTOOLBARFc.fsState = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "fsState", "B");
+       NMTOOLBARFc.fsStyle = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "fsStyle", "B");
+       NMTOOLBARFc.dwData = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "dwData", "J");
+       NMTOOLBARFc.iString = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "iString", "J");
+       NMTOOLBARFc.cchText = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "cchText", "I");
+       NMTOOLBARFc.pszText = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "pszText", "J");
+       NMTOOLBARFc.left = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "left", "I");
+       NMTOOLBARFc.top = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "top", "I");
+       NMTOOLBARFc.right = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "right", "I");
+       NMTOOLBARFc.bottom = (*env)->GetFieldID(env, NMTOOLBARFc.clazz, "bottom", "I");
+       NMTOOLBARFc.cached = 1;
+}
+
+NMTOOLBAR *getNMTOOLBARFields(JNIEnv *env, jobject lpObject, NMTOOLBAR *lpStruct)
+{
+       if (!NMTOOLBARFc.cached) cacheNMTOOLBARFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->iItem = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.iItem);
+       lpStruct->tbButton.iBitmap = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.iBitmap);
+       lpStruct->tbButton.idCommand = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.idCommand);
+       lpStruct->tbButton.fsState = (*env)->GetByteField(env, lpObject, NMTOOLBARFc.fsState);
+       lpStruct->tbButton.fsStyle = (*env)->GetByteField(env, lpObject, NMTOOLBARFc.fsStyle);
+       lpStruct->tbButton.dwData = (*env)->GetLongField(env, lpObject, NMTOOLBARFc.dwData);
+       lpStruct->tbButton.iString = (*env)->GetLongField(env, lpObject, NMTOOLBARFc.iString);
+       lpStruct->cchText = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.cchText);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, NMTOOLBARFc.pszText);
+       lpStruct->rcButton.left = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.left);
+       lpStruct->rcButton.top = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.top);
+       lpStruct->rcButton.right = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.right);
+       lpStruct->rcButton.bottom = (*env)->GetIntField(env, lpObject, NMTOOLBARFc.bottom);
+       return lpStruct;
+}
+
+void setNMTOOLBARFields(JNIEnv *env, jobject lpObject, NMTOOLBAR *lpStruct)
+{
+       if (!NMTOOLBARFc.cached) cacheNMTOOLBARFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.iItem, (jint)lpStruct->iItem);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.iBitmap, (jint)lpStruct->tbButton.iBitmap);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.idCommand, (jint)lpStruct->tbButton.idCommand);
+       (*env)->SetByteField(env, lpObject, NMTOOLBARFc.fsState, (jbyte)lpStruct->tbButton.fsState);
+       (*env)->SetByteField(env, lpObject, NMTOOLBARFc.fsStyle, (jbyte)lpStruct->tbButton.fsStyle);
+       (*env)->SetLongField(env, lpObject, NMTOOLBARFc.dwData, (jlong)lpStruct->tbButton.dwData);
+       (*env)->SetLongField(env, lpObject, NMTOOLBARFc.iString, (jlong)lpStruct->tbButton.iString);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.cchText, (jint)lpStruct->cchText);
+       (*env)->SetLongField(env, lpObject, NMTOOLBARFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.left, (jint)lpStruct->rcButton.left);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.top, (jint)lpStruct->rcButton.top);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.right, (jint)lpStruct->rcButton.right);
+       (*env)->SetIntField(env, lpObject, NMTOOLBARFc.bottom, (jint)lpStruct->rcButton.bottom);
+}
+#endif
+
+#ifndef NO_NMTREEVIEW
+typedef struct NMTREEVIEW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hdr, action, itemOld, itemNew, ptDrag;
+} NMTREEVIEW_FID_CACHE;
+
+NMTREEVIEW_FID_CACHE NMTREEVIEWFc;
+
+void cacheNMTREEVIEWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTREEVIEWFc.cached) return;
+       NMTREEVIEWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTREEVIEWFc.hdr = (*env)->GetFieldID(env, NMTREEVIEWFc.clazz, "hdr", "Lorg/eclipse/swt/internal/win32/NMHDR;");
+       NMTREEVIEWFc.action = (*env)->GetFieldID(env, NMTREEVIEWFc.clazz, "action", "I");
+       NMTREEVIEWFc.itemOld = (*env)->GetFieldID(env, NMTREEVIEWFc.clazz, "itemOld", "Lorg/eclipse/swt/internal/win32/TVITEM;");
+       NMTREEVIEWFc.itemNew = (*env)->GetFieldID(env, NMTREEVIEWFc.clazz, "itemNew", "Lorg/eclipse/swt/internal/win32/TVITEM;");
+       NMTREEVIEWFc.ptDrag = (*env)->GetFieldID(env, NMTREEVIEWFc.clazz, "ptDrag", "Lorg/eclipse/swt/internal/win32/POINT;");
+       NMTREEVIEWFc.cached = 1;
+}
+
+NMTREEVIEW *getNMTREEVIEWFields(JNIEnv *env, jobject lpObject, NMTREEVIEW *lpStruct)
+{
+       if (!NMTREEVIEWFc.cached) cacheNMTREEVIEWFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.hdr);
+       if (lpObject1 != NULL) getNMHDRFields(env, lpObject1, &lpStruct->hdr);
+       }
+       lpStruct->action = (*env)->GetIntField(env, lpObject, NMTREEVIEWFc.action);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.itemOld);
+       if (lpObject1 != NULL) getTVITEMFields(env, lpObject1, &lpStruct->itemOld);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.itemNew);
+       if (lpObject1 != NULL) getTVITEMFields(env, lpObject1, &lpStruct->itemNew);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.ptDrag);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->ptDrag);
+       }
+       return lpStruct;
+}
+
+void setNMTREEVIEWFields(JNIEnv *env, jobject lpObject, NMTREEVIEW *lpStruct)
+{
+       if (!NMTREEVIEWFc.cached) cacheNMTREEVIEWFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.hdr);
+       if (lpObject1 != NULL) setNMHDRFields(env, lpObject1, &lpStruct->hdr);
+       }
+       (*env)->SetIntField(env, lpObject, NMTREEVIEWFc.action, (jint)lpStruct->action);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.itemOld);
+       if (lpObject1 != NULL) setTVITEMFields(env, lpObject1, &lpStruct->itemOld);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.itemNew);
+       if (lpObject1 != NULL) setTVITEMFields(env, lpObject1, &lpStruct->itemNew);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NMTREEVIEWFc.ptDrag);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->ptDrag);
+       }
+}
+#endif
+
+#ifndef NO_NMTTCUSTOMDRAW
+typedef struct NMTTCUSTOMDRAW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID uDrawFlags;
+} NMTTCUSTOMDRAW_FID_CACHE;
+
+NMTTCUSTOMDRAW_FID_CACHE NMTTCUSTOMDRAWFc;
+
+void cacheNMTTCUSTOMDRAWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTTCUSTOMDRAWFc.cached) return;
+       cacheNMCUSTOMDRAWFields(env, lpObject);
+       NMTTCUSTOMDRAWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTTCUSTOMDRAWFc.uDrawFlags = (*env)->GetFieldID(env, NMTTCUSTOMDRAWFc.clazz, "uDrawFlags", "I");
+       NMTTCUSTOMDRAWFc.cached = 1;
+}
+
+NMTTCUSTOMDRAW *getNMTTCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTTCUSTOMDRAW *lpStruct)
+{
+       if (!NMTTCUSTOMDRAWFc.cached) cacheNMTTCUSTOMDRAWFields(env, lpObject);
+       getNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       lpStruct->uDrawFlags = (*env)->GetIntField(env, lpObject, NMTTCUSTOMDRAWFc.uDrawFlags);
+       return lpStruct;
+}
+
+void setNMTTCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTTCUSTOMDRAW *lpStruct)
+{
+       if (!NMTTCUSTOMDRAWFc.cached) cacheNMTTCUSTOMDRAWFields(env, lpObject);
+       setNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMTTCUSTOMDRAWFc.uDrawFlags, (jint)lpStruct->uDrawFlags);
+}
+#endif
+
+#ifndef NO_NMTTDISPINFO
+typedef struct NMTTDISPINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lpszText, szText, hinst, uFlags, lParam;
+} NMTTDISPINFO_FID_CACHE;
+
+NMTTDISPINFO_FID_CACHE NMTTDISPINFOFc;
+
+void cacheNMTTDISPINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTTDISPINFOFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMTTDISPINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTTDISPINFOFc.lpszText = (*env)->GetFieldID(env, NMTTDISPINFOFc.clazz, "lpszText", "J");
+       NMTTDISPINFOFc.szText = (*env)->GetFieldID(env, NMTTDISPINFOFc.clazz, "szText", "[C");
+       NMTTDISPINFOFc.hinst = (*env)->GetFieldID(env, NMTTDISPINFOFc.clazz, "hinst", "J");
+       NMTTDISPINFOFc.uFlags = (*env)->GetFieldID(env, NMTTDISPINFOFc.clazz, "uFlags", "I");
+       NMTTDISPINFOFc.lParam = (*env)->GetFieldID(env, NMTTDISPINFOFc.clazz, "lParam", "J");
+       NMTTDISPINFOFc.cached = 1;
+}
+
+NMTTDISPINFO *getNMTTDISPINFOFields(JNIEnv *env, jobject lpObject, NMTTDISPINFO *lpStruct)
+{
+       if (!NMTTDISPINFOFc.cached) cacheNMTTDISPINFOFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->lpszText = (void *)(*env)->GetLongField(env, lpObject, NMTTDISPINFOFc.lpszText);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NMTTDISPINFOFc.szText);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szText) / sizeof(jchar), (jchar *)lpStruct->szText);
+       }
+       lpStruct->hinst = (HINSTANCE)(*env)->GetLongField(env, lpObject, NMTTDISPINFOFc.hinst);
+       lpStruct->uFlags = (*env)->GetIntField(env, lpObject, NMTTDISPINFOFc.uFlags);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, NMTTDISPINFOFc.lParam);
+       return lpStruct;
+}
+
+void setNMTTDISPINFOFields(JNIEnv *env, jobject lpObject, NMTTDISPINFO *lpStruct)
+{
+       if (!NMTTDISPINFOFc.cached) cacheNMTTDISPINFOFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetLongField(env, lpObject, NMTTDISPINFOFc.lpszText, (jlong)lpStruct->lpszText);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NMTTDISPINFOFc.szText);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szText) / sizeof(jchar), (jchar *)lpStruct->szText);
+       }
+       (*env)->SetLongField(env, lpObject, NMTTDISPINFOFc.hinst, (jlong)lpStruct->hinst);
+       (*env)->SetIntField(env, lpObject, NMTTDISPINFOFc.uFlags, (jint)lpStruct->uFlags);
+       (*env)->SetLongField(env, lpObject, NMTTDISPINFOFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_NMTVCUSTOMDRAW
+typedef struct NMTVCUSTOMDRAW_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID clrText, clrTextBk, iLevel;
+} NMTVCUSTOMDRAW_FID_CACHE;
+
+NMTVCUSTOMDRAW_FID_CACHE NMTVCUSTOMDRAWFc;
+
+void cacheNMTVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTVCUSTOMDRAWFc.cached) return;
+       cacheNMCUSTOMDRAWFields(env, lpObject);
+       NMTVCUSTOMDRAWFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTVCUSTOMDRAWFc.clrText = (*env)->GetFieldID(env, NMTVCUSTOMDRAWFc.clazz, "clrText", "I");
+       NMTVCUSTOMDRAWFc.clrTextBk = (*env)->GetFieldID(env, NMTVCUSTOMDRAWFc.clazz, "clrTextBk", "I");
+       NMTVCUSTOMDRAWFc.iLevel = (*env)->GetFieldID(env, NMTVCUSTOMDRAWFc.clazz, "iLevel", "I");
+       NMTVCUSTOMDRAWFc.cached = 1;
+}
+
+NMTVCUSTOMDRAW *getNMTVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTVCUSTOMDRAW *lpStruct)
+{
+       if (!NMTVCUSTOMDRAWFc.cached) cacheNMTVCUSTOMDRAWFields(env, lpObject);
+       getNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       lpStruct->clrText = (*env)->GetIntField(env, lpObject, NMTVCUSTOMDRAWFc.clrText);
+       lpStruct->clrTextBk = (*env)->GetIntField(env, lpObject, NMTVCUSTOMDRAWFc.clrTextBk);
+       lpStruct->iLevel = (*env)->GetIntField(env, lpObject, NMTVCUSTOMDRAWFc.iLevel);
+       return lpStruct;
+}
+
+void setNMTVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTVCUSTOMDRAW *lpStruct)
+{
+       if (!NMTVCUSTOMDRAWFc.cached) cacheNMTVCUSTOMDRAWFields(env, lpObject);
+       setNMCUSTOMDRAWFields(env, lpObject, (NMCUSTOMDRAW *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMTVCUSTOMDRAWFc.clrText, (jint)lpStruct->clrText);
+       (*env)->SetIntField(env, lpObject, NMTVCUSTOMDRAWFc.clrTextBk, (jint)lpStruct->clrTextBk);
+       (*env)->SetIntField(env, lpObject, NMTVCUSTOMDRAWFc.iLevel, (jint)lpStruct->iLevel);
+}
+#endif
+
+#ifndef NO_NMTVDISPINFO
+typedef struct NMTVDISPINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, hItem, state, stateMask, pszText, cchTextMax, iImage, iSelectedImage, cChildren, lParam;
+} NMTVDISPINFO_FID_CACHE;
+
+NMTVDISPINFO_FID_CACHE NMTVDISPINFOFc;
+
+void cacheNMTVDISPINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTVDISPINFOFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMTVDISPINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTVDISPINFOFc.mask = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "mask", "I");
+       NMTVDISPINFOFc.hItem = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "hItem", "J");
+       NMTVDISPINFOFc.state = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "state", "I");
+       NMTVDISPINFOFc.stateMask = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "stateMask", "I");
+       NMTVDISPINFOFc.pszText = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "pszText", "J");
+       NMTVDISPINFOFc.cchTextMax = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "cchTextMax", "I");
+       NMTVDISPINFOFc.iImage = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "iImage", "I");
+       NMTVDISPINFOFc.iSelectedImage = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "iSelectedImage", "I");
+       NMTVDISPINFOFc.cChildren = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "cChildren", "I");
+       NMTVDISPINFOFc.lParam = (*env)->GetFieldID(env, NMTVDISPINFOFc.clazz, "lParam", "J");
+       NMTVDISPINFOFc.cached = 1;
+}
+
+NMTVDISPINFO *getNMTVDISPINFOFields(JNIEnv *env, jobject lpObject, NMTVDISPINFO *lpStruct)
+{
+       if (!NMTVDISPINFOFc.cached) cacheNMTVDISPINFOFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->item.mask = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.mask);
+       lpStruct->item.hItem = (HTREEITEM)(*env)->GetLongField(env, lpObject, NMTVDISPINFOFc.hItem);
+       lpStruct->item.state = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.state);
+       lpStruct->item.stateMask = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.stateMask);
+       lpStruct->item.pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, NMTVDISPINFOFc.pszText);
+       lpStruct->item.cchTextMax = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.cchTextMax);
+       lpStruct->item.iImage = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.iImage);
+       lpStruct->item.iSelectedImage = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.iSelectedImage);
+       lpStruct->item.cChildren = (*env)->GetIntField(env, lpObject, NMTVDISPINFOFc.cChildren);
+       lpStruct->item.lParam = (*env)->GetLongField(env, lpObject, NMTVDISPINFOFc.lParam);
+       return lpStruct;
+}
+
+void setNMTVDISPINFOFields(JNIEnv *env, jobject lpObject, NMTVDISPINFO *lpStruct)
+{
+       if (!NMTVDISPINFOFc.cached) cacheNMTVDISPINFOFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.mask, (jint)lpStruct->item.mask);
+       (*env)->SetLongField(env, lpObject, NMTVDISPINFOFc.hItem, (jlong)lpStruct->item.hItem);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.state, (jint)lpStruct->item.state);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.stateMask, (jint)lpStruct->item.stateMask);
+       (*env)->SetLongField(env, lpObject, NMTVDISPINFOFc.pszText, (jlong)lpStruct->item.pszText);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.cchTextMax, (jint)lpStruct->item.cchTextMax);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.iImage, (jint)lpStruct->item.iImage);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.iSelectedImage, (jint)lpStruct->item.iSelectedImage);
+       (*env)->SetIntField(env, lpObject, NMTVDISPINFOFc.cChildren, (jint)lpStruct->item.cChildren);
+       (*env)->SetLongField(env, lpObject, NMTVDISPINFOFc.lParam, (jlong)lpStruct->item.lParam);
+}
+#endif
+
+#ifndef NO_NMTVITEMCHANGE
+typedef struct NMTVITEMCHANGE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID uChanged, hItem, uStateNew, uStateOld, lParam;
+} NMTVITEMCHANGE_FID_CACHE;
+
+NMTVITEMCHANGE_FID_CACHE NMTVITEMCHANGEFc;
+
+void cacheNMTVITEMCHANGEFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMTVITEMCHANGEFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMTVITEMCHANGEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMTVITEMCHANGEFc.uChanged = (*env)->GetFieldID(env, NMTVITEMCHANGEFc.clazz, "uChanged", "I");
+       NMTVITEMCHANGEFc.hItem = (*env)->GetFieldID(env, NMTVITEMCHANGEFc.clazz, "hItem", "J");
+       NMTVITEMCHANGEFc.uStateNew = (*env)->GetFieldID(env, NMTVITEMCHANGEFc.clazz, "uStateNew", "I");
+       NMTVITEMCHANGEFc.uStateOld = (*env)->GetFieldID(env, NMTVITEMCHANGEFc.clazz, "uStateOld", "I");
+       NMTVITEMCHANGEFc.lParam = (*env)->GetFieldID(env, NMTVITEMCHANGEFc.clazz, "lParam", "J");
+       NMTVITEMCHANGEFc.cached = 1;
+}
+
+NMTVITEMCHANGE *getNMTVITEMCHANGEFields(JNIEnv *env, jobject lpObject, NMTVITEMCHANGE *lpStruct)
+{
+       if (!NMTVITEMCHANGEFc.cached) cacheNMTVITEMCHANGEFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->uChanged = (*env)->GetIntField(env, lpObject, NMTVITEMCHANGEFc.uChanged);
+       lpStruct->hItem = (HTREEITEM)(*env)->GetLongField(env, lpObject, NMTVITEMCHANGEFc.hItem);
+       lpStruct->uStateNew = (*env)->GetIntField(env, lpObject, NMTVITEMCHANGEFc.uStateNew);
+       lpStruct->uStateOld = (*env)->GetIntField(env, lpObject, NMTVITEMCHANGEFc.uStateOld);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, NMTVITEMCHANGEFc.lParam);
+       return lpStruct;
+}
+
+void setNMTVITEMCHANGEFields(JNIEnv *env, jobject lpObject, NMTVITEMCHANGE *lpStruct)
+{
+       if (!NMTVITEMCHANGEFc.cached) cacheNMTVITEMCHANGEFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMTVITEMCHANGEFc.uChanged, (jint)lpStruct->uChanged);
+       (*env)->SetLongField(env, lpObject, NMTVITEMCHANGEFc.hItem, (jlong)lpStruct->hItem);
+       (*env)->SetIntField(env, lpObject, NMTVITEMCHANGEFc.uStateNew, (jint)lpStruct->uStateNew);
+       (*env)->SetIntField(env, lpObject, NMTVITEMCHANGEFc.uStateOld, (jint)lpStruct->uStateOld);
+       (*env)->SetLongField(env, lpObject, NMTVITEMCHANGEFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_NMUPDOWN
+typedef struct NMUPDOWN_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iPos, iDelta;
+} NMUPDOWN_FID_CACHE;
+
+NMUPDOWN_FID_CACHE NMUPDOWNFc;
+
+void cacheNMUPDOWNFields(JNIEnv *env, jobject lpObject)
+{
+       if (NMUPDOWNFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       NMUPDOWNFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NMUPDOWNFc.iPos = (*env)->GetFieldID(env, NMUPDOWNFc.clazz, "iPos", "I");
+       NMUPDOWNFc.iDelta = (*env)->GetFieldID(env, NMUPDOWNFc.clazz, "iDelta", "I");
+       NMUPDOWNFc.cached = 1;
+}
+
+NMUPDOWN *getNMUPDOWNFields(JNIEnv *env, jobject lpObject, NMUPDOWN *lpStruct)
+{
+       if (!NMUPDOWNFc.cached) cacheNMUPDOWNFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->iPos = (*env)->GetIntField(env, lpObject, NMUPDOWNFc.iPos);
+       lpStruct->iDelta = (*env)->GetIntField(env, lpObject, NMUPDOWNFc.iDelta);
+       return lpStruct;
+}
+
+void setNMUPDOWNFields(JNIEnv *env, jobject lpObject, NMUPDOWN *lpStruct)
+{
+       if (!NMUPDOWNFc.cached) cacheNMUPDOWNFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetIntField(env, lpObject, NMUPDOWNFc.iPos, (jint)lpStruct->iPos);
+       (*env)->SetIntField(env, lpObject, NMUPDOWNFc.iDelta, (jint)lpStruct->iDelta);
+}
+#endif
+
+#ifndef NO_NONCLIENTMETRICS
+typedef struct NONCLIENTMETRICS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, iBorderWidth, iScrollWidth, iScrollHeight, iCaptionWidth, iCaptionHeight, lfCaptionFont, iSmCaptionWidth, iSmCaptionHeight, lfSmCaptionFont, iMenuWidth, iMenuHeight, lfMenuFont, lfStatusFont, lfMessageFont;
+} NONCLIENTMETRICS_FID_CACHE;
+
+NONCLIENTMETRICS_FID_CACHE NONCLIENTMETRICSFc;
+
+void cacheNONCLIENTMETRICSFields(JNIEnv *env, jobject lpObject)
+{
+       if (NONCLIENTMETRICSFc.cached) return;
+       NONCLIENTMETRICSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NONCLIENTMETRICSFc.cbSize = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "cbSize", "I");
+       NONCLIENTMETRICSFc.iBorderWidth = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iBorderWidth", "I");
+       NONCLIENTMETRICSFc.iScrollWidth = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iScrollWidth", "I");
+       NONCLIENTMETRICSFc.iScrollHeight = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iScrollHeight", "I");
+       NONCLIENTMETRICSFc.iCaptionWidth = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iCaptionWidth", "I");
+       NONCLIENTMETRICSFc.iCaptionHeight = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iCaptionHeight", "I");
+       NONCLIENTMETRICSFc.lfCaptionFont = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "lfCaptionFont", "Lorg/eclipse/swt/internal/win32/LOGFONT;");
+       NONCLIENTMETRICSFc.iSmCaptionWidth = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iSmCaptionWidth", "I");
+       NONCLIENTMETRICSFc.iSmCaptionHeight = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iSmCaptionHeight", "I");
+       NONCLIENTMETRICSFc.lfSmCaptionFont = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "lfSmCaptionFont", "Lorg/eclipse/swt/internal/win32/LOGFONT;");
+       NONCLIENTMETRICSFc.iMenuWidth = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iMenuWidth", "I");
+       NONCLIENTMETRICSFc.iMenuHeight = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "iMenuHeight", "I");
+       NONCLIENTMETRICSFc.lfMenuFont = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "lfMenuFont", "Lorg/eclipse/swt/internal/win32/LOGFONT;");
+       NONCLIENTMETRICSFc.lfStatusFont = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "lfStatusFont", "Lorg/eclipse/swt/internal/win32/LOGFONT;");
+       NONCLIENTMETRICSFc.lfMessageFont = (*env)->GetFieldID(env, NONCLIENTMETRICSFc.clazz, "lfMessageFont", "Lorg/eclipse/swt/internal/win32/LOGFONT;");
+       NONCLIENTMETRICSFc.cached = 1;
+}
+
+NONCLIENTMETRICS *getNONCLIENTMETRICSFields(JNIEnv *env, jobject lpObject, NONCLIENTMETRICS *lpStruct)
+{
+       if (!NONCLIENTMETRICSFc.cached) cacheNONCLIENTMETRICSFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.cbSize);
+       lpStruct->iBorderWidth = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iBorderWidth);
+       lpStruct->iScrollWidth = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iScrollWidth);
+       lpStruct->iScrollHeight = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iScrollHeight);
+       lpStruct->iCaptionWidth = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iCaptionWidth);
+       lpStruct->iCaptionHeight = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iCaptionHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfCaptionFont);
+       if (lpObject1 != NULL) getLOGFONTFields(env, lpObject1, &lpStruct->lfCaptionFont);
+       }
+       lpStruct->iSmCaptionWidth = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iSmCaptionWidth);
+       lpStruct->iSmCaptionHeight = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iSmCaptionHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfSmCaptionFont);
+       if (lpObject1 != NULL) getLOGFONTFields(env, lpObject1, &lpStruct->lfSmCaptionFont);
+       }
+       lpStruct->iMenuWidth = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iMenuWidth);
+       lpStruct->iMenuHeight = (*env)->GetIntField(env, lpObject, NONCLIENTMETRICSFc.iMenuHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfMenuFont);
+       if (lpObject1 != NULL) getLOGFONTFields(env, lpObject1, &lpStruct->lfMenuFont);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfStatusFont);
+       if (lpObject1 != NULL) getLOGFONTFields(env, lpObject1, &lpStruct->lfStatusFont);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfMessageFont);
+       if (lpObject1 != NULL) getLOGFONTFields(env, lpObject1, &lpStruct->lfMessageFont);
+       }
+       return lpStruct;
+}
+
+void setNONCLIENTMETRICSFields(JNIEnv *env, jobject lpObject, NONCLIENTMETRICS *lpStruct)
+{
+       if (!NONCLIENTMETRICSFc.cached) cacheNONCLIENTMETRICSFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iBorderWidth, (jint)lpStruct->iBorderWidth);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iScrollWidth, (jint)lpStruct->iScrollWidth);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iScrollHeight, (jint)lpStruct->iScrollHeight);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iCaptionWidth, (jint)lpStruct->iCaptionWidth);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iCaptionHeight, (jint)lpStruct->iCaptionHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfCaptionFont);
+       if (lpObject1 != NULL) setLOGFONTFields(env, lpObject1, &lpStruct->lfCaptionFont);
+       }
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iSmCaptionWidth, (jint)lpStruct->iSmCaptionWidth);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iSmCaptionHeight, (jint)lpStruct->iSmCaptionHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfSmCaptionFont);
+       if (lpObject1 != NULL) setLOGFONTFields(env, lpObject1, &lpStruct->lfSmCaptionFont);
+       }
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iMenuWidth, (jint)lpStruct->iMenuWidth);
+       (*env)->SetIntField(env, lpObject, NONCLIENTMETRICSFc.iMenuHeight, (jint)lpStruct->iMenuHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfMenuFont);
+       if (lpObject1 != NULL) setLOGFONTFields(env, lpObject1, &lpStruct->lfMenuFont);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfStatusFont);
+       if (lpObject1 != NULL) setLOGFONTFields(env, lpObject1, &lpStruct->lfStatusFont);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, NONCLIENTMETRICSFc.lfMessageFont);
+       if (lpObject1 != NULL) setLOGFONTFields(env, lpObject1, &lpStruct->lfMessageFont);
+       }
+}
+#endif
+
+#ifndef NO_NOTIFYICONDATA
+typedef struct NOTIFYICONDATA_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, hWnd, uID, uFlags, uCallbackMessage, hIcon, szTip, dwState, dwStateMask, szInfo, szInfoTitle, uVersion, dwInfoFlags;
+} NOTIFYICONDATA_FID_CACHE;
+
+NOTIFYICONDATA_FID_CACHE NOTIFYICONDATAFc;
+
+void cacheNOTIFYICONDATAFields(JNIEnv *env, jobject lpObject)
+{
+       if (NOTIFYICONDATAFc.cached) return;
+       NOTIFYICONDATAFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       NOTIFYICONDATAFc.cbSize = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "cbSize", "I");
+       NOTIFYICONDATAFc.hWnd = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "hWnd", "J");
+       NOTIFYICONDATAFc.uID = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "uID", "I");
+       NOTIFYICONDATAFc.uFlags = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "uFlags", "I");
+       NOTIFYICONDATAFc.uCallbackMessage = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "uCallbackMessage", "I");
+       NOTIFYICONDATAFc.hIcon = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "hIcon", "J");
+       NOTIFYICONDATAFc.szTip = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "szTip", "[C");
+       NOTIFYICONDATAFc.dwState = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "dwState", "I");
+       NOTIFYICONDATAFc.dwStateMask = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "dwStateMask", "I");
+       NOTIFYICONDATAFc.szInfo = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "szInfo", "[C");
+       NOTIFYICONDATAFc.szInfoTitle = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "szInfoTitle", "[C");
+       NOTIFYICONDATAFc.uVersion = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "uVersion", "I");
+       NOTIFYICONDATAFc.dwInfoFlags = (*env)->GetFieldID(env, NOTIFYICONDATAFc.clazz, "dwInfoFlags", "I");
+       NOTIFYICONDATAFc.cached = 1;
+}
+
+NOTIFYICONDATA *getNOTIFYICONDATAFields(JNIEnv *env, jobject lpObject, NOTIFYICONDATA *lpStruct)
+{
+       if (!NOTIFYICONDATAFc.cached) cacheNOTIFYICONDATAFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.cbSize);
+       lpStruct->hWnd = (HWND)(*env)->GetLongField(env, lpObject, NOTIFYICONDATAFc.hWnd);
+       lpStruct->uID = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.uID);
+       lpStruct->uFlags = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.uFlags);
+       lpStruct->uCallbackMessage = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.uCallbackMessage);
+       lpStruct->hIcon = (HICON)(*env)->GetLongField(env, lpObject, NOTIFYICONDATAFc.hIcon);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NOTIFYICONDATAFc.szTip);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szTip) / sizeof(jchar), (jchar *)lpStruct->szTip);
+       }
+       lpStruct->dwState = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.dwState);
+       lpStruct->dwStateMask = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.dwStateMask);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NOTIFYICONDATAFc.szInfo);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szInfo) / sizeof(jchar), (jchar *)lpStruct->szInfo);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NOTIFYICONDATAFc.szInfoTitle);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szInfoTitle) / sizeof(jchar), (jchar *)lpStruct->szInfoTitle);
+       }
+       lpStruct->uVersion = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.uVersion);
+       lpStruct->dwInfoFlags = (*env)->GetIntField(env, lpObject, NOTIFYICONDATAFc.dwInfoFlags);
+       return lpStruct;
+}
+
+void setNOTIFYICONDATAFields(JNIEnv *env, jobject lpObject, NOTIFYICONDATA *lpStruct)
+{
+       if (!NOTIFYICONDATAFc.cached) cacheNOTIFYICONDATAFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetLongField(env, lpObject, NOTIFYICONDATAFc.hWnd, (jlong)lpStruct->hWnd);
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.uID, (jint)lpStruct->uID);
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.uFlags, (jint)lpStruct->uFlags);
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.uCallbackMessage, (jint)lpStruct->uCallbackMessage);
+       (*env)->SetLongField(env, lpObject, NOTIFYICONDATAFc.hIcon, (jlong)lpStruct->hIcon);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NOTIFYICONDATAFc.szTip);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szTip) / sizeof(jchar), (jchar *)lpStruct->szTip);
+       }
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.dwState, (jint)lpStruct->dwState);
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.dwStateMask, (jint)lpStruct->dwStateMask);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NOTIFYICONDATAFc.szInfo);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szInfo) / sizeof(jchar), (jchar *)lpStruct->szInfo);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, NOTIFYICONDATAFc.szInfoTitle);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szInfoTitle) / sizeof(jchar), (jchar *)lpStruct->szInfoTitle);
+       }
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.uVersion, (jint)lpStruct->uVersion);
+       (*env)->SetIntField(env, lpObject, NOTIFYICONDATAFc.dwInfoFlags, (jint)lpStruct->dwInfoFlags);
+}
+#endif
+
+#ifndef NO_OFNOTIFY
+typedef struct OFNOTIFY_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lpOFN, pszFile;
+} OFNOTIFY_FID_CACHE;
+
+OFNOTIFY_FID_CACHE OFNOTIFYFc;
+
+void cacheOFNOTIFYFields(JNIEnv *env, jobject lpObject)
+{
+       if (OFNOTIFYFc.cached) return;
+       cacheNMHDRFields(env, lpObject);
+       OFNOTIFYFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       OFNOTIFYFc.lpOFN = (*env)->GetFieldID(env, OFNOTIFYFc.clazz, "lpOFN", "J");
+       OFNOTIFYFc.pszFile = (*env)->GetFieldID(env, OFNOTIFYFc.clazz, "pszFile", "J");
+       OFNOTIFYFc.cached = 1;
+}
+
+OFNOTIFY *getOFNOTIFYFields(JNIEnv *env, jobject lpObject, OFNOTIFY *lpStruct)
+{
+       if (!OFNOTIFYFc.cached) cacheOFNOTIFYFields(env, lpObject);
+       getNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       lpStruct->lpOFN = (LPOPENFILENAME)(*env)->GetLongField(env, lpObject, OFNOTIFYFc.lpOFN);
+       lpStruct->pszFile = (LPTSTR)(*env)->GetLongField(env, lpObject, OFNOTIFYFc.pszFile);
+       return lpStruct;
+}
+
+void setOFNOTIFYFields(JNIEnv *env, jobject lpObject, OFNOTIFY *lpStruct)
+{
+       if (!OFNOTIFYFc.cached) cacheOFNOTIFYFields(env, lpObject);
+       setNMHDRFields(env, lpObject, (NMHDR *)lpStruct);
+       (*env)->SetLongField(env, lpObject, OFNOTIFYFc.lpOFN, (jlong)lpStruct->lpOFN);
+       (*env)->SetLongField(env, lpObject, OFNOTIFYFc.pszFile, (jlong)lpStruct->pszFile);
+}
+#endif
+
+#ifndef NO_OPENFILENAME
+typedef struct OPENFILENAME_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lStructSize, hwndOwner, hInstance, lpstrFilter, lpstrCustomFilter, nMaxCustFilter, nFilterIndex, lpstrFile, nMaxFile, lpstrFileTitle, nMaxFileTitle, lpstrInitialDir, lpstrTitle, Flags, nFileOffset, nFileExtension, lpstrDefExt, lCustData, lpfnHook, lpTemplateName, pvReserved, dwReserved, FlagsEx;
+} OPENFILENAME_FID_CACHE;
+
+OPENFILENAME_FID_CACHE OPENFILENAMEFc;
+
+void cacheOPENFILENAMEFields(JNIEnv *env, jobject lpObject)
+{
+       if (OPENFILENAMEFc.cached) return;
+       OPENFILENAMEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       OPENFILENAMEFc.lStructSize = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lStructSize", "I");
+       OPENFILENAMEFc.hwndOwner = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "hwndOwner", "J");
+       OPENFILENAMEFc.hInstance = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "hInstance", "J");
+       OPENFILENAMEFc.lpstrFilter = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrFilter", "J");
+       OPENFILENAMEFc.lpstrCustomFilter = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrCustomFilter", "J");
+       OPENFILENAMEFc.nMaxCustFilter = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "nMaxCustFilter", "I");
+       OPENFILENAMEFc.nFilterIndex = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "nFilterIndex", "I");
+       OPENFILENAMEFc.lpstrFile = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrFile", "J");
+       OPENFILENAMEFc.nMaxFile = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "nMaxFile", "I");
+       OPENFILENAMEFc.lpstrFileTitle = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrFileTitle", "J");
+       OPENFILENAMEFc.nMaxFileTitle = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "nMaxFileTitle", "I");
+       OPENFILENAMEFc.lpstrInitialDir = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrInitialDir", "J");
+       OPENFILENAMEFc.lpstrTitle = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrTitle", "J");
+       OPENFILENAMEFc.Flags = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "Flags", "I");
+       OPENFILENAMEFc.nFileOffset = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "nFileOffset", "S");
+       OPENFILENAMEFc.nFileExtension = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "nFileExtension", "S");
+       OPENFILENAMEFc.lpstrDefExt = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpstrDefExt", "J");
+       OPENFILENAMEFc.lCustData = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lCustData", "J");
+       OPENFILENAMEFc.lpfnHook = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpfnHook", "J");
+       OPENFILENAMEFc.lpTemplateName = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "lpTemplateName", "J");
+       OPENFILENAMEFc.pvReserved = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "pvReserved", "J");
+       OPENFILENAMEFc.dwReserved = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "dwReserved", "I");
+       OPENFILENAMEFc.FlagsEx = (*env)->GetFieldID(env, OPENFILENAMEFc.clazz, "FlagsEx", "I");
+       OPENFILENAMEFc.cached = 1;
+}
+
+OPENFILENAME *getOPENFILENAMEFields(JNIEnv *env, jobject lpObject, OPENFILENAME *lpStruct)
+{
+       if (!OPENFILENAMEFc.cached) cacheOPENFILENAMEFields(env, lpObject);
+       lpStruct->lStructSize = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.lStructSize);
+       lpStruct->hwndOwner = (HWND)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.hwndOwner);
+       lpStruct->hInstance = (HINSTANCE)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.hInstance);
+       lpStruct->lpstrFilter = (LPCTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrFilter);
+       lpStruct->lpstrCustomFilter = (LPTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrCustomFilter);
+       lpStruct->nMaxCustFilter = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.nMaxCustFilter);
+       lpStruct->nFilterIndex = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.nFilterIndex);
+       lpStruct->lpstrFile = (LPTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrFile);
+       lpStruct->nMaxFile = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.nMaxFile);
+       lpStruct->lpstrFileTitle = (LPTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrFileTitle);
+       lpStruct->nMaxFileTitle = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.nMaxFileTitle);
+       lpStruct->lpstrInitialDir = (LPCTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrInitialDir);
+       lpStruct->lpstrTitle = (LPCTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrTitle);
+       lpStruct->Flags = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.Flags);
+       lpStruct->nFileOffset = (*env)->GetShortField(env, lpObject, OPENFILENAMEFc.nFileOffset);
+       lpStruct->nFileExtension = (*env)->GetShortField(env, lpObject, OPENFILENAMEFc.nFileExtension);
+       lpStruct->lpstrDefExt = (LPCTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpstrDefExt);
+       lpStruct->lCustData = (*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lCustData);
+       lpStruct->lpfnHook = (LPOFNHOOKPROC)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpfnHook);
+       lpStruct->lpTemplateName = (LPCTSTR)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.lpTemplateName);
+       lpStruct->pvReserved = (void *)(*env)->GetLongField(env, lpObject, OPENFILENAMEFc.pvReserved);
+       lpStruct->dwReserved = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.dwReserved);
+       lpStruct->FlagsEx = (*env)->GetIntField(env, lpObject, OPENFILENAMEFc.FlagsEx);
+       return lpStruct;
+}
+
+void setOPENFILENAMEFields(JNIEnv *env, jobject lpObject, OPENFILENAME *lpStruct)
+{
+       if (!OPENFILENAMEFc.cached) cacheOPENFILENAMEFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.lStructSize, (jint)lpStruct->lStructSize);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.hwndOwner, (jlong)lpStruct->hwndOwner);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.hInstance, (jlong)lpStruct->hInstance);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrFilter, (jlong)lpStruct->lpstrFilter);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrCustomFilter, (jlong)lpStruct->lpstrCustomFilter);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.nMaxCustFilter, (jint)lpStruct->nMaxCustFilter);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.nFilterIndex, (jint)lpStruct->nFilterIndex);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrFile, (jlong)lpStruct->lpstrFile);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.nMaxFile, (jint)lpStruct->nMaxFile);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrFileTitle, (jlong)lpStruct->lpstrFileTitle);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.nMaxFileTitle, (jint)lpStruct->nMaxFileTitle);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrInitialDir, (jlong)lpStruct->lpstrInitialDir);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrTitle, (jlong)lpStruct->lpstrTitle);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.Flags, (jint)lpStruct->Flags);
+       (*env)->SetShortField(env, lpObject, OPENFILENAMEFc.nFileOffset, (jshort)lpStruct->nFileOffset);
+       (*env)->SetShortField(env, lpObject, OPENFILENAMEFc.nFileExtension, (jshort)lpStruct->nFileExtension);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpstrDefExt, (jlong)lpStruct->lpstrDefExt);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lCustData, (jlong)lpStruct->lCustData);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpfnHook, (jlong)lpStruct->lpfnHook);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.lpTemplateName, (jlong)lpStruct->lpTemplateName);
+       (*env)->SetLongField(env, lpObject, OPENFILENAMEFc.pvReserved, (jlong)lpStruct->pvReserved);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.dwReserved, (jint)lpStruct->dwReserved);
+       (*env)->SetIntField(env, lpObject, OPENFILENAMEFc.FlagsEx, (jint)lpStruct->FlagsEx);
+}
+#endif
+
+#ifndef NO_OUTLINETEXTMETRIC
+typedef struct OUTLINETEXTMETRIC_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID otmSize, otmTextMetrics, otmFiller, otmPanoseNumber_bFamilyType, otmPanoseNumber_bSerifStyle, otmPanoseNumber_bWeight, otmPanoseNumber_bProportion, otmPanoseNumber_bContrast, otmPanoseNumber_bStrokeVariation, otmPanoseNumber_bArmStyle, otmPanoseNumber_bLetterform, otmPanoseNumber_bMidline, otmPanoseNumber_bXHeight, otmfsSelection, otmfsType, otmsCharSlopeRise, otmsCharSlopeRun, otmItalicAngle, otmEMSquare, otmAscent, otmDescent, otmLineGap, otmsCapEmHeight, otmsXHeight, otmrcFontBox, otmMacAscent, otmMacDescent, otmMacLineGap, otmusMinimumPPEM, otmptSubscriptSize, otmptSubscriptOffset, otmptSuperscriptSize, otmptSuperscriptOffset, otmsStrikeoutSize, otmsStrikeoutPosition, otmsUnderscoreSize, otmsUnderscorePosition, otmpFamilyName, otmpFaceName, otmpStyleName, otmpFullName;
+} OUTLINETEXTMETRIC_FID_CACHE;
+
+OUTLINETEXTMETRIC_FID_CACHE OUTLINETEXTMETRICFc;
+
+void cacheOUTLINETEXTMETRICFields(JNIEnv *env, jobject lpObject)
+{
+       if (OUTLINETEXTMETRICFc.cached) return;
+       OUTLINETEXTMETRICFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       OUTLINETEXTMETRICFc.otmSize = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmSize", "I");
+       OUTLINETEXTMETRICFc.otmTextMetrics = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmTextMetrics", "Lorg/eclipse/swt/internal/win32/TEXTMETRIC;");
+       OUTLINETEXTMETRICFc.otmFiller = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmFiller", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bFamilyType = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bFamilyType", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bSerifStyle = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bSerifStyle", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bWeight = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bWeight", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bProportion = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bProportion", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bContrast = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bContrast", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bStrokeVariation = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bStrokeVariation", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bArmStyle = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bArmStyle", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bLetterform = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bLetterform", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bMidline = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bMidline", "B");
+       OUTLINETEXTMETRICFc.otmPanoseNumber_bXHeight = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmPanoseNumber_bXHeight", "B");
+       OUTLINETEXTMETRICFc.otmfsSelection = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmfsSelection", "I");
+       OUTLINETEXTMETRICFc.otmfsType = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmfsType", "I");
+       OUTLINETEXTMETRICFc.otmsCharSlopeRise = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsCharSlopeRise", "I");
+       OUTLINETEXTMETRICFc.otmsCharSlopeRun = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsCharSlopeRun", "I");
+       OUTLINETEXTMETRICFc.otmItalicAngle = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmItalicAngle", "I");
+       OUTLINETEXTMETRICFc.otmEMSquare = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmEMSquare", "I");
+       OUTLINETEXTMETRICFc.otmAscent = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmAscent", "I");
+       OUTLINETEXTMETRICFc.otmDescent = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmDescent", "I");
+       OUTLINETEXTMETRICFc.otmLineGap = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmLineGap", "I");
+       OUTLINETEXTMETRICFc.otmsCapEmHeight = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsCapEmHeight", "I");
+       OUTLINETEXTMETRICFc.otmsXHeight = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsXHeight", "I");
+       OUTLINETEXTMETRICFc.otmrcFontBox = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmrcFontBox", "Lorg/eclipse/swt/internal/win32/RECT;");
+       OUTLINETEXTMETRICFc.otmMacAscent = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmMacAscent", "I");
+       OUTLINETEXTMETRICFc.otmMacDescent = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmMacDescent", "I");
+       OUTLINETEXTMETRICFc.otmMacLineGap = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmMacLineGap", "I");
+       OUTLINETEXTMETRICFc.otmusMinimumPPEM = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmusMinimumPPEM", "I");
+       OUTLINETEXTMETRICFc.otmptSubscriptSize = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmptSubscriptSize", "Lorg/eclipse/swt/internal/win32/POINT;");
+       OUTLINETEXTMETRICFc.otmptSubscriptOffset = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmptSubscriptOffset", "Lorg/eclipse/swt/internal/win32/POINT;");
+       OUTLINETEXTMETRICFc.otmptSuperscriptSize = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmptSuperscriptSize", "Lorg/eclipse/swt/internal/win32/POINT;");
+       OUTLINETEXTMETRICFc.otmptSuperscriptOffset = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmptSuperscriptOffset", "Lorg/eclipse/swt/internal/win32/POINT;");
+       OUTLINETEXTMETRICFc.otmsStrikeoutSize = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsStrikeoutSize", "I");
+       OUTLINETEXTMETRICFc.otmsStrikeoutPosition = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsStrikeoutPosition", "I");
+       OUTLINETEXTMETRICFc.otmsUnderscoreSize = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsUnderscoreSize", "I");
+       OUTLINETEXTMETRICFc.otmsUnderscorePosition = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmsUnderscorePosition", "I");
+       OUTLINETEXTMETRICFc.otmpFamilyName = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmpFamilyName", "J");
+       OUTLINETEXTMETRICFc.otmpFaceName = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmpFaceName", "J");
+       OUTLINETEXTMETRICFc.otmpStyleName = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmpStyleName", "J");
+       OUTLINETEXTMETRICFc.otmpFullName = (*env)->GetFieldID(env, OUTLINETEXTMETRICFc.clazz, "otmpFullName", "J");
+       OUTLINETEXTMETRICFc.cached = 1;
+}
+
+OUTLINETEXTMETRIC *getOUTLINETEXTMETRICFields(JNIEnv *env, jobject lpObject, OUTLINETEXTMETRIC *lpStruct)
+{
+       if (!OUTLINETEXTMETRICFc.cached) cacheOUTLINETEXTMETRICFields(env, lpObject);
+       lpStruct->otmSize = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmSize);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmTextMetrics);
+       if (lpObject1 != NULL) getTEXTMETRICFields(env, lpObject1, &lpStruct->otmTextMetrics);
+       }
+       lpStruct->otmFiller = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmFiller);
+       lpStruct->otmPanoseNumber.bFamilyType = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bFamilyType);
+       lpStruct->otmPanoseNumber.bSerifStyle = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bSerifStyle);
+       lpStruct->otmPanoseNumber.bWeight = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bWeight);
+       lpStruct->otmPanoseNumber.bProportion = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bProportion);
+       lpStruct->otmPanoseNumber.bContrast = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bContrast);
+       lpStruct->otmPanoseNumber.bStrokeVariation = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bStrokeVariation);
+       lpStruct->otmPanoseNumber.bArmStyle = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bArmStyle);
+       lpStruct->otmPanoseNumber.bLetterform = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bLetterform);
+       lpStruct->otmPanoseNumber.bMidline = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bMidline);
+       lpStruct->otmPanoseNumber.bXHeight = (*env)->GetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bXHeight);
+       lpStruct->otmfsSelection = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmfsSelection);
+       lpStruct->otmfsType = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmfsType);
+       lpStruct->otmsCharSlopeRise = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsCharSlopeRise);
+       lpStruct->otmsCharSlopeRun = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsCharSlopeRun);
+       lpStruct->otmItalicAngle = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmItalicAngle);
+       lpStruct->otmEMSquare = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmEMSquare);
+       lpStruct->otmAscent = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmAscent);
+       lpStruct->otmDescent = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmDescent);
+       lpStruct->otmLineGap = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmLineGap);
+       lpStruct->otmsCapEmHeight = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsCapEmHeight);
+       lpStruct->otmsXHeight = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsXHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmrcFontBox);
+       if (lpObject1 != NULL) getRECTFields(env, lpObject1, &lpStruct->otmrcFontBox);
+       }
+       lpStruct->otmMacAscent = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmMacAscent);
+       lpStruct->otmMacDescent = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmMacDescent);
+       lpStruct->otmMacLineGap = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmMacLineGap);
+       lpStruct->otmusMinimumPPEM = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmusMinimumPPEM);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSubscriptSize);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->otmptSubscriptSize);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSubscriptOffset);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->otmptSubscriptOffset);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSuperscriptSize);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->otmptSuperscriptSize);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSuperscriptOffset);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->otmptSuperscriptOffset);
+       }
+       lpStruct->otmsStrikeoutSize = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsStrikeoutSize);
+       lpStruct->otmsStrikeoutPosition = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsStrikeoutPosition);
+       lpStruct->otmsUnderscoreSize = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsUnderscoreSize);
+       lpStruct->otmsUnderscorePosition = (*env)->GetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsUnderscorePosition);
+       lpStruct->otmpFamilyName = (PSTR)(*env)->GetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpFamilyName);
+       lpStruct->otmpFaceName = (PSTR)(*env)->GetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpFaceName);
+       lpStruct->otmpStyleName = (PSTR)(*env)->GetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpStyleName);
+       lpStruct->otmpFullName = (PSTR)(*env)->GetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpFullName);
+       return lpStruct;
+}
+
+void setOUTLINETEXTMETRICFields(JNIEnv *env, jobject lpObject, OUTLINETEXTMETRIC *lpStruct)
+{
+       if (!OUTLINETEXTMETRICFc.cached) cacheOUTLINETEXTMETRICFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmSize, (jint)lpStruct->otmSize);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmTextMetrics);
+       if (lpObject1 != NULL) setTEXTMETRICFields(env, lpObject1, &lpStruct->otmTextMetrics);
+       }
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmFiller, (jbyte)lpStruct->otmFiller);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bFamilyType, (jbyte)lpStruct->otmPanoseNumber.bFamilyType);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bSerifStyle, (jbyte)lpStruct->otmPanoseNumber.bSerifStyle);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bWeight, (jbyte)lpStruct->otmPanoseNumber.bWeight);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bProportion, (jbyte)lpStruct->otmPanoseNumber.bProportion);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bContrast, (jbyte)lpStruct->otmPanoseNumber.bContrast);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bStrokeVariation, (jbyte)lpStruct->otmPanoseNumber.bStrokeVariation);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bArmStyle, (jbyte)lpStruct->otmPanoseNumber.bArmStyle);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bLetterform, (jbyte)lpStruct->otmPanoseNumber.bLetterform);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bMidline, (jbyte)lpStruct->otmPanoseNumber.bMidline);
+       (*env)->SetByteField(env, lpObject, OUTLINETEXTMETRICFc.otmPanoseNumber_bXHeight, (jbyte)lpStruct->otmPanoseNumber.bXHeight);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmfsSelection, (jint)lpStruct->otmfsSelection);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmfsType, (jint)lpStruct->otmfsType);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsCharSlopeRise, (jint)lpStruct->otmsCharSlopeRise);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsCharSlopeRun, (jint)lpStruct->otmsCharSlopeRun);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmItalicAngle, (jint)lpStruct->otmItalicAngle);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmEMSquare, (jint)lpStruct->otmEMSquare);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmAscent, (jint)lpStruct->otmAscent);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmDescent, (jint)lpStruct->otmDescent);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmLineGap, (jint)lpStruct->otmLineGap);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsCapEmHeight, (jint)lpStruct->otmsCapEmHeight);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsXHeight, (jint)lpStruct->otmsXHeight);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmrcFontBox);
+       if (lpObject1 != NULL) setRECTFields(env, lpObject1, &lpStruct->otmrcFontBox);
+       }
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmMacAscent, (jint)lpStruct->otmMacAscent);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmMacDescent, (jint)lpStruct->otmMacDescent);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmMacLineGap, (jint)lpStruct->otmMacLineGap);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmusMinimumPPEM, (jint)lpStruct->otmusMinimumPPEM);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSubscriptSize);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->otmptSubscriptSize);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSubscriptOffset);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->otmptSubscriptOffset);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSuperscriptSize);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->otmptSuperscriptSize);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, OUTLINETEXTMETRICFc.otmptSuperscriptOffset);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->otmptSuperscriptOffset);
+       }
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsStrikeoutSize, (jint)lpStruct->otmsStrikeoutSize);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsStrikeoutPosition, (jint)lpStruct->otmsStrikeoutPosition);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsUnderscoreSize, (jint)lpStruct->otmsUnderscoreSize);
+       (*env)->SetIntField(env, lpObject, OUTLINETEXTMETRICFc.otmsUnderscorePosition, (jint)lpStruct->otmsUnderscorePosition);
+       (*env)->SetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpFamilyName, (jlong)lpStruct->otmpFamilyName);
+       (*env)->SetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpFaceName, (jlong)lpStruct->otmpFaceName);
+       (*env)->SetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpStyleName, (jlong)lpStruct->otmpStyleName);
+       (*env)->SetLongField(env, lpObject, OUTLINETEXTMETRICFc.otmpFullName, (jlong)lpStruct->otmpFullName);
+}
+#endif
+
+#ifndef NO_PAINTSTRUCT
+typedef struct PAINTSTRUCT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hdc, fErase, left, top, right, bottom, fRestore, fIncUpdate, rgbReserved;
+} PAINTSTRUCT_FID_CACHE;
+
+PAINTSTRUCT_FID_CACHE PAINTSTRUCTFc;
+
+void cachePAINTSTRUCTFields(JNIEnv *env, jobject lpObject)
+{
+       if (PAINTSTRUCTFc.cached) return;
+       PAINTSTRUCTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       PAINTSTRUCTFc.hdc = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "hdc", "J");
+       PAINTSTRUCTFc.fErase = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "fErase", "Z");
+       PAINTSTRUCTFc.left = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "left", "I");
+       PAINTSTRUCTFc.top = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "top", "I");
+       PAINTSTRUCTFc.right = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "right", "I");
+       PAINTSTRUCTFc.bottom = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "bottom", "I");
+       PAINTSTRUCTFc.fRestore = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "fRestore", "Z");
+       PAINTSTRUCTFc.fIncUpdate = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "fIncUpdate", "Z");
+       PAINTSTRUCTFc.rgbReserved = (*env)->GetFieldID(env, PAINTSTRUCTFc.clazz, "rgbReserved", "[B");
+       PAINTSTRUCTFc.cached = 1;
+}
+
+PAINTSTRUCT *getPAINTSTRUCTFields(JNIEnv *env, jobject lpObject, PAINTSTRUCT *lpStruct)
+{
+       if (!PAINTSTRUCTFc.cached) cachePAINTSTRUCTFields(env, lpObject);
+       lpStruct->hdc = (HDC)(*env)->GetLongField(env, lpObject, PAINTSTRUCTFc.hdc);
+       lpStruct->fErase = (*env)->GetBooleanField(env, lpObject, PAINTSTRUCTFc.fErase);
+       lpStruct->rcPaint.left = (*env)->GetIntField(env, lpObject, PAINTSTRUCTFc.left);
+       lpStruct->rcPaint.top = (*env)->GetIntField(env, lpObject, PAINTSTRUCTFc.top);
+       lpStruct->rcPaint.right = (*env)->GetIntField(env, lpObject, PAINTSTRUCTFc.right);
+       lpStruct->rcPaint.bottom = (*env)->GetIntField(env, lpObject, PAINTSTRUCTFc.bottom);
+       lpStruct->fRestore = (*env)->GetBooleanField(env, lpObject, PAINTSTRUCTFc.fRestore);
+       lpStruct->fIncUpdate = (*env)->GetBooleanField(env, lpObject, PAINTSTRUCTFc.fIncUpdate);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, PAINTSTRUCTFc.rgbReserved);
+       (*env)->GetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->rgbReserved), (jbyte *)lpStruct->rgbReserved);
+       }
+       return lpStruct;
+}
+
+void setPAINTSTRUCTFields(JNIEnv *env, jobject lpObject, PAINTSTRUCT *lpStruct)
+{
+       if (!PAINTSTRUCTFc.cached) cachePAINTSTRUCTFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, PAINTSTRUCTFc.hdc, (jlong)lpStruct->hdc);
+       (*env)->SetBooleanField(env, lpObject, PAINTSTRUCTFc.fErase, (jboolean)lpStruct->fErase);
+       (*env)->SetIntField(env, lpObject, PAINTSTRUCTFc.left, (jint)lpStruct->rcPaint.left);
+       (*env)->SetIntField(env, lpObject, PAINTSTRUCTFc.top, (jint)lpStruct->rcPaint.top);
+       (*env)->SetIntField(env, lpObject, PAINTSTRUCTFc.right, (jint)lpStruct->rcPaint.right);
+       (*env)->SetIntField(env, lpObject, PAINTSTRUCTFc.bottom, (jint)lpStruct->rcPaint.bottom);
+       (*env)->SetBooleanField(env, lpObject, PAINTSTRUCTFc.fRestore, (jboolean)lpStruct->fRestore);
+       (*env)->SetBooleanField(env, lpObject, PAINTSTRUCTFc.fIncUpdate, (jboolean)lpStruct->fIncUpdate);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, PAINTSTRUCTFc.rgbReserved);
+       (*env)->SetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->rgbReserved), (jbyte *)lpStruct->rgbReserved);
+       }
+}
+#endif
+
+#ifndef NO_PANOSE
+typedef struct PANOSE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID bFamilyType, bSerifStyle, bWeight, bProportion, bContrast, bStrokeVariation, bArmStyle, bLetterform, bMidline, bXHeight;
+} PANOSE_FID_CACHE;
+
+PANOSE_FID_CACHE PANOSEFc;
+
+void cachePANOSEFields(JNIEnv *env, jobject lpObject)
+{
+       if (PANOSEFc.cached) return;
+       PANOSEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       PANOSEFc.bFamilyType = (*env)->GetFieldID(env, PANOSEFc.clazz, "bFamilyType", "B");
+       PANOSEFc.bSerifStyle = (*env)->GetFieldID(env, PANOSEFc.clazz, "bSerifStyle", "B");
+       PANOSEFc.bWeight = (*env)->GetFieldID(env, PANOSEFc.clazz, "bWeight", "B");
+       PANOSEFc.bProportion = (*env)->GetFieldID(env, PANOSEFc.clazz, "bProportion", "B");
+       PANOSEFc.bContrast = (*env)->GetFieldID(env, PANOSEFc.clazz, "bContrast", "B");
+       PANOSEFc.bStrokeVariation = (*env)->GetFieldID(env, PANOSEFc.clazz, "bStrokeVariation", "B");
+       PANOSEFc.bArmStyle = (*env)->GetFieldID(env, PANOSEFc.clazz, "bArmStyle", "B");
+       PANOSEFc.bLetterform = (*env)->GetFieldID(env, PANOSEFc.clazz, "bLetterform", "B");
+       PANOSEFc.bMidline = (*env)->GetFieldID(env, PANOSEFc.clazz, "bMidline", "B");
+       PANOSEFc.bXHeight = (*env)->GetFieldID(env, PANOSEFc.clazz, "bXHeight", "B");
+       PANOSEFc.cached = 1;
+}
+
+PANOSE *getPANOSEFields(JNIEnv *env, jobject lpObject, PANOSE *lpStruct)
+{
+       if (!PANOSEFc.cached) cachePANOSEFields(env, lpObject);
+       lpStruct->bFamilyType = (*env)->GetByteField(env, lpObject, PANOSEFc.bFamilyType);
+       lpStruct->bSerifStyle = (*env)->GetByteField(env, lpObject, PANOSEFc.bSerifStyle);
+       lpStruct->bWeight = (*env)->GetByteField(env, lpObject, PANOSEFc.bWeight);
+       lpStruct->bProportion = (*env)->GetByteField(env, lpObject, PANOSEFc.bProportion);
+       lpStruct->bContrast = (*env)->GetByteField(env, lpObject, PANOSEFc.bContrast);
+       lpStruct->bStrokeVariation = (*env)->GetByteField(env, lpObject, PANOSEFc.bStrokeVariation);
+       lpStruct->bArmStyle = (*env)->GetByteField(env, lpObject, PANOSEFc.bArmStyle);
+       lpStruct->bLetterform = (*env)->GetByteField(env, lpObject, PANOSEFc.bLetterform);
+       lpStruct->bMidline = (*env)->GetByteField(env, lpObject, PANOSEFc.bMidline);
+       lpStruct->bXHeight = (*env)->GetByteField(env, lpObject, PANOSEFc.bXHeight);
+       return lpStruct;
+}
+
+void setPANOSEFields(JNIEnv *env, jobject lpObject, PANOSE *lpStruct)
+{
+       if (!PANOSEFc.cached) cachePANOSEFields(env, lpObject);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bFamilyType, (jbyte)lpStruct->bFamilyType);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bSerifStyle, (jbyte)lpStruct->bSerifStyle);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bWeight, (jbyte)lpStruct->bWeight);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bProportion, (jbyte)lpStruct->bProportion);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bContrast, (jbyte)lpStruct->bContrast);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bStrokeVariation, (jbyte)lpStruct->bStrokeVariation);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bArmStyle, (jbyte)lpStruct->bArmStyle);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bLetterform, (jbyte)lpStruct->bLetterform);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bMidline, (jbyte)lpStruct->bMidline);
+       (*env)->SetByteField(env, lpObject, PANOSEFc.bXHeight, (jbyte)lpStruct->bXHeight);
+}
+#endif
+
+#ifndef NO_POINT
+typedef struct POINT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y;
+} POINT_FID_CACHE;
+
+POINT_FID_CACHE POINTFc;
+
+void cachePOINTFields(JNIEnv *env, jobject lpObject)
+{
+       if (POINTFc.cached) return;
+       POINTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       POINTFc.x = (*env)->GetFieldID(env, POINTFc.clazz, "x", "I");
+       POINTFc.y = (*env)->GetFieldID(env, POINTFc.clazz, "y", "I");
+       POINTFc.cached = 1;
+}
+
+POINT *getPOINTFields(JNIEnv *env, jobject lpObject, POINT *lpStruct)
+{
+       if (!POINTFc.cached) cachePOINTFields(env, lpObject);
+       lpStruct->x = (*env)->GetIntField(env, lpObject, POINTFc.x);
+       lpStruct->y = (*env)->GetIntField(env, lpObject, POINTFc.y);
+       return lpStruct;
+}
+
+void setPOINTFields(JNIEnv *env, jobject lpObject, POINT *lpStruct)
+{
+       if (!POINTFc.cached) cachePOINTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, POINTFc.x, (jint)lpStruct->x);
+       (*env)->SetIntField(env, lpObject, POINTFc.y, (jint)lpStruct->y);
+}
+#endif
+
+#ifndef NO_PRINTDLG
+typedef struct PRINTDLG_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID lStructSize, hwndOwner, hDevMode, hDevNames, hDC, Flags, nFromPage, nToPage, nMinPage, nMaxPage, nCopies, hInstance, lCustData, lpfnPrintHook, lpfnSetupHook, lpPrintTemplateName, lpSetupTemplateName, hPrintTemplate, hSetupTemplate;
+} PRINTDLG_FID_CACHE;
+
+PRINTDLG_FID_CACHE PRINTDLGFc;
+
+void cachePRINTDLGFields(JNIEnv *env, jobject lpObject)
+{
+       if (PRINTDLGFc.cached) return;
+       PRINTDLGFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       PRINTDLGFc.lStructSize = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "lStructSize", "I");
+       PRINTDLGFc.hwndOwner = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hwndOwner", "J");
+       PRINTDLGFc.hDevMode = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hDevMode", "J");
+       PRINTDLGFc.hDevNames = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hDevNames", "J");
+       PRINTDLGFc.hDC = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hDC", "J");
+       PRINTDLGFc.Flags = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "Flags", "I");
+       PRINTDLGFc.nFromPage = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "nFromPage", "S");
+       PRINTDLGFc.nToPage = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "nToPage", "S");
+       PRINTDLGFc.nMinPage = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "nMinPage", "S");
+       PRINTDLGFc.nMaxPage = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "nMaxPage", "S");
+       PRINTDLGFc.nCopies = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "nCopies", "S");
+       PRINTDLGFc.hInstance = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hInstance", "J");
+       PRINTDLGFc.lCustData = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "lCustData", "J");
+       PRINTDLGFc.lpfnPrintHook = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "lpfnPrintHook", "J");
+       PRINTDLGFc.lpfnSetupHook = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "lpfnSetupHook", "J");
+       PRINTDLGFc.lpPrintTemplateName = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "lpPrintTemplateName", "J");
+       PRINTDLGFc.lpSetupTemplateName = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "lpSetupTemplateName", "J");
+       PRINTDLGFc.hPrintTemplate = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hPrintTemplate", "J");
+       PRINTDLGFc.hSetupTemplate = (*env)->GetFieldID(env, PRINTDLGFc.clazz, "hSetupTemplate", "J");
+       PRINTDLGFc.cached = 1;
+}
+
+PRINTDLG *getPRINTDLGFields(JNIEnv *env, jobject lpObject, PRINTDLG *lpStruct)
+{
+       if (!PRINTDLGFc.cached) cachePRINTDLGFields(env, lpObject);
+       lpStruct->lStructSize = (*env)->GetIntField(env, lpObject, PRINTDLGFc.lStructSize);
+       lpStruct->hwndOwner = (HWND)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hwndOwner);
+       lpStruct->hDevMode = (HGLOBAL)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hDevMode);
+       lpStruct->hDevNames = (HGLOBAL)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hDevNames);
+       lpStruct->hDC = (HDC)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hDC);
+       lpStruct->Flags = (*env)->GetIntField(env, lpObject, PRINTDLGFc.Flags);
+       lpStruct->nFromPage = (*env)->GetShortField(env, lpObject, PRINTDLGFc.nFromPage);
+       lpStruct->nToPage = (*env)->GetShortField(env, lpObject, PRINTDLGFc.nToPage);
+       lpStruct->nMinPage = (*env)->GetShortField(env, lpObject, PRINTDLGFc.nMinPage);
+       lpStruct->nMaxPage = (*env)->GetShortField(env, lpObject, PRINTDLGFc.nMaxPage);
+       lpStruct->nCopies = (*env)->GetShortField(env, lpObject, PRINTDLGFc.nCopies);
+       lpStruct->hInstance = (HINSTANCE)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hInstance);
+       lpStruct->lCustData = (*env)->GetLongField(env, lpObject, PRINTDLGFc.lCustData);
+       lpStruct->lpfnPrintHook = (LPPRINTHOOKPROC)(*env)->GetLongField(env, lpObject, PRINTDLGFc.lpfnPrintHook);
+       lpStruct->lpfnSetupHook = (LPPRINTHOOKPROC)(*env)->GetLongField(env, lpObject, PRINTDLGFc.lpfnSetupHook);
+       lpStruct->lpPrintTemplateName = (LPCTSTR)(*env)->GetLongField(env, lpObject, PRINTDLGFc.lpPrintTemplateName);
+       lpStruct->lpSetupTemplateName = (LPCTSTR)(*env)->GetLongField(env, lpObject, PRINTDLGFc.lpSetupTemplateName);
+       lpStruct->hPrintTemplate = (HGLOBAL)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hPrintTemplate);
+       lpStruct->hSetupTemplate = (HGLOBAL)(*env)->GetLongField(env, lpObject, PRINTDLGFc.hSetupTemplate);
+       return lpStruct;
+}
+
+void setPRINTDLGFields(JNIEnv *env, jobject lpObject, PRINTDLG *lpStruct)
+{
+       if (!PRINTDLGFc.cached) cachePRINTDLGFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, PRINTDLGFc.lStructSize, (jint)lpStruct->lStructSize);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hwndOwner, (jlong)lpStruct->hwndOwner);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hDevMode, (jlong)lpStruct->hDevMode);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hDevNames, (jlong)lpStruct->hDevNames);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hDC, (jlong)lpStruct->hDC);
+       (*env)->SetIntField(env, lpObject, PRINTDLGFc.Flags, (jint)lpStruct->Flags);
+       (*env)->SetShortField(env, lpObject, PRINTDLGFc.nFromPage, (jshort)lpStruct->nFromPage);
+       (*env)->SetShortField(env, lpObject, PRINTDLGFc.nToPage, (jshort)lpStruct->nToPage);
+       (*env)->SetShortField(env, lpObject, PRINTDLGFc.nMinPage, (jshort)lpStruct->nMinPage);
+       (*env)->SetShortField(env, lpObject, PRINTDLGFc.nMaxPage, (jshort)lpStruct->nMaxPage);
+       (*env)->SetShortField(env, lpObject, PRINTDLGFc.nCopies, (jshort)lpStruct->nCopies);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hInstance, (jlong)lpStruct->hInstance);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.lCustData, (jlong)lpStruct->lCustData);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.lpfnPrintHook, (jlong)lpStruct->lpfnPrintHook);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.lpfnSetupHook, (jlong)lpStruct->lpfnSetupHook);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.lpPrintTemplateName, (jlong)lpStruct->lpPrintTemplateName);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.lpSetupTemplateName, (jlong)lpStruct->lpSetupTemplateName);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hPrintTemplate, (jlong)lpStruct->hPrintTemplate);
+       (*env)->SetLongField(env, lpObject, PRINTDLGFc.hSetupTemplate, (jlong)lpStruct->hSetupTemplate);
+}
+#endif
+
+#ifndef NO_PROCESS_INFORMATION
+typedef struct PROCESS_INFORMATION_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hProcess, hThread, dwProcessId, dwThreadId;
+} PROCESS_INFORMATION_FID_CACHE;
+
+PROCESS_INFORMATION_FID_CACHE PROCESS_INFORMATIONFc;
+
+void cachePROCESS_INFORMATIONFields(JNIEnv *env, jobject lpObject)
+{
+       if (PROCESS_INFORMATIONFc.cached) return;
+       PROCESS_INFORMATIONFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       PROCESS_INFORMATIONFc.hProcess = (*env)->GetFieldID(env, PROCESS_INFORMATIONFc.clazz, "hProcess", "J");
+       PROCESS_INFORMATIONFc.hThread = (*env)->GetFieldID(env, PROCESS_INFORMATIONFc.clazz, "hThread", "J");
+       PROCESS_INFORMATIONFc.dwProcessId = (*env)->GetFieldID(env, PROCESS_INFORMATIONFc.clazz, "dwProcessId", "I");
+       PROCESS_INFORMATIONFc.dwThreadId = (*env)->GetFieldID(env, PROCESS_INFORMATIONFc.clazz, "dwThreadId", "I");
+       PROCESS_INFORMATIONFc.cached = 1;
+}
+
+PROCESS_INFORMATION *getPROCESS_INFORMATIONFields(JNIEnv *env, jobject lpObject, PROCESS_INFORMATION *lpStruct)
+{
+       if (!PROCESS_INFORMATIONFc.cached) cachePROCESS_INFORMATIONFields(env, lpObject);
+       lpStruct->hProcess = (HANDLE)(*env)->GetLongField(env, lpObject, PROCESS_INFORMATIONFc.hProcess);
+       lpStruct->hThread = (HANDLE)(*env)->GetLongField(env, lpObject, PROCESS_INFORMATIONFc.hThread);
+       lpStruct->dwProcessId = (*env)->GetIntField(env, lpObject, PROCESS_INFORMATIONFc.dwProcessId);
+       lpStruct->dwThreadId = (*env)->GetIntField(env, lpObject, PROCESS_INFORMATIONFc.dwThreadId);
+       return lpStruct;
+}
+
+void setPROCESS_INFORMATIONFields(JNIEnv *env, jobject lpObject, PROCESS_INFORMATION *lpStruct)
+{
+       if (!PROCESS_INFORMATIONFc.cached) cachePROCESS_INFORMATIONFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, PROCESS_INFORMATIONFc.hProcess, (jlong)lpStruct->hProcess);
+       (*env)->SetLongField(env, lpObject, PROCESS_INFORMATIONFc.hThread, (jlong)lpStruct->hThread);
+       (*env)->SetIntField(env, lpObject, PROCESS_INFORMATIONFc.dwProcessId, (jint)lpStruct->dwProcessId);
+       (*env)->SetIntField(env, lpObject, PROCESS_INFORMATIONFc.dwThreadId, (jint)lpStruct->dwThreadId);
+}
+#endif
+
+#ifndef NO_PROPERTYKEY
+typedef struct PROPERTYKEY_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID fmtid, pid;
+} PROPERTYKEY_FID_CACHE;
+
+PROPERTYKEY_FID_CACHE PROPERTYKEYFc;
+
+void cachePROPERTYKEYFields(JNIEnv *env, jobject lpObject)
+{
+       if (PROPERTYKEYFc.cached) return;
+       PROPERTYKEYFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       PROPERTYKEYFc.fmtid = (*env)->GetFieldID(env, PROPERTYKEYFc.clazz, "fmtid", "[B");
+       PROPERTYKEYFc.pid = (*env)->GetFieldID(env, PROPERTYKEYFc.clazz, "pid", "I");
+       PROPERTYKEYFc.cached = 1;
+}
+
+PROPERTYKEY *getPROPERTYKEYFields(JNIEnv *env, jobject lpObject, PROPERTYKEY *lpStruct)
+{
+       if (!PROPERTYKEYFc.cached) cachePROPERTYKEYFields(env, lpObject);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, PROPERTYKEYFc.fmtid);
+       (*env)->GetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->fmtid), (jbyte *)&lpStruct->fmtid);
+       }
+       lpStruct->pid = (*env)->GetIntField(env, lpObject, PROPERTYKEYFc.pid);
+       return lpStruct;
+}
+
+void setPROPERTYKEYFields(JNIEnv *env, jobject lpObject, PROPERTYKEY *lpStruct)
+{
+       if (!PROPERTYKEYFc.cached) cachePROPERTYKEYFields(env, lpObject);
+       {
+       jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, PROPERTYKEYFc.fmtid);
+       (*env)->SetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->fmtid), (jbyte *)&lpStruct->fmtid);
+       }
+       (*env)->SetIntField(env, lpObject, PROPERTYKEYFc.pid, (jint)lpStruct->pid);
+}
+#endif
+
+#ifndef NO_REBARBANDINFO
+typedef struct REBARBANDINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, fMask, fStyle, clrFore, clrBack, lpText, cch, iImage, hwndChild, cxMinChild, cyMinChild, cx, hbmBack, wID, cyChild, cyMaxChild, cyIntegral, cxIdeal, lParam, cxHeader;
+} REBARBANDINFO_FID_CACHE;
+
+REBARBANDINFO_FID_CACHE REBARBANDINFOFc;
+
+void cacheREBARBANDINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (REBARBANDINFOFc.cached) return;
+       REBARBANDINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       REBARBANDINFOFc.cbSize = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cbSize", "I");
+       REBARBANDINFOFc.fMask = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "fMask", "I");
+       REBARBANDINFOFc.fStyle = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "fStyle", "I");
+       REBARBANDINFOFc.clrFore = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "clrFore", "I");
+       REBARBANDINFOFc.clrBack = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "clrBack", "I");
+       REBARBANDINFOFc.lpText = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "lpText", "J");
+       REBARBANDINFOFc.cch = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cch", "I");
+       REBARBANDINFOFc.iImage = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "iImage", "I");
+       REBARBANDINFOFc.hwndChild = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "hwndChild", "J");
+       REBARBANDINFOFc.cxMinChild = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cxMinChild", "I");
+       REBARBANDINFOFc.cyMinChild = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cyMinChild", "I");
+       REBARBANDINFOFc.cx = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cx", "I");
+       REBARBANDINFOFc.hbmBack = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "hbmBack", "J");
+       REBARBANDINFOFc.wID = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "wID", "I");
+       REBARBANDINFOFc.cyChild = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cyChild", "I");
+       REBARBANDINFOFc.cyMaxChild = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cyMaxChild", "I");
+       REBARBANDINFOFc.cyIntegral = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cyIntegral", "I");
+       REBARBANDINFOFc.cxIdeal = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cxIdeal", "I");
+       REBARBANDINFOFc.lParam = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "lParam", "J");
+       REBARBANDINFOFc.cxHeader = (*env)->GetFieldID(env, REBARBANDINFOFc.clazz, "cxHeader", "I");
+       REBARBANDINFOFc.cached = 1;
+}
+
+REBARBANDINFO *getREBARBANDINFOFields(JNIEnv *env, jobject lpObject, REBARBANDINFO *lpStruct)
+{
+       if (!REBARBANDINFOFc.cached) cacheREBARBANDINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cbSize);
+       lpStruct->fMask = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.fMask);
+       lpStruct->fStyle = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.fStyle);
+       lpStruct->clrFore = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.clrFore);
+       lpStruct->clrBack = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.clrBack);
+       lpStruct->lpText = (LPTSTR)(*env)->GetLongField(env, lpObject, REBARBANDINFOFc.lpText);
+       lpStruct->cch = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cch);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.iImage);
+       lpStruct->hwndChild = (HWND)(*env)->GetLongField(env, lpObject, REBARBANDINFOFc.hwndChild);
+       lpStruct->cxMinChild = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cxMinChild);
+       lpStruct->cyMinChild = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cyMinChild);
+       lpStruct->cx = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cx);
+       lpStruct->hbmBack = (HBITMAP)(*env)->GetLongField(env, lpObject, REBARBANDINFOFc.hbmBack);
+       lpStruct->wID = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.wID);
+       lpStruct->cyChild = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cyChild);
+       lpStruct->cyMaxChild = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cyMaxChild);
+       lpStruct->cyIntegral = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cyIntegral);
+       lpStruct->cxIdeal = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cxIdeal);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, REBARBANDINFOFc.lParam);
+       lpStruct->cxHeader = (*env)->GetIntField(env, lpObject, REBARBANDINFOFc.cxHeader);
+       return lpStruct;
+}
+
+void setREBARBANDINFOFields(JNIEnv *env, jobject lpObject, REBARBANDINFO *lpStruct)
+{
+       if (!REBARBANDINFOFc.cached) cacheREBARBANDINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.fMask, (jint)lpStruct->fMask);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.fStyle, (jint)lpStruct->fStyle);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.clrFore, (jint)lpStruct->clrFore);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.clrBack, (jint)lpStruct->clrBack);
+       (*env)->SetLongField(env, lpObject, REBARBANDINFOFc.lpText, (jlong)lpStruct->lpText);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cch, (jint)lpStruct->cch);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetLongField(env, lpObject, REBARBANDINFOFc.hwndChild, (jlong)lpStruct->hwndChild);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cxMinChild, (jint)lpStruct->cxMinChild);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cyMinChild, (jint)lpStruct->cyMinChild);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cx, (jint)lpStruct->cx);
+       (*env)->SetLongField(env, lpObject, REBARBANDINFOFc.hbmBack, (jlong)lpStruct->hbmBack);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.wID, (jint)lpStruct->wID);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cyChild, (jint)lpStruct->cyChild);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cyMaxChild, (jint)lpStruct->cyMaxChild);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cyIntegral, (jint)lpStruct->cyIntegral);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cxIdeal, (jint)lpStruct->cxIdeal);
+       (*env)->SetLongField(env, lpObject, REBARBANDINFOFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetIntField(env, lpObject, REBARBANDINFOFc.cxHeader, (jint)lpStruct->cxHeader);
+}
+#endif
+
+#ifndef NO_RECT
+typedef struct RECT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID left, top, right, bottom;
+} RECT_FID_CACHE;
+
+RECT_FID_CACHE RECTFc;
+
+void cacheRECTFields(JNIEnv *env, jobject lpObject)
+{
+       if (RECTFc.cached) return;
+       RECTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       RECTFc.left = (*env)->GetFieldID(env, RECTFc.clazz, "left", "I");
+       RECTFc.top = (*env)->GetFieldID(env, RECTFc.clazz, "top", "I");
+       RECTFc.right = (*env)->GetFieldID(env, RECTFc.clazz, "right", "I");
+       RECTFc.bottom = (*env)->GetFieldID(env, RECTFc.clazz, "bottom", "I");
+       RECTFc.cached = 1;
+}
+
+RECT *getRECTFields(JNIEnv *env, jobject lpObject, RECT *lpStruct)
+{
+       if (!RECTFc.cached) cacheRECTFields(env, lpObject);
+       lpStruct->left = (*env)->GetIntField(env, lpObject, RECTFc.left);
+       lpStruct->top = (*env)->GetIntField(env, lpObject, RECTFc.top);
+       lpStruct->right = (*env)->GetIntField(env, lpObject, RECTFc.right);
+       lpStruct->bottom = (*env)->GetIntField(env, lpObject, RECTFc.bottom);
+       return lpStruct;
+}
+
+void setRECTFields(JNIEnv *env, jobject lpObject, RECT *lpStruct)
+{
+       if (!RECTFc.cached) cacheRECTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, RECTFc.left, (jint)lpStruct->left);
+       (*env)->SetIntField(env, lpObject, RECTFc.top, (jint)lpStruct->top);
+       (*env)->SetIntField(env, lpObject, RECTFc.right, (jint)lpStruct->right);
+       (*env)->SetIntField(env, lpObject, RECTFc.bottom, (jint)lpStruct->bottom);
+}
+#endif
+
+#ifndef NO_SAFEARRAY
+typedef struct SAFEARRAY_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cDims, fFeatures, cbElements, cLocks, pvData, rgsabound;
+} SAFEARRAY_FID_CACHE;
+
+SAFEARRAY_FID_CACHE SAFEARRAYFc;
+
+void cacheSAFEARRAYFields(JNIEnv *env, jobject lpObject)
+{
+       if (SAFEARRAYFc.cached) return;
+       SAFEARRAYFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SAFEARRAYFc.cDims = (*env)->GetFieldID(env, SAFEARRAYFc.clazz, "cDims", "S");
+       SAFEARRAYFc.fFeatures = (*env)->GetFieldID(env, SAFEARRAYFc.clazz, "fFeatures", "S");
+       SAFEARRAYFc.cbElements = (*env)->GetFieldID(env, SAFEARRAYFc.clazz, "cbElements", "I");
+       SAFEARRAYFc.cLocks = (*env)->GetFieldID(env, SAFEARRAYFc.clazz, "cLocks", "I");
+       SAFEARRAYFc.pvData = (*env)->GetFieldID(env, SAFEARRAYFc.clazz, "pvData", "J");
+       SAFEARRAYFc.rgsabound = (*env)->GetFieldID(env, SAFEARRAYFc.clazz, "rgsabound", "Lorg/eclipse/swt/internal/win32/SAFEARRAYBOUND;");
+       SAFEARRAYFc.cached = 1;
+}
+
+SAFEARRAY *getSAFEARRAYFields(JNIEnv *env, jobject lpObject, SAFEARRAY *lpStruct)
+{
+       if (!SAFEARRAYFc.cached) cacheSAFEARRAYFields(env, lpObject);
+       lpStruct->cDims = (*env)->GetShortField(env, lpObject, SAFEARRAYFc.cDims);
+       lpStruct->fFeatures = (*env)->GetShortField(env, lpObject, SAFEARRAYFc.fFeatures);
+       lpStruct->cbElements = (*env)->GetIntField(env, lpObject, SAFEARRAYFc.cbElements);
+       lpStruct->cLocks = (*env)->GetIntField(env, lpObject, SAFEARRAYFc.cLocks);
+       lpStruct->pvData = (PVOID)(*env)->GetLongField(env, lpObject, SAFEARRAYFc.pvData);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SAFEARRAYFc.rgsabound);
+       if (lpObject1 != NULL) getSAFEARRAYBOUNDFields(env, lpObject1, &lpStruct->rgsabound[0]);
+       }
+       return lpStruct;
+}
+
+void setSAFEARRAYFields(JNIEnv *env, jobject lpObject, SAFEARRAY *lpStruct)
+{
+       if (!SAFEARRAYFc.cached) cacheSAFEARRAYFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, SAFEARRAYFc.cDims, (jshort)lpStruct->cDims);
+       (*env)->SetShortField(env, lpObject, SAFEARRAYFc.fFeatures, (jshort)lpStruct->fFeatures);
+       (*env)->SetIntField(env, lpObject, SAFEARRAYFc.cbElements, (jint)lpStruct->cbElements);
+       (*env)->SetIntField(env, lpObject, SAFEARRAYFc.cLocks, (jint)lpStruct->cLocks);
+       (*env)->SetLongField(env, lpObject, SAFEARRAYFc.pvData, (jlong)lpStruct->pvData);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SAFEARRAYFc.rgsabound);
+       if (lpObject1 != NULL) setSAFEARRAYBOUNDFields(env, lpObject1, &lpStruct->rgsabound[0]);
+       }
+}
+#endif
+
+#ifndef NO_SAFEARRAYBOUND
+typedef struct SAFEARRAYBOUND_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cElements, lLbound;
+} SAFEARRAYBOUND_FID_CACHE;
+
+SAFEARRAYBOUND_FID_CACHE SAFEARRAYBOUNDFc;
+
+void cacheSAFEARRAYBOUNDFields(JNIEnv *env, jobject lpObject)
+{
+       if (SAFEARRAYBOUNDFc.cached) return;
+       SAFEARRAYBOUNDFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SAFEARRAYBOUNDFc.cElements = (*env)->GetFieldID(env, SAFEARRAYBOUNDFc.clazz, "cElements", "I");
+       SAFEARRAYBOUNDFc.lLbound = (*env)->GetFieldID(env, SAFEARRAYBOUNDFc.clazz, "lLbound", "I");
+       SAFEARRAYBOUNDFc.cached = 1;
+}
+
+SAFEARRAYBOUND *getSAFEARRAYBOUNDFields(JNIEnv *env, jobject lpObject, SAFEARRAYBOUND *lpStruct)
+{
+       if (!SAFEARRAYBOUNDFc.cached) cacheSAFEARRAYBOUNDFields(env, lpObject);
+       lpStruct->cElements = (*env)->GetIntField(env, lpObject, SAFEARRAYBOUNDFc.cElements);
+       lpStruct->lLbound = (*env)->GetIntField(env, lpObject, SAFEARRAYBOUNDFc.lLbound);
+       return lpStruct;
+}
+
+void setSAFEARRAYBOUNDFields(JNIEnv *env, jobject lpObject, SAFEARRAYBOUND *lpStruct)
+{
+       if (!SAFEARRAYBOUNDFc.cached) cacheSAFEARRAYBOUNDFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SAFEARRAYBOUNDFc.cElements, (jint)lpStruct->cElements);
+       (*env)->SetIntField(env, lpObject, SAFEARRAYBOUNDFc.lLbound, (jint)lpStruct->lLbound);
+}
+#endif
+
+#ifndef NO_SCRIPT_ANALYSIS
+typedef struct SCRIPT_ANALYSIS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID eScript, fRTL, fLayoutRTL, fLinkBefore, fLinkAfter, fLogicalOrder, fNoGlyphIndex, s;
+} SCRIPT_ANALYSIS_FID_CACHE;
+
+SCRIPT_ANALYSIS_FID_CACHE SCRIPT_ANALYSISFc;
+
+void cacheSCRIPT_ANALYSISFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_ANALYSISFc.cached) return;
+       SCRIPT_ANALYSISFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_ANALYSISFc.eScript = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "eScript", "S");
+       SCRIPT_ANALYSISFc.fRTL = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "fRTL", "Z");
+       SCRIPT_ANALYSISFc.fLayoutRTL = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "fLayoutRTL", "Z");
+       SCRIPT_ANALYSISFc.fLinkBefore = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "fLinkBefore", "Z");
+       SCRIPT_ANALYSISFc.fLinkAfter = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "fLinkAfter", "Z");
+       SCRIPT_ANALYSISFc.fLogicalOrder = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "fLogicalOrder", "Z");
+       SCRIPT_ANALYSISFc.fNoGlyphIndex = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "fNoGlyphIndex", "Z");
+       SCRIPT_ANALYSISFc.s = (*env)->GetFieldID(env, SCRIPT_ANALYSISFc.clazz, "s", "Lorg/eclipse/swt/internal/win32/SCRIPT_STATE;");
+       SCRIPT_ANALYSISFc.cached = 1;
+}
+
+SCRIPT_ANALYSIS *getSCRIPT_ANALYSISFields(JNIEnv *env, jobject lpObject, SCRIPT_ANALYSIS *lpStruct)
+{
+       if (!SCRIPT_ANALYSISFc.cached) cacheSCRIPT_ANALYSISFields(env, lpObject);
+       lpStruct->eScript = (*env)->GetShortField(env, lpObject, SCRIPT_ANALYSISFc.eScript);
+       lpStruct->fRTL = (*env)->GetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fRTL);
+       lpStruct->fLayoutRTL = (*env)->GetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLayoutRTL);
+       lpStruct->fLinkBefore = (*env)->GetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLinkBefore);
+       lpStruct->fLinkAfter = (*env)->GetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLinkAfter);
+       lpStruct->fLogicalOrder = (*env)->GetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLogicalOrder);
+       lpStruct->fNoGlyphIndex = (*env)->GetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fNoGlyphIndex);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SCRIPT_ANALYSISFc.s);
+       if (lpObject1 != NULL) getSCRIPT_STATEFields(env, lpObject1, &lpStruct->s);
+       }
+       return lpStruct;
+}
+
+void setSCRIPT_ANALYSISFields(JNIEnv *env, jobject lpObject, SCRIPT_ANALYSIS *lpStruct)
+{
+       if (!SCRIPT_ANALYSISFc.cached) cacheSCRIPT_ANALYSISFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, SCRIPT_ANALYSISFc.eScript, (jshort)lpStruct->eScript);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fRTL, (jboolean)lpStruct->fRTL);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLayoutRTL, (jboolean)lpStruct->fLayoutRTL);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLinkBefore, (jboolean)lpStruct->fLinkBefore);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLinkAfter, (jboolean)lpStruct->fLinkAfter);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fLogicalOrder, (jboolean)lpStruct->fLogicalOrder);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_ANALYSISFc.fNoGlyphIndex, (jboolean)lpStruct->fNoGlyphIndex);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SCRIPT_ANALYSISFc.s);
+       if (lpObject1 != NULL) setSCRIPT_STATEFields(env, lpObject1, &lpStruct->s);
+       }
+}
+#endif
+
+#ifndef NO_SCRIPT_CONTROL
+typedef struct SCRIPT_CONTROL_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID uDefaultLanguage, fContextDigits, fInvertPreBoundDir, fInvertPostBoundDir, fLinkStringBefore, fLinkStringAfter, fNeutralOverride, fNumericOverride, fLegacyBidiClass, fMergeNeutralItems, fUseStandardBidi, fReserved;
+} SCRIPT_CONTROL_FID_CACHE;
+
+SCRIPT_CONTROL_FID_CACHE SCRIPT_CONTROLFc;
+
+void cacheSCRIPT_CONTROLFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_CONTROLFc.cached) return;
+       SCRIPT_CONTROLFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_CONTROLFc.uDefaultLanguage = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "uDefaultLanguage", "I");
+       SCRIPT_CONTROLFc.fContextDigits = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fContextDigits", "Z");
+       SCRIPT_CONTROLFc.fInvertPreBoundDir = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fInvertPreBoundDir", "Z");
+       SCRIPT_CONTROLFc.fInvertPostBoundDir = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fInvertPostBoundDir", "Z");
+       SCRIPT_CONTROLFc.fLinkStringBefore = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fLinkStringBefore", "Z");
+       SCRIPT_CONTROLFc.fLinkStringAfter = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fLinkStringAfter", "Z");
+       SCRIPT_CONTROLFc.fNeutralOverride = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fNeutralOverride", "Z");
+       SCRIPT_CONTROLFc.fNumericOverride = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fNumericOverride", "Z");
+       SCRIPT_CONTROLFc.fLegacyBidiClass = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fLegacyBidiClass", "Z");
+       SCRIPT_CONTROLFc.fMergeNeutralItems = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fMergeNeutralItems", "Z");
+       SCRIPT_CONTROLFc.fUseStandardBidi = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fUseStandardBidi", "Z");
+       SCRIPT_CONTROLFc.fReserved = (*env)->GetFieldID(env, SCRIPT_CONTROLFc.clazz, "fReserved", "I");
+       SCRIPT_CONTROLFc.cached = 1;
+}
+
+SCRIPT_CONTROL *getSCRIPT_CONTROLFields(JNIEnv *env, jobject lpObject, SCRIPT_CONTROL *lpStruct)
+{
+       if (!SCRIPT_CONTROLFc.cached) cacheSCRIPT_CONTROLFields(env, lpObject);
+       lpStruct->uDefaultLanguage = (*env)->GetIntField(env, lpObject, SCRIPT_CONTROLFc.uDefaultLanguage);
+       lpStruct->fContextDigits = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fContextDigits);
+       lpStruct->fInvertPreBoundDir = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fInvertPreBoundDir);
+       lpStruct->fInvertPostBoundDir = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fInvertPostBoundDir);
+       lpStruct->fLinkStringBefore = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fLinkStringBefore);
+       lpStruct->fLinkStringAfter = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fLinkStringAfter);
+       lpStruct->fNeutralOverride = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fNeutralOverride);
+       lpStruct->fNumericOverride = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fNumericOverride);
+       lpStruct->fLegacyBidiClass = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fLegacyBidiClass);
+       lpStruct->fMergeNeutralItems = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fMergeNeutralItems);
+       lpStruct->fUseStandardBidi = (*env)->GetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fUseStandardBidi);
+       lpStruct->fReserved = (*env)->GetIntField(env, lpObject, SCRIPT_CONTROLFc.fReserved);
+       return lpStruct;
+}
+
+void setSCRIPT_CONTROLFields(JNIEnv *env, jobject lpObject, SCRIPT_CONTROL *lpStruct)
+{
+       if (!SCRIPT_CONTROLFc.cached) cacheSCRIPT_CONTROLFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SCRIPT_CONTROLFc.uDefaultLanguage, (jint)lpStruct->uDefaultLanguage);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fContextDigits, (jboolean)lpStruct->fContextDigits);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fInvertPreBoundDir, (jboolean)lpStruct->fInvertPreBoundDir);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fInvertPostBoundDir, (jboolean)lpStruct->fInvertPostBoundDir);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fLinkStringBefore, (jboolean)lpStruct->fLinkStringBefore);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fLinkStringAfter, (jboolean)lpStruct->fLinkStringAfter);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fNeutralOverride, (jboolean)lpStruct->fNeutralOverride);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fNumericOverride, (jboolean)lpStruct->fNumericOverride);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fLegacyBidiClass, (jboolean)lpStruct->fLegacyBidiClass);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fMergeNeutralItems, (jboolean)lpStruct->fMergeNeutralItems);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_CONTROLFc.fUseStandardBidi, (jboolean)lpStruct->fUseStandardBidi);
+       (*env)->SetIntField(env, lpObject, SCRIPT_CONTROLFc.fReserved, (jint)lpStruct->fReserved);
+}
+#endif
+
+#ifndef NO_SCRIPT_DIGITSUBSTITUTE
+typedef struct SCRIPT_DIGITSUBSTITUTE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID NationalDigitLanguage, TraditionalDigitLanguage, DigitSubstitute, dwReserved;
+} SCRIPT_DIGITSUBSTITUTE_FID_CACHE;
+
+SCRIPT_DIGITSUBSTITUTE_FID_CACHE SCRIPT_DIGITSUBSTITUTEFc;
+
+void cacheSCRIPT_DIGITSUBSTITUTEFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_DIGITSUBSTITUTEFc.cached) return;
+       SCRIPT_DIGITSUBSTITUTEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_DIGITSUBSTITUTEFc.NationalDigitLanguage = (*env)->GetFieldID(env, SCRIPT_DIGITSUBSTITUTEFc.clazz, "NationalDigitLanguage", "S");
+       SCRIPT_DIGITSUBSTITUTEFc.TraditionalDigitLanguage = (*env)->GetFieldID(env, SCRIPT_DIGITSUBSTITUTEFc.clazz, "TraditionalDigitLanguage", "S");
+       SCRIPT_DIGITSUBSTITUTEFc.DigitSubstitute = (*env)->GetFieldID(env, SCRIPT_DIGITSUBSTITUTEFc.clazz, "DigitSubstitute", "B");
+       SCRIPT_DIGITSUBSTITUTEFc.dwReserved = (*env)->GetFieldID(env, SCRIPT_DIGITSUBSTITUTEFc.clazz, "dwReserved", "I");
+       SCRIPT_DIGITSUBSTITUTEFc.cached = 1;
+}
+
+SCRIPT_DIGITSUBSTITUTE *getSCRIPT_DIGITSUBSTITUTEFields(JNIEnv *env, jobject lpObject, SCRIPT_DIGITSUBSTITUTE *lpStruct)
+{
+       if (!SCRIPT_DIGITSUBSTITUTEFc.cached) cacheSCRIPT_DIGITSUBSTITUTEFields(env, lpObject);
+       lpStruct->NationalDigitLanguage = (*env)->GetShortField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.NationalDigitLanguage);
+       lpStruct->TraditionalDigitLanguage = (*env)->GetShortField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.TraditionalDigitLanguage);
+       lpStruct->DigitSubstitute = (*env)->GetByteField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.DigitSubstitute);
+       lpStruct->dwReserved = (*env)->GetIntField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.dwReserved);
+       return lpStruct;
+}
+
+void setSCRIPT_DIGITSUBSTITUTEFields(JNIEnv *env, jobject lpObject, SCRIPT_DIGITSUBSTITUTE *lpStruct)
+{
+       if (!SCRIPT_DIGITSUBSTITUTEFc.cached) cacheSCRIPT_DIGITSUBSTITUTEFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.NationalDigitLanguage, (jshort)lpStruct->NationalDigitLanguage);
+       (*env)->SetShortField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.TraditionalDigitLanguage, (jshort)lpStruct->TraditionalDigitLanguage);
+       (*env)->SetByteField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.DigitSubstitute, (jbyte)lpStruct->DigitSubstitute);
+       (*env)->SetIntField(env, lpObject, SCRIPT_DIGITSUBSTITUTEFc.dwReserved, (jint)lpStruct->dwReserved);
+}
+#endif
+
+#ifndef NO_SCRIPT_FONTPROPERTIES
+typedef struct SCRIPT_FONTPROPERTIES_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cBytes, wgBlank, wgDefault, wgInvalid, wgKashida, iKashidaWidth;
+} SCRIPT_FONTPROPERTIES_FID_CACHE;
+
+SCRIPT_FONTPROPERTIES_FID_CACHE SCRIPT_FONTPROPERTIESFc;
+
+void cacheSCRIPT_FONTPROPERTIESFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_FONTPROPERTIESFc.cached) return;
+       SCRIPT_FONTPROPERTIESFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_FONTPROPERTIESFc.cBytes = (*env)->GetFieldID(env, SCRIPT_FONTPROPERTIESFc.clazz, "cBytes", "I");
+       SCRIPT_FONTPROPERTIESFc.wgBlank = (*env)->GetFieldID(env, SCRIPT_FONTPROPERTIESFc.clazz, "wgBlank", "S");
+       SCRIPT_FONTPROPERTIESFc.wgDefault = (*env)->GetFieldID(env, SCRIPT_FONTPROPERTIESFc.clazz, "wgDefault", "S");
+       SCRIPT_FONTPROPERTIESFc.wgInvalid = (*env)->GetFieldID(env, SCRIPT_FONTPROPERTIESFc.clazz, "wgInvalid", "S");
+       SCRIPT_FONTPROPERTIESFc.wgKashida = (*env)->GetFieldID(env, SCRIPT_FONTPROPERTIESFc.clazz, "wgKashida", "S");
+       SCRIPT_FONTPROPERTIESFc.iKashidaWidth = (*env)->GetFieldID(env, SCRIPT_FONTPROPERTIESFc.clazz, "iKashidaWidth", "I");
+       SCRIPT_FONTPROPERTIESFc.cached = 1;
+}
+
+SCRIPT_FONTPROPERTIES *getSCRIPT_FONTPROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_FONTPROPERTIES *lpStruct)
+{
+       if (!SCRIPT_FONTPROPERTIESFc.cached) cacheSCRIPT_FONTPROPERTIESFields(env, lpObject);
+       lpStruct->cBytes = (*env)->GetIntField(env, lpObject, SCRIPT_FONTPROPERTIESFc.cBytes);
+       lpStruct->wgBlank = (*env)->GetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgBlank);
+       lpStruct->wgDefault = (*env)->GetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgDefault);
+       lpStruct->wgInvalid = (*env)->GetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgInvalid);
+       lpStruct->wgKashida = (*env)->GetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgKashida);
+       lpStruct->iKashidaWidth = (*env)->GetIntField(env, lpObject, SCRIPT_FONTPROPERTIESFc.iKashidaWidth);
+       return lpStruct;
+}
+
+void setSCRIPT_FONTPROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_FONTPROPERTIES *lpStruct)
+{
+       if (!SCRIPT_FONTPROPERTIESFc.cached) cacheSCRIPT_FONTPROPERTIESFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SCRIPT_FONTPROPERTIESFc.cBytes, (jint)lpStruct->cBytes);
+       (*env)->SetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgBlank, (jshort)lpStruct->wgBlank);
+       (*env)->SetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgDefault, (jshort)lpStruct->wgDefault);
+       (*env)->SetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgInvalid, (jshort)lpStruct->wgInvalid);
+       (*env)->SetShortField(env, lpObject, SCRIPT_FONTPROPERTIESFc.wgKashida, (jshort)lpStruct->wgKashida);
+       (*env)->SetIntField(env, lpObject, SCRIPT_FONTPROPERTIESFc.iKashidaWidth, (jint)lpStruct->iKashidaWidth);
+}
+#endif
+
+#ifndef NO_SCRIPT_ITEM
+typedef struct SCRIPT_ITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iCharPos, a;
+} SCRIPT_ITEM_FID_CACHE;
+
+SCRIPT_ITEM_FID_CACHE SCRIPT_ITEMFc;
+
+void cacheSCRIPT_ITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_ITEMFc.cached) return;
+       SCRIPT_ITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_ITEMFc.iCharPos = (*env)->GetFieldID(env, SCRIPT_ITEMFc.clazz, "iCharPos", "I");
+       SCRIPT_ITEMFc.a = (*env)->GetFieldID(env, SCRIPT_ITEMFc.clazz, "a", "Lorg/eclipse/swt/internal/win32/SCRIPT_ANALYSIS;");
+       SCRIPT_ITEMFc.cached = 1;
+}
+
+SCRIPT_ITEM *getSCRIPT_ITEMFields(JNIEnv *env, jobject lpObject, SCRIPT_ITEM *lpStruct)
+{
+       if (!SCRIPT_ITEMFc.cached) cacheSCRIPT_ITEMFields(env, lpObject);
+       lpStruct->iCharPos = (*env)->GetIntField(env, lpObject, SCRIPT_ITEMFc.iCharPos);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SCRIPT_ITEMFc.a);
+       if (lpObject1 != NULL) getSCRIPT_ANALYSISFields(env, lpObject1, &lpStruct->a);
+       }
+       return lpStruct;
+}
+
+void setSCRIPT_ITEMFields(JNIEnv *env, jobject lpObject, SCRIPT_ITEM *lpStruct)
+{
+       if (!SCRIPT_ITEMFc.cached) cacheSCRIPT_ITEMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SCRIPT_ITEMFc.iCharPos, (jint)lpStruct->iCharPos);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SCRIPT_ITEMFc.a);
+       if (lpObject1 != NULL) setSCRIPT_ANALYSISFields(env, lpObject1, &lpStruct->a);
+       }
+}
+#endif
+
+#ifndef NO_SCRIPT_LOGATTR
+typedef struct SCRIPT_LOGATTR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID fSoftBreak, fWhiteSpace, fCharStop, fWordStop, fInvalid, fReserved;
+} SCRIPT_LOGATTR_FID_CACHE;
+
+SCRIPT_LOGATTR_FID_CACHE SCRIPT_LOGATTRFc;
+
+void cacheSCRIPT_LOGATTRFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_LOGATTRFc.cached) return;
+       SCRIPT_LOGATTRFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_LOGATTRFc.fSoftBreak = (*env)->GetFieldID(env, SCRIPT_LOGATTRFc.clazz, "fSoftBreak", "Z");
+       SCRIPT_LOGATTRFc.fWhiteSpace = (*env)->GetFieldID(env, SCRIPT_LOGATTRFc.clazz, "fWhiteSpace", "Z");
+       SCRIPT_LOGATTRFc.fCharStop = (*env)->GetFieldID(env, SCRIPT_LOGATTRFc.clazz, "fCharStop", "Z");
+       SCRIPT_LOGATTRFc.fWordStop = (*env)->GetFieldID(env, SCRIPT_LOGATTRFc.clazz, "fWordStop", "Z");
+       SCRIPT_LOGATTRFc.fInvalid = (*env)->GetFieldID(env, SCRIPT_LOGATTRFc.clazz, "fInvalid", "Z");
+       SCRIPT_LOGATTRFc.fReserved = (*env)->GetFieldID(env, SCRIPT_LOGATTRFc.clazz, "fReserved", "B");
+       SCRIPT_LOGATTRFc.cached = 1;
+}
+
+SCRIPT_LOGATTR *getSCRIPT_LOGATTRFields(JNIEnv *env, jobject lpObject, SCRIPT_LOGATTR *lpStruct)
+{
+       if (!SCRIPT_LOGATTRFc.cached) cacheSCRIPT_LOGATTRFields(env, lpObject);
+       lpStruct->fSoftBreak = (*env)->GetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fSoftBreak);
+       lpStruct->fWhiteSpace = (*env)->GetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fWhiteSpace);
+       lpStruct->fCharStop = (*env)->GetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fCharStop);
+       lpStruct->fWordStop = (*env)->GetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fWordStop);
+       lpStruct->fInvalid = (*env)->GetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fInvalid);
+       lpStruct->fReserved = (*env)->GetByteField(env, lpObject, SCRIPT_LOGATTRFc.fReserved);
+       return lpStruct;
+}
+
+void setSCRIPT_LOGATTRFields(JNIEnv *env, jobject lpObject, SCRIPT_LOGATTR *lpStruct)
+{
+       if (!SCRIPT_LOGATTRFc.cached) cacheSCRIPT_LOGATTRFields(env, lpObject);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fSoftBreak, (jboolean)lpStruct->fSoftBreak);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fWhiteSpace, (jboolean)lpStruct->fWhiteSpace);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fCharStop, (jboolean)lpStruct->fCharStop);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fWordStop, (jboolean)lpStruct->fWordStop);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_LOGATTRFc.fInvalid, (jboolean)lpStruct->fInvalid);
+       (*env)->SetByteField(env, lpObject, SCRIPT_LOGATTRFc.fReserved, (jbyte)lpStruct->fReserved);
+}
+#endif
+
+#ifndef NO_SCRIPT_PROPERTIES
+typedef struct SCRIPT_PROPERTIES_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID langid, fNumeric, fComplex, fNeedsWordBreaking, fNeedsCaretInfo, bCharSet, fControl, fPrivateUseArea, fNeedsCharacterJustify, fInvalidGlyph, fInvalidLogAttr, fCDM, fAmbiguousCharSet, fClusterSizeVaries, fRejectInvalid;
+} SCRIPT_PROPERTIES_FID_CACHE;
+
+SCRIPT_PROPERTIES_FID_CACHE SCRIPT_PROPERTIESFc;
+
+void cacheSCRIPT_PROPERTIESFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_PROPERTIESFc.cached) return;
+       SCRIPT_PROPERTIESFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_PROPERTIESFc.langid = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "langid", "S");
+       SCRIPT_PROPERTIESFc.fNumeric = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fNumeric", "Z");
+       SCRIPT_PROPERTIESFc.fComplex = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fComplex", "Z");
+       SCRIPT_PROPERTIESFc.fNeedsWordBreaking = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fNeedsWordBreaking", "Z");
+       SCRIPT_PROPERTIESFc.fNeedsCaretInfo = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fNeedsCaretInfo", "Z");
+       SCRIPT_PROPERTIESFc.bCharSet = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "bCharSet", "B");
+       SCRIPT_PROPERTIESFc.fControl = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fControl", "Z");
+       SCRIPT_PROPERTIESFc.fPrivateUseArea = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fPrivateUseArea", "Z");
+       SCRIPT_PROPERTIESFc.fNeedsCharacterJustify = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fNeedsCharacterJustify", "Z");
+       SCRIPT_PROPERTIESFc.fInvalidGlyph = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fInvalidGlyph", "Z");
+       SCRIPT_PROPERTIESFc.fInvalidLogAttr = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fInvalidLogAttr", "Z");
+       SCRIPT_PROPERTIESFc.fCDM = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fCDM", "Z");
+       SCRIPT_PROPERTIESFc.fAmbiguousCharSet = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fAmbiguousCharSet", "Z");
+       SCRIPT_PROPERTIESFc.fClusterSizeVaries = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fClusterSizeVaries", "Z");
+       SCRIPT_PROPERTIESFc.fRejectInvalid = (*env)->GetFieldID(env, SCRIPT_PROPERTIESFc.clazz, "fRejectInvalid", "Z");
+       SCRIPT_PROPERTIESFc.cached = 1;
+}
+
+SCRIPT_PROPERTIES *getSCRIPT_PROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_PROPERTIES *lpStruct)
+{
+       if (!SCRIPT_PROPERTIESFc.cached) cacheSCRIPT_PROPERTIESFields(env, lpObject);
+       lpStruct->langid = (*env)->GetShortField(env, lpObject, SCRIPT_PROPERTIESFc.langid);
+       lpStruct->fNumeric = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNumeric);
+       lpStruct->fComplex = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fComplex);
+       lpStruct->fNeedsWordBreaking = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNeedsWordBreaking);
+       lpStruct->fNeedsCaretInfo = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNeedsCaretInfo);
+       lpStruct->bCharSet = (*env)->GetByteField(env, lpObject, SCRIPT_PROPERTIESFc.bCharSet);
+       lpStruct->fControl = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fControl);
+       lpStruct->fPrivateUseArea = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fPrivateUseArea);
+       lpStruct->fNeedsCharacterJustify = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNeedsCharacterJustify);
+       lpStruct->fInvalidGlyph = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fInvalidGlyph);
+       lpStruct->fInvalidLogAttr = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fInvalidLogAttr);
+       lpStruct->fCDM = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fCDM);
+       lpStruct->fAmbiguousCharSet = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fAmbiguousCharSet);
+       lpStruct->fClusterSizeVaries = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fClusterSizeVaries);
+       lpStruct->fRejectInvalid = (*env)->GetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fRejectInvalid);
+       return lpStruct;
+}
+
+void setSCRIPT_PROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_PROPERTIES *lpStruct)
+{
+       if (!SCRIPT_PROPERTIESFc.cached) cacheSCRIPT_PROPERTIESFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, SCRIPT_PROPERTIESFc.langid, (jshort)lpStruct->langid);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNumeric, (jboolean)lpStruct->fNumeric);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fComplex, (jboolean)lpStruct->fComplex);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNeedsWordBreaking, (jboolean)lpStruct->fNeedsWordBreaking);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNeedsCaretInfo, (jboolean)lpStruct->fNeedsCaretInfo);
+       (*env)->SetByteField(env, lpObject, SCRIPT_PROPERTIESFc.bCharSet, (jbyte)lpStruct->bCharSet);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fControl, (jboolean)lpStruct->fControl);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fPrivateUseArea, (jboolean)lpStruct->fPrivateUseArea);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fNeedsCharacterJustify, (jboolean)lpStruct->fNeedsCharacterJustify);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fInvalidGlyph, (jboolean)lpStruct->fInvalidGlyph);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fInvalidLogAttr, (jboolean)lpStruct->fInvalidLogAttr);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fCDM, (jboolean)lpStruct->fCDM);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fAmbiguousCharSet, (jboolean)lpStruct->fAmbiguousCharSet);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fClusterSizeVaries, (jboolean)lpStruct->fClusterSizeVaries);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_PROPERTIESFc.fRejectInvalid, (jboolean)lpStruct->fRejectInvalid);
+}
+#endif
+
+#ifndef NO_SCRIPT_STATE
+typedef struct SCRIPT_STATE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID uBidiLevel, fOverrideDirection, fInhibitSymSwap, fCharShape, fDigitSubstitute, fInhibitLigate, fDisplayZWG, fArabicNumContext, fGcpClusters, fReserved, fEngineReserved;
+} SCRIPT_STATE_FID_CACHE;
+
+SCRIPT_STATE_FID_CACHE SCRIPT_STATEFc;
+
+void cacheSCRIPT_STATEFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCRIPT_STATEFc.cached) return;
+       SCRIPT_STATEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCRIPT_STATEFc.uBidiLevel = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "uBidiLevel", "S");
+       SCRIPT_STATEFc.fOverrideDirection = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fOverrideDirection", "Z");
+       SCRIPT_STATEFc.fInhibitSymSwap = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fInhibitSymSwap", "Z");
+       SCRIPT_STATEFc.fCharShape = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fCharShape", "Z");
+       SCRIPT_STATEFc.fDigitSubstitute = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fDigitSubstitute", "Z");
+       SCRIPT_STATEFc.fInhibitLigate = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fInhibitLigate", "Z");
+       SCRIPT_STATEFc.fDisplayZWG = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fDisplayZWG", "Z");
+       SCRIPT_STATEFc.fArabicNumContext = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fArabicNumContext", "Z");
+       SCRIPT_STATEFc.fGcpClusters = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fGcpClusters", "Z");
+       SCRIPT_STATEFc.fReserved = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fReserved", "Z");
+       SCRIPT_STATEFc.fEngineReserved = (*env)->GetFieldID(env, SCRIPT_STATEFc.clazz, "fEngineReserved", "S");
+       SCRIPT_STATEFc.cached = 1;
+}
+
+SCRIPT_STATE *getSCRIPT_STATEFields(JNIEnv *env, jobject lpObject, SCRIPT_STATE *lpStruct)
+{
+       if (!SCRIPT_STATEFc.cached) cacheSCRIPT_STATEFields(env, lpObject);
+       lpStruct->uBidiLevel = (*env)->GetShortField(env, lpObject, SCRIPT_STATEFc.uBidiLevel);
+       lpStruct->fOverrideDirection = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fOverrideDirection);
+       lpStruct->fInhibitSymSwap = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fInhibitSymSwap);
+       lpStruct->fCharShape = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fCharShape);
+       lpStruct->fDigitSubstitute = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fDigitSubstitute);
+       lpStruct->fInhibitLigate = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fInhibitLigate);
+       lpStruct->fDisplayZWG = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fDisplayZWG);
+       lpStruct->fArabicNumContext = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fArabicNumContext);
+       lpStruct->fGcpClusters = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fGcpClusters);
+       lpStruct->fReserved = (*env)->GetBooleanField(env, lpObject, SCRIPT_STATEFc.fReserved);
+       lpStruct->fEngineReserved = (*env)->GetShortField(env, lpObject, SCRIPT_STATEFc.fEngineReserved);
+       return lpStruct;
+}
+
+void setSCRIPT_STATEFields(JNIEnv *env, jobject lpObject, SCRIPT_STATE *lpStruct)
+{
+       if (!SCRIPT_STATEFc.cached) cacheSCRIPT_STATEFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, SCRIPT_STATEFc.uBidiLevel, (jshort)lpStruct->uBidiLevel);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fOverrideDirection, (jboolean)lpStruct->fOverrideDirection);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fInhibitSymSwap, (jboolean)lpStruct->fInhibitSymSwap);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fCharShape, (jboolean)lpStruct->fCharShape);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fDigitSubstitute, (jboolean)lpStruct->fDigitSubstitute);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fInhibitLigate, (jboolean)lpStruct->fInhibitLigate);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fDisplayZWG, (jboolean)lpStruct->fDisplayZWG);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fArabicNumContext, (jboolean)lpStruct->fArabicNumContext);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fGcpClusters, (jboolean)lpStruct->fGcpClusters);
+       (*env)->SetBooleanField(env, lpObject, SCRIPT_STATEFc.fReserved, (jboolean)lpStruct->fReserved);
+       (*env)->SetShortField(env, lpObject, SCRIPT_STATEFc.fEngineReserved, (jshort)lpStruct->fEngineReserved);
+}
+#endif
+
+#ifndef NO_SCROLLBARINFO
+typedef struct SCROLLBARINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, rcScrollBar, dxyLineButton, xyThumbTop, xyThumbBottom, reserved, rgstate;
+} SCROLLBARINFO_FID_CACHE;
+
+SCROLLBARINFO_FID_CACHE SCROLLBARINFOFc;
+
+void cacheSCROLLBARINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCROLLBARINFOFc.cached) return;
+       SCROLLBARINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCROLLBARINFOFc.cbSize = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "cbSize", "I");
+       SCROLLBARINFOFc.rcScrollBar = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "rcScrollBar", "Lorg/eclipse/swt/internal/win32/RECT;");
+       SCROLLBARINFOFc.dxyLineButton = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "dxyLineButton", "I");
+       SCROLLBARINFOFc.xyThumbTop = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "xyThumbTop", "I");
+       SCROLLBARINFOFc.xyThumbBottom = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "xyThumbBottom", "I");
+       SCROLLBARINFOFc.reserved = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "reserved", "I");
+       SCROLLBARINFOFc.rgstate = (*env)->GetFieldID(env, SCROLLBARINFOFc.clazz, "rgstate", "[I");
+       SCROLLBARINFOFc.cached = 1;
+}
+
+SCROLLBARINFO *getSCROLLBARINFOFields(JNIEnv *env, jobject lpObject, SCROLLBARINFO *lpStruct)
+{
+       if (!SCROLLBARINFOFc.cached) cacheSCROLLBARINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, SCROLLBARINFOFc.cbSize);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SCROLLBARINFOFc.rcScrollBar);
+       if (lpObject1 != NULL) getRECTFields(env, lpObject1, &lpStruct->rcScrollBar);
+       }
+       lpStruct->dxyLineButton = (*env)->GetIntField(env, lpObject, SCROLLBARINFOFc.dxyLineButton);
+       lpStruct->xyThumbTop = (*env)->GetIntField(env, lpObject, SCROLLBARINFOFc.xyThumbTop);
+       lpStruct->xyThumbBottom = (*env)->GetIntField(env, lpObject, SCROLLBARINFOFc.xyThumbBottom);
+       lpStruct->reserved = (*env)->GetIntField(env, lpObject, SCROLLBARINFOFc.reserved);
+       {
+       jintArray lpObject1 = (jintArray)(*env)->GetObjectField(env, lpObject, SCROLLBARINFOFc.rgstate);
+       (*env)->GetIntArrayRegion(env, lpObject1, 0, sizeof(lpStruct->rgstate) / sizeof(jint), (jint *)lpStruct->rgstate);
+       }
+       return lpStruct;
+}
+
+void setSCROLLBARINFOFields(JNIEnv *env, jobject lpObject, SCROLLBARINFO *lpStruct)
+{
+       if (!SCROLLBARINFOFc.cached) cacheSCROLLBARINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SCROLLBARINFOFc.cbSize, (jint)lpStruct->cbSize);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SCROLLBARINFOFc.rcScrollBar);
+       if (lpObject1 != NULL) setRECTFields(env, lpObject1, &lpStruct->rcScrollBar);
+       }
+       (*env)->SetIntField(env, lpObject, SCROLLBARINFOFc.dxyLineButton, (jint)lpStruct->dxyLineButton);
+       (*env)->SetIntField(env, lpObject, SCROLLBARINFOFc.xyThumbTop, (jint)lpStruct->xyThumbTop);
+       (*env)->SetIntField(env, lpObject, SCROLLBARINFOFc.xyThumbBottom, (jint)lpStruct->xyThumbBottom);
+       (*env)->SetIntField(env, lpObject, SCROLLBARINFOFc.reserved, (jint)lpStruct->reserved);
+       {
+       jintArray lpObject1 = (jintArray)(*env)->GetObjectField(env, lpObject, SCROLLBARINFOFc.rgstate);
+       (*env)->SetIntArrayRegion(env, lpObject1, 0, sizeof(lpStruct->rgstate) / sizeof(jint), (jint *)lpStruct->rgstate);
+       }
+}
+#endif
+
+#ifndef NO_SCROLLINFO
+typedef struct SCROLLINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, fMask, nMin, nMax, nPage, nPos, nTrackPos;
+} SCROLLINFO_FID_CACHE;
+
+SCROLLINFO_FID_CACHE SCROLLINFOFc;
+
+void cacheSCROLLINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (SCROLLINFOFc.cached) return;
+       SCROLLINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SCROLLINFOFc.cbSize = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "cbSize", "I");
+       SCROLLINFOFc.fMask = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "fMask", "I");
+       SCROLLINFOFc.nMin = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "nMin", "I");
+       SCROLLINFOFc.nMax = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "nMax", "I");
+       SCROLLINFOFc.nPage = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "nPage", "I");
+       SCROLLINFOFc.nPos = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "nPos", "I");
+       SCROLLINFOFc.nTrackPos = (*env)->GetFieldID(env, SCROLLINFOFc.clazz, "nTrackPos", "I");
+       SCROLLINFOFc.cached = 1;
+}
+
+SCROLLINFO *getSCROLLINFOFields(JNIEnv *env, jobject lpObject, SCROLLINFO *lpStruct)
+{
+       if (!SCROLLINFOFc.cached) cacheSCROLLINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.cbSize);
+       lpStruct->fMask = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.fMask);
+       lpStruct->nMin = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.nMin);
+       lpStruct->nMax = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.nMax);
+       lpStruct->nPage = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.nPage);
+       lpStruct->nPos = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.nPos);
+       lpStruct->nTrackPos = (*env)->GetIntField(env, lpObject, SCROLLINFOFc.nTrackPos);
+       return lpStruct;
+}
+
+void setSCROLLINFOFields(JNIEnv *env, jobject lpObject, SCROLLINFO *lpStruct)
+{
+       if (!SCROLLINFOFc.cached) cacheSCROLLINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.fMask, (jint)lpStruct->fMask);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.nMin, (jint)lpStruct->nMin);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.nMax, (jint)lpStruct->nMax);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.nPage, (jint)lpStruct->nPage);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.nPos, (jint)lpStruct->nPos);
+       (*env)->SetIntField(env, lpObject, SCROLLINFOFc.nTrackPos, (jint)lpStruct->nTrackPos);
+}
+#endif
+
+#ifndef NO_SHDRAGIMAGE
+typedef struct SHDRAGIMAGE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID sizeDragImage, ptOffset, hbmpDragImage, crColorKey;
+} SHDRAGIMAGE_FID_CACHE;
+
+SHDRAGIMAGE_FID_CACHE SHDRAGIMAGEFc;
+
+void cacheSHDRAGIMAGEFields(JNIEnv *env, jobject lpObject)
+{
+       if (SHDRAGIMAGEFc.cached) return;
+       SHDRAGIMAGEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SHDRAGIMAGEFc.sizeDragImage = (*env)->GetFieldID(env, SHDRAGIMAGEFc.clazz, "sizeDragImage", "Lorg/eclipse/swt/internal/win32/SIZE;");
+       SHDRAGIMAGEFc.ptOffset = (*env)->GetFieldID(env, SHDRAGIMAGEFc.clazz, "ptOffset", "Lorg/eclipse/swt/internal/win32/POINT;");
+       SHDRAGIMAGEFc.hbmpDragImage = (*env)->GetFieldID(env, SHDRAGIMAGEFc.clazz, "hbmpDragImage", "J");
+       SHDRAGIMAGEFc.crColorKey = (*env)->GetFieldID(env, SHDRAGIMAGEFc.clazz, "crColorKey", "I");
+       SHDRAGIMAGEFc.cached = 1;
+}
+
+SHDRAGIMAGE *getSHDRAGIMAGEFields(JNIEnv *env, jobject lpObject, SHDRAGIMAGE *lpStruct)
+{
+       if (!SHDRAGIMAGEFc.cached) cacheSHDRAGIMAGEFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SHDRAGIMAGEFc.sizeDragImage);
+       if (lpObject1 != NULL) getSIZEFields(env, lpObject1, &lpStruct->sizeDragImage);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SHDRAGIMAGEFc.ptOffset);
+       if (lpObject1 != NULL) getPOINTFields(env, lpObject1, &lpStruct->ptOffset);
+       }
+       lpStruct->hbmpDragImage = (HBITMAP)(*env)->GetLongField(env, lpObject, SHDRAGIMAGEFc.hbmpDragImage);
+       lpStruct->crColorKey = (*env)->GetIntField(env, lpObject, SHDRAGIMAGEFc.crColorKey);
+       return lpStruct;
+}
+
+void setSHDRAGIMAGEFields(JNIEnv *env, jobject lpObject, SHDRAGIMAGE *lpStruct)
+{
+       if (!SHDRAGIMAGEFc.cached) cacheSHDRAGIMAGEFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SHDRAGIMAGEFc.sizeDragImage);
+       if (lpObject1 != NULL) setSIZEFields(env, lpObject1, &lpStruct->sizeDragImage);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, SHDRAGIMAGEFc.ptOffset);
+       if (lpObject1 != NULL) setPOINTFields(env, lpObject1, &lpStruct->ptOffset);
+       }
+       (*env)->SetLongField(env, lpObject, SHDRAGIMAGEFc.hbmpDragImage, (jlong)lpStruct->hbmpDragImage);
+       (*env)->SetIntField(env, lpObject, SHDRAGIMAGEFc.crColorKey, (jint)lpStruct->crColorKey);
+}
+#endif
+
+#ifndef NO_SHELLEXECUTEINFO
+typedef struct SHELLEXECUTEINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, fMask, hwnd, lpVerb, lpFile, lpParameters, lpDirectory, nShow, hInstApp, lpIDList, lpClass, hkeyClass, dwHotKey, hIcon, hProcess;
+} SHELLEXECUTEINFO_FID_CACHE;
+
+SHELLEXECUTEINFO_FID_CACHE SHELLEXECUTEINFOFc;
+
+void cacheSHELLEXECUTEINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (SHELLEXECUTEINFOFc.cached) return;
+       SHELLEXECUTEINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SHELLEXECUTEINFOFc.cbSize = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "cbSize", "I");
+       SHELLEXECUTEINFOFc.fMask = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "fMask", "I");
+       SHELLEXECUTEINFOFc.hwnd = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "hwnd", "J");
+       SHELLEXECUTEINFOFc.lpVerb = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "lpVerb", "J");
+       SHELLEXECUTEINFOFc.lpFile = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "lpFile", "J");
+       SHELLEXECUTEINFOFc.lpParameters = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "lpParameters", "J");
+       SHELLEXECUTEINFOFc.lpDirectory = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "lpDirectory", "J");
+       SHELLEXECUTEINFOFc.nShow = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "nShow", "I");
+       SHELLEXECUTEINFOFc.hInstApp = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "hInstApp", "J");
+       SHELLEXECUTEINFOFc.lpIDList = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "lpIDList", "J");
+       SHELLEXECUTEINFOFc.lpClass = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "lpClass", "J");
+       SHELLEXECUTEINFOFc.hkeyClass = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "hkeyClass", "J");
+       SHELLEXECUTEINFOFc.dwHotKey = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "dwHotKey", "I");
+       SHELLEXECUTEINFOFc.hIcon = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "hIcon", "J");
+       SHELLEXECUTEINFOFc.hProcess = (*env)->GetFieldID(env, SHELLEXECUTEINFOFc.clazz, "hProcess", "J");
+       SHELLEXECUTEINFOFc.cached = 1;
+}
+
+SHELLEXECUTEINFO *getSHELLEXECUTEINFOFields(JNIEnv *env, jobject lpObject, SHELLEXECUTEINFO *lpStruct)
+{
+       if (!SHELLEXECUTEINFOFc.cached) cacheSHELLEXECUTEINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, SHELLEXECUTEINFOFc.cbSize);
+       lpStruct->fMask = (*env)->GetIntField(env, lpObject, SHELLEXECUTEINFOFc.fMask);
+       lpStruct->hwnd = (HWND)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.hwnd);
+       lpStruct->lpVerb = (LPCTSTR)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpVerb);
+       lpStruct->lpFile = (LPCTSTR)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpFile);
+       lpStruct->lpParameters = (LPCTSTR)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpParameters);
+       lpStruct->lpDirectory = (LPCTSTR)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpDirectory);
+       lpStruct->nShow = (*env)->GetIntField(env, lpObject, SHELLEXECUTEINFOFc.nShow);
+       lpStruct->hInstApp = (HINSTANCE)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.hInstApp);
+       lpStruct->lpIDList = (LPVOID)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpIDList);
+       lpStruct->lpClass = (LPCTSTR)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpClass);
+       lpStruct->hkeyClass = (HKEY)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.hkeyClass);
+       lpStruct->dwHotKey = (*env)->GetIntField(env, lpObject, SHELLEXECUTEINFOFc.dwHotKey);
+       lpStruct->hIcon = (HANDLE)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.hIcon);
+       lpStruct->hProcess = (HANDLE)(*env)->GetLongField(env, lpObject, SHELLEXECUTEINFOFc.hProcess);
+       return lpStruct;
+}
+
+void setSHELLEXECUTEINFOFields(JNIEnv *env, jobject lpObject, SHELLEXECUTEINFO *lpStruct)
+{
+       if (!SHELLEXECUTEINFOFc.cached) cacheSHELLEXECUTEINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SHELLEXECUTEINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, SHELLEXECUTEINFOFc.fMask, (jint)lpStruct->fMask);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.hwnd, (jlong)lpStruct->hwnd);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpVerb, (jlong)lpStruct->lpVerb);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpFile, (jlong)lpStruct->lpFile);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpParameters, (jlong)lpStruct->lpParameters);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpDirectory, (jlong)lpStruct->lpDirectory);
+       (*env)->SetIntField(env, lpObject, SHELLEXECUTEINFOFc.nShow, (jint)lpStruct->nShow);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.hInstApp, (jlong)lpStruct->hInstApp);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpIDList, (jlong)lpStruct->lpIDList);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.lpClass, (jlong)lpStruct->lpClass);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.hkeyClass, (jlong)lpStruct->hkeyClass);
+       (*env)->SetIntField(env, lpObject, SHELLEXECUTEINFOFc.dwHotKey, (jint)lpStruct->dwHotKey);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.hIcon, (jlong)lpStruct->hIcon);
+       (*env)->SetLongField(env, lpObject, SHELLEXECUTEINFOFc.hProcess, (jlong)lpStruct->hProcess);
+}
+#endif
+
+#ifndef NO_SHFILEINFO
+typedef struct SHFILEINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hIcon, iIcon, dwAttributes, szDisplayName, szTypeName;
+} SHFILEINFO_FID_CACHE;
+
+SHFILEINFO_FID_CACHE SHFILEINFOFc;
+
+void cacheSHFILEINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (SHFILEINFOFc.cached) return;
+       SHFILEINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SHFILEINFOFc.hIcon = (*env)->GetFieldID(env, SHFILEINFOFc.clazz, "hIcon", "J");
+       SHFILEINFOFc.iIcon = (*env)->GetFieldID(env, SHFILEINFOFc.clazz, "iIcon", "I");
+       SHFILEINFOFc.dwAttributes = (*env)->GetFieldID(env, SHFILEINFOFc.clazz, "dwAttributes", "I");
+       SHFILEINFOFc.szDisplayName = (*env)->GetFieldID(env, SHFILEINFOFc.clazz, "szDisplayName", "[C");
+       SHFILEINFOFc.szTypeName = (*env)->GetFieldID(env, SHFILEINFOFc.clazz, "szTypeName", "[C");
+       SHFILEINFOFc.cached = 1;
+}
+
+SHFILEINFO *getSHFILEINFOFields(JNIEnv *env, jobject lpObject, SHFILEINFO *lpStruct)
+{
+       if (!SHFILEINFOFc.cached) cacheSHFILEINFOFields(env, lpObject);
+       lpStruct->hIcon = (HICON)(*env)->GetLongField(env, lpObject, SHFILEINFOFc.hIcon);
+       lpStruct->iIcon = (*env)->GetIntField(env, lpObject, SHFILEINFOFc.iIcon);
+       lpStruct->dwAttributes = (*env)->GetIntField(env, lpObject, SHFILEINFOFc.dwAttributes);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, SHFILEINFOFc.szDisplayName);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szDisplayName) / sizeof(jchar), (jchar *)lpStruct->szDisplayName);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, SHFILEINFOFc.szTypeName);
+       (*env)->GetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szTypeName) / sizeof(jchar), (jchar *)lpStruct->szTypeName);
+       }
+       return lpStruct;
+}
+
+void setSHFILEINFOFields(JNIEnv *env, jobject lpObject, SHFILEINFO *lpStruct)
+{
+       if (!SHFILEINFOFc.cached) cacheSHFILEINFOFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, SHFILEINFOFc.hIcon, (jlong)lpStruct->hIcon);
+       (*env)->SetIntField(env, lpObject, SHFILEINFOFc.iIcon, (jint)lpStruct->iIcon);
+       (*env)->SetIntField(env, lpObject, SHFILEINFOFc.dwAttributes, (jint)lpStruct->dwAttributes);
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, SHFILEINFOFc.szDisplayName);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szDisplayName) / sizeof(jchar), (jchar *)lpStruct->szDisplayName);
+       }
+       {
+       jcharArray lpObject1 = (jcharArray)(*env)->GetObjectField(env, lpObject, SHFILEINFOFc.szTypeName);
+       (*env)->SetCharArrayRegion(env, lpObject1, 0, sizeof(lpStruct->szTypeName) / sizeof(jchar), (jchar *)lpStruct->szTypeName);
+       }
+}
+#endif
+
+#ifndef NO_SIZE
+typedef struct SIZE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cx, cy;
+} SIZE_FID_CACHE;
+
+SIZE_FID_CACHE SIZEFc;
+
+void cacheSIZEFields(JNIEnv *env, jobject lpObject)
+{
+       if (SIZEFc.cached) return;
+       SIZEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SIZEFc.cx = (*env)->GetFieldID(env, SIZEFc.clazz, "cx", "I");
+       SIZEFc.cy = (*env)->GetFieldID(env, SIZEFc.clazz, "cy", "I");
+       SIZEFc.cached = 1;
+}
+
+SIZE *getSIZEFields(JNIEnv *env, jobject lpObject, SIZE *lpStruct)
+{
+       if (!SIZEFc.cached) cacheSIZEFields(env, lpObject);
+       lpStruct->cx = (*env)->GetIntField(env, lpObject, SIZEFc.cx);
+       lpStruct->cy = (*env)->GetIntField(env, lpObject, SIZEFc.cy);
+       return lpStruct;
+}
+
+void setSIZEFields(JNIEnv *env, jobject lpObject, SIZE *lpStruct)
+{
+       if (!SIZEFc.cached) cacheSIZEFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, SIZEFc.cx, (jint)lpStruct->cx);
+       (*env)->SetIntField(env, lpObject, SIZEFc.cy, (jint)lpStruct->cy);
+}
+#endif
+
+#ifndef NO_STARTUPINFO
+typedef struct STARTUPINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cb, lpReserved, lpDesktop, lpTitle, dwX, dwY, dwXSize, dwYSize, dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags, wShowWindow, cbReserved2, lpReserved2, hStdInput, hStdOutput, hStdError;
+} STARTUPINFO_FID_CACHE;
+
+STARTUPINFO_FID_CACHE STARTUPINFOFc;
+
+void cacheSTARTUPINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (STARTUPINFOFc.cached) return;
+       STARTUPINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       STARTUPINFOFc.cb = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "cb", "I");
+       STARTUPINFOFc.lpReserved = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "lpReserved", "J");
+       STARTUPINFOFc.lpDesktop = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "lpDesktop", "J");
+       STARTUPINFOFc.lpTitle = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "lpTitle", "J");
+       STARTUPINFOFc.dwX = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwX", "I");
+       STARTUPINFOFc.dwY = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwY", "I");
+       STARTUPINFOFc.dwXSize = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwXSize", "I");
+       STARTUPINFOFc.dwYSize = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwYSize", "I");
+       STARTUPINFOFc.dwXCountChars = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwXCountChars", "I");
+       STARTUPINFOFc.dwYCountChars = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwYCountChars", "I");
+       STARTUPINFOFc.dwFillAttribute = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwFillAttribute", "I");
+       STARTUPINFOFc.dwFlags = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "dwFlags", "I");
+       STARTUPINFOFc.wShowWindow = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "wShowWindow", "S");
+       STARTUPINFOFc.cbReserved2 = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "cbReserved2", "S");
+       STARTUPINFOFc.lpReserved2 = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "lpReserved2", "J");
+       STARTUPINFOFc.hStdInput = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "hStdInput", "J");
+       STARTUPINFOFc.hStdOutput = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "hStdOutput", "J");
+       STARTUPINFOFc.hStdError = (*env)->GetFieldID(env, STARTUPINFOFc.clazz, "hStdError", "J");
+       STARTUPINFOFc.cached = 1;
+}
+
+STARTUPINFO *getSTARTUPINFOFields(JNIEnv *env, jobject lpObject, STARTUPINFO *lpStruct)
+{
+       if (!STARTUPINFOFc.cached) cacheSTARTUPINFOFields(env, lpObject);
+       lpStruct->cb = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.cb);
+       lpStruct->lpReserved = (LPTSTR)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.lpReserved);
+       lpStruct->lpDesktop = (LPTSTR)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.lpDesktop);
+       lpStruct->lpTitle = (LPTSTR)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.lpTitle);
+       lpStruct->dwX = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwX);
+       lpStruct->dwY = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwY);
+       lpStruct->dwXSize = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwXSize);
+       lpStruct->dwYSize = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwYSize);
+       lpStruct->dwXCountChars = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwXCountChars);
+       lpStruct->dwYCountChars = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwYCountChars);
+       lpStruct->dwFillAttribute = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwFillAttribute);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, STARTUPINFOFc.dwFlags);
+       lpStruct->wShowWindow = (*env)->GetShortField(env, lpObject, STARTUPINFOFc.wShowWindow);
+       lpStruct->cbReserved2 = (*env)->GetShortField(env, lpObject, STARTUPINFOFc.cbReserved2);
+       lpStruct->lpReserved2 = (LPBYTE)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.lpReserved2);
+       lpStruct->hStdInput = (HANDLE)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.hStdInput);
+       lpStruct->hStdOutput = (HANDLE)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.hStdOutput);
+       lpStruct->hStdError = (HANDLE)(*env)->GetLongField(env, lpObject, STARTUPINFOFc.hStdError);
+       return lpStruct;
+}
+
+void setSTARTUPINFOFields(JNIEnv *env, jobject lpObject, STARTUPINFO *lpStruct)
+{
+       if (!STARTUPINFOFc.cached) cacheSTARTUPINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.cb, (jint)lpStruct->cb);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.lpReserved, (jlong)lpStruct->lpReserved);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.lpDesktop, (jlong)lpStruct->lpDesktop);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.lpTitle, (jlong)lpStruct->lpTitle);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwX, (jint)lpStruct->dwX);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwY, (jint)lpStruct->dwY);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwXSize, (jint)lpStruct->dwXSize);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwYSize, (jint)lpStruct->dwYSize);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwXCountChars, (jint)lpStruct->dwXCountChars);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwYCountChars, (jint)lpStruct->dwYCountChars);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwFillAttribute, (jint)lpStruct->dwFillAttribute);
+       (*env)->SetIntField(env, lpObject, STARTUPINFOFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetShortField(env, lpObject, STARTUPINFOFc.wShowWindow, (jshort)lpStruct->wShowWindow);
+       (*env)->SetShortField(env, lpObject, STARTUPINFOFc.cbReserved2, (jshort)lpStruct->cbReserved2);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.lpReserved2, (jlong)lpStruct->lpReserved2);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.hStdInput, (jlong)lpStruct->hStdInput);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.hStdOutput, (jlong)lpStruct->hStdOutput);
+       (*env)->SetLongField(env, lpObject, STARTUPINFOFc.hStdError, (jlong)lpStruct->hStdError);
+}
+#endif
+
+#ifndef NO_SYSTEMTIME
+typedef struct SYSTEMTIME_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID wYear, wMonth, wDayOfWeek, wDay, wHour, wMinute, wSecond, wMilliseconds;
+} SYSTEMTIME_FID_CACHE;
+
+SYSTEMTIME_FID_CACHE SYSTEMTIMEFc;
+
+void cacheSYSTEMTIMEFields(JNIEnv *env, jobject lpObject)
+{
+       if (SYSTEMTIMEFc.cached) return;
+       SYSTEMTIMEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       SYSTEMTIMEFc.wYear = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wYear", "S");
+       SYSTEMTIMEFc.wMonth = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wMonth", "S");
+       SYSTEMTIMEFc.wDayOfWeek = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wDayOfWeek", "S");
+       SYSTEMTIMEFc.wDay = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wDay", "S");
+       SYSTEMTIMEFc.wHour = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wHour", "S");
+       SYSTEMTIMEFc.wMinute = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wMinute", "S");
+       SYSTEMTIMEFc.wSecond = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wSecond", "S");
+       SYSTEMTIMEFc.wMilliseconds = (*env)->GetFieldID(env, SYSTEMTIMEFc.clazz, "wMilliseconds", "S");
+       SYSTEMTIMEFc.cached = 1;
+}
+
+SYSTEMTIME *getSYSTEMTIMEFields(JNIEnv *env, jobject lpObject, SYSTEMTIME *lpStruct)
+{
+       if (!SYSTEMTIMEFc.cached) cacheSYSTEMTIMEFields(env, lpObject);
+       lpStruct->wYear = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wYear);
+       lpStruct->wMonth = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wMonth);
+       lpStruct->wDayOfWeek = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wDayOfWeek);
+       lpStruct->wDay = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wDay);
+       lpStruct->wHour = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wHour);
+       lpStruct->wMinute = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wMinute);
+       lpStruct->wSecond = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wSecond);
+       lpStruct->wMilliseconds = (*env)->GetShortField(env, lpObject, SYSTEMTIMEFc.wMilliseconds);
+       return lpStruct;
+}
+
+void setSYSTEMTIMEFields(JNIEnv *env, jobject lpObject, SYSTEMTIME *lpStruct)
+{
+       if (!SYSTEMTIMEFc.cached) cacheSYSTEMTIMEFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wYear, (jshort)lpStruct->wYear);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wMonth, (jshort)lpStruct->wMonth);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wDayOfWeek, (jshort)lpStruct->wDayOfWeek);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wDay, (jshort)lpStruct->wDay);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wHour, (jshort)lpStruct->wHour);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wMinute, (jshort)lpStruct->wMinute);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wSecond, (jshort)lpStruct->wSecond);
+       (*env)->SetShortField(env, lpObject, SYSTEMTIMEFc.wMilliseconds, (jshort)lpStruct->wMilliseconds);
+}
+#endif
+
+#ifndef NO_TBBUTTON
+typedef struct TBBUTTON_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iBitmap, idCommand, fsState, fsStyle, dwData, iString;
+} TBBUTTON_FID_CACHE;
+
+TBBUTTON_FID_CACHE TBBUTTONFc;
+
+void cacheTBBUTTONFields(JNIEnv *env, jobject lpObject)
+{
+       if (TBBUTTONFc.cached) return;
+       TBBUTTONFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TBBUTTONFc.iBitmap = (*env)->GetFieldID(env, TBBUTTONFc.clazz, "iBitmap", "I");
+       TBBUTTONFc.idCommand = (*env)->GetFieldID(env, TBBUTTONFc.clazz, "idCommand", "I");
+       TBBUTTONFc.fsState = (*env)->GetFieldID(env, TBBUTTONFc.clazz, "fsState", "B");
+       TBBUTTONFc.fsStyle = (*env)->GetFieldID(env, TBBUTTONFc.clazz, "fsStyle", "B");
+       TBBUTTONFc.dwData = (*env)->GetFieldID(env, TBBUTTONFc.clazz, "dwData", "J");
+       TBBUTTONFc.iString = (*env)->GetFieldID(env, TBBUTTONFc.clazz, "iString", "J");
+       TBBUTTONFc.cached = 1;
+}
+
+TBBUTTON *getTBBUTTONFields(JNIEnv *env, jobject lpObject, TBBUTTON *lpStruct)
+{
+       if (!TBBUTTONFc.cached) cacheTBBUTTONFields(env, lpObject);
+       lpStruct->iBitmap = (*env)->GetIntField(env, lpObject, TBBUTTONFc.iBitmap);
+       lpStruct->idCommand = (*env)->GetIntField(env, lpObject, TBBUTTONFc.idCommand);
+       lpStruct->fsState = (*env)->GetByteField(env, lpObject, TBBUTTONFc.fsState);
+       lpStruct->fsStyle = (*env)->GetByteField(env, lpObject, TBBUTTONFc.fsStyle);
+       lpStruct->dwData = (*env)->GetLongField(env, lpObject, TBBUTTONFc.dwData);
+       lpStruct->iString = (*env)->GetLongField(env, lpObject, TBBUTTONFc.iString);
+       return lpStruct;
+}
+
+void setTBBUTTONFields(JNIEnv *env, jobject lpObject, TBBUTTON *lpStruct)
+{
+       if (!TBBUTTONFc.cached) cacheTBBUTTONFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TBBUTTONFc.iBitmap, (jint)lpStruct->iBitmap);
+       (*env)->SetIntField(env, lpObject, TBBUTTONFc.idCommand, (jint)lpStruct->idCommand);
+       (*env)->SetByteField(env, lpObject, TBBUTTONFc.fsState, (jbyte)lpStruct->fsState);
+       (*env)->SetByteField(env, lpObject, TBBUTTONFc.fsStyle, (jbyte)lpStruct->fsStyle);
+       (*env)->SetLongField(env, lpObject, TBBUTTONFc.dwData, (jlong)lpStruct->dwData);
+       (*env)->SetLongField(env, lpObject, TBBUTTONFc.iString, (jlong)lpStruct->iString);
+}
+#endif
+
+#ifndef NO_TBBUTTONINFO
+typedef struct TBBUTTONINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwMask, idCommand, iImage, fsState, fsStyle, cx, lParam, pszText, cchText;
+} TBBUTTONINFO_FID_CACHE;
+
+TBBUTTONINFO_FID_CACHE TBBUTTONINFOFc;
+
+void cacheTBBUTTONINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (TBBUTTONINFOFc.cached) return;
+       TBBUTTONINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TBBUTTONINFOFc.cbSize = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "cbSize", "I");
+       TBBUTTONINFOFc.dwMask = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "dwMask", "I");
+       TBBUTTONINFOFc.idCommand = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "idCommand", "I");
+       TBBUTTONINFOFc.iImage = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "iImage", "I");
+       TBBUTTONINFOFc.fsState = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "fsState", "B");
+       TBBUTTONINFOFc.fsStyle = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "fsStyle", "B");
+       TBBUTTONINFOFc.cx = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "cx", "S");
+       TBBUTTONINFOFc.lParam = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "lParam", "J");
+       TBBUTTONINFOFc.pszText = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "pszText", "J");
+       TBBUTTONINFOFc.cchText = (*env)->GetFieldID(env, TBBUTTONINFOFc.clazz, "cchText", "I");
+       TBBUTTONINFOFc.cached = 1;
+}
+
+TBBUTTONINFO *getTBBUTTONINFOFields(JNIEnv *env, jobject lpObject, TBBUTTONINFO *lpStruct)
+{
+       if (!TBBUTTONINFOFc.cached) cacheTBBUTTONINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, TBBUTTONINFOFc.cbSize);
+       lpStruct->dwMask = (*env)->GetIntField(env, lpObject, TBBUTTONINFOFc.dwMask);
+       lpStruct->idCommand = (*env)->GetIntField(env, lpObject, TBBUTTONINFOFc.idCommand);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, TBBUTTONINFOFc.iImage);
+       lpStruct->fsState = (*env)->GetByteField(env, lpObject, TBBUTTONINFOFc.fsState);
+       lpStruct->fsStyle = (*env)->GetByteField(env, lpObject, TBBUTTONINFOFc.fsStyle);
+       lpStruct->cx = (*env)->GetShortField(env, lpObject, TBBUTTONINFOFc.cx);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, TBBUTTONINFOFc.lParam);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, TBBUTTONINFOFc.pszText);
+       lpStruct->cchText = (*env)->GetIntField(env, lpObject, TBBUTTONINFOFc.cchText);
+       return lpStruct;
+}
+
+void setTBBUTTONINFOFields(JNIEnv *env, jobject lpObject, TBBUTTONINFO *lpStruct)
+{
+       if (!TBBUTTONINFOFc.cached) cacheTBBUTTONINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TBBUTTONINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, TBBUTTONINFOFc.dwMask, (jint)lpStruct->dwMask);
+       (*env)->SetIntField(env, lpObject, TBBUTTONINFOFc.idCommand, (jint)lpStruct->idCommand);
+       (*env)->SetIntField(env, lpObject, TBBUTTONINFOFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetByteField(env, lpObject, TBBUTTONINFOFc.fsState, (jbyte)lpStruct->fsState);
+       (*env)->SetByteField(env, lpObject, TBBUTTONINFOFc.fsStyle, (jbyte)lpStruct->fsStyle);
+       (*env)->SetShortField(env, lpObject, TBBUTTONINFOFc.cx, (jshort)lpStruct->cx);
+       (*env)->SetLongField(env, lpObject, TBBUTTONINFOFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetLongField(env, lpObject, TBBUTTONINFOFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetIntField(env, lpObject, TBBUTTONINFOFc.cchText, (jint)lpStruct->cchText);
+}
+#endif
+
+#ifndef NO_TCHITTESTINFO
+typedef struct TCHITTESTINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y, flags;
+} TCHITTESTINFO_FID_CACHE;
+
+TCHITTESTINFO_FID_CACHE TCHITTESTINFOFc;
+
+void cacheTCHITTESTINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (TCHITTESTINFOFc.cached) return;
+       TCHITTESTINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TCHITTESTINFOFc.x = (*env)->GetFieldID(env, TCHITTESTINFOFc.clazz, "x", "I");
+       TCHITTESTINFOFc.y = (*env)->GetFieldID(env, TCHITTESTINFOFc.clazz, "y", "I");
+       TCHITTESTINFOFc.flags = (*env)->GetFieldID(env, TCHITTESTINFOFc.clazz, "flags", "I");
+       TCHITTESTINFOFc.cached = 1;
+}
+
+TCHITTESTINFO *getTCHITTESTINFOFields(JNIEnv *env, jobject lpObject, TCHITTESTINFO *lpStruct)
+{
+       if (!TCHITTESTINFOFc.cached) cacheTCHITTESTINFOFields(env, lpObject);
+       lpStruct->pt.x = (*env)->GetIntField(env, lpObject, TCHITTESTINFOFc.x);
+       lpStruct->pt.y = (*env)->GetIntField(env, lpObject, TCHITTESTINFOFc.y);
+       lpStruct->flags = (*env)->GetIntField(env, lpObject, TCHITTESTINFOFc.flags);
+       return lpStruct;
+}
+
+void setTCHITTESTINFOFields(JNIEnv *env, jobject lpObject, TCHITTESTINFO *lpStruct)
+{
+       if (!TCHITTESTINFOFc.cached) cacheTCHITTESTINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TCHITTESTINFOFc.x, (jint)lpStruct->pt.x);
+       (*env)->SetIntField(env, lpObject, TCHITTESTINFOFc.y, (jint)lpStruct->pt.y);
+       (*env)->SetIntField(env, lpObject, TCHITTESTINFOFc.flags, (jint)lpStruct->flags);
+}
+#endif
+
+#ifndef NO_TCITEM
+typedef struct TCITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, dwState, dwStateMask, pszText, cchTextMax, iImage, lParam;
+} TCITEM_FID_CACHE;
+
+TCITEM_FID_CACHE TCITEMFc;
+
+void cacheTCITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (TCITEMFc.cached) return;
+       TCITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TCITEMFc.mask = (*env)->GetFieldID(env, TCITEMFc.clazz, "mask", "I");
+       TCITEMFc.dwState = (*env)->GetFieldID(env, TCITEMFc.clazz, "dwState", "I");
+       TCITEMFc.dwStateMask = (*env)->GetFieldID(env, TCITEMFc.clazz, "dwStateMask", "I");
+       TCITEMFc.pszText = (*env)->GetFieldID(env, TCITEMFc.clazz, "pszText", "J");
+       TCITEMFc.cchTextMax = (*env)->GetFieldID(env, TCITEMFc.clazz, "cchTextMax", "I");
+       TCITEMFc.iImage = (*env)->GetFieldID(env, TCITEMFc.clazz, "iImage", "I");
+       TCITEMFc.lParam = (*env)->GetFieldID(env, TCITEMFc.clazz, "lParam", "J");
+       TCITEMFc.cached = 1;
+}
+
+TCITEM *getTCITEMFields(JNIEnv *env, jobject lpObject, TCITEM *lpStruct)
+{
+       if (!TCITEMFc.cached) cacheTCITEMFields(env, lpObject);
+       lpStruct->mask = (*env)->GetIntField(env, lpObject, TCITEMFc.mask);
+       lpStruct->dwState = (*env)->GetIntField(env, lpObject, TCITEMFc.dwState);
+       lpStruct->dwStateMask = (*env)->GetIntField(env, lpObject, TCITEMFc.dwStateMask);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, TCITEMFc.pszText);
+       lpStruct->cchTextMax = (*env)->GetIntField(env, lpObject, TCITEMFc.cchTextMax);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, TCITEMFc.iImage);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, TCITEMFc.lParam);
+       return lpStruct;
+}
+
+void setTCITEMFields(JNIEnv *env, jobject lpObject, TCITEM *lpStruct)
+{
+       if (!TCITEMFc.cached) cacheTCITEMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TCITEMFc.mask, (jint)lpStruct->mask);
+       (*env)->SetIntField(env, lpObject, TCITEMFc.dwState, (jint)lpStruct->dwState);
+       (*env)->SetIntField(env, lpObject, TCITEMFc.dwStateMask, (jint)lpStruct->dwStateMask);
+       (*env)->SetLongField(env, lpObject, TCITEMFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetIntField(env, lpObject, TCITEMFc.cchTextMax, (jint)lpStruct->cchTextMax);
+       (*env)->SetIntField(env, lpObject, TCITEMFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetLongField(env, lpObject, TCITEMFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_TEXTMETRIC
+typedef struct TEXTMETRIC_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID tmHeight, tmAscent, tmDescent, tmInternalLeading, tmExternalLeading, tmAveCharWidth, tmMaxCharWidth, tmWeight, tmOverhang, tmDigitizedAspectX, tmDigitizedAspectY, tmFirstChar, tmLastChar, tmDefaultChar, tmBreakChar, tmItalic, tmUnderlined, tmStruckOut, tmPitchAndFamily, tmCharSet;
+} TEXTMETRIC_FID_CACHE;
+
+TEXTMETRIC_FID_CACHE TEXTMETRICFc;
+
+void cacheTEXTMETRICFields(JNIEnv *env, jobject lpObject)
+{
+       if (TEXTMETRICFc.cached) return;
+       TEXTMETRICFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TEXTMETRICFc.tmHeight = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmHeight", "I");
+       TEXTMETRICFc.tmAscent = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmAscent", "I");
+       TEXTMETRICFc.tmDescent = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmDescent", "I");
+       TEXTMETRICFc.tmInternalLeading = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmInternalLeading", "I");
+       TEXTMETRICFc.tmExternalLeading = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmExternalLeading", "I");
+       TEXTMETRICFc.tmAveCharWidth = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmAveCharWidth", "I");
+       TEXTMETRICFc.tmMaxCharWidth = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmMaxCharWidth", "I");
+       TEXTMETRICFc.tmWeight = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmWeight", "I");
+       TEXTMETRICFc.tmOverhang = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmOverhang", "I");
+       TEXTMETRICFc.tmDigitizedAspectX = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmDigitizedAspectX", "I");
+       TEXTMETRICFc.tmDigitizedAspectY = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmDigitizedAspectY", "I");
+       TEXTMETRICFc.tmFirstChar = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmFirstChar", "C");
+       TEXTMETRICFc.tmLastChar = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmLastChar", "C");
+       TEXTMETRICFc.tmDefaultChar = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmDefaultChar", "C");
+       TEXTMETRICFc.tmBreakChar = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmBreakChar", "C");
+       TEXTMETRICFc.tmItalic = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmItalic", "B");
+       TEXTMETRICFc.tmUnderlined = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmUnderlined", "B");
+       TEXTMETRICFc.tmStruckOut = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmStruckOut", "B");
+       TEXTMETRICFc.tmPitchAndFamily = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmPitchAndFamily", "B");
+       TEXTMETRICFc.tmCharSet = (*env)->GetFieldID(env, TEXTMETRICFc.clazz, "tmCharSet", "B");
+       TEXTMETRICFc.cached = 1;
+}
+
+TEXTMETRIC *getTEXTMETRICFields(JNIEnv *env, jobject lpObject, TEXTMETRIC *lpStruct)
+{
+       if (!TEXTMETRICFc.cached) cacheTEXTMETRICFields(env, lpObject);
+       lpStruct->tmHeight = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmHeight);
+       lpStruct->tmAscent = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmAscent);
+       lpStruct->tmDescent = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmDescent);
+       lpStruct->tmInternalLeading = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmInternalLeading);
+       lpStruct->tmExternalLeading = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmExternalLeading);
+       lpStruct->tmAveCharWidth = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmAveCharWidth);
+       lpStruct->tmMaxCharWidth = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmMaxCharWidth);
+       lpStruct->tmWeight = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmWeight);
+       lpStruct->tmOverhang = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmOverhang);
+       lpStruct->tmDigitizedAspectX = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmDigitizedAspectX);
+       lpStruct->tmDigitizedAspectY = (*env)->GetIntField(env, lpObject, TEXTMETRICFc.tmDigitizedAspectY);
+       lpStruct->tmFirstChar = (*env)->GetCharField(env, lpObject, TEXTMETRICFc.tmFirstChar);
+       lpStruct->tmLastChar = (*env)->GetCharField(env, lpObject, TEXTMETRICFc.tmLastChar);
+       lpStruct->tmDefaultChar = (*env)->GetCharField(env, lpObject, TEXTMETRICFc.tmDefaultChar);
+       lpStruct->tmBreakChar = (*env)->GetCharField(env, lpObject, TEXTMETRICFc.tmBreakChar);
+       lpStruct->tmItalic = (*env)->GetByteField(env, lpObject, TEXTMETRICFc.tmItalic);
+       lpStruct->tmUnderlined = (*env)->GetByteField(env, lpObject, TEXTMETRICFc.tmUnderlined);
+       lpStruct->tmStruckOut = (*env)->GetByteField(env, lpObject, TEXTMETRICFc.tmStruckOut);
+       lpStruct->tmPitchAndFamily = (*env)->GetByteField(env, lpObject, TEXTMETRICFc.tmPitchAndFamily);
+       lpStruct->tmCharSet = (*env)->GetByteField(env, lpObject, TEXTMETRICFc.tmCharSet);
+       return lpStruct;
+}
+
+void setTEXTMETRICFields(JNIEnv *env, jobject lpObject, TEXTMETRIC *lpStruct)
+{
+       if (!TEXTMETRICFc.cached) cacheTEXTMETRICFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmHeight, (jint)lpStruct->tmHeight);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmAscent, (jint)lpStruct->tmAscent);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmDescent, (jint)lpStruct->tmDescent);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmInternalLeading, (jint)lpStruct->tmInternalLeading);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmExternalLeading, (jint)lpStruct->tmExternalLeading);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmAveCharWidth, (jint)lpStruct->tmAveCharWidth);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmMaxCharWidth, (jint)lpStruct->tmMaxCharWidth);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmWeight, (jint)lpStruct->tmWeight);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmOverhang, (jint)lpStruct->tmOverhang);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmDigitizedAspectX, (jint)lpStruct->tmDigitizedAspectX);
+       (*env)->SetIntField(env, lpObject, TEXTMETRICFc.tmDigitizedAspectY, (jint)lpStruct->tmDigitizedAspectY);
+       (*env)->SetCharField(env, lpObject, TEXTMETRICFc.tmFirstChar, (jchar)lpStruct->tmFirstChar);
+       (*env)->SetCharField(env, lpObject, TEXTMETRICFc.tmLastChar, (jchar)lpStruct->tmLastChar);
+       (*env)->SetCharField(env, lpObject, TEXTMETRICFc.tmDefaultChar, (jchar)lpStruct->tmDefaultChar);
+       (*env)->SetCharField(env, lpObject, TEXTMETRICFc.tmBreakChar, (jchar)lpStruct->tmBreakChar);
+       (*env)->SetByteField(env, lpObject, TEXTMETRICFc.tmItalic, (jbyte)lpStruct->tmItalic);
+       (*env)->SetByteField(env, lpObject, TEXTMETRICFc.tmUnderlined, (jbyte)lpStruct->tmUnderlined);
+       (*env)->SetByteField(env, lpObject, TEXTMETRICFc.tmStruckOut, (jbyte)lpStruct->tmStruckOut);
+       (*env)->SetByteField(env, lpObject, TEXTMETRICFc.tmPitchAndFamily, (jbyte)lpStruct->tmPitchAndFamily);
+       (*env)->SetByteField(env, lpObject, TEXTMETRICFc.tmCharSet, (jbyte)lpStruct->tmCharSet);
+}
+#endif
+
+#ifndef NO_TF_DA_COLOR
+typedef struct TF_DA_COLOR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID type, cr;
+} TF_DA_COLOR_FID_CACHE;
+
+TF_DA_COLOR_FID_CACHE TF_DA_COLORFc;
+
+void cacheTF_DA_COLORFields(JNIEnv *env, jobject lpObject)
+{
+       if (TF_DA_COLORFc.cached) return;
+       TF_DA_COLORFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TF_DA_COLORFc.type = (*env)->GetFieldID(env, TF_DA_COLORFc.clazz, "type", "I");
+       TF_DA_COLORFc.cr = (*env)->GetFieldID(env, TF_DA_COLORFc.clazz, "cr", "I");
+       TF_DA_COLORFc.cached = 1;
+}
+
+TF_DA_COLOR *getTF_DA_COLORFields(JNIEnv *env, jobject lpObject, TF_DA_COLOR *lpStruct)
+{
+       if (!TF_DA_COLORFc.cached) cacheTF_DA_COLORFields(env, lpObject);
+       lpStruct->type = (*env)->GetIntField(env, lpObject, TF_DA_COLORFc.type);
+       lpStruct->cr = (*env)->GetIntField(env, lpObject, TF_DA_COLORFc.cr);
+       return lpStruct;
+}
+
+void setTF_DA_COLORFields(JNIEnv *env, jobject lpObject, TF_DA_COLOR *lpStruct)
+{
+       if (!TF_DA_COLORFc.cached) cacheTF_DA_COLORFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TF_DA_COLORFc.type, (jint)lpStruct->type);
+       (*env)->SetIntField(env, lpObject, TF_DA_COLORFc.cr, (jint)lpStruct->cr);
+}
+#endif
+
+#ifndef NO_TF_DISPLAYATTRIBUTE
+typedef struct TF_DISPLAYATTRIBUTE_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID crText, crBk, lsStyle, fBoldLine, crLine, bAttr;
+} TF_DISPLAYATTRIBUTE_FID_CACHE;
+
+TF_DISPLAYATTRIBUTE_FID_CACHE TF_DISPLAYATTRIBUTEFc;
+
+void cacheTF_DISPLAYATTRIBUTEFields(JNIEnv *env, jobject lpObject)
+{
+       if (TF_DISPLAYATTRIBUTEFc.cached) return;
+       TF_DISPLAYATTRIBUTEFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TF_DISPLAYATTRIBUTEFc.crText = (*env)->GetFieldID(env, TF_DISPLAYATTRIBUTEFc.clazz, "crText", "Lorg/eclipse/swt/internal/win32/TF_DA_COLOR;");
+       TF_DISPLAYATTRIBUTEFc.crBk = (*env)->GetFieldID(env, TF_DISPLAYATTRIBUTEFc.clazz, "crBk", "Lorg/eclipse/swt/internal/win32/TF_DA_COLOR;");
+       TF_DISPLAYATTRIBUTEFc.lsStyle = (*env)->GetFieldID(env, TF_DISPLAYATTRIBUTEFc.clazz, "lsStyle", "I");
+       TF_DISPLAYATTRIBUTEFc.fBoldLine = (*env)->GetFieldID(env, TF_DISPLAYATTRIBUTEFc.clazz, "fBoldLine", "Z");
+       TF_DISPLAYATTRIBUTEFc.crLine = (*env)->GetFieldID(env, TF_DISPLAYATTRIBUTEFc.clazz, "crLine", "Lorg/eclipse/swt/internal/win32/TF_DA_COLOR;");
+       TF_DISPLAYATTRIBUTEFc.bAttr = (*env)->GetFieldID(env, TF_DISPLAYATTRIBUTEFc.clazz, "bAttr", "I");
+       TF_DISPLAYATTRIBUTEFc.cached = 1;
+}
+
+TF_DISPLAYATTRIBUTE *getTF_DISPLAYATTRIBUTEFields(JNIEnv *env, jobject lpObject, TF_DISPLAYATTRIBUTE *lpStruct)
+{
+       if (!TF_DISPLAYATTRIBUTEFc.cached) cacheTF_DISPLAYATTRIBUTEFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, TF_DISPLAYATTRIBUTEFc.crText);
+       if (lpObject1 != NULL) getTF_DA_COLORFields(env, lpObject1, &lpStruct->crText);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, TF_DISPLAYATTRIBUTEFc.crBk);
+       if (lpObject1 != NULL) getTF_DA_COLORFields(env, lpObject1, &lpStruct->crBk);
+       }
+       lpStruct->lsStyle = (*env)->GetIntField(env, lpObject, TF_DISPLAYATTRIBUTEFc.lsStyle);
+       lpStruct->fBoldLine = (*env)->GetBooleanField(env, lpObject, TF_DISPLAYATTRIBUTEFc.fBoldLine);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, TF_DISPLAYATTRIBUTEFc.crLine);
+       if (lpObject1 != NULL) getTF_DA_COLORFields(env, lpObject1, &lpStruct->crLine);
+       }
+       lpStruct->bAttr = (*env)->GetIntField(env, lpObject, TF_DISPLAYATTRIBUTEFc.bAttr);
+       return lpStruct;
+}
+
+void setTF_DISPLAYATTRIBUTEFields(JNIEnv *env, jobject lpObject, TF_DISPLAYATTRIBUTE *lpStruct)
+{
+       if (!TF_DISPLAYATTRIBUTEFc.cached) cacheTF_DISPLAYATTRIBUTEFields(env, lpObject);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, TF_DISPLAYATTRIBUTEFc.crText);
+       if (lpObject1 != NULL) setTF_DA_COLORFields(env, lpObject1, &lpStruct->crText);
+       }
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, TF_DISPLAYATTRIBUTEFc.crBk);
+       if (lpObject1 != NULL) setTF_DA_COLORFields(env, lpObject1, &lpStruct->crBk);
+       }
+       (*env)->SetIntField(env, lpObject, TF_DISPLAYATTRIBUTEFc.lsStyle, (jint)lpStruct->lsStyle);
+       (*env)->SetBooleanField(env, lpObject, TF_DISPLAYATTRIBUTEFc.fBoldLine, (jboolean)lpStruct->fBoldLine);
+       {
+       jobject lpObject1 = (*env)->GetObjectField(env, lpObject, TF_DISPLAYATTRIBUTEFc.crLine);
+       if (lpObject1 != NULL) setTF_DA_COLORFields(env, lpObject1, &lpStruct->crLine);
+       }
+       (*env)->SetIntField(env, lpObject, TF_DISPLAYATTRIBUTEFc.bAttr, (jint)lpStruct->bAttr);
+}
+#endif
+
+#ifndef NO_TOOLINFO
+typedef struct TOOLINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, uFlags, hwnd, uId, left, top, right, bottom, hinst, lpszText, lParam, lpReserved;
+} TOOLINFO_FID_CACHE;
+
+TOOLINFO_FID_CACHE TOOLINFOFc;
+
+void cacheTOOLINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (TOOLINFOFc.cached) return;
+       TOOLINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TOOLINFOFc.cbSize = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "cbSize", "I");
+       TOOLINFOFc.uFlags = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "uFlags", "I");
+       TOOLINFOFc.hwnd = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "hwnd", "J");
+       TOOLINFOFc.uId = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "uId", "J");
+       TOOLINFOFc.left = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "left", "I");
+       TOOLINFOFc.top = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "top", "I");
+       TOOLINFOFc.right = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "right", "I");
+       TOOLINFOFc.bottom = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "bottom", "I");
+       TOOLINFOFc.hinst = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "hinst", "J");
+       TOOLINFOFc.lpszText = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "lpszText", "J");
+       TOOLINFOFc.lParam = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "lParam", "J");
+       TOOLINFOFc.lpReserved = (*env)->GetFieldID(env, TOOLINFOFc.clazz, "lpReserved", "J");
+       TOOLINFOFc.cached = 1;
+}
+
+TOOLINFO *getTOOLINFOFields(JNIEnv *env, jobject lpObject, TOOLINFO *lpStruct)
+{
+       if (!TOOLINFOFc.cached) cacheTOOLINFOFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, TOOLINFOFc.cbSize);
+       lpStruct->uFlags = (*env)->GetIntField(env, lpObject, TOOLINFOFc.uFlags);
+       lpStruct->hwnd = (HWND)(*env)->GetLongField(env, lpObject, TOOLINFOFc.hwnd);
+       lpStruct->uId = (*env)->GetLongField(env, lpObject, TOOLINFOFc.uId);
+       lpStruct->rect.left = (*env)->GetIntField(env, lpObject, TOOLINFOFc.left);
+       lpStruct->rect.top = (*env)->GetIntField(env, lpObject, TOOLINFOFc.top);
+       lpStruct->rect.right = (*env)->GetIntField(env, lpObject, TOOLINFOFc.right);
+       lpStruct->rect.bottom = (*env)->GetIntField(env, lpObject, TOOLINFOFc.bottom);
+       lpStruct->hinst = (HINSTANCE)(*env)->GetLongField(env, lpObject, TOOLINFOFc.hinst);
+       lpStruct->lpszText = (LPTSTR)(*env)->GetLongField(env, lpObject, TOOLINFOFc.lpszText);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, TOOLINFOFc.lParam);
+       lpStruct->lpReserved = (void *)(*env)->GetLongField(env, lpObject, TOOLINFOFc.lpReserved);
+       return lpStruct;
+}
+
+void setTOOLINFOFields(JNIEnv *env, jobject lpObject, TOOLINFO *lpStruct)
+{
+       if (!TOOLINFOFc.cached) cacheTOOLINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TOOLINFOFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, TOOLINFOFc.uFlags, (jint)lpStruct->uFlags);
+       (*env)->SetLongField(env, lpObject, TOOLINFOFc.hwnd, (jlong)lpStruct->hwnd);
+       (*env)->SetLongField(env, lpObject, TOOLINFOFc.uId, (jlong)lpStruct->uId);
+       (*env)->SetIntField(env, lpObject, TOOLINFOFc.left, (jint)lpStruct->rect.left);
+       (*env)->SetIntField(env, lpObject, TOOLINFOFc.top, (jint)lpStruct->rect.top);
+       (*env)->SetIntField(env, lpObject, TOOLINFOFc.right, (jint)lpStruct->rect.right);
+       (*env)->SetIntField(env, lpObject, TOOLINFOFc.bottom, (jint)lpStruct->rect.bottom);
+       (*env)->SetLongField(env, lpObject, TOOLINFOFc.hinst, (jlong)lpStruct->hinst);
+       (*env)->SetLongField(env, lpObject, TOOLINFOFc.lpszText, (jlong)lpStruct->lpszText);
+       (*env)->SetLongField(env, lpObject, TOOLINFOFc.lParam, (jlong)lpStruct->lParam);
+       (*env)->SetLongField(env, lpObject, TOOLINFOFc.lpReserved, (jlong)lpStruct->lpReserved);
+}
+#endif
+
+#ifndef NO_TOUCHINPUT
+typedef struct TOUCHINPUT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y, hSource, dwID, dwFlags, dwMask, dwTime, dwExtraInfo, cxContact, cyContact;
+} TOUCHINPUT_FID_CACHE;
+
+TOUCHINPUT_FID_CACHE TOUCHINPUTFc;
+
+void cacheTOUCHINPUTFields(JNIEnv *env, jobject lpObject)
+{
+       if (TOUCHINPUTFc.cached) return;
+       TOUCHINPUTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TOUCHINPUTFc.x = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "x", "I");
+       TOUCHINPUTFc.y = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "y", "I");
+       TOUCHINPUTFc.hSource = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "hSource", "J");
+       TOUCHINPUTFc.dwID = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "dwID", "I");
+       TOUCHINPUTFc.dwFlags = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "dwFlags", "I");
+       TOUCHINPUTFc.dwMask = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "dwMask", "I");
+       TOUCHINPUTFc.dwTime = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "dwTime", "I");
+       TOUCHINPUTFc.dwExtraInfo = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "dwExtraInfo", "J");
+       TOUCHINPUTFc.cxContact = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "cxContact", "I");
+       TOUCHINPUTFc.cyContact = (*env)->GetFieldID(env, TOUCHINPUTFc.clazz, "cyContact", "I");
+       TOUCHINPUTFc.cached = 1;
+}
+
+TOUCHINPUT *getTOUCHINPUTFields(JNIEnv *env, jobject lpObject, TOUCHINPUT *lpStruct)
+{
+       if (!TOUCHINPUTFc.cached) cacheTOUCHINPUTFields(env, lpObject);
+       lpStruct->x = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.x);
+       lpStruct->y = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.y);
+       lpStruct->hSource = (HWND)(*env)->GetLongField(env, lpObject, TOUCHINPUTFc.hSource);
+       lpStruct->dwID = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.dwID);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.dwFlags);
+       lpStruct->dwMask = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.dwMask);
+       lpStruct->dwTime = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.dwTime);
+       lpStruct->dwExtraInfo = (*env)->GetLongField(env, lpObject, TOUCHINPUTFc.dwExtraInfo);
+       lpStruct->cxContact = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.cxContact);
+       lpStruct->cyContact = (*env)->GetIntField(env, lpObject, TOUCHINPUTFc.cyContact);
+       return lpStruct;
+}
+
+void setTOUCHINPUTFields(JNIEnv *env, jobject lpObject, TOUCHINPUT *lpStruct)
+{
+       if (!TOUCHINPUTFc.cached) cacheTOUCHINPUTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.x, (jint)lpStruct->x);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.y, (jint)lpStruct->y);
+       (*env)->SetLongField(env, lpObject, TOUCHINPUTFc.hSource, (jlong)lpStruct->hSource);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.dwID, (jint)lpStruct->dwID);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.dwMask, (jint)lpStruct->dwMask);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.dwTime, (jint)lpStruct->dwTime);
+       (*env)->SetLongField(env, lpObject, TOUCHINPUTFc.dwExtraInfo, (jlong)lpStruct->dwExtraInfo);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.cxContact, (jint)lpStruct->cxContact);
+       (*env)->SetIntField(env, lpObject, TOUCHINPUTFc.cyContact, (jint)lpStruct->cyContact);
+}
+#endif
+
+#ifndef NO_TRACKMOUSEEVENT
+typedef struct TRACKMOUSEEVENT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID cbSize, dwFlags, hwndTrack, dwHoverTime;
+} TRACKMOUSEEVENT_FID_CACHE;
+
+TRACKMOUSEEVENT_FID_CACHE TRACKMOUSEEVENTFc;
+
+void cacheTRACKMOUSEEVENTFields(JNIEnv *env, jobject lpObject)
+{
+       if (TRACKMOUSEEVENTFc.cached) return;
+       TRACKMOUSEEVENTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TRACKMOUSEEVENTFc.cbSize = (*env)->GetFieldID(env, TRACKMOUSEEVENTFc.clazz, "cbSize", "I");
+       TRACKMOUSEEVENTFc.dwFlags = (*env)->GetFieldID(env, TRACKMOUSEEVENTFc.clazz, "dwFlags", "I");
+       TRACKMOUSEEVENTFc.hwndTrack = (*env)->GetFieldID(env, TRACKMOUSEEVENTFc.clazz, "hwndTrack", "J");
+       TRACKMOUSEEVENTFc.dwHoverTime = (*env)->GetFieldID(env, TRACKMOUSEEVENTFc.clazz, "dwHoverTime", "I");
+       TRACKMOUSEEVENTFc.cached = 1;
+}
+
+TRACKMOUSEEVENT *getTRACKMOUSEEVENTFields(JNIEnv *env, jobject lpObject, TRACKMOUSEEVENT *lpStruct)
+{
+       if (!TRACKMOUSEEVENTFc.cached) cacheTRACKMOUSEEVENTFields(env, lpObject);
+       lpStruct->cbSize = (*env)->GetIntField(env, lpObject, TRACKMOUSEEVENTFc.cbSize);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, TRACKMOUSEEVENTFc.dwFlags);
+       lpStruct->hwndTrack = (HWND)(*env)->GetLongField(env, lpObject, TRACKMOUSEEVENTFc.hwndTrack);
+       lpStruct->dwHoverTime = (*env)->GetIntField(env, lpObject, TRACKMOUSEEVENTFc.dwHoverTime);
+       return lpStruct;
+}
+
+void setTRACKMOUSEEVENTFields(JNIEnv *env, jobject lpObject, TRACKMOUSEEVENT *lpStruct)
+{
+       if (!TRACKMOUSEEVENTFc.cached) cacheTRACKMOUSEEVENTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TRACKMOUSEEVENTFc.cbSize, (jint)lpStruct->cbSize);
+       (*env)->SetIntField(env, lpObject, TRACKMOUSEEVENTFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetLongField(env, lpObject, TRACKMOUSEEVENTFc.hwndTrack, (jlong)lpStruct->hwndTrack);
+       (*env)->SetIntField(env, lpObject, TRACKMOUSEEVENTFc.dwHoverTime, (jint)lpStruct->dwHoverTime);
+}
+#endif
+
+#ifndef NO_TRIVERTEX
+typedef struct TRIVERTEX_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y, Red, Green, Blue, Alpha;
+} TRIVERTEX_FID_CACHE;
+
+TRIVERTEX_FID_CACHE TRIVERTEXFc;
+
+void cacheTRIVERTEXFields(JNIEnv *env, jobject lpObject)
+{
+       if (TRIVERTEXFc.cached) return;
+       TRIVERTEXFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TRIVERTEXFc.x = (*env)->GetFieldID(env, TRIVERTEXFc.clazz, "x", "I");
+       TRIVERTEXFc.y = (*env)->GetFieldID(env, TRIVERTEXFc.clazz, "y", "I");
+       TRIVERTEXFc.Red = (*env)->GetFieldID(env, TRIVERTEXFc.clazz, "Red", "S");
+       TRIVERTEXFc.Green = (*env)->GetFieldID(env, TRIVERTEXFc.clazz, "Green", "S");
+       TRIVERTEXFc.Blue = (*env)->GetFieldID(env, TRIVERTEXFc.clazz, "Blue", "S");
+       TRIVERTEXFc.Alpha = (*env)->GetFieldID(env, TRIVERTEXFc.clazz, "Alpha", "S");
+       TRIVERTEXFc.cached = 1;
+}
+
+TRIVERTEX *getTRIVERTEXFields(JNIEnv *env, jobject lpObject, TRIVERTEX *lpStruct)
+{
+       if (!TRIVERTEXFc.cached) cacheTRIVERTEXFields(env, lpObject);
+       lpStruct->x = (*env)->GetIntField(env, lpObject, TRIVERTEXFc.x);
+       lpStruct->y = (*env)->GetIntField(env, lpObject, TRIVERTEXFc.y);
+       lpStruct->Red = (*env)->GetShortField(env, lpObject, TRIVERTEXFc.Red);
+       lpStruct->Green = (*env)->GetShortField(env, lpObject, TRIVERTEXFc.Green);
+       lpStruct->Blue = (*env)->GetShortField(env, lpObject, TRIVERTEXFc.Blue);
+       lpStruct->Alpha = (*env)->GetShortField(env, lpObject, TRIVERTEXFc.Alpha);
+       return lpStruct;
+}
+
+void setTRIVERTEXFields(JNIEnv *env, jobject lpObject, TRIVERTEX *lpStruct)
+{
+       if (!TRIVERTEXFc.cached) cacheTRIVERTEXFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TRIVERTEXFc.x, (jint)lpStruct->x);
+       (*env)->SetIntField(env, lpObject, TRIVERTEXFc.y, (jint)lpStruct->y);
+       (*env)->SetShortField(env, lpObject, TRIVERTEXFc.Red, (jshort)lpStruct->Red);
+       (*env)->SetShortField(env, lpObject, TRIVERTEXFc.Green, (jshort)lpStruct->Green);
+       (*env)->SetShortField(env, lpObject, TRIVERTEXFc.Blue, (jshort)lpStruct->Blue);
+       (*env)->SetShortField(env, lpObject, TRIVERTEXFc.Alpha, (jshort)lpStruct->Alpha);
+}
+#endif
+
+#ifndef NO_TVHITTESTINFO
+typedef struct TVHITTESTINFO_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID x, y, flags, hItem;
+} TVHITTESTINFO_FID_CACHE;
+
+TVHITTESTINFO_FID_CACHE TVHITTESTINFOFc;
+
+void cacheTVHITTESTINFOFields(JNIEnv *env, jobject lpObject)
+{
+       if (TVHITTESTINFOFc.cached) return;
+       TVHITTESTINFOFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TVHITTESTINFOFc.x = (*env)->GetFieldID(env, TVHITTESTINFOFc.clazz, "x", "I");
+       TVHITTESTINFOFc.y = (*env)->GetFieldID(env, TVHITTESTINFOFc.clazz, "y", "I");
+       TVHITTESTINFOFc.flags = (*env)->GetFieldID(env, TVHITTESTINFOFc.clazz, "flags", "I");
+       TVHITTESTINFOFc.hItem = (*env)->GetFieldID(env, TVHITTESTINFOFc.clazz, "hItem", "J");
+       TVHITTESTINFOFc.cached = 1;
+}
+
+TVHITTESTINFO *getTVHITTESTINFOFields(JNIEnv *env, jobject lpObject, TVHITTESTINFO *lpStruct)
+{
+       if (!TVHITTESTINFOFc.cached) cacheTVHITTESTINFOFields(env, lpObject);
+       lpStruct->pt.x = (*env)->GetIntField(env, lpObject, TVHITTESTINFOFc.x);
+       lpStruct->pt.y = (*env)->GetIntField(env, lpObject, TVHITTESTINFOFc.y);
+       lpStruct->flags = (*env)->GetIntField(env, lpObject, TVHITTESTINFOFc.flags);
+       lpStruct->hItem = (HTREEITEM)(*env)->GetLongField(env, lpObject, TVHITTESTINFOFc.hItem);
+       return lpStruct;
+}
+
+void setTVHITTESTINFOFields(JNIEnv *env, jobject lpObject, TVHITTESTINFO *lpStruct)
+{
+       if (!TVHITTESTINFOFc.cached) cacheTVHITTESTINFOFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TVHITTESTINFOFc.x, (jint)lpStruct->pt.x);
+       (*env)->SetIntField(env, lpObject, TVHITTESTINFOFc.y, (jint)lpStruct->pt.y);
+       (*env)->SetIntField(env, lpObject, TVHITTESTINFOFc.flags, (jint)lpStruct->flags);
+       (*env)->SetLongField(env, lpObject, TVHITTESTINFOFc.hItem, (jlong)lpStruct->hItem);
+}
+#endif
+
+#ifndef NO_TVINSERTSTRUCT
+typedef struct TVINSERTSTRUCT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hParent, hInsertAfter, mask, hItem, state, stateMask, pszText, cchTextMax, iImage, iSelectedImage, cChildren, lParam, iIntegral;
+} TVINSERTSTRUCT_FID_CACHE;
+
+TVINSERTSTRUCT_FID_CACHE TVINSERTSTRUCTFc;
+
+void cacheTVINSERTSTRUCTFields(JNIEnv *env, jobject lpObject)
+{
+       if (TVINSERTSTRUCTFc.cached) return;
+       TVINSERTSTRUCTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TVINSERTSTRUCTFc.hParent = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "hParent", "J");
+       TVINSERTSTRUCTFc.hInsertAfter = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "hInsertAfter", "J");
+       TVINSERTSTRUCTFc.mask = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "mask", "I");
+       TVINSERTSTRUCTFc.hItem = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "hItem", "J");
+       TVINSERTSTRUCTFc.state = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "state", "I");
+       TVINSERTSTRUCTFc.stateMask = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "stateMask", "I");
+       TVINSERTSTRUCTFc.pszText = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "pszText", "J");
+       TVINSERTSTRUCTFc.cchTextMax = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "cchTextMax", "I");
+       TVINSERTSTRUCTFc.iImage = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "iImage", "I");
+       TVINSERTSTRUCTFc.iSelectedImage = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "iSelectedImage", "I");
+       TVINSERTSTRUCTFc.cChildren = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "cChildren", "I");
+       TVINSERTSTRUCTFc.lParam = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "lParam", "J");
+       TVINSERTSTRUCTFc.iIntegral = (*env)->GetFieldID(env, TVINSERTSTRUCTFc.clazz, "iIntegral", "I");
+       TVINSERTSTRUCTFc.cached = 1;
+}
+
+TVINSERTSTRUCT *getTVINSERTSTRUCTFields(JNIEnv *env, jobject lpObject, TVINSERTSTRUCT *lpStruct)
+{
+       if (!TVINSERTSTRUCTFc.cached) cacheTVINSERTSTRUCTFields(env, lpObject);
+       lpStruct->hParent = (HTREEITEM)(*env)->GetLongField(env, lpObject, TVINSERTSTRUCTFc.hParent);
+       lpStruct->hInsertAfter = (HTREEITEM)(*env)->GetLongField(env, lpObject, TVINSERTSTRUCTFc.hInsertAfter);
+       lpStruct->item.mask = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.mask);
+       lpStruct->item.hItem = (HTREEITEM)(*env)->GetLongField(env, lpObject, TVINSERTSTRUCTFc.hItem);
+       lpStruct->item.state = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.state);
+       lpStruct->item.stateMask = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.stateMask);
+       lpStruct->item.pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, TVINSERTSTRUCTFc.pszText);
+       lpStruct->item.cchTextMax = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.cchTextMax);
+       lpStruct->item.iImage = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.iImage);
+       lpStruct->item.iSelectedImage = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.iSelectedImage);
+       lpStruct->item.cChildren = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.cChildren);
+       lpStruct->item.lParam = (*env)->GetLongField(env, lpObject, TVINSERTSTRUCTFc.lParam);
+       lpStruct->itemex.iIntegral = (*env)->GetIntField(env, lpObject, TVINSERTSTRUCTFc.iIntegral);
+       return lpStruct;
+}
+
+void setTVINSERTSTRUCTFields(JNIEnv *env, jobject lpObject, TVINSERTSTRUCT *lpStruct)
+{
+       if (!TVINSERTSTRUCTFc.cached) cacheTVINSERTSTRUCTFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, TVINSERTSTRUCTFc.hParent, (jlong)lpStruct->hParent);
+       (*env)->SetLongField(env, lpObject, TVINSERTSTRUCTFc.hInsertAfter, (jlong)lpStruct->hInsertAfter);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.mask, (jint)lpStruct->item.mask);
+       (*env)->SetLongField(env, lpObject, TVINSERTSTRUCTFc.hItem, (jlong)lpStruct->item.hItem);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.state, (jint)lpStruct->item.state);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.stateMask, (jint)lpStruct->item.stateMask);
+       (*env)->SetLongField(env, lpObject, TVINSERTSTRUCTFc.pszText, (jlong)lpStruct->item.pszText);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.cchTextMax, (jint)lpStruct->item.cchTextMax);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.iImage, (jint)lpStruct->item.iImage);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.iSelectedImage, (jint)lpStruct->item.iSelectedImage);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.cChildren, (jint)lpStruct->item.cChildren);
+       (*env)->SetLongField(env, lpObject, TVINSERTSTRUCTFc.lParam, (jlong)lpStruct->item.lParam);
+       (*env)->SetIntField(env, lpObject, TVINSERTSTRUCTFc.iIntegral, (jint)lpStruct->itemex.iIntegral);
+}
+#endif
+
+#ifndef NO_TVITEM
+typedef struct TVITEM_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID mask, hItem, state, stateMask, pszText, cchTextMax, iImage, iSelectedImage, cChildren, lParam;
+} TVITEM_FID_CACHE;
+
+TVITEM_FID_CACHE TVITEMFc;
+
+void cacheTVITEMFields(JNIEnv *env, jobject lpObject)
+{
+       if (TVITEMFc.cached) return;
+       TVITEMFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TVITEMFc.mask = (*env)->GetFieldID(env, TVITEMFc.clazz, "mask", "I");
+       TVITEMFc.hItem = (*env)->GetFieldID(env, TVITEMFc.clazz, "hItem", "J");
+       TVITEMFc.state = (*env)->GetFieldID(env, TVITEMFc.clazz, "state", "I");
+       TVITEMFc.stateMask = (*env)->GetFieldID(env, TVITEMFc.clazz, "stateMask", "I");
+       TVITEMFc.pszText = (*env)->GetFieldID(env, TVITEMFc.clazz, "pszText", "J");
+       TVITEMFc.cchTextMax = (*env)->GetFieldID(env, TVITEMFc.clazz, "cchTextMax", "I");
+       TVITEMFc.iImage = (*env)->GetFieldID(env, TVITEMFc.clazz, "iImage", "I");
+       TVITEMFc.iSelectedImage = (*env)->GetFieldID(env, TVITEMFc.clazz, "iSelectedImage", "I");
+       TVITEMFc.cChildren = (*env)->GetFieldID(env, TVITEMFc.clazz, "cChildren", "I");
+       TVITEMFc.lParam = (*env)->GetFieldID(env, TVITEMFc.clazz, "lParam", "J");
+       TVITEMFc.cached = 1;
+}
+
+TVITEM *getTVITEMFields(JNIEnv *env, jobject lpObject, TVITEM *lpStruct)
+{
+       if (!TVITEMFc.cached) cacheTVITEMFields(env, lpObject);
+       lpStruct->mask = (*env)->GetIntField(env, lpObject, TVITEMFc.mask);
+       lpStruct->hItem = (HTREEITEM)(*env)->GetLongField(env, lpObject, TVITEMFc.hItem);
+       lpStruct->state = (*env)->GetIntField(env, lpObject, TVITEMFc.state);
+       lpStruct->stateMask = (*env)->GetIntField(env, lpObject, TVITEMFc.stateMask);
+       lpStruct->pszText = (LPTSTR)(*env)->GetLongField(env, lpObject, TVITEMFc.pszText);
+       lpStruct->cchTextMax = (*env)->GetIntField(env, lpObject, TVITEMFc.cchTextMax);
+       lpStruct->iImage = (*env)->GetIntField(env, lpObject, TVITEMFc.iImage);
+       lpStruct->iSelectedImage = (*env)->GetIntField(env, lpObject, TVITEMFc.iSelectedImage);
+       lpStruct->cChildren = (*env)->GetIntField(env, lpObject, TVITEMFc.cChildren);
+       lpStruct->lParam = (*env)->GetLongField(env, lpObject, TVITEMFc.lParam);
+       return lpStruct;
+}
+
+void setTVITEMFields(JNIEnv *env, jobject lpObject, TVITEM *lpStruct)
+{
+       if (!TVITEMFc.cached) cacheTVITEMFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.mask, (jint)lpStruct->mask);
+       (*env)->SetLongField(env, lpObject, TVITEMFc.hItem, (jlong)lpStruct->hItem);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.state, (jint)lpStruct->state);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.stateMask, (jint)lpStruct->stateMask);
+       (*env)->SetLongField(env, lpObject, TVITEMFc.pszText, (jlong)lpStruct->pszText);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.cchTextMax, (jint)lpStruct->cchTextMax);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.iImage, (jint)lpStruct->iImage);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.iSelectedImage, (jint)lpStruct->iSelectedImage);
+       (*env)->SetIntField(env, lpObject, TVITEMFc.cChildren, (jint)lpStruct->cChildren);
+       (*env)->SetLongField(env, lpObject, TVITEMFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_TVITEMEX
+typedef struct TVITEMEX_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID iIntegral;
+} TVITEMEX_FID_CACHE;
+
+TVITEMEX_FID_CACHE TVITEMEXFc;
+
+void cacheTVITEMEXFields(JNIEnv *env, jobject lpObject)
+{
+       if (TVITEMEXFc.cached) return;
+       cacheTVITEMFields(env, lpObject);
+       TVITEMEXFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TVITEMEXFc.iIntegral = (*env)->GetFieldID(env, TVITEMEXFc.clazz, "iIntegral", "I");
+       TVITEMEXFc.cached = 1;
+}
+
+TVITEMEX *getTVITEMEXFields(JNIEnv *env, jobject lpObject, TVITEMEX *lpStruct)
+{
+       if (!TVITEMEXFc.cached) cacheTVITEMEXFields(env, lpObject);
+       getTVITEMFields(env, lpObject, (TVITEM *)lpStruct);
+       lpStruct->iIntegral = (*env)->GetIntField(env, lpObject, TVITEMEXFc.iIntegral);
+       return lpStruct;
+}
+
+void setTVITEMEXFields(JNIEnv *env, jobject lpObject, TVITEMEX *lpStruct)
+{
+       if (!TVITEMEXFc.cached) cacheTVITEMEXFields(env, lpObject);
+       setTVITEMFields(env, lpObject, (TVITEM *)lpStruct);
+       (*env)->SetIntField(env, lpObject, TVITEMEXFc.iIntegral, (jint)lpStruct->iIntegral);
+}
+#endif
+
+#ifndef NO_TVSORTCB
+typedef struct TVSORTCB_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hParent, lpfnCompare, lParam;
+} TVSORTCB_FID_CACHE;
+
+TVSORTCB_FID_CACHE TVSORTCBFc;
+
+void cacheTVSORTCBFields(JNIEnv *env, jobject lpObject)
+{
+       if (TVSORTCBFc.cached) return;
+       TVSORTCBFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       TVSORTCBFc.hParent = (*env)->GetFieldID(env, TVSORTCBFc.clazz, "hParent", "J");
+       TVSORTCBFc.lpfnCompare = (*env)->GetFieldID(env, TVSORTCBFc.clazz, "lpfnCompare", "J");
+       TVSORTCBFc.lParam = (*env)->GetFieldID(env, TVSORTCBFc.clazz, "lParam", "J");
+       TVSORTCBFc.cached = 1;
+}
+
+TVSORTCB *getTVSORTCBFields(JNIEnv *env, jobject lpObject, TVSORTCB *lpStruct)
+{
+       if (!TVSORTCBFc.cached) cacheTVSORTCBFields(env, lpObject);
+       lpStruct->hParent = (HTREEITEM)(*env)->GetLongField(env, lpObject, TVSORTCBFc.hParent);
+       lpStruct->lpfnCompare = (PFNTVCOMPARE)(*env)->GetLongField(env, lpObject, TVSORTCBFc.lpfnCompare);
+       lpStruct->lParam = (LPARAM)(*env)->GetLongField(env, lpObject, TVSORTCBFc.lParam);
+       return lpStruct;
+}
+
+void setTVSORTCBFields(JNIEnv *env, jobject lpObject, TVSORTCB *lpStruct)
+{
+       if (!TVSORTCBFc.cached) cacheTVSORTCBFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, TVSORTCBFc.hParent, (jlong)lpStruct->hParent);
+       (*env)->SetLongField(env, lpObject, TVSORTCBFc.lpfnCompare, (jlong)lpStruct->lpfnCompare);
+       (*env)->SetLongField(env, lpObject, TVSORTCBFc.lParam, (jlong)lpStruct->lParam);
+}
+#endif
+
+#ifndef NO_UDACCEL
+typedef struct UDACCEL_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID nSec, nInc;
+} UDACCEL_FID_CACHE;
+
+UDACCEL_FID_CACHE UDACCELFc;
+
+void cacheUDACCELFields(JNIEnv *env, jobject lpObject)
+{
+       if (UDACCELFc.cached) return;
+       UDACCELFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       UDACCELFc.nSec = (*env)->GetFieldID(env, UDACCELFc.clazz, "nSec", "I");
+       UDACCELFc.nInc = (*env)->GetFieldID(env, UDACCELFc.clazz, "nInc", "I");
+       UDACCELFc.cached = 1;
+}
+
+UDACCEL *getUDACCELFields(JNIEnv *env, jobject lpObject, UDACCEL *lpStruct)
+{
+       if (!UDACCELFc.cached) cacheUDACCELFields(env, lpObject);
+       lpStruct->nSec = (*env)->GetIntField(env, lpObject, UDACCELFc.nSec);
+       lpStruct->nInc = (*env)->GetIntField(env, lpObject, UDACCELFc.nInc);
+       return lpStruct;
+}
+
+void setUDACCELFields(JNIEnv *env, jobject lpObject, UDACCEL *lpStruct)
+{
+       if (!UDACCELFc.cached) cacheUDACCELFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, UDACCELFc.nSec, (jint)lpStruct->nSec);
+       (*env)->SetIntField(env, lpObject, UDACCELFc.nInc, (jint)lpStruct->nInc);
+}
+#endif
+
+#ifndef NO_WINDOWPLACEMENT
+typedef struct WINDOWPLACEMENT_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID length, flags, showCmd, ptMinPosition_x, ptMinPosition_y, ptMaxPosition_x, ptMaxPosition_y, left, top, right, bottom;
+} WINDOWPLACEMENT_FID_CACHE;
+
+WINDOWPLACEMENT_FID_CACHE WINDOWPLACEMENTFc;
+
+void cacheWINDOWPLACEMENTFields(JNIEnv *env, jobject lpObject)
+{
+       if (WINDOWPLACEMENTFc.cached) return;
+       WINDOWPLACEMENTFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       WINDOWPLACEMENTFc.length = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "length", "I");
+       WINDOWPLACEMENTFc.flags = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "flags", "I");
+       WINDOWPLACEMENTFc.showCmd = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "showCmd", "I");
+       WINDOWPLACEMENTFc.ptMinPosition_x = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "ptMinPosition_x", "I");
+       WINDOWPLACEMENTFc.ptMinPosition_y = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "ptMinPosition_y", "I");
+       WINDOWPLACEMENTFc.ptMaxPosition_x = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "ptMaxPosition_x", "I");
+       WINDOWPLACEMENTFc.ptMaxPosition_y = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "ptMaxPosition_y", "I");
+       WINDOWPLACEMENTFc.left = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "left", "I");
+       WINDOWPLACEMENTFc.top = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "top", "I");
+       WINDOWPLACEMENTFc.right = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "right", "I");
+       WINDOWPLACEMENTFc.bottom = (*env)->GetFieldID(env, WINDOWPLACEMENTFc.clazz, "bottom", "I");
+       WINDOWPLACEMENTFc.cached = 1;
+}
+
+WINDOWPLACEMENT *getWINDOWPLACEMENTFields(JNIEnv *env, jobject lpObject, WINDOWPLACEMENT *lpStruct)
+{
+       if (!WINDOWPLACEMENTFc.cached) cacheWINDOWPLACEMENTFields(env, lpObject);
+       lpStruct->length = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.length);
+       lpStruct->flags = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.flags);
+       lpStruct->showCmd = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.showCmd);
+       lpStruct->ptMinPosition.x = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMinPosition_x);
+       lpStruct->ptMinPosition.y = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMinPosition_y);
+       lpStruct->ptMaxPosition.x = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMaxPosition_x);
+       lpStruct->ptMaxPosition.y = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMaxPosition_y);
+       lpStruct->rcNormalPosition.left = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.left);
+       lpStruct->rcNormalPosition.top = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.top);
+       lpStruct->rcNormalPosition.right = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.right);
+       lpStruct->rcNormalPosition.bottom = (*env)->GetIntField(env, lpObject, WINDOWPLACEMENTFc.bottom);
+       return lpStruct;
+}
+
+void setWINDOWPLACEMENTFields(JNIEnv *env, jobject lpObject, WINDOWPLACEMENT *lpStruct)
+{
+       if (!WINDOWPLACEMENTFc.cached) cacheWINDOWPLACEMENTFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.length, (jint)lpStruct->length);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.flags, (jint)lpStruct->flags);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.showCmd, (jint)lpStruct->showCmd);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMinPosition_x, (jint)lpStruct->ptMinPosition.x);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMinPosition_y, (jint)lpStruct->ptMinPosition.y);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMaxPosition_x, (jint)lpStruct->ptMaxPosition.x);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.ptMaxPosition_y, (jint)lpStruct->ptMaxPosition.y);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.left, (jint)lpStruct->rcNormalPosition.left);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.top, (jint)lpStruct->rcNormalPosition.top);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.right, (jint)lpStruct->rcNormalPosition.right);
+       (*env)->SetIntField(env, lpObject, WINDOWPLACEMENTFc.bottom, (jint)lpStruct->rcNormalPosition.bottom);
+}
+#endif
+
+#ifndef NO_WINDOWPOS
+typedef struct WINDOWPOS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID hwnd, hwndInsertAfter, x, y, cx, cy, flags;
+} WINDOWPOS_FID_CACHE;
+
+WINDOWPOS_FID_CACHE WINDOWPOSFc;
+
+void cacheWINDOWPOSFields(JNIEnv *env, jobject lpObject)
+{
+       if (WINDOWPOSFc.cached) return;
+       WINDOWPOSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       WINDOWPOSFc.hwnd = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "hwnd", "J");
+       WINDOWPOSFc.hwndInsertAfter = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "hwndInsertAfter", "J");
+       WINDOWPOSFc.x = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "x", "I");
+       WINDOWPOSFc.y = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "y", "I");
+       WINDOWPOSFc.cx = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "cx", "I");
+       WINDOWPOSFc.cy = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "cy", "I");
+       WINDOWPOSFc.flags = (*env)->GetFieldID(env, WINDOWPOSFc.clazz, "flags", "I");
+       WINDOWPOSFc.cached = 1;
+}
+
+WINDOWPOS *getWINDOWPOSFields(JNIEnv *env, jobject lpObject, WINDOWPOS *lpStruct)
+{
+       if (!WINDOWPOSFc.cached) cacheWINDOWPOSFields(env, lpObject);
+       lpStruct->hwnd = (HWND)(*env)->GetLongField(env, lpObject, WINDOWPOSFc.hwnd);
+       lpStruct->hwndInsertAfter = (HWND)(*env)->GetLongField(env, lpObject, WINDOWPOSFc.hwndInsertAfter);
+       lpStruct->x = (*env)->GetIntField(env, lpObject, WINDOWPOSFc.x);
+       lpStruct->y = (*env)->GetIntField(env, lpObject, WINDOWPOSFc.y);
+       lpStruct->cx = (*env)->GetIntField(env, lpObject, WINDOWPOSFc.cx);
+       lpStruct->cy = (*env)->GetIntField(env, lpObject, WINDOWPOSFc.cy);
+       lpStruct->flags = (*env)->GetIntField(env, lpObject, WINDOWPOSFc.flags);
+       return lpStruct;
+}
+
+void setWINDOWPOSFields(JNIEnv *env, jobject lpObject, WINDOWPOS *lpStruct)
+{
+       if (!WINDOWPOSFc.cached) cacheWINDOWPOSFields(env, lpObject);
+       (*env)->SetLongField(env, lpObject, WINDOWPOSFc.hwnd, (jlong)lpStruct->hwnd);
+       (*env)->SetLongField(env, lpObject, WINDOWPOSFc.hwndInsertAfter, (jlong)lpStruct->hwndInsertAfter);
+       (*env)->SetIntField(env, lpObject, WINDOWPOSFc.x, (jint)lpStruct->x);
+       (*env)->SetIntField(env, lpObject, WINDOWPOSFc.y, (jint)lpStruct->y);
+       (*env)->SetIntField(env, lpObject, WINDOWPOSFc.cx, (jint)lpStruct->cx);
+       (*env)->SetIntField(env, lpObject, WINDOWPOSFc.cy, (jint)lpStruct->cy);
+       (*env)->SetIntField(env, lpObject, WINDOWPOSFc.flags, (jint)lpStruct->flags);
+}
+#endif
+
+#ifndef NO_WNDCLASS
+typedef struct WNDCLASS_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID style, lpfnWndProc, cbClsExtra, cbWndExtra, hInstance, hIcon, hCursor, hbrBackground, lpszMenuName, lpszClassName;
+} WNDCLASS_FID_CACHE;
+
+WNDCLASS_FID_CACHE WNDCLASSFc;
+
+void cacheWNDCLASSFields(JNIEnv *env, jobject lpObject)
+{
+       if (WNDCLASSFc.cached) return;
+       WNDCLASSFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       WNDCLASSFc.style = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "style", "I");
+       WNDCLASSFc.lpfnWndProc = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "lpfnWndProc", "J");
+       WNDCLASSFc.cbClsExtra = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "cbClsExtra", "I");
+       WNDCLASSFc.cbWndExtra = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "cbWndExtra", "I");
+       WNDCLASSFc.hInstance = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "hInstance", "J");
+       WNDCLASSFc.hIcon = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "hIcon", "J");
+       WNDCLASSFc.hCursor = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "hCursor", "J");
+       WNDCLASSFc.hbrBackground = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "hbrBackground", "J");
+       WNDCLASSFc.lpszMenuName = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "lpszMenuName", "J");
+       WNDCLASSFc.lpszClassName = (*env)->GetFieldID(env, WNDCLASSFc.clazz, "lpszClassName", "J");
+       WNDCLASSFc.cached = 1;
+}
+
+WNDCLASS *getWNDCLASSFields(JNIEnv *env, jobject lpObject, WNDCLASS *lpStruct)
+{
+       if (!WNDCLASSFc.cached) cacheWNDCLASSFields(env, lpObject);
+       lpStruct->style = (*env)->GetIntField(env, lpObject, WNDCLASSFc.style);
+       lpStruct->lpfnWndProc = (WNDPROC)(*env)->GetLongField(env, lpObject, WNDCLASSFc.lpfnWndProc);
+       lpStruct->cbClsExtra = (*env)->GetIntField(env, lpObject, WNDCLASSFc.cbClsExtra);
+       lpStruct->cbWndExtra = (*env)->GetIntField(env, lpObject, WNDCLASSFc.cbWndExtra);
+       lpStruct->hInstance = (HINSTANCE)(*env)->GetLongField(env, lpObject, WNDCLASSFc.hInstance);
+       lpStruct->hIcon = (HICON)(*env)->GetLongField(env, lpObject, WNDCLASSFc.hIcon);
+       lpStruct->hCursor = (HCURSOR)(*env)->GetLongField(env, lpObject, WNDCLASSFc.hCursor);
+       lpStruct->hbrBackground = (HBRUSH)(*env)->GetLongField(env, lpObject, WNDCLASSFc.hbrBackground);
+       lpStruct->lpszMenuName = (LPCTSTR)(*env)->GetLongField(env, lpObject, WNDCLASSFc.lpszMenuName);
+       lpStruct->lpszClassName = (LPCTSTR)(*env)->GetLongField(env, lpObject, WNDCLASSFc.lpszClassName);
+       return lpStruct;
+}
+
+void setWNDCLASSFields(JNIEnv *env, jobject lpObject, WNDCLASS *lpStruct)
+{
+       if (!WNDCLASSFc.cached) cacheWNDCLASSFields(env, lpObject);
+       (*env)->SetIntField(env, lpObject, WNDCLASSFc.style, (jint)lpStruct->style);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.lpfnWndProc, (jlong)lpStruct->lpfnWndProc);
+       (*env)->SetIntField(env, lpObject, WNDCLASSFc.cbClsExtra, (jint)lpStruct->cbClsExtra);
+       (*env)->SetIntField(env, lpObject, WNDCLASSFc.cbWndExtra, (jint)lpStruct->cbWndExtra);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.hInstance, (jlong)lpStruct->hInstance);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.hIcon, (jlong)lpStruct->hIcon);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.hCursor, (jlong)lpStruct->hCursor);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.hbrBackground, (jlong)lpStruct->hbrBackground);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.lpszMenuName, (jlong)lpStruct->lpszMenuName);
+       (*env)->SetLongField(env, lpObject, WNDCLASSFc.lpszClassName, (jlong)lpStruct->lpszClassName);
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_structs.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/os_structs.h
new file mode 100644 (file)
index 0000000..6182b6c
--- /dev/null
@@ -0,0 +1,1699 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "os.h"
+
+#ifndef NO_ACCEL
+void cacheACCELFields(JNIEnv *env, jobject lpObject);
+ACCEL *getACCELFields(JNIEnv *env, jobject lpObject, ACCEL *lpStruct);
+void setACCELFields(JNIEnv *env, jobject lpObject, ACCEL *lpStruct);
+#define ACCEL_sizeof() sizeof(ACCEL)
+#else
+#define cacheACCELFields(a,b)
+#define getACCELFields(a,b,c) NULL
+#define setACCELFields(a,b,c)
+#define ACCEL_sizeof() 0
+#endif
+
+#ifndef NO_ACTCTX
+void cacheACTCTXFields(JNIEnv *env, jobject lpObject);
+ACTCTX *getACTCTXFields(JNIEnv *env, jobject lpObject, ACTCTX *lpStruct);
+void setACTCTXFields(JNIEnv *env, jobject lpObject, ACTCTX *lpStruct);
+#define ACTCTX_sizeof() sizeof(ACTCTX)
+#else
+#define cacheACTCTXFields(a,b)
+#define getACTCTXFields(a,b,c) NULL
+#define setACTCTXFields(a,b,c)
+#define ACTCTX_sizeof() 0
+#endif
+
+#ifndef NO_BITMAP
+void cacheBITMAPFields(JNIEnv *env, jobject lpObject);
+BITMAP *getBITMAPFields(JNIEnv *env, jobject lpObject, BITMAP *lpStruct);
+void setBITMAPFields(JNIEnv *env, jobject lpObject, BITMAP *lpStruct);
+#define BITMAP_sizeof() sizeof(BITMAP)
+#else
+#define cacheBITMAPFields(a,b)
+#define getBITMAPFields(a,b,c) NULL
+#define setBITMAPFields(a,b,c)
+#define BITMAP_sizeof() 0
+#endif
+
+#ifndef NO_BITMAPINFOHEADER
+void cacheBITMAPINFOHEADERFields(JNIEnv *env, jobject lpObject);
+BITMAPINFOHEADER *getBITMAPINFOHEADERFields(JNIEnv *env, jobject lpObject, BITMAPINFOHEADER *lpStruct);
+void setBITMAPINFOHEADERFields(JNIEnv *env, jobject lpObject, BITMAPINFOHEADER *lpStruct);
+#define BITMAPINFOHEADER_sizeof() sizeof(BITMAPINFOHEADER)
+#else
+#define cacheBITMAPINFOHEADERFields(a,b)
+#define getBITMAPINFOHEADERFields(a,b,c) NULL
+#define setBITMAPINFOHEADERFields(a,b,c)
+#define BITMAPINFOHEADER_sizeof() 0
+#endif
+
+#ifndef NO_BLENDFUNCTION
+void cacheBLENDFUNCTIONFields(JNIEnv *env, jobject lpObject);
+BLENDFUNCTION *getBLENDFUNCTIONFields(JNIEnv *env, jobject lpObject, BLENDFUNCTION *lpStruct);
+void setBLENDFUNCTIONFields(JNIEnv *env, jobject lpObject, BLENDFUNCTION *lpStruct);
+#define BLENDFUNCTION_sizeof() sizeof(BLENDFUNCTION)
+#else
+#define cacheBLENDFUNCTIONFields(a,b)
+#define getBLENDFUNCTIONFields(a,b,c) NULL
+#define setBLENDFUNCTIONFields(a,b,c)
+#define BLENDFUNCTION_sizeof() 0
+#endif
+
+#ifndef NO_BP_PAINTPARAMS
+void cacheBP_PAINTPARAMSFields(JNIEnv *env, jobject lpObject);
+BP_PAINTPARAMS *getBP_PAINTPARAMSFields(JNIEnv *env, jobject lpObject, BP_PAINTPARAMS *lpStruct);
+void setBP_PAINTPARAMSFields(JNIEnv *env, jobject lpObject, BP_PAINTPARAMS *lpStruct);
+#define BP_PAINTPARAMS_sizeof() sizeof(BP_PAINTPARAMS)
+#else
+#define cacheBP_PAINTPARAMSFields(a,b)
+#define getBP_PAINTPARAMSFields(a,b,c) NULL
+#define setBP_PAINTPARAMSFields(a,b,c)
+#define BP_PAINTPARAMS_sizeof() 0
+#endif
+
+#ifndef NO_BROWSEINFO
+void cacheBROWSEINFOFields(JNIEnv *env, jobject lpObject);
+BROWSEINFO *getBROWSEINFOFields(JNIEnv *env, jobject lpObject, BROWSEINFO *lpStruct);
+void setBROWSEINFOFields(JNIEnv *env, jobject lpObject, BROWSEINFO *lpStruct);
+#define BROWSEINFO_sizeof() sizeof(BROWSEINFO)
+#else
+#define cacheBROWSEINFOFields(a,b)
+#define getBROWSEINFOFields(a,b,c) NULL
+#define setBROWSEINFOFields(a,b,c)
+#define BROWSEINFO_sizeof() 0
+#endif
+
+#ifndef NO_BUTTON_IMAGELIST
+void cacheBUTTON_IMAGELISTFields(JNIEnv *env, jobject lpObject);
+BUTTON_IMAGELIST *getBUTTON_IMAGELISTFields(JNIEnv *env, jobject lpObject, BUTTON_IMAGELIST *lpStruct);
+void setBUTTON_IMAGELISTFields(JNIEnv *env, jobject lpObject, BUTTON_IMAGELIST *lpStruct);
+#define BUTTON_IMAGELIST_sizeof() sizeof(BUTTON_IMAGELIST)
+#else
+#define cacheBUTTON_IMAGELISTFields(a,b)
+#define getBUTTON_IMAGELISTFields(a,b,c) NULL
+#define setBUTTON_IMAGELISTFields(a,b,c)
+#define BUTTON_IMAGELIST_sizeof() 0
+#endif
+
+#ifndef NO_CANDIDATEFORM
+void cacheCANDIDATEFORMFields(JNIEnv *env, jobject lpObject);
+CANDIDATEFORM *getCANDIDATEFORMFields(JNIEnv *env, jobject lpObject, CANDIDATEFORM *lpStruct);
+void setCANDIDATEFORMFields(JNIEnv *env, jobject lpObject, CANDIDATEFORM *lpStruct);
+#define CANDIDATEFORM_sizeof() sizeof(CANDIDATEFORM)
+#else
+#define cacheCANDIDATEFORMFields(a,b)
+#define getCANDIDATEFORMFields(a,b,c) NULL
+#define setCANDIDATEFORMFields(a,b,c)
+#define CANDIDATEFORM_sizeof() 0
+#endif
+
+#ifndef NO_CERT_CONTEXT
+void cacheCERT_CONTEXTFields(JNIEnv *env, jobject lpObject);
+CERT_CONTEXT *getCERT_CONTEXTFields(JNIEnv *env, jobject lpObject, CERT_CONTEXT *lpStruct);
+void setCERT_CONTEXTFields(JNIEnv *env, jobject lpObject, CERT_CONTEXT *lpStruct);
+#define CERT_CONTEXT_sizeof() sizeof(CERT_CONTEXT)
+#else
+#define cacheCERT_CONTEXTFields(a,b)
+#define getCERT_CONTEXTFields(a,b,c) NULL
+#define setCERT_CONTEXTFields(a,b,c)
+#define CERT_CONTEXT_sizeof() 0
+#endif
+
+#ifndef NO_CERT_INFO
+void cacheCERT_INFOFields(JNIEnv *env, jobject lpObject);
+CERT_INFO *getCERT_INFOFields(JNIEnv *env, jobject lpObject, CERT_INFO *lpStruct);
+void setCERT_INFOFields(JNIEnv *env, jobject lpObject, CERT_INFO *lpStruct);
+#define CERT_INFO_sizeof() sizeof(CERT_INFO)
+#else
+#define cacheCERT_INFOFields(a,b)
+#define getCERT_INFOFields(a,b,c) NULL
+#define setCERT_INFOFields(a,b,c)
+#define CERT_INFO_sizeof() 0
+#endif
+
+#ifndef NO_CERT_NAME_BLOB
+void cacheCERT_NAME_BLOBFields(JNIEnv *env, jobject lpObject);
+CERT_NAME_BLOB *getCERT_NAME_BLOBFields(JNIEnv *env, jobject lpObject, CERT_NAME_BLOB *lpStruct);
+void setCERT_NAME_BLOBFields(JNIEnv *env, jobject lpObject, CERT_NAME_BLOB *lpStruct);
+#define CERT_NAME_BLOB_sizeof() sizeof(CERT_NAME_BLOB)
+#else
+#define cacheCERT_NAME_BLOBFields(a,b)
+#define getCERT_NAME_BLOBFields(a,b,c) NULL
+#define setCERT_NAME_BLOBFields(a,b,c)
+#define CERT_NAME_BLOB_sizeof() 0
+#endif
+
+#ifndef NO_CERT_PUBLIC_KEY_INFO
+void cacheCERT_PUBLIC_KEY_INFOFields(JNIEnv *env, jobject lpObject);
+CERT_PUBLIC_KEY_INFO *getCERT_PUBLIC_KEY_INFOFields(JNIEnv *env, jobject lpObject, CERT_PUBLIC_KEY_INFO *lpStruct);
+void setCERT_PUBLIC_KEY_INFOFields(JNIEnv *env, jobject lpObject, CERT_PUBLIC_KEY_INFO *lpStruct);
+#define CERT_PUBLIC_KEY_INFO_sizeof() sizeof(CERT_PUBLIC_KEY_INFO)
+#else
+#define cacheCERT_PUBLIC_KEY_INFOFields(a,b)
+#define getCERT_PUBLIC_KEY_INFOFields(a,b,c) NULL
+#define setCERT_PUBLIC_KEY_INFOFields(a,b,c)
+#define CERT_PUBLIC_KEY_INFO_sizeof() 0
+#endif
+
+#ifndef NO_CHOOSECOLOR
+void cacheCHOOSECOLORFields(JNIEnv *env, jobject lpObject);
+CHOOSECOLOR *getCHOOSECOLORFields(JNIEnv *env, jobject lpObject, CHOOSECOLOR *lpStruct);
+void setCHOOSECOLORFields(JNIEnv *env, jobject lpObject, CHOOSECOLOR *lpStruct);
+#define CHOOSECOLOR_sizeof() sizeof(CHOOSECOLOR)
+#else
+#define cacheCHOOSECOLORFields(a,b)
+#define getCHOOSECOLORFields(a,b,c) NULL
+#define setCHOOSECOLORFields(a,b,c)
+#define CHOOSECOLOR_sizeof() 0
+#endif
+
+#ifndef NO_CHOOSEFONT
+void cacheCHOOSEFONTFields(JNIEnv *env, jobject lpObject);
+CHOOSEFONT *getCHOOSEFONTFields(JNIEnv *env, jobject lpObject, CHOOSEFONT *lpStruct);
+void setCHOOSEFONTFields(JNIEnv *env, jobject lpObject, CHOOSEFONT *lpStruct);
+#define CHOOSEFONT_sizeof() sizeof(CHOOSEFONT)
+#else
+#define cacheCHOOSEFONTFields(a,b)
+#define getCHOOSEFONTFields(a,b,c) NULL
+#define setCHOOSEFONTFields(a,b,c)
+#define CHOOSEFONT_sizeof() 0
+#endif
+
+#ifndef NO_CIDA
+void cacheCIDAFields(JNIEnv *env, jobject lpObject);
+CIDA *getCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct);
+void setCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct);
+#define CIDA_sizeof() sizeof(CIDA)
+#else
+#define cacheCIDAFields(a,b)
+#define getCIDAFields(a,b,c) NULL
+#define setCIDAFields(a,b,c)
+#define CIDA_sizeof() 0
+#endif
+
+#ifndef NO_COMBOBOXINFO
+void cacheCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject);
+COMBOBOXINFO *getCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject, COMBOBOXINFO *lpStruct);
+void setCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject, COMBOBOXINFO *lpStruct);
+#define COMBOBOXINFO_sizeof() sizeof(COMBOBOXINFO)
+#else
+#define cacheCOMBOBOXINFOFields(a,b)
+#define getCOMBOBOXINFOFields(a,b,c) NULL
+#define setCOMBOBOXINFOFields(a,b,c)
+#define COMBOBOXINFO_sizeof() 0
+#endif
+
+#ifndef NO_COMPOSITIONFORM
+void cacheCOMPOSITIONFORMFields(JNIEnv *env, jobject lpObject);
+COMPOSITIONFORM *getCOMPOSITIONFORMFields(JNIEnv *env, jobject lpObject, COMPOSITIONFORM *lpStruct);
+void setCOMPOSITIONFORMFields(JNIEnv *env, jobject lpObject, COMPOSITIONFORM *lpStruct);
+#define COMPOSITIONFORM_sizeof() sizeof(COMPOSITIONFORM)
+#else
+#define cacheCOMPOSITIONFORMFields(a,b)
+#define getCOMPOSITIONFORMFields(a,b,c) NULL
+#define setCOMPOSITIONFORMFields(a,b,c)
+#define COMPOSITIONFORM_sizeof() 0
+#endif
+
+#ifndef NO_CREATESTRUCT
+void cacheCREATESTRUCTFields(JNIEnv *env, jobject lpObject);
+CREATESTRUCT *getCREATESTRUCTFields(JNIEnv *env, jobject lpObject, CREATESTRUCT *lpStruct);
+void setCREATESTRUCTFields(JNIEnv *env, jobject lpObject, CREATESTRUCT *lpStruct);
+#define CREATESTRUCT_sizeof() sizeof(CREATESTRUCT)
+#else
+#define cacheCREATESTRUCTFields(a,b)
+#define getCREATESTRUCTFields(a,b,c) NULL
+#define setCREATESTRUCTFields(a,b,c)
+#define CREATESTRUCT_sizeof() 0
+#endif
+
+#ifndef NO_CRYPT_ALGORITHM_IDENTIFIER
+void cacheCRYPT_ALGORITHM_IDENTIFIERFields(JNIEnv *env, jobject lpObject);
+CRYPT_ALGORITHM_IDENTIFIER *getCRYPT_ALGORITHM_IDENTIFIERFields(JNIEnv *env, jobject lpObject, CRYPT_ALGORITHM_IDENTIFIER *lpStruct);
+void setCRYPT_ALGORITHM_IDENTIFIERFields(JNIEnv *env, jobject lpObject, CRYPT_ALGORITHM_IDENTIFIER *lpStruct);
+#define CRYPT_ALGORITHM_IDENTIFIER_sizeof() sizeof(CRYPT_ALGORITHM_IDENTIFIER)
+#else
+#define cacheCRYPT_ALGORITHM_IDENTIFIERFields(a,b)
+#define getCRYPT_ALGORITHM_IDENTIFIERFields(a,b,c) NULL
+#define setCRYPT_ALGORITHM_IDENTIFIERFields(a,b,c)
+#define CRYPT_ALGORITHM_IDENTIFIER_sizeof() 0
+#endif
+
+#ifndef NO_CRYPT_BIT_BLOB
+void cacheCRYPT_BIT_BLOBFields(JNIEnv *env, jobject lpObject);
+CRYPT_BIT_BLOB *getCRYPT_BIT_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_BIT_BLOB *lpStruct);
+void setCRYPT_BIT_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_BIT_BLOB *lpStruct);
+#define CRYPT_BIT_BLOB_sizeof() sizeof(CRYPT_BIT_BLOB)
+#else
+#define cacheCRYPT_BIT_BLOBFields(a,b)
+#define getCRYPT_BIT_BLOBFields(a,b,c) NULL
+#define setCRYPT_BIT_BLOBFields(a,b,c)
+#define CRYPT_BIT_BLOB_sizeof() 0
+#endif
+
+#ifndef NO_CRYPT_INTEGER_BLOB
+void cacheCRYPT_INTEGER_BLOBFields(JNIEnv *env, jobject lpObject);
+CRYPT_INTEGER_BLOB *getCRYPT_INTEGER_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_INTEGER_BLOB *lpStruct);
+void setCRYPT_INTEGER_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_INTEGER_BLOB *lpStruct);
+#define CRYPT_INTEGER_BLOB_sizeof() sizeof(CRYPT_INTEGER_BLOB)
+#else
+#define cacheCRYPT_INTEGER_BLOBFields(a,b)
+#define getCRYPT_INTEGER_BLOBFields(a,b,c) NULL
+#define setCRYPT_INTEGER_BLOBFields(a,b,c)
+#define CRYPT_INTEGER_BLOB_sizeof() 0
+#endif
+
+#ifndef NO_CRYPT_OBJID_BLOB
+void cacheCRYPT_OBJID_BLOBFields(JNIEnv *env, jobject lpObject);
+CRYPT_OBJID_BLOB *getCRYPT_OBJID_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_OBJID_BLOB *lpStruct);
+void setCRYPT_OBJID_BLOBFields(JNIEnv *env, jobject lpObject, CRYPT_OBJID_BLOB *lpStruct);
+#define CRYPT_OBJID_BLOB_sizeof() sizeof(CRYPT_OBJID_BLOB)
+#else
+#define cacheCRYPT_OBJID_BLOBFields(a,b)
+#define getCRYPT_OBJID_BLOBFields(a,b,c) NULL
+#define setCRYPT_OBJID_BLOBFields(a,b,c)
+#define CRYPT_OBJID_BLOB_sizeof() 0
+#endif
+
+#ifndef NO_DEVMODE
+void cacheDEVMODEFields(JNIEnv *env, jobject lpObject);
+DEVMODE *getDEVMODEFields(JNIEnv *env, jobject lpObject, DEVMODE *lpStruct);
+void setDEVMODEFields(JNIEnv *env, jobject lpObject, DEVMODE *lpStruct);
+#define DEVMODE_sizeof() sizeof(DEVMODE)
+#else
+#define cacheDEVMODEFields(a,b)
+#define getDEVMODEFields(a,b,c) NULL
+#define setDEVMODEFields(a,b,c)
+#define DEVMODE_sizeof() 0
+#endif
+
+#ifndef NO_DIBSECTION
+void cacheDIBSECTIONFields(JNIEnv *env, jobject lpObject);
+DIBSECTION *getDIBSECTIONFields(JNIEnv *env, jobject lpObject, DIBSECTION *lpStruct);
+void setDIBSECTIONFields(JNIEnv *env, jobject lpObject, DIBSECTION *lpStruct);
+#define DIBSECTION_sizeof() sizeof(DIBSECTION)
+#else
+#define cacheDIBSECTIONFields(a,b)
+#define getDIBSECTIONFields(a,b,c) NULL
+#define setDIBSECTIONFields(a,b,c)
+#define DIBSECTION_sizeof() 0
+#endif
+
+#ifndef NO_DOCHOSTUIINFO
+void cacheDOCHOSTUIINFOFields(JNIEnv *env, jobject lpObject);
+DOCHOSTUIINFO *getDOCHOSTUIINFOFields(JNIEnv *env, jobject lpObject, DOCHOSTUIINFO *lpStruct);
+void setDOCHOSTUIINFOFields(JNIEnv *env, jobject lpObject, DOCHOSTUIINFO *lpStruct);
+#define DOCHOSTUIINFO_sizeof() sizeof(DOCHOSTUIINFO)
+#else
+#define cacheDOCHOSTUIINFOFields(a,b)
+#define getDOCHOSTUIINFOFields(a,b,c) NULL
+#define setDOCHOSTUIINFOFields(a,b,c)
+#define DOCHOSTUIINFO_sizeof() 0
+#endif
+
+#ifndef NO_DOCINFO
+void cacheDOCINFOFields(JNIEnv *env, jobject lpObject);
+DOCINFO *getDOCINFOFields(JNIEnv *env, jobject lpObject, DOCINFO *lpStruct);
+void setDOCINFOFields(JNIEnv *env, jobject lpObject, DOCINFO *lpStruct);
+#define DOCINFO_sizeof() sizeof(DOCINFO)
+#else
+#define cacheDOCINFOFields(a,b)
+#define getDOCINFOFields(a,b,c) NULL
+#define setDOCINFOFields(a,b,c)
+#define DOCINFO_sizeof() 0
+#endif
+
+#ifndef NO_DRAWITEMSTRUCT
+void cacheDRAWITEMSTRUCTFields(JNIEnv *env, jobject lpObject);
+DRAWITEMSTRUCT *getDRAWITEMSTRUCTFields(JNIEnv *env, jobject lpObject, DRAWITEMSTRUCT *lpStruct);
+void setDRAWITEMSTRUCTFields(JNIEnv *env, jobject lpObject, DRAWITEMSTRUCT *lpStruct);
+#define DRAWITEMSTRUCT_sizeof() sizeof(DRAWITEMSTRUCT)
+#else
+#define cacheDRAWITEMSTRUCTFields(a,b)
+#define getDRAWITEMSTRUCTFields(a,b,c) NULL
+#define setDRAWITEMSTRUCTFields(a,b,c)
+#define DRAWITEMSTRUCT_sizeof() 0
+#endif
+
+#ifndef NO_DROPFILES
+void cacheDROPFILESFields(JNIEnv *env, jobject lpObject);
+DROPFILES *getDROPFILESFields(JNIEnv *env, jobject lpObject, DROPFILES *lpStruct);
+void setDROPFILESFields(JNIEnv *env, jobject lpObject, DROPFILES *lpStruct);
+#define DROPFILES_sizeof() sizeof(DROPFILES)
+#else
+#define cacheDROPFILESFields(a,b)
+#define getDROPFILESFields(a,b,c) NULL
+#define setDROPFILESFields(a,b,c)
+#define DROPFILES_sizeof() 0
+#endif
+
+#ifndef NO_DTTOPTS
+void cacheDTTOPTSFields(JNIEnv *env, jobject lpObject);
+DTTOPTS *getDTTOPTSFields(JNIEnv *env, jobject lpObject, DTTOPTS *lpStruct);
+void setDTTOPTSFields(JNIEnv *env, jobject lpObject, DTTOPTS *lpStruct);
+#define DTTOPTS_sizeof() sizeof(DTTOPTS)
+#else
+#define cacheDTTOPTSFields(a,b)
+#define getDTTOPTSFields(a,b,c) NULL
+#define setDTTOPTSFields(a,b,c)
+#define DTTOPTS_sizeof() 0
+#endif
+
+#ifndef NO_EMR
+void cacheEMRFields(JNIEnv *env, jobject lpObject);
+EMR *getEMRFields(JNIEnv *env, jobject lpObject, EMR *lpStruct);
+void setEMRFields(JNIEnv *env, jobject lpObject, EMR *lpStruct);
+#define EMR_sizeof() sizeof(EMR)
+#else
+#define cacheEMRFields(a,b)
+#define getEMRFields(a,b,c) NULL
+#define setEMRFields(a,b,c)
+#define EMR_sizeof() 0
+#endif
+
+#ifndef NO_EMREXTCREATEFONTINDIRECTW
+void cacheEMREXTCREATEFONTINDIRECTWFields(JNIEnv *env, jobject lpObject);
+EMREXTCREATEFONTINDIRECTW *getEMREXTCREATEFONTINDIRECTWFields(JNIEnv *env, jobject lpObject, EMREXTCREATEFONTINDIRECTW *lpStruct);
+void setEMREXTCREATEFONTINDIRECTWFields(JNIEnv *env, jobject lpObject, EMREXTCREATEFONTINDIRECTW *lpStruct);
+#define EMREXTCREATEFONTINDIRECTW_sizeof() sizeof(EMREXTCREATEFONTINDIRECTW)
+#else
+#define cacheEMREXTCREATEFONTINDIRECTWFields(a,b)
+#define getEMREXTCREATEFONTINDIRECTWFields(a,b,c) NULL
+#define setEMREXTCREATEFONTINDIRECTWFields(a,b,c)
+#define EMREXTCREATEFONTINDIRECTW_sizeof() 0
+#endif
+
+#ifndef NO_EXTLOGFONTW
+void cacheEXTLOGFONTWFields(JNIEnv *env, jobject lpObject);
+EXTLOGFONTW *getEXTLOGFONTWFields(JNIEnv *env, jobject lpObject, EXTLOGFONTW *lpStruct);
+void setEXTLOGFONTWFields(JNIEnv *env, jobject lpObject, EXTLOGFONTW *lpStruct);
+#define EXTLOGFONTW_sizeof() sizeof(EXTLOGFONTW)
+#else
+#define cacheEXTLOGFONTWFields(a,b)
+#define getEXTLOGFONTWFields(a,b,c) NULL
+#define setEXTLOGFONTWFields(a,b,c)
+#define EXTLOGFONTW_sizeof() 0
+#endif
+
+#ifndef NO_FILETIME
+void cacheFILETIMEFields(JNIEnv *env, jobject lpObject);
+FILETIME *getFILETIMEFields(JNIEnv *env, jobject lpObject, FILETIME *lpStruct);
+void setFILETIMEFields(JNIEnv *env, jobject lpObject, FILETIME *lpStruct);
+#define FILETIME_sizeof() sizeof(FILETIME)
+#else
+#define cacheFILETIMEFields(a,b)
+#define getFILETIMEFields(a,b,c) NULL
+#define setFILETIMEFields(a,b,c)
+#define FILETIME_sizeof() 0
+#endif
+
+#ifndef NO_FLICK_DATA
+void cacheFLICK_DATAFields(JNIEnv *env, jobject lpObject);
+FLICK_DATA *getFLICK_DATAFields(JNIEnv *env, jobject lpObject, FLICK_DATA *lpStruct);
+void setFLICK_DATAFields(JNIEnv *env, jobject lpObject, FLICK_DATA *lpStruct);
+#define FLICK_DATA_sizeof() sizeof(FLICK_DATA)
+#else
+#define cacheFLICK_DATAFields(a,b)
+#define getFLICK_DATAFields(a,b,c) NULL
+#define setFLICK_DATAFields(a,b,c)
+#define FLICK_DATA_sizeof() 0
+#endif
+
+#ifndef NO_FLICK_POINT
+void cacheFLICK_POINTFields(JNIEnv *env, jobject lpObject);
+FLICK_POINT *getFLICK_POINTFields(JNIEnv *env, jobject lpObject, FLICK_POINT *lpStruct);
+void setFLICK_POINTFields(JNIEnv *env, jobject lpObject, FLICK_POINT *lpStruct);
+#define FLICK_POINT_sizeof() sizeof(FLICK_POINT)
+#else
+#define cacheFLICK_POINTFields(a,b)
+#define getFLICK_POINTFields(a,b,c) NULL
+#define setFLICK_POINTFields(a,b,c)
+#define FLICK_POINT_sizeof() 0
+#endif
+
+#ifndef NO_GCP_RESULTS
+void cacheGCP_RESULTSFields(JNIEnv *env, jobject lpObject);
+GCP_RESULTS *getGCP_RESULTSFields(JNIEnv *env, jobject lpObject, GCP_RESULTS *lpStruct);
+void setGCP_RESULTSFields(JNIEnv *env, jobject lpObject, GCP_RESULTS *lpStruct);
+#define GCP_RESULTS_sizeof() sizeof(GCP_RESULTS)
+#else
+#define cacheGCP_RESULTSFields(a,b)
+#define getGCP_RESULTSFields(a,b,c) NULL
+#define setGCP_RESULTSFields(a,b,c)
+#define GCP_RESULTS_sizeof() 0
+#endif
+
+#ifndef NO_GESTURECONFIG
+void cacheGESTURECONFIGFields(JNIEnv *env, jobject lpObject);
+GESTURECONFIG *getGESTURECONFIGFields(JNIEnv *env, jobject lpObject, GESTURECONFIG *lpStruct);
+void setGESTURECONFIGFields(JNIEnv *env, jobject lpObject, GESTURECONFIG *lpStruct);
+#define GESTURECONFIG_sizeof() sizeof(GESTURECONFIG)
+#else
+#define cacheGESTURECONFIGFields(a,b)
+#define getGESTURECONFIGFields(a,b,c) NULL
+#define setGESTURECONFIGFields(a,b,c)
+#define GESTURECONFIG_sizeof() 0
+#endif
+
+#ifndef NO_GESTUREINFO
+void cacheGESTUREINFOFields(JNIEnv *env, jobject lpObject);
+GESTUREINFO *getGESTUREINFOFields(JNIEnv *env, jobject lpObject, GESTUREINFO *lpStruct);
+void setGESTUREINFOFields(JNIEnv *env, jobject lpObject, GESTUREINFO *lpStruct);
+#define GESTUREINFO_sizeof() sizeof(GESTUREINFO)
+#else
+#define cacheGESTUREINFOFields(a,b)
+#define getGESTUREINFOFields(a,b,c) NULL
+#define setGESTUREINFOFields(a,b,c)
+#define GESTUREINFO_sizeof() 0
+#endif
+
+#ifndef NO_GRADIENT_RECT
+void cacheGRADIENT_RECTFields(JNIEnv *env, jobject lpObject);
+GRADIENT_RECT *getGRADIENT_RECTFields(JNIEnv *env, jobject lpObject, GRADIENT_RECT *lpStruct);
+void setGRADIENT_RECTFields(JNIEnv *env, jobject lpObject, GRADIENT_RECT *lpStruct);
+#define GRADIENT_RECT_sizeof() sizeof(GRADIENT_RECT)
+#else
+#define cacheGRADIENT_RECTFields(a,b)
+#define getGRADIENT_RECTFields(a,b,c) NULL
+#define setGRADIENT_RECTFields(a,b,c)
+#define GRADIENT_RECT_sizeof() 0
+#endif
+
+#ifndef NO_GUITHREADINFO
+void cacheGUITHREADINFOFields(JNIEnv *env, jobject lpObject);
+GUITHREADINFO *getGUITHREADINFOFields(JNIEnv *env, jobject lpObject, GUITHREADINFO *lpStruct);
+void setGUITHREADINFOFields(JNIEnv *env, jobject lpObject, GUITHREADINFO *lpStruct);
+#define GUITHREADINFO_sizeof() sizeof(GUITHREADINFO)
+#else
+#define cacheGUITHREADINFOFields(a,b)
+#define getGUITHREADINFOFields(a,b,c) NULL
+#define setGUITHREADINFOFields(a,b,c)
+#define GUITHREADINFO_sizeof() 0
+#endif
+
+#ifndef NO_HDHITTESTINFO
+void cacheHDHITTESTINFOFields(JNIEnv *env, jobject lpObject);
+HDHITTESTINFO *getHDHITTESTINFOFields(JNIEnv *env, jobject lpObject, HDHITTESTINFO *lpStruct);
+void setHDHITTESTINFOFields(JNIEnv *env, jobject lpObject, HDHITTESTINFO *lpStruct);
+#define HDHITTESTINFO_sizeof() sizeof(HDHITTESTINFO)
+#else
+#define cacheHDHITTESTINFOFields(a,b)
+#define getHDHITTESTINFOFields(a,b,c) NULL
+#define setHDHITTESTINFOFields(a,b,c)
+#define HDHITTESTINFO_sizeof() 0
+#endif
+
+#ifndef NO_HDITEM
+void cacheHDITEMFields(JNIEnv *env, jobject lpObject);
+HDITEM *getHDITEMFields(JNIEnv *env, jobject lpObject, HDITEM *lpStruct);
+void setHDITEMFields(JNIEnv *env, jobject lpObject, HDITEM *lpStruct);
+#define HDITEM_sizeof() sizeof(HDITEM)
+#else
+#define cacheHDITEMFields(a,b)
+#define getHDITEMFields(a,b,c) NULL
+#define setHDITEMFields(a,b,c)
+#define HDITEM_sizeof() 0
+#endif
+
+#ifndef NO_HDLAYOUT
+void cacheHDLAYOUTFields(JNIEnv *env, jobject lpObject);
+HDLAYOUT *getHDLAYOUTFields(JNIEnv *env, jobject lpObject, HDLAYOUT *lpStruct);
+void setHDLAYOUTFields(JNIEnv *env, jobject lpObject, HDLAYOUT *lpStruct);
+#define HDLAYOUT_sizeof() sizeof(HDLAYOUT)
+#else
+#define cacheHDLAYOUTFields(a,b)
+#define getHDLAYOUTFields(a,b,c) NULL
+#define setHDLAYOUTFields(a,b,c)
+#define HDLAYOUT_sizeof() 0
+#endif
+
+#ifndef NO_HELPINFO
+void cacheHELPINFOFields(JNIEnv *env, jobject lpObject);
+HELPINFO *getHELPINFOFields(JNIEnv *env, jobject lpObject, HELPINFO *lpStruct);
+void setHELPINFOFields(JNIEnv *env, jobject lpObject, HELPINFO *lpStruct);
+#define HELPINFO_sizeof() sizeof(HELPINFO)
+#else
+#define cacheHELPINFOFields(a,b)
+#define getHELPINFOFields(a,b,c) NULL
+#define setHELPINFOFields(a,b,c)
+#define HELPINFO_sizeof() 0
+#endif
+
+#ifndef NO_HIGHCONTRAST
+void cacheHIGHCONTRASTFields(JNIEnv *env, jobject lpObject);
+HIGHCONTRAST *getHIGHCONTRASTFields(JNIEnv *env, jobject lpObject, HIGHCONTRAST *lpStruct);
+void setHIGHCONTRASTFields(JNIEnv *env, jobject lpObject, HIGHCONTRAST *lpStruct);
+#define HIGHCONTRAST_sizeof() sizeof(HIGHCONTRAST)
+#else
+#define cacheHIGHCONTRASTFields(a,b)
+#define getHIGHCONTRASTFields(a,b,c) NULL
+#define setHIGHCONTRASTFields(a,b,c)
+#define HIGHCONTRAST_sizeof() 0
+#endif
+
+#ifndef NO_ICONINFO
+void cacheICONINFOFields(JNIEnv *env, jobject lpObject);
+ICONINFO *getICONINFOFields(JNIEnv *env, jobject lpObject, ICONINFO *lpStruct);
+void setICONINFOFields(JNIEnv *env, jobject lpObject, ICONINFO *lpStruct);
+#define ICONINFO_sizeof() sizeof(ICONINFO)
+#else
+#define cacheICONINFOFields(a,b)
+#define getICONINFOFields(a,b,c) NULL
+#define setICONINFOFields(a,b,c)
+#define ICONINFO_sizeof() 0
+#endif
+
+#ifndef NO_INITCOMMONCONTROLSEX
+void cacheINITCOMMONCONTROLSEXFields(JNIEnv *env, jobject lpObject);
+INITCOMMONCONTROLSEX *getINITCOMMONCONTROLSEXFields(JNIEnv *env, jobject lpObject, INITCOMMONCONTROLSEX *lpStruct);
+void setINITCOMMONCONTROLSEXFields(JNIEnv *env, jobject lpObject, INITCOMMONCONTROLSEX *lpStruct);
+#define INITCOMMONCONTROLSEX_sizeof() sizeof(INITCOMMONCONTROLSEX)
+#else
+#define cacheINITCOMMONCONTROLSEXFields(a,b)
+#define getINITCOMMONCONTROLSEXFields(a,b,c) NULL
+#define setINITCOMMONCONTROLSEXFields(a,b,c)
+#define INITCOMMONCONTROLSEX_sizeof() 0
+#endif
+
+#ifndef NO_INPUT
+void cacheINPUTFields(JNIEnv *env, jobject lpObject);
+INPUT *getINPUTFields(JNIEnv *env, jobject lpObject, INPUT *lpStruct);
+void setINPUTFields(JNIEnv *env, jobject lpObject, INPUT *lpStruct);
+#define INPUT_sizeof() sizeof(INPUT)
+#else
+#define cacheINPUTFields(a,b)
+#define getINPUTFields(a,b,c) NULL
+#define setINPUTFields(a,b,c)
+#define INPUT_sizeof() 0
+#endif
+
+#ifndef NO_KEYBDINPUT
+void cacheKEYBDINPUTFields(JNIEnv *env, jobject lpObject);
+KEYBDINPUT *getKEYBDINPUTFields(JNIEnv *env, jobject lpObject, KEYBDINPUT *lpStruct);
+void setKEYBDINPUTFields(JNIEnv *env, jobject lpObject, KEYBDINPUT *lpStruct);
+#define KEYBDINPUT_sizeof() sizeof(KEYBDINPUT)
+#else
+#define cacheKEYBDINPUTFields(a,b)
+#define getKEYBDINPUTFields(a,b,c) NULL
+#define setKEYBDINPUTFields(a,b,c)
+#define KEYBDINPUT_sizeof() 0
+#endif
+
+#ifndef NO_LITEM
+void cacheLITEMFields(JNIEnv *env, jobject lpObject);
+LITEM *getLITEMFields(JNIEnv *env, jobject lpObject, LITEM *lpStruct);
+void setLITEMFields(JNIEnv *env, jobject lpObject, LITEM *lpStruct);
+#define LITEM_sizeof() sizeof(LITEM)
+#else
+#define cacheLITEMFields(a,b)
+#define getLITEMFields(a,b,c) NULL
+#define setLITEMFields(a,b,c)
+#define LITEM_sizeof() 0
+#endif
+
+#ifndef NO_LOGBRUSH
+void cacheLOGBRUSHFields(JNIEnv *env, jobject lpObject);
+LOGBRUSH *getLOGBRUSHFields(JNIEnv *env, jobject lpObject, LOGBRUSH *lpStruct);
+void setLOGBRUSHFields(JNIEnv *env, jobject lpObject, LOGBRUSH *lpStruct);
+#define LOGBRUSH_sizeof() sizeof(LOGBRUSH)
+#else
+#define cacheLOGBRUSHFields(a,b)
+#define getLOGBRUSHFields(a,b,c) NULL
+#define setLOGBRUSHFields(a,b,c)
+#define LOGBRUSH_sizeof() 0
+#endif
+
+#ifndef NO_LOGFONT
+void cacheLOGFONTFields(JNIEnv *env, jobject lpObject);
+LOGFONT *getLOGFONTFields(JNIEnv *env, jobject lpObject, LOGFONT *lpStruct);
+void setLOGFONTFields(JNIEnv *env, jobject lpObject, LOGFONT *lpStruct);
+#define LOGFONT_sizeof() sizeof(LOGFONT)
+#else
+#define cacheLOGFONTFields(a,b)
+#define getLOGFONTFields(a,b,c) NULL
+#define setLOGFONTFields(a,b,c)
+#define LOGFONT_sizeof() 0
+#endif
+
+#ifndef NO_LOGPEN
+void cacheLOGPENFields(JNIEnv *env, jobject lpObject);
+LOGPEN *getLOGPENFields(JNIEnv *env, jobject lpObject, LOGPEN *lpStruct);
+void setLOGPENFields(JNIEnv *env, jobject lpObject, LOGPEN *lpStruct);
+#define LOGPEN_sizeof() sizeof(LOGPEN)
+#else
+#define cacheLOGPENFields(a,b)
+#define getLOGPENFields(a,b,c) NULL
+#define setLOGPENFields(a,b,c)
+#define LOGPEN_sizeof() 0
+#endif
+
+#ifndef NO_LVCOLUMN
+void cacheLVCOLUMNFields(JNIEnv *env, jobject lpObject);
+LVCOLUMN *getLVCOLUMNFields(JNIEnv *env, jobject lpObject, LVCOLUMN *lpStruct);
+void setLVCOLUMNFields(JNIEnv *env, jobject lpObject, LVCOLUMN *lpStruct);
+#define LVCOLUMN_sizeof() sizeof(LVCOLUMN)
+#else
+#define cacheLVCOLUMNFields(a,b)
+#define getLVCOLUMNFields(a,b,c) NULL
+#define setLVCOLUMNFields(a,b,c)
+#define LVCOLUMN_sizeof() 0
+#endif
+
+#ifndef NO_LVHITTESTINFO
+void cacheLVHITTESTINFOFields(JNIEnv *env, jobject lpObject);
+LVHITTESTINFO *getLVHITTESTINFOFields(JNIEnv *env, jobject lpObject, LVHITTESTINFO *lpStruct);
+void setLVHITTESTINFOFields(JNIEnv *env, jobject lpObject, LVHITTESTINFO *lpStruct);
+#define LVHITTESTINFO_sizeof() sizeof(LVHITTESTINFO)
+#else
+#define cacheLVHITTESTINFOFields(a,b)
+#define getLVHITTESTINFOFields(a,b,c) NULL
+#define setLVHITTESTINFOFields(a,b,c)
+#define LVHITTESTINFO_sizeof() 0
+#endif
+
+#ifndef NO_LVINSERTMARK
+void cacheLVINSERTMARKFields(JNIEnv *env, jobject lpObject);
+LVINSERTMARK *getLVINSERTMARKFields(JNIEnv *env, jobject lpObject, LVINSERTMARK *lpStruct);
+void setLVINSERTMARKFields(JNIEnv *env, jobject lpObject, LVINSERTMARK *lpStruct);
+#define LVINSERTMARK_sizeof() sizeof(LVINSERTMARK)
+#else
+#define cacheLVINSERTMARKFields(a,b)
+#define getLVINSERTMARKFields(a,b,c) NULL
+#define setLVINSERTMARKFields(a,b,c)
+#define LVINSERTMARK_sizeof() 0
+#endif
+
+#ifndef NO_LVITEM
+void cacheLVITEMFields(JNIEnv *env, jobject lpObject);
+LVITEM *getLVITEMFields(JNIEnv *env, jobject lpObject, LVITEM *lpStruct);
+void setLVITEMFields(JNIEnv *env, jobject lpObject, LVITEM *lpStruct);
+#define LVITEM_sizeof() sizeof(LVITEM)
+#else
+#define cacheLVITEMFields(a,b)
+#define getLVITEMFields(a,b,c) NULL
+#define setLVITEMFields(a,b,c)
+#define LVITEM_sizeof() 0
+#endif
+
+#ifndef NO_MARGINS
+void cacheMARGINSFields(JNIEnv *env, jobject lpObject);
+MARGINS *getMARGINSFields(JNIEnv *env, jobject lpObject, MARGINS *lpStruct);
+void setMARGINSFields(JNIEnv *env, jobject lpObject, MARGINS *lpStruct);
+#define MARGINS_sizeof() sizeof(MARGINS)
+#else
+#define cacheMARGINSFields(a,b)
+#define getMARGINSFields(a,b,c) NULL
+#define setMARGINSFields(a,b,c)
+#define MARGINS_sizeof() 0
+#endif
+
+#ifndef NO_MCHITTESTINFO
+void cacheMCHITTESTINFOFields(JNIEnv *env, jobject lpObject);
+MCHITTESTINFO *getMCHITTESTINFOFields(JNIEnv *env, jobject lpObject, MCHITTESTINFO *lpStruct);
+void setMCHITTESTINFOFields(JNIEnv *env, jobject lpObject, MCHITTESTINFO *lpStruct);
+#define MCHITTESTINFO_sizeof() sizeof(MCHITTESTINFO)
+#else
+#define cacheMCHITTESTINFOFields(a,b)
+#define getMCHITTESTINFOFields(a,b,c) NULL
+#define setMCHITTESTINFOFields(a,b,c)
+#define MCHITTESTINFO_sizeof() 0
+#endif
+
+#ifndef NO_MEASUREITEMSTRUCT
+void cacheMEASUREITEMSTRUCTFields(JNIEnv *env, jobject lpObject);
+MEASUREITEMSTRUCT *getMEASUREITEMSTRUCTFields(JNIEnv *env, jobject lpObject, MEASUREITEMSTRUCT *lpStruct);
+void setMEASUREITEMSTRUCTFields(JNIEnv *env, jobject lpObject, MEASUREITEMSTRUCT *lpStruct);
+#define MEASUREITEMSTRUCT_sizeof() sizeof(MEASUREITEMSTRUCT)
+#else
+#define cacheMEASUREITEMSTRUCTFields(a,b)
+#define getMEASUREITEMSTRUCTFields(a,b,c) NULL
+#define setMEASUREITEMSTRUCTFields(a,b,c)
+#define MEASUREITEMSTRUCT_sizeof() 0
+#endif
+
+#ifndef NO_MENUBARINFO
+void cacheMENUBARINFOFields(JNIEnv *env, jobject lpObject);
+MENUBARINFO *getMENUBARINFOFields(JNIEnv *env, jobject lpObject, MENUBARINFO *lpStruct);
+void setMENUBARINFOFields(JNIEnv *env, jobject lpObject, MENUBARINFO *lpStruct);
+#define MENUBARINFO_sizeof() sizeof(MENUBARINFO)
+#else
+#define cacheMENUBARINFOFields(a,b)
+#define getMENUBARINFOFields(a,b,c) NULL
+#define setMENUBARINFOFields(a,b,c)
+#define MENUBARINFO_sizeof() 0
+#endif
+
+#ifndef NO_MENUINFO
+void cacheMENUINFOFields(JNIEnv *env, jobject lpObject);
+MENUINFO *getMENUINFOFields(JNIEnv *env, jobject lpObject, MENUINFO *lpStruct);
+void setMENUINFOFields(JNIEnv *env, jobject lpObject, MENUINFO *lpStruct);
+#define MENUINFO_sizeof() sizeof(MENUINFO)
+#else
+#define cacheMENUINFOFields(a,b)
+#define getMENUINFOFields(a,b,c) NULL
+#define setMENUINFOFields(a,b,c)
+#define MENUINFO_sizeof() 0
+#endif
+
+#ifndef NO_MENUITEMINFO
+void cacheMENUITEMINFOFields(JNIEnv *env, jobject lpObject);
+MENUITEMINFO *getMENUITEMINFOFields(JNIEnv *env, jobject lpObject, MENUITEMINFO *lpStruct);
+void setMENUITEMINFOFields(JNIEnv *env, jobject lpObject, MENUITEMINFO *lpStruct);
+#define MENUITEMINFO_sizeof() sizeof(MENUITEMINFO)
+#else
+#define cacheMENUITEMINFOFields(a,b)
+#define getMENUITEMINFOFields(a,b,c) NULL
+#define setMENUITEMINFOFields(a,b,c)
+#define MENUITEMINFO_sizeof() 0
+#endif
+
+#ifndef NO_MINMAXINFO
+void cacheMINMAXINFOFields(JNIEnv *env, jobject lpObject);
+MINMAXINFO *getMINMAXINFOFields(JNIEnv *env, jobject lpObject, MINMAXINFO *lpStruct);
+void setMINMAXINFOFields(JNIEnv *env, jobject lpObject, MINMAXINFO *lpStruct);
+#define MINMAXINFO_sizeof() sizeof(MINMAXINFO)
+#else
+#define cacheMINMAXINFOFields(a,b)
+#define getMINMAXINFOFields(a,b,c) NULL
+#define setMINMAXINFOFields(a,b,c)
+#define MINMAXINFO_sizeof() 0
+#endif
+
+#ifndef NO_MONITORINFO
+void cacheMONITORINFOFields(JNIEnv *env, jobject lpObject);
+MONITORINFO *getMONITORINFOFields(JNIEnv *env, jobject lpObject, MONITORINFO *lpStruct);
+void setMONITORINFOFields(JNIEnv *env, jobject lpObject, MONITORINFO *lpStruct);
+#define MONITORINFO_sizeof() sizeof(MONITORINFO)
+#else
+#define cacheMONITORINFOFields(a,b)
+#define getMONITORINFOFields(a,b,c) NULL
+#define setMONITORINFOFields(a,b,c)
+#define MONITORINFO_sizeof() 0
+#endif
+
+#ifndef NO_MOUSEINPUT
+void cacheMOUSEINPUTFields(JNIEnv *env, jobject lpObject);
+MOUSEINPUT *getMOUSEINPUTFields(JNIEnv *env, jobject lpObject, MOUSEINPUT *lpStruct);
+void setMOUSEINPUTFields(JNIEnv *env, jobject lpObject, MOUSEINPUT *lpStruct);
+#define MOUSEINPUT_sizeof() sizeof(MOUSEINPUT)
+#else
+#define cacheMOUSEINPUTFields(a,b)
+#define getMOUSEINPUTFields(a,b,c) NULL
+#define setMOUSEINPUTFields(a,b,c)
+#define MOUSEINPUT_sizeof() 0
+#endif
+
+#ifndef NO_MSG
+void cacheMSGFields(JNIEnv *env, jobject lpObject);
+MSG *getMSGFields(JNIEnv *env, jobject lpObject, MSG *lpStruct);
+void setMSGFields(JNIEnv *env, jobject lpObject, MSG *lpStruct);
+#define MSG_sizeof() sizeof(MSG)
+#else
+#define cacheMSGFields(a,b)
+#define getMSGFields(a,b,c) NULL
+#define setMSGFields(a,b,c)
+#define MSG_sizeof() 0
+#endif
+
+#ifndef NO_NMCUSTOMDRAW
+void cacheNMCUSTOMDRAWFields(JNIEnv *env, jobject lpObject);
+NMCUSTOMDRAW *getNMCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMCUSTOMDRAW *lpStruct);
+void setNMCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMCUSTOMDRAW *lpStruct);
+#define NMCUSTOMDRAW_sizeof() sizeof(NMCUSTOMDRAW)
+#else
+#define cacheNMCUSTOMDRAWFields(a,b)
+#define getNMCUSTOMDRAWFields(a,b,c) NULL
+#define setNMCUSTOMDRAWFields(a,b,c)
+#define NMCUSTOMDRAW_sizeof() 0
+#endif
+
+#ifndef NO_NMHDR
+void cacheNMHDRFields(JNIEnv *env, jobject lpObject);
+NMHDR *getNMHDRFields(JNIEnv *env, jobject lpObject, NMHDR *lpStruct);
+void setNMHDRFields(JNIEnv *env, jobject lpObject, NMHDR *lpStruct);
+#define NMHDR_sizeof() sizeof(NMHDR)
+#else
+#define cacheNMHDRFields(a,b)
+#define getNMHDRFields(a,b,c) NULL
+#define setNMHDRFields(a,b,c)
+#define NMHDR_sizeof() 0
+#endif
+
+#ifndef NO_NMHEADER
+void cacheNMHEADERFields(JNIEnv *env, jobject lpObject);
+NMHEADER *getNMHEADERFields(JNIEnv *env, jobject lpObject, NMHEADER *lpStruct);
+void setNMHEADERFields(JNIEnv *env, jobject lpObject, NMHEADER *lpStruct);
+#define NMHEADER_sizeof() sizeof(NMHEADER)
+#else
+#define cacheNMHEADERFields(a,b)
+#define getNMHEADERFields(a,b,c) NULL
+#define setNMHEADERFields(a,b,c)
+#define NMHEADER_sizeof() 0
+#endif
+
+#ifndef NO_NMLINK
+void cacheNMLINKFields(JNIEnv *env, jobject lpObject);
+NMLINK *getNMLINKFields(JNIEnv *env, jobject lpObject, NMLINK *lpStruct);
+void setNMLINKFields(JNIEnv *env, jobject lpObject, NMLINK *lpStruct);
+#define NMLINK_sizeof() sizeof(NMLINK)
+#else
+#define cacheNMLINKFields(a,b)
+#define getNMLINKFields(a,b,c) NULL
+#define setNMLINKFields(a,b,c)
+#define NMLINK_sizeof() 0
+#endif
+
+#ifndef NO_NMLISTVIEW
+void cacheNMLISTVIEWFields(JNIEnv *env, jobject lpObject);
+NMLISTVIEW *getNMLISTVIEWFields(JNIEnv *env, jobject lpObject, NMLISTVIEW *lpStruct);
+void setNMLISTVIEWFields(JNIEnv *env, jobject lpObject, NMLISTVIEW *lpStruct);
+#define NMLISTVIEW_sizeof() sizeof(NMLISTVIEW)
+#else
+#define cacheNMLISTVIEWFields(a,b)
+#define getNMLISTVIEWFields(a,b,c) NULL
+#define setNMLISTVIEWFields(a,b,c)
+#define NMLISTVIEW_sizeof() 0
+#endif
+
+#ifndef NO_NMLVCUSTOMDRAW
+void cacheNMLVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject);
+NMLVCUSTOMDRAW *getNMLVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMLVCUSTOMDRAW *lpStruct);
+void setNMLVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMLVCUSTOMDRAW *lpStruct);
+#define NMLVCUSTOMDRAW_sizeof() sizeof(NMLVCUSTOMDRAW)
+#else
+#define cacheNMLVCUSTOMDRAWFields(a,b)
+#define getNMLVCUSTOMDRAWFields(a,b,c) NULL
+#define setNMLVCUSTOMDRAWFields(a,b,c)
+#define NMLVCUSTOMDRAW_sizeof() 0
+#endif
+
+#ifndef NO_NMLVDISPINFO
+void cacheNMLVDISPINFOFields(JNIEnv *env, jobject lpObject);
+NMLVDISPINFO *getNMLVDISPINFOFields(JNIEnv *env, jobject lpObject, NMLVDISPINFO *lpStruct);
+void setNMLVDISPINFOFields(JNIEnv *env, jobject lpObject, NMLVDISPINFO *lpStruct);
+#define NMLVDISPINFO_sizeof() sizeof(NMLVDISPINFO)
+#else
+#define cacheNMLVDISPINFOFields(a,b)
+#define getNMLVDISPINFOFields(a,b,c) NULL
+#define setNMLVDISPINFOFields(a,b,c)
+#define NMLVDISPINFO_sizeof() 0
+#endif
+
+#ifndef NO_NMLVFINDITEM
+void cacheNMLVFINDITEMFields(JNIEnv *env, jobject lpObject);
+NMLVFINDITEM *getNMLVFINDITEMFields(JNIEnv *env, jobject lpObject, NMLVFINDITEM *lpStruct);
+void setNMLVFINDITEMFields(JNIEnv *env, jobject lpObject, NMLVFINDITEM *lpStruct);
+#define NMLVFINDITEM_sizeof() sizeof(NMLVFINDITEM)
+#else
+#define cacheNMLVFINDITEMFields(a,b)
+#define getNMLVFINDITEMFields(a,b,c) NULL
+#define setNMLVFINDITEMFields(a,b,c)
+#define NMLVFINDITEM_sizeof() 0
+#endif
+
+#ifndef NO_NMLVODSTATECHANGE
+void cacheNMLVODSTATECHANGEFields(JNIEnv *env, jobject lpObject);
+NMLVODSTATECHANGE *getNMLVODSTATECHANGEFields(JNIEnv *env, jobject lpObject, NMLVODSTATECHANGE *lpStruct);
+void setNMLVODSTATECHANGEFields(JNIEnv *env, jobject lpObject, NMLVODSTATECHANGE *lpStruct);
+#define NMLVODSTATECHANGE_sizeof() sizeof(NMLVODSTATECHANGE)
+#else
+#define cacheNMLVODSTATECHANGEFields(a,b)
+#define getNMLVODSTATECHANGEFields(a,b,c) NULL
+#define setNMLVODSTATECHANGEFields(a,b,c)
+#define NMLVODSTATECHANGE_sizeof() 0
+#endif
+
+#ifndef NO_NMREBARCHEVRON
+void cacheNMREBARCHEVRONFields(JNIEnv *env, jobject lpObject);
+NMREBARCHEVRON *getNMREBARCHEVRONFields(JNIEnv *env, jobject lpObject, NMREBARCHEVRON *lpStruct);
+void setNMREBARCHEVRONFields(JNIEnv *env, jobject lpObject, NMREBARCHEVRON *lpStruct);
+#define NMREBARCHEVRON_sizeof() sizeof(NMREBARCHEVRON)
+#else
+#define cacheNMREBARCHEVRONFields(a,b)
+#define getNMREBARCHEVRONFields(a,b,c) NULL
+#define setNMREBARCHEVRONFields(a,b,c)
+#define NMREBARCHEVRON_sizeof() 0
+#endif
+
+#ifndef NO_NMREBARCHILDSIZE
+void cacheNMREBARCHILDSIZEFields(JNIEnv *env, jobject lpObject);
+NMREBARCHILDSIZE *getNMREBARCHILDSIZEFields(JNIEnv *env, jobject lpObject, NMREBARCHILDSIZE *lpStruct);
+void setNMREBARCHILDSIZEFields(JNIEnv *env, jobject lpObject, NMREBARCHILDSIZE *lpStruct);
+#define NMREBARCHILDSIZE_sizeof() sizeof(NMREBARCHILDSIZE)
+#else
+#define cacheNMREBARCHILDSIZEFields(a,b)
+#define getNMREBARCHILDSIZEFields(a,b,c) NULL
+#define setNMREBARCHILDSIZEFields(a,b,c)
+#define NMREBARCHILDSIZE_sizeof() 0
+#endif
+
+#ifndef NO_NMTBCUSTOMDRAW
+void cacheNMTBCUSTOMDRAWFields(JNIEnv *env, jobject lpObject);
+NMTBCUSTOMDRAW *getNMTBCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTBCUSTOMDRAW *lpStruct);
+void setNMTBCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTBCUSTOMDRAW *lpStruct);
+#define NMTBCUSTOMDRAW_sizeof() sizeof(NMTBCUSTOMDRAW)
+#else
+#define cacheNMTBCUSTOMDRAWFields(a,b)
+#define getNMTBCUSTOMDRAWFields(a,b,c) NULL
+#define setNMTBCUSTOMDRAWFields(a,b,c)
+#define NMTBCUSTOMDRAW_sizeof() 0
+#endif
+
+#ifndef NO_NMTBHOTITEM
+void cacheNMTBHOTITEMFields(JNIEnv *env, jobject lpObject);
+NMTBHOTITEM *getNMTBHOTITEMFields(JNIEnv *env, jobject lpObject, NMTBHOTITEM *lpStruct);
+void setNMTBHOTITEMFields(JNIEnv *env, jobject lpObject, NMTBHOTITEM *lpStruct);
+#define NMTBHOTITEM_sizeof() sizeof(NMTBHOTITEM)
+#else
+#define cacheNMTBHOTITEMFields(a,b)
+#define getNMTBHOTITEMFields(a,b,c) NULL
+#define setNMTBHOTITEMFields(a,b,c)
+#define NMTBHOTITEM_sizeof() 0
+#endif
+
+#ifndef NO_NMTOOLBAR
+void cacheNMTOOLBARFields(JNIEnv *env, jobject lpObject);
+NMTOOLBAR *getNMTOOLBARFields(JNIEnv *env, jobject lpObject, NMTOOLBAR *lpStruct);
+void setNMTOOLBARFields(JNIEnv *env, jobject lpObject, NMTOOLBAR *lpStruct);
+#define NMTOOLBAR_sizeof() sizeof(NMTOOLBAR)
+#else
+#define cacheNMTOOLBARFields(a,b)
+#define getNMTOOLBARFields(a,b,c) NULL
+#define setNMTOOLBARFields(a,b,c)
+#define NMTOOLBAR_sizeof() 0
+#endif
+
+#ifndef NO_NMTREEVIEW
+void cacheNMTREEVIEWFields(JNIEnv *env, jobject lpObject);
+NMTREEVIEW *getNMTREEVIEWFields(JNIEnv *env, jobject lpObject, NMTREEVIEW *lpStruct);
+void setNMTREEVIEWFields(JNIEnv *env, jobject lpObject, NMTREEVIEW *lpStruct);
+#define NMTREEVIEW_sizeof() sizeof(NMTREEVIEW)
+#else
+#define cacheNMTREEVIEWFields(a,b)
+#define getNMTREEVIEWFields(a,b,c) NULL
+#define setNMTREEVIEWFields(a,b,c)
+#define NMTREEVIEW_sizeof() 0
+#endif
+
+#ifndef NO_NMTTCUSTOMDRAW
+void cacheNMTTCUSTOMDRAWFields(JNIEnv *env, jobject lpObject);
+NMTTCUSTOMDRAW *getNMTTCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTTCUSTOMDRAW *lpStruct);
+void setNMTTCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTTCUSTOMDRAW *lpStruct);
+#define NMTTCUSTOMDRAW_sizeof() sizeof(NMTTCUSTOMDRAW)
+#else
+#define cacheNMTTCUSTOMDRAWFields(a,b)
+#define getNMTTCUSTOMDRAWFields(a,b,c) NULL
+#define setNMTTCUSTOMDRAWFields(a,b,c)
+#define NMTTCUSTOMDRAW_sizeof() 0
+#endif
+
+#ifndef NO_NMTTDISPINFO
+void cacheNMTTDISPINFOFields(JNIEnv *env, jobject lpObject);
+NMTTDISPINFO *getNMTTDISPINFOFields(JNIEnv *env, jobject lpObject, NMTTDISPINFO *lpStruct);
+void setNMTTDISPINFOFields(JNIEnv *env, jobject lpObject, NMTTDISPINFO *lpStruct);
+#define NMTTDISPINFO_sizeof() sizeof(NMTTDISPINFO)
+#else
+#define cacheNMTTDISPINFOFields(a,b)
+#define getNMTTDISPINFOFields(a,b,c) NULL
+#define setNMTTDISPINFOFields(a,b,c)
+#define NMTTDISPINFO_sizeof() 0
+#endif
+
+#ifndef NO_NMTVCUSTOMDRAW
+void cacheNMTVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject);
+NMTVCUSTOMDRAW *getNMTVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTVCUSTOMDRAW *lpStruct);
+void setNMTVCUSTOMDRAWFields(JNIEnv *env, jobject lpObject, NMTVCUSTOMDRAW *lpStruct);
+#define NMTVCUSTOMDRAW_sizeof() sizeof(NMTVCUSTOMDRAW)
+#else
+#define cacheNMTVCUSTOMDRAWFields(a,b)
+#define getNMTVCUSTOMDRAWFields(a,b,c) NULL
+#define setNMTVCUSTOMDRAWFields(a,b,c)
+#define NMTVCUSTOMDRAW_sizeof() 0
+#endif
+
+#ifndef NO_NMTVDISPINFO
+void cacheNMTVDISPINFOFields(JNIEnv *env, jobject lpObject);
+NMTVDISPINFO *getNMTVDISPINFOFields(JNIEnv *env, jobject lpObject, NMTVDISPINFO *lpStruct);
+void setNMTVDISPINFOFields(JNIEnv *env, jobject lpObject, NMTVDISPINFO *lpStruct);
+#define NMTVDISPINFO_sizeof() sizeof(NMTVDISPINFO)
+#else
+#define cacheNMTVDISPINFOFields(a,b)
+#define getNMTVDISPINFOFields(a,b,c) NULL
+#define setNMTVDISPINFOFields(a,b,c)
+#define NMTVDISPINFO_sizeof() 0
+#endif
+
+#ifndef NO_NMTVITEMCHANGE
+void cacheNMTVITEMCHANGEFields(JNIEnv *env, jobject lpObject);
+NMTVITEMCHANGE *getNMTVITEMCHANGEFields(JNIEnv *env, jobject lpObject, NMTVITEMCHANGE *lpStruct);
+void setNMTVITEMCHANGEFields(JNIEnv *env, jobject lpObject, NMTVITEMCHANGE *lpStruct);
+#define NMTVITEMCHANGE_sizeof() sizeof(NMTVITEMCHANGE)
+#else
+#define cacheNMTVITEMCHANGEFields(a,b)
+#define getNMTVITEMCHANGEFields(a,b,c) NULL
+#define setNMTVITEMCHANGEFields(a,b,c)
+#define NMTVITEMCHANGE_sizeof() 0
+#endif
+
+#ifndef NO_NMUPDOWN
+void cacheNMUPDOWNFields(JNIEnv *env, jobject lpObject);
+NMUPDOWN *getNMUPDOWNFields(JNIEnv *env, jobject lpObject, NMUPDOWN *lpStruct);
+void setNMUPDOWNFields(JNIEnv *env, jobject lpObject, NMUPDOWN *lpStruct);
+#define NMUPDOWN_sizeof() sizeof(NMUPDOWN)
+#else
+#define cacheNMUPDOWNFields(a,b)
+#define getNMUPDOWNFields(a,b,c) NULL
+#define setNMUPDOWNFields(a,b,c)
+#define NMUPDOWN_sizeof() 0
+#endif
+
+#ifndef NO_NONCLIENTMETRICS
+void cacheNONCLIENTMETRICSFields(JNIEnv *env, jobject lpObject);
+NONCLIENTMETRICS *getNONCLIENTMETRICSFields(JNIEnv *env, jobject lpObject, NONCLIENTMETRICS *lpStruct);
+void setNONCLIENTMETRICSFields(JNIEnv *env, jobject lpObject, NONCLIENTMETRICS *lpStruct);
+#define NONCLIENTMETRICS_sizeof() sizeof(NONCLIENTMETRICS)
+#else
+#define cacheNONCLIENTMETRICSFields(a,b)
+#define getNONCLIENTMETRICSFields(a,b,c) NULL
+#define setNONCLIENTMETRICSFields(a,b,c)
+#define NONCLIENTMETRICS_sizeof() 0
+#endif
+
+#ifndef NO_NOTIFYICONDATA
+void cacheNOTIFYICONDATAFields(JNIEnv *env, jobject lpObject);
+NOTIFYICONDATA *getNOTIFYICONDATAFields(JNIEnv *env, jobject lpObject, NOTIFYICONDATA *lpStruct);
+void setNOTIFYICONDATAFields(JNIEnv *env, jobject lpObject, NOTIFYICONDATA *lpStruct);
+#define NOTIFYICONDATA_sizeof() sizeof(NOTIFYICONDATA)
+#else
+#define cacheNOTIFYICONDATAFields(a,b)
+#define getNOTIFYICONDATAFields(a,b,c) NULL
+#define setNOTIFYICONDATAFields(a,b,c)
+#define NOTIFYICONDATA_sizeof() 0
+#endif
+
+#ifndef NO_OFNOTIFY
+void cacheOFNOTIFYFields(JNIEnv *env, jobject lpObject);
+OFNOTIFY *getOFNOTIFYFields(JNIEnv *env, jobject lpObject, OFNOTIFY *lpStruct);
+void setOFNOTIFYFields(JNIEnv *env, jobject lpObject, OFNOTIFY *lpStruct);
+#define OFNOTIFY_sizeof() sizeof(OFNOTIFY)
+#else
+#define cacheOFNOTIFYFields(a,b)
+#define getOFNOTIFYFields(a,b,c) NULL
+#define setOFNOTIFYFields(a,b,c)
+#define OFNOTIFY_sizeof() 0
+#endif
+
+#ifndef NO_OPENFILENAME
+void cacheOPENFILENAMEFields(JNIEnv *env, jobject lpObject);
+OPENFILENAME *getOPENFILENAMEFields(JNIEnv *env, jobject lpObject, OPENFILENAME *lpStruct);
+void setOPENFILENAMEFields(JNIEnv *env, jobject lpObject, OPENFILENAME *lpStruct);
+#define OPENFILENAME_sizeof() sizeof(OPENFILENAME)
+#else
+#define cacheOPENFILENAMEFields(a,b)
+#define getOPENFILENAMEFields(a,b,c) NULL
+#define setOPENFILENAMEFields(a,b,c)
+#define OPENFILENAME_sizeof() 0
+#endif
+
+#ifndef NO_OUTLINETEXTMETRIC
+void cacheOUTLINETEXTMETRICFields(JNIEnv *env, jobject lpObject);
+OUTLINETEXTMETRIC *getOUTLINETEXTMETRICFields(JNIEnv *env, jobject lpObject, OUTLINETEXTMETRIC *lpStruct);
+void setOUTLINETEXTMETRICFields(JNIEnv *env, jobject lpObject, OUTLINETEXTMETRIC *lpStruct);
+#define OUTLINETEXTMETRIC_sizeof() sizeof(OUTLINETEXTMETRIC)
+#else
+#define cacheOUTLINETEXTMETRICFields(a,b)
+#define getOUTLINETEXTMETRICFields(a,b,c) NULL
+#define setOUTLINETEXTMETRICFields(a,b,c)
+#define OUTLINETEXTMETRIC_sizeof() 0
+#endif
+
+#ifndef NO_PAINTSTRUCT
+void cachePAINTSTRUCTFields(JNIEnv *env, jobject lpObject);
+PAINTSTRUCT *getPAINTSTRUCTFields(JNIEnv *env, jobject lpObject, PAINTSTRUCT *lpStruct);
+void setPAINTSTRUCTFields(JNIEnv *env, jobject lpObject, PAINTSTRUCT *lpStruct);
+#define PAINTSTRUCT_sizeof() sizeof(PAINTSTRUCT)
+#else
+#define cachePAINTSTRUCTFields(a,b)
+#define getPAINTSTRUCTFields(a,b,c) NULL
+#define setPAINTSTRUCTFields(a,b,c)
+#define PAINTSTRUCT_sizeof() 0
+#endif
+
+#ifndef NO_PANOSE
+void cachePANOSEFields(JNIEnv *env, jobject lpObject);
+PANOSE *getPANOSEFields(JNIEnv *env, jobject lpObject, PANOSE *lpStruct);
+void setPANOSEFields(JNIEnv *env, jobject lpObject, PANOSE *lpStruct);
+#define PANOSE_sizeof() sizeof(PANOSE)
+#else
+#define cachePANOSEFields(a,b)
+#define getPANOSEFields(a,b,c) NULL
+#define setPANOSEFields(a,b,c)
+#define PANOSE_sizeof() 0
+#endif
+
+#ifndef NO_POINT
+void cachePOINTFields(JNIEnv *env, jobject lpObject);
+POINT *getPOINTFields(JNIEnv *env, jobject lpObject, POINT *lpStruct);
+void setPOINTFields(JNIEnv *env, jobject lpObject, POINT *lpStruct);
+#define POINT_sizeof() sizeof(POINT)
+#else
+#define cachePOINTFields(a,b)
+#define getPOINTFields(a,b,c) NULL
+#define setPOINTFields(a,b,c)
+#define POINT_sizeof() 0
+#endif
+
+#ifndef NO_PRINTDLG
+void cachePRINTDLGFields(JNIEnv *env, jobject lpObject);
+PRINTDLG *getPRINTDLGFields(JNIEnv *env, jobject lpObject, PRINTDLG *lpStruct);
+void setPRINTDLGFields(JNIEnv *env, jobject lpObject, PRINTDLG *lpStruct);
+#define PRINTDLG_sizeof() sizeof(PRINTDLG)
+#else
+#define cachePRINTDLGFields(a,b)
+#define getPRINTDLGFields(a,b,c) NULL
+#define setPRINTDLGFields(a,b,c)
+#define PRINTDLG_sizeof() 0
+#endif
+
+#ifndef NO_PROCESS_INFORMATION
+void cachePROCESS_INFORMATIONFields(JNIEnv *env, jobject lpObject);
+PROCESS_INFORMATION *getPROCESS_INFORMATIONFields(JNIEnv *env, jobject lpObject, PROCESS_INFORMATION *lpStruct);
+void setPROCESS_INFORMATIONFields(JNIEnv *env, jobject lpObject, PROCESS_INFORMATION *lpStruct);
+#define PROCESS_INFORMATION_sizeof() sizeof(PROCESS_INFORMATION)
+#else
+#define cachePROCESS_INFORMATIONFields(a,b)
+#define getPROCESS_INFORMATIONFields(a,b,c) NULL
+#define setPROCESS_INFORMATIONFields(a,b,c)
+#define PROCESS_INFORMATION_sizeof() 0
+#endif
+
+#ifndef NO_PROPERTYKEY
+void cachePROPERTYKEYFields(JNIEnv *env, jobject lpObject);
+PROPERTYKEY *getPROPERTYKEYFields(JNIEnv *env, jobject lpObject, PROPERTYKEY *lpStruct);
+void setPROPERTYKEYFields(JNIEnv *env, jobject lpObject, PROPERTYKEY *lpStruct);
+#define PROPERTYKEY_sizeof() sizeof(PROPERTYKEY)
+#else
+#define cachePROPERTYKEYFields(a,b)
+#define getPROPERTYKEYFields(a,b,c) NULL
+#define setPROPERTYKEYFields(a,b,c)
+#define PROPERTYKEY_sizeof() 0
+#endif
+
+#ifndef NO_REBARBANDINFO
+void cacheREBARBANDINFOFields(JNIEnv *env, jobject lpObject);
+REBARBANDINFO *getREBARBANDINFOFields(JNIEnv *env, jobject lpObject, REBARBANDINFO *lpStruct);
+void setREBARBANDINFOFields(JNIEnv *env, jobject lpObject, REBARBANDINFO *lpStruct);
+#define REBARBANDINFO_sizeof() sizeof(REBARBANDINFO)
+#else
+#define cacheREBARBANDINFOFields(a,b)
+#define getREBARBANDINFOFields(a,b,c) NULL
+#define setREBARBANDINFOFields(a,b,c)
+#define REBARBANDINFO_sizeof() 0
+#endif
+
+#ifndef NO_RECT
+void cacheRECTFields(JNIEnv *env, jobject lpObject);
+RECT *getRECTFields(JNIEnv *env, jobject lpObject, RECT *lpStruct);
+void setRECTFields(JNIEnv *env, jobject lpObject, RECT *lpStruct);
+#define RECT_sizeof() sizeof(RECT)
+#else
+#define cacheRECTFields(a,b)
+#define getRECTFields(a,b,c) NULL
+#define setRECTFields(a,b,c)
+#define RECT_sizeof() 0
+#endif
+
+#ifndef NO_SAFEARRAY
+void cacheSAFEARRAYFields(JNIEnv *env, jobject lpObject);
+SAFEARRAY *getSAFEARRAYFields(JNIEnv *env, jobject lpObject, SAFEARRAY *lpStruct);
+void setSAFEARRAYFields(JNIEnv *env, jobject lpObject, SAFEARRAY *lpStruct);
+#define SAFEARRAY_sizeof() sizeof(SAFEARRAY)
+#else
+#define cacheSAFEARRAYFields(a,b)
+#define getSAFEARRAYFields(a,b,c) NULL
+#define setSAFEARRAYFields(a,b,c)
+#define SAFEARRAY_sizeof() 0
+#endif
+
+#ifndef NO_SAFEARRAYBOUND
+void cacheSAFEARRAYBOUNDFields(JNIEnv *env, jobject lpObject);
+SAFEARRAYBOUND *getSAFEARRAYBOUNDFields(JNIEnv *env, jobject lpObject, SAFEARRAYBOUND *lpStruct);
+void setSAFEARRAYBOUNDFields(JNIEnv *env, jobject lpObject, SAFEARRAYBOUND *lpStruct);
+#define SAFEARRAYBOUND_sizeof() sizeof(SAFEARRAYBOUND)
+#else
+#define cacheSAFEARRAYBOUNDFields(a,b)
+#define getSAFEARRAYBOUNDFields(a,b,c) NULL
+#define setSAFEARRAYBOUNDFields(a,b,c)
+#define SAFEARRAYBOUND_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_ANALYSIS
+void cacheSCRIPT_ANALYSISFields(JNIEnv *env, jobject lpObject);
+SCRIPT_ANALYSIS *getSCRIPT_ANALYSISFields(JNIEnv *env, jobject lpObject, SCRIPT_ANALYSIS *lpStruct);
+void setSCRIPT_ANALYSISFields(JNIEnv *env, jobject lpObject, SCRIPT_ANALYSIS *lpStruct);
+#define SCRIPT_ANALYSIS_sizeof() sizeof(SCRIPT_ANALYSIS)
+#else
+#define cacheSCRIPT_ANALYSISFields(a,b)
+#define getSCRIPT_ANALYSISFields(a,b,c) NULL
+#define setSCRIPT_ANALYSISFields(a,b,c)
+#define SCRIPT_ANALYSIS_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_CONTROL
+void cacheSCRIPT_CONTROLFields(JNIEnv *env, jobject lpObject);
+SCRIPT_CONTROL *getSCRIPT_CONTROLFields(JNIEnv *env, jobject lpObject, SCRIPT_CONTROL *lpStruct);
+void setSCRIPT_CONTROLFields(JNIEnv *env, jobject lpObject, SCRIPT_CONTROL *lpStruct);
+#define SCRIPT_CONTROL_sizeof() sizeof(SCRIPT_CONTROL)
+#else
+#define cacheSCRIPT_CONTROLFields(a,b)
+#define getSCRIPT_CONTROLFields(a,b,c) NULL
+#define setSCRIPT_CONTROLFields(a,b,c)
+#define SCRIPT_CONTROL_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_DIGITSUBSTITUTE
+void cacheSCRIPT_DIGITSUBSTITUTEFields(JNIEnv *env, jobject lpObject);
+SCRIPT_DIGITSUBSTITUTE *getSCRIPT_DIGITSUBSTITUTEFields(JNIEnv *env, jobject lpObject, SCRIPT_DIGITSUBSTITUTE *lpStruct);
+void setSCRIPT_DIGITSUBSTITUTEFields(JNIEnv *env, jobject lpObject, SCRIPT_DIGITSUBSTITUTE *lpStruct);
+#define SCRIPT_DIGITSUBSTITUTE_sizeof() sizeof(SCRIPT_DIGITSUBSTITUTE)
+#else
+#define cacheSCRIPT_DIGITSUBSTITUTEFields(a,b)
+#define getSCRIPT_DIGITSUBSTITUTEFields(a,b,c) NULL
+#define setSCRIPT_DIGITSUBSTITUTEFields(a,b,c)
+#define SCRIPT_DIGITSUBSTITUTE_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_FONTPROPERTIES
+void cacheSCRIPT_FONTPROPERTIESFields(JNIEnv *env, jobject lpObject);
+SCRIPT_FONTPROPERTIES *getSCRIPT_FONTPROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_FONTPROPERTIES *lpStruct);
+void setSCRIPT_FONTPROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_FONTPROPERTIES *lpStruct);
+#define SCRIPT_FONTPROPERTIES_sizeof() sizeof(SCRIPT_FONTPROPERTIES)
+#else
+#define cacheSCRIPT_FONTPROPERTIESFields(a,b)
+#define getSCRIPT_FONTPROPERTIESFields(a,b,c) NULL
+#define setSCRIPT_FONTPROPERTIESFields(a,b,c)
+#define SCRIPT_FONTPROPERTIES_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_ITEM
+void cacheSCRIPT_ITEMFields(JNIEnv *env, jobject lpObject);
+SCRIPT_ITEM *getSCRIPT_ITEMFields(JNIEnv *env, jobject lpObject, SCRIPT_ITEM *lpStruct);
+void setSCRIPT_ITEMFields(JNIEnv *env, jobject lpObject, SCRIPT_ITEM *lpStruct);
+#define SCRIPT_ITEM_sizeof() sizeof(SCRIPT_ITEM)
+#else
+#define cacheSCRIPT_ITEMFields(a,b)
+#define getSCRIPT_ITEMFields(a,b,c) NULL
+#define setSCRIPT_ITEMFields(a,b,c)
+#define SCRIPT_ITEM_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_LOGATTR
+void cacheSCRIPT_LOGATTRFields(JNIEnv *env, jobject lpObject);
+SCRIPT_LOGATTR *getSCRIPT_LOGATTRFields(JNIEnv *env, jobject lpObject, SCRIPT_LOGATTR *lpStruct);
+void setSCRIPT_LOGATTRFields(JNIEnv *env, jobject lpObject, SCRIPT_LOGATTR *lpStruct);
+#define SCRIPT_LOGATTR_sizeof() sizeof(SCRIPT_LOGATTR)
+#else
+#define cacheSCRIPT_LOGATTRFields(a,b)
+#define getSCRIPT_LOGATTRFields(a,b,c) NULL
+#define setSCRIPT_LOGATTRFields(a,b,c)
+#define SCRIPT_LOGATTR_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_PROPERTIES
+void cacheSCRIPT_PROPERTIESFields(JNIEnv *env, jobject lpObject);
+SCRIPT_PROPERTIES *getSCRIPT_PROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_PROPERTIES *lpStruct);
+void setSCRIPT_PROPERTIESFields(JNIEnv *env, jobject lpObject, SCRIPT_PROPERTIES *lpStruct);
+#define SCRIPT_PROPERTIES_sizeof() sizeof(SCRIPT_PROPERTIES)
+#else
+#define cacheSCRIPT_PROPERTIESFields(a,b)
+#define getSCRIPT_PROPERTIESFields(a,b,c) NULL
+#define setSCRIPT_PROPERTIESFields(a,b,c)
+#define SCRIPT_PROPERTIES_sizeof() 0
+#endif
+
+#ifndef NO_SCRIPT_STATE
+void cacheSCRIPT_STATEFields(JNIEnv *env, jobject lpObject);
+SCRIPT_STATE *getSCRIPT_STATEFields(JNIEnv *env, jobject lpObject, SCRIPT_STATE *lpStruct);
+void setSCRIPT_STATEFields(JNIEnv *env, jobject lpObject, SCRIPT_STATE *lpStruct);
+#define SCRIPT_STATE_sizeof() sizeof(SCRIPT_STATE)
+#else
+#define cacheSCRIPT_STATEFields(a,b)
+#define getSCRIPT_STATEFields(a,b,c) NULL
+#define setSCRIPT_STATEFields(a,b,c)
+#define SCRIPT_STATE_sizeof() 0
+#endif
+
+#ifndef NO_SCROLLBARINFO
+void cacheSCROLLBARINFOFields(JNIEnv *env, jobject lpObject);
+SCROLLBARINFO *getSCROLLBARINFOFields(JNIEnv *env, jobject lpObject, SCROLLBARINFO *lpStruct);
+void setSCROLLBARINFOFields(JNIEnv *env, jobject lpObject, SCROLLBARINFO *lpStruct);
+#define SCROLLBARINFO_sizeof() sizeof(SCROLLBARINFO)
+#else
+#define cacheSCROLLBARINFOFields(a,b)
+#define getSCROLLBARINFOFields(a,b,c) NULL
+#define setSCROLLBARINFOFields(a,b,c)
+#define SCROLLBARINFO_sizeof() 0
+#endif
+
+#ifndef NO_SCROLLINFO
+void cacheSCROLLINFOFields(JNIEnv *env, jobject lpObject);
+SCROLLINFO *getSCROLLINFOFields(JNIEnv *env, jobject lpObject, SCROLLINFO *lpStruct);
+void setSCROLLINFOFields(JNIEnv *env, jobject lpObject, SCROLLINFO *lpStruct);
+#define SCROLLINFO_sizeof() sizeof(SCROLLINFO)
+#else
+#define cacheSCROLLINFOFields(a,b)
+#define getSCROLLINFOFields(a,b,c) NULL
+#define setSCROLLINFOFields(a,b,c)
+#define SCROLLINFO_sizeof() 0
+#endif
+
+#ifndef NO_SHDRAGIMAGE
+void cacheSHDRAGIMAGEFields(JNIEnv *env, jobject lpObject);
+SHDRAGIMAGE *getSHDRAGIMAGEFields(JNIEnv *env, jobject lpObject, SHDRAGIMAGE *lpStruct);
+void setSHDRAGIMAGEFields(JNIEnv *env, jobject lpObject, SHDRAGIMAGE *lpStruct);
+#define SHDRAGIMAGE_sizeof() sizeof(SHDRAGIMAGE)
+#else
+#define cacheSHDRAGIMAGEFields(a,b)
+#define getSHDRAGIMAGEFields(a,b,c) NULL
+#define setSHDRAGIMAGEFields(a,b,c)
+#define SHDRAGIMAGE_sizeof() 0
+#endif
+
+#ifndef NO_SHELLEXECUTEINFO
+void cacheSHELLEXECUTEINFOFields(JNIEnv *env, jobject lpObject);
+SHELLEXECUTEINFO *getSHELLEXECUTEINFOFields(JNIEnv *env, jobject lpObject, SHELLEXECUTEINFO *lpStruct);
+void setSHELLEXECUTEINFOFields(JNIEnv *env, jobject lpObject, SHELLEXECUTEINFO *lpStruct);
+#define SHELLEXECUTEINFO_sizeof() sizeof(SHELLEXECUTEINFO)
+#else
+#define cacheSHELLEXECUTEINFOFields(a,b)
+#define getSHELLEXECUTEINFOFields(a,b,c) NULL
+#define setSHELLEXECUTEINFOFields(a,b,c)
+#define SHELLEXECUTEINFO_sizeof() 0
+#endif
+
+#ifndef NO_SHFILEINFO
+void cacheSHFILEINFOFields(JNIEnv *env, jobject lpObject);
+SHFILEINFO *getSHFILEINFOFields(JNIEnv *env, jobject lpObject, SHFILEINFO *lpStruct);
+void setSHFILEINFOFields(JNIEnv *env, jobject lpObject, SHFILEINFO *lpStruct);
+#define SHFILEINFO_sizeof() sizeof(SHFILEINFO)
+#else
+#define cacheSHFILEINFOFields(a,b)
+#define getSHFILEINFOFields(a,b,c) NULL
+#define setSHFILEINFOFields(a,b,c)
+#define SHFILEINFO_sizeof() 0
+#endif
+
+#ifndef NO_SIZE
+void cacheSIZEFields(JNIEnv *env, jobject lpObject);
+SIZE *getSIZEFields(JNIEnv *env, jobject lpObject, SIZE *lpStruct);
+void setSIZEFields(JNIEnv *env, jobject lpObject, SIZE *lpStruct);
+#define SIZE_sizeof() sizeof(SIZE)
+#else
+#define cacheSIZEFields(a,b)
+#define getSIZEFields(a,b,c) NULL
+#define setSIZEFields(a,b,c)
+#define SIZE_sizeof() 0
+#endif
+
+#ifndef NO_STARTUPINFO
+void cacheSTARTUPINFOFields(JNIEnv *env, jobject lpObject);
+STARTUPINFO *getSTARTUPINFOFields(JNIEnv *env, jobject lpObject, STARTUPINFO *lpStruct);
+void setSTARTUPINFOFields(JNIEnv *env, jobject lpObject, STARTUPINFO *lpStruct);
+#define STARTUPINFO_sizeof() sizeof(STARTUPINFO)
+#else
+#define cacheSTARTUPINFOFields(a,b)
+#define getSTARTUPINFOFields(a,b,c) NULL
+#define setSTARTUPINFOFields(a,b,c)
+#define STARTUPINFO_sizeof() 0
+#endif
+
+#ifndef NO_SYSTEMTIME
+void cacheSYSTEMTIMEFields(JNIEnv *env, jobject lpObject);
+SYSTEMTIME *getSYSTEMTIMEFields(JNIEnv *env, jobject lpObject, SYSTEMTIME *lpStruct);
+void setSYSTEMTIMEFields(JNIEnv *env, jobject lpObject, SYSTEMTIME *lpStruct);
+#define SYSTEMTIME_sizeof() sizeof(SYSTEMTIME)
+#else
+#define cacheSYSTEMTIMEFields(a,b)
+#define getSYSTEMTIMEFields(a,b,c) NULL
+#define setSYSTEMTIMEFields(a,b,c)
+#define SYSTEMTIME_sizeof() 0
+#endif
+
+#ifndef NO_TBBUTTON
+void cacheTBBUTTONFields(JNIEnv *env, jobject lpObject);
+TBBUTTON *getTBBUTTONFields(JNIEnv *env, jobject lpObject, TBBUTTON *lpStruct);
+void setTBBUTTONFields(JNIEnv *env, jobject lpObject, TBBUTTON *lpStruct);
+#define TBBUTTON_sizeof() sizeof(TBBUTTON)
+#else
+#define cacheTBBUTTONFields(a,b)
+#define getTBBUTTONFields(a,b,c) NULL
+#define setTBBUTTONFields(a,b,c)
+#define TBBUTTON_sizeof() 0
+#endif
+
+#ifndef NO_TBBUTTONINFO
+void cacheTBBUTTONINFOFields(JNIEnv *env, jobject lpObject);
+TBBUTTONINFO *getTBBUTTONINFOFields(JNIEnv *env, jobject lpObject, TBBUTTONINFO *lpStruct);
+void setTBBUTTONINFOFields(JNIEnv *env, jobject lpObject, TBBUTTONINFO *lpStruct);
+#define TBBUTTONINFO_sizeof() sizeof(TBBUTTONINFO)
+#else
+#define cacheTBBUTTONINFOFields(a,b)
+#define getTBBUTTONINFOFields(a,b,c) NULL
+#define setTBBUTTONINFOFields(a,b,c)
+#define TBBUTTONINFO_sizeof() 0
+#endif
+
+#ifndef NO_TCHITTESTINFO
+void cacheTCHITTESTINFOFields(JNIEnv *env, jobject lpObject);
+TCHITTESTINFO *getTCHITTESTINFOFields(JNIEnv *env, jobject lpObject, TCHITTESTINFO *lpStruct);
+void setTCHITTESTINFOFields(JNIEnv *env, jobject lpObject, TCHITTESTINFO *lpStruct);
+#define TCHITTESTINFO_sizeof() sizeof(TCHITTESTINFO)
+#else
+#define cacheTCHITTESTINFOFields(a,b)
+#define getTCHITTESTINFOFields(a,b,c) NULL
+#define setTCHITTESTINFOFields(a,b,c)
+#define TCHITTESTINFO_sizeof() 0
+#endif
+
+#ifndef NO_TCITEM
+void cacheTCITEMFields(JNIEnv *env, jobject lpObject);
+TCITEM *getTCITEMFields(JNIEnv *env, jobject lpObject, TCITEM *lpStruct);
+void setTCITEMFields(JNIEnv *env, jobject lpObject, TCITEM *lpStruct);
+#define TCITEM_sizeof() sizeof(TCITEM)
+#else
+#define cacheTCITEMFields(a,b)
+#define getTCITEMFields(a,b,c) NULL
+#define setTCITEMFields(a,b,c)
+#define TCITEM_sizeof() 0
+#endif
+
+#ifndef NO_TEXTMETRIC
+void cacheTEXTMETRICFields(JNIEnv *env, jobject lpObject);
+TEXTMETRIC *getTEXTMETRICFields(JNIEnv *env, jobject lpObject, TEXTMETRIC *lpStruct);
+void setTEXTMETRICFields(JNIEnv *env, jobject lpObject, TEXTMETRIC *lpStruct);
+#define TEXTMETRIC_sizeof() sizeof(TEXTMETRIC)
+#else
+#define cacheTEXTMETRICFields(a,b)
+#define getTEXTMETRICFields(a,b,c) NULL
+#define setTEXTMETRICFields(a,b,c)
+#define TEXTMETRIC_sizeof() 0
+#endif
+
+#ifndef NO_TF_DA_COLOR
+void cacheTF_DA_COLORFields(JNIEnv *env, jobject lpObject);
+TF_DA_COLOR *getTF_DA_COLORFields(JNIEnv *env, jobject lpObject, TF_DA_COLOR *lpStruct);
+void setTF_DA_COLORFields(JNIEnv *env, jobject lpObject, TF_DA_COLOR *lpStruct);
+#define TF_DA_COLOR_sizeof() sizeof(TF_DA_COLOR)
+#else
+#define cacheTF_DA_COLORFields(a,b)
+#define getTF_DA_COLORFields(a,b,c) NULL
+#define setTF_DA_COLORFields(a,b,c)
+#define TF_DA_COLOR_sizeof() 0
+#endif
+
+#ifndef NO_TF_DISPLAYATTRIBUTE
+void cacheTF_DISPLAYATTRIBUTEFields(JNIEnv *env, jobject lpObject);
+TF_DISPLAYATTRIBUTE *getTF_DISPLAYATTRIBUTEFields(JNIEnv *env, jobject lpObject, TF_DISPLAYATTRIBUTE *lpStruct);
+void setTF_DISPLAYATTRIBUTEFields(JNIEnv *env, jobject lpObject, TF_DISPLAYATTRIBUTE *lpStruct);
+#define TF_DISPLAYATTRIBUTE_sizeof() sizeof(TF_DISPLAYATTRIBUTE)
+#else
+#define cacheTF_DISPLAYATTRIBUTEFields(a,b)
+#define getTF_DISPLAYATTRIBUTEFields(a,b,c) NULL
+#define setTF_DISPLAYATTRIBUTEFields(a,b,c)
+#define TF_DISPLAYATTRIBUTE_sizeof() 0
+#endif
+
+#ifndef NO_TOOLINFO
+void cacheTOOLINFOFields(JNIEnv *env, jobject lpObject);
+TOOLINFO *getTOOLINFOFields(JNIEnv *env, jobject lpObject, TOOLINFO *lpStruct);
+void setTOOLINFOFields(JNIEnv *env, jobject lpObject, TOOLINFO *lpStruct);
+#define TOOLINFO_sizeof() sizeof(TOOLINFO)
+#else
+#define cacheTOOLINFOFields(a,b)
+#define getTOOLINFOFields(a,b,c) NULL
+#define setTOOLINFOFields(a,b,c)
+#define TOOLINFO_sizeof() 0
+#endif
+
+#ifndef NO_TOUCHINPUT
+void cacheTOUCHINPUTFields(JNIEnv *env, jobject lpObject);
+TOUCHINPUT *getTOUCHINPUTFields(JNIEnv *env, jobject lpObject, TOUCHINPUT *lpStruct);
+void setTOUCHINPUTFields(JNIEnv *env, jobject lpObject, TOUCHINPUT *lpStruct);
+#define TOUCHINPUT_sizeof() sizeof(TOUCHINPUT)
+#else
+#define cacheTOUCHINPUTFields(a,b)
+#define getTOUCHINPUTFields(a,b,c) NULL
+#define setTOUCHINPUTFields(a,b,c)
+#define TOUCHINPUT_sizeof() 0
+#endif
+
+#ifndef NO_TRACKMOUSEEVENT
+void cacheTRACKMOUSEEVENTFields(JNIEnv *env, jobject lpObject);
+TRACKMOUSEEVENT *getTRACKMOUSEEVENTFields(JNIEnv *env, jobject lpObject, TRACKMOUSEEVENT *lpStruct);
+void setTRACKMOUSEEVENTFields(JNIEnv *env, jobject lpObject, TRACKMOUSEEVENT *lpStruct);
+#define TRACKMOUSEEVENT_sizeof() sizeof(TRACKMOUSEEVENT)
+#else
+#define cacheTRACKMOUSEEVENTFields(a,b)
+#define getTRACKMOUSEEVENTFields(a,b,c) NULL
+#define setTRACKMOUSEEVENTFields(a,b,c)
+#define TRACKMOUSEEVENT_sizeof() 0
+#endif
+
+#ifndef NO_TRIVERTEX
+void cacheTRIVERTEXFields(JNIEnv *env, jobject lpObject);
+TRIVERTEX *getTRIVERTEXFields(JNIEnv *env, jobject lpObject, TRIVERTEX *lpStruct);
+void setTRIVERTEXFields(JNIEnv *env, jobject lpObject, TRIVERTEX *lpStruct);
+#define TRIVERTEX_sizeof() sizeof(TRIVERTEX)
+#else
+#define cacheTRIVERTEXFields(a,b)
+#define getTRIVERTEXFields(a,b,c) NULL
+#define setTRIVERTEXFields(a,b,c)
+#define TRIVERTEX_sizeof() 0
+#endif
+
+#ifndef NO_TVHITTESTINFO
+void cacheTVHITTESTINFOFields(JNIEnv *env, jobject lpObject);
+TVHITTESTINFO *getTVHITTESTINFOFields(JNIEnv *env, jobject lpObject, TVHITTESTINFO *lpStruct);
+void setTVHITTESTINFOFields(JNIEnv *env, jobject lpObject, TVHITTESTINFO *lpStruct);
+#define TVHITTESTINFO_sizeof() sizeof(TVHITTESTINFO)
+#else
+#define cacheTVHITTESTINFOFields(a,b)
+#define getTVHITTESTINFOFields(a,b,c) NULL
+#define setTVHITTESTINFOFields(a,b,c)
+#define TVHITTESTINFO_sizeof() 0
+#endif
+
+#ifndef NO_TVINSERTSTRUCT
+void cacheTVINSERTSTRUCTFields(JNIEnv *env, jobject lpObject);
+TVINSERTSTRUCT *getTVINSERTSTRUCTFields(JNIEnv *env, jobject lpObject, TVINSERTSTRUCT *lpStruct);
+void setTVINSERTSTRUCTFields(JNIEnv *env, jobject lpObject, TVINSERTSTRUCT *lpStruct);
+#define TVINSERTSTRUCT_sizeof() sizeof(TVINSERTSTRUCT)
+#else
+#define cacheTVINSERTSTRUCTFields(a,b)
+#define getTVINSERTSTRUCTFields(a,b,c) NULL
+#define setTVINSERTSTRUCTFields(a,b,c)
+#define TVINSERTSTRUCT_sizeof() 0
+#endif
+
+#ifndef NO_TVITEM
+void cacheTVITEMFields(JNIEnv *env, jobject lpObject);
+TVITEM *getTVITEMFields(JNIEnv *env, jobject lpObject, TVITEM *lpStruct);
+void setTVITEMFields(JNIEnv *env, jobject lpObject, TVITEM *lpStruct);
+#define TVITEM_sizeof() sizeof(TVITEM)
+#else
+#define cacheTVITEMFields(a,b)
+#define getTVITEMFields(a,b,c) NULL
+#define setTVITEMFields(a,b,c)
+#define TVITEM_sizeof() 0
+#endif
+
+#ifndef NO_TVITEMEX
+void cacheTVITEMEXFields(JNIEnv *env, jobject lpObject);
+TVITEMEX *getTVITEMEXFields(JNIEnv *env, jobject lpObject, TVITEMEX *lpStruct);
+void setTVITEMEXFields(JNIEnv *env, jobject lpObject, TVITEMEX *lpStruct);
+#define TVITEMEX_sizeof() sizeof(TVITEMEX)
+#else
+#define cacheTVITEMEXFields(a,b)
+#define getTVITEMEXFields(a,b,c) NULL
+#define setTVITEMEXFields(a,b,c)
+#define TVITEMEX_sizeof() 0
+#endif
+
+#ifndef NO_TVSORTCB
+void cacheTVSORTCBFields(JNIEnv *env, jobject lpObject);
+TVSORTCB *getTVSORTCBFields(JNIEnv *env, jobject lpObject, TVSORTCB *lpStruct);
+void setTVSORTCBFields(JNIEnv *env, jobject lpObject, TVSORTCB *lpStruct);
+#define TVSORTCB_sizeof() sizeof(TVSORTCB)
+#else
+#define cacheTVSORTCBFields(a,b)
+#define getTVSORTCBFields(a,b,c) NULL
+#define setTVSORTCBFields(a,b,c)
+#define TVSORTCB_sizeof() 0
+#endif
+
+#ifndef NO_UDACCEL
+void cacheUDACCELFields(JNIEnv *env, jobject lpObject);
+UDACCEL *getUDACCELFields(JNIEnv *env, jobject lpObject, UDACCEL *lpStruct);
+void setUDACCELFields(JNIEnv *env, jobject lpObject, UDACCEL *lpStruct);
+#define UDACCEL_sizeof() sizeof(UDACCEL)
+#else
+#define cacheUDACCELFields(a,b)
+#define getUDACCELFields(a,b,c) NULL
+#define setUDACCELFields(a,b,c)
+#define UDACCEL_sizeof() 0
+#endif
+
+#ifndef NO_WINDOWPLACEMENT
+void cacheWINDOWPLACEMENTFields(JNIEnv *env, jobject lpObject);
+WINDOWPLACEMENT *getWINDOWPLACEMENTFields(JNIEnv *env, jobject lpObject, WINDOWPLACEMENT *lpStruct);
+void setWINDOWPLACEMENTFields(JNIEnv *env, jobject lpObject, WINDOWPLACEMENT *lpStruct);
+#define WINDOWPLACEMENT_sizeof() sizeof(WINDOWPLACEMENT)
+#else
+#define cacheWINDOWPLACEMENTFields(a,b)
+#define getWINDOWPLACEMENTFields(a,b,c) NULL
+#define setWINDOWPLACEMENTFields(a,b,c)
+#define WINDOWPLACEMENT_sizeof() 0
+#endif
+
+#ifndef NO_WINDOWPOS
+void cacheWINDOWPOSFields(JNIEnv *env, jobject lpObject);
+WINDOWPOS *getWINDOWPOSFields(JNIEnv *env, jobject lpObject, WINDOWPOS *lpStruct);
+void setWINDOWPOSFields(JNIEnv *env, jobject lpObject, WINDOWPOS *lpStruct);
+#define WINDOWPOS_sizeof() sizeof(WINDOWPOS)
+#else
+#define cacheWINDOWPOSFields(a,b)
+#define getWINDOWPOSFields(a,b,c) NULL
+#define setWINDOWPOSFields(a,b,c)
+#define WINDOWPOS_sizeof() 0
+#endif
+
+#ifndef NO_WNDCLASS
+void cacheWNDCLASSFields(JNIEnv *env, jobject lpObject);
+WNDCLASS *getWNDCLASSFields(JNIEnv *env, jobject lpObject, WNDCLASS *lpStruct);
+void setWNDCLASSFields(JNIEnv *env, jobject lpObject, WNDCLASS *lpStruct);
+#define WNDCLASS_sizeof() sizeof(WNDCLASS)
+#else
+#define cacheWNDCLASSFields(a,b)
+#define getWNDCLASSFields(a,b,c) NULL
+#define setWNDCLASSFields(a,b,c)
+#define WNDCLASS_sizeof() 0
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/search.ico b/bundles/org.eclipse.swt.win32.win32.x86_64/library/search.ico
new file mode 100644 (file)
index 0000000..5eaf35c
Binary files /dev/null and b/bundles/org.eclipse.swt.win32.win32.x86_64/library/search.ico differ
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.c
new file mode 100644 (file)
index 0000000..3e7d47c
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+#include "swt.h"
+
+int IS_JNI_1_2 = 0;
+
+#ifdef JNI_VERSION_1_2
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+       IS_JNI_1_2 = 1;
+       return JNI_VERSION_1_2;
+}
+#endif
+
+void throwOutOfMemory(JNIEnv *env) {
+       jclass clazz = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
+       if (clazz != NULL) {
+               (*env)->ThrowNew(env, clazz, "");
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.h
new file mode 100644 (file)
index 0000000..61122b8
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/**
+ * swt.h
+ *
+ * This file contains the global macro declarations for the
+ * SWT library.
+ *
+ */
+
+#ifndef INC_swt_H
+#define INC_swt_H
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int IS_JNI_1_2;
+
+/* #define DEBUG */
+
+/* if DEBUG is defined print messages from dlerror */
+#ifdef DEBUG
+#define CHECK_DLERROR \
+    char* error = dlerror(); \
+    if (error != NULL) { \
+        fprintf(stderr, "dlerror: %s\n", error); \
+    }
+#else
+#define CHECK_DLERROR
+#endif
+
+#ifndef JNI64
+#if __x86_64__
+#define JNI64
+#endif
+#endif
+
+/* 64 bit support */
+#ifndef JNI64
+
+/* int/long defines */
+#define GetIntLongField GetIntField
+#define SetIntLongField SetIntField
+#define GetIntLongArrayElements GetIntArrayElements
+#define ReleaseIntLongArrayElements ReleaseIntArrayElements
+#define GetIntLongArrayRegion GetIntArrayRegion
+#define SetIntLongArrayRegion SetIntArrayRegion
+#define NewIntLongArray NewIntArray
+#define CallStaticIntLongMethod CallStaticIntMethod
+#define CallIntLongMethod CallIntMethod
+#define CallStaticIntLongMethodV CallStaticIntMethodV
+#define CallIntLongMethodV CallIntMethodV
+#define jintLongArray jintArray
+#define jintLong jint
+#define I_J "I"
+#define I_JArray "[I"
+
+/* float/double defines */
+#define GetFloatDoubleField GetFloatField
+#define SetFloatDoubleField SetFloatField
+#define GetFloatDoubleArrayElements GetFloatArrayElements
+#define ReleaseFloatDoubleArrayElements ReleaseFloatArrayElements
+#define GetFloatDoubleArrayRegion GetFloatArrayRegion
+#define jfloatDoubleArray jfloatArray
+#define jfloatDouble jfloat
+#define F_D "F"
+#define F_DArray "[F"
+
+#else
+
+/* int/long defines */
+#define GetIntLongField GetLongField
+#define SetIntLongField SetLongField
+#define GetIntLongArrayElements GetLongArrayElements
+#define ReleaseIntLongArrayElements ReleaseLongArrayElements
+#define GetIntLongArrayRegion GetLongArrayRegion
+#define SetIntLongArrayRegion SetLongArrayRegion
+#define NewIntLongArray NewLongArray
+#define CallStaticIntLongMethod CallStaticLongMethod
+#define CallIntLongMethod CallLongMethod
+#define CallStaticIntLongMethodV CallStaticLongMethodV
+#define CallIntLongMethodV CallLongMethodV
+#define jintLongArray jlongArray
+#define jintLong jlong
+#define I_J "J"
+#define I_JArray "[J"
+
+/* float/double defines */
+#define GetFloatDoubleField GetDoubleField
+#define SetFloatDoubleField SetDoubleField
+#define GetFloatDoubleArrayElements GetDoubleArrayElements
+#define ReleaseFloatDoubleArrayElements ReleaseDoubleArrayElements
+#define GetFloatDoubleArrayRegion GetDoubleArrayRegion
+#define jfloatDoubleArray jdoubleArray
+#define jfloatDouble jdouble
+#define F_D "D"
+#define F_DArray "[D"
+
+#endif
+
+#ifdef __APPLE__
+#define CALLING_CONVENTION
+#define LOAD_FUNCTION(var, name) \
+               static int initialized = 0; \
+               static void *var = NULL; \
+               if (!initialized) { \
+                       CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR(name##_LIB)); \
+                       if (bundle) var = CFBundleGetFunctionPointerForName(bundle, CFSTR(#name)); \
+                       initialized = 1; \
+               } 
+#elif defined (_WIN32) || defined (_WIN32_WCE)
+#define CALLING_CONVENTION CALLBACK
+#define LOAD_FUNCTION(var, name) \
+               static int initialized = 0; \
+               static FARPROC var = NULL; \
+               if (!initialized) { \
+                       HMODULE hm = LoadLibraryA(name##_LIB); \
+                       if (hm) var = GetProcAddress(hm, #name); \
+                       initialized = 1; \
+               }
+#else
+#define CALLING_CONVENTION
+#define LOAD_FLAGS RTLD_LAZY
+#define LOAD_FUNCTION(var, name) \
+               static int initialized = 0; \
+               static void *var = NULL; \
+               if (!initialized) { \
+                       void* handle = dlopen(name##_LIB, LOAD_FLAGS); \
+                       if (handle) var = dlsym(handle, #name); \
+                       initialized = 1; \
+                       CHECK_DLERROR \
+               }
+#endif
+
+void throwOutOfMemory(JNIEnv *env);
+
+#define CHECK_NULL_VOID(ptr) \
+       if ((ptr) == NULL) { \
+               throwOutOfMemory(env); \
+               return; \
+       }
+
+#define CHECK_NULL(ptr) \
+       if ((ptr) == NULL) { \
+               throwOutOfMemory(env); \
+               return 0; \
+       }
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif /* ifndef INC_swt_H */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.rc b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt.rc
new file mode 100644 (file)
index 0000000..3057b6d
--- /dev/null
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+#include "windows.h"
+
+/* NOTE: PUTTING NEW LINES IN THE MANIFEST FILE CAUSES IT TO FAIL */
+#define MANIFEST_RESOURCE_ID 2
+MANIFEST_RESOURCE_ID RT_MANIFEST "javaw.exe.manifest"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SWT_COMMA_VERSION
+ PRODUCTVERSION 0,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName", "Eclipse Foundation\0"
+            VALUE "FileDescription", "SWT for Windows native library\0"
+            VALUE "FileVersion", SWT_FILE_VERSION
+            VALUE "InternalName", "SWT\0"
+            VALUE "LegalCopyright", "Copyright (c) 2000, 2011 IBM Corp.  All Rights Reserved.\0"
+            VALUE "OriginalFilename", SWT_ORG_FILENAME
+            VALUE "ProductName", "Standard Widget Toolkit\0"
+            VALUE "ProductVersion", "0,0,0,0\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+/* Icons for Text widget */
+101 ICON "search.ico"
+102 ICON "cancel.ico"
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_awt.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_awt.c
new file mode 100644 (file)
index 0000000..98aff60
--- /dev/null
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#include "swt.h"
+#include "jawt_md.h"
+
+#define SWT_AWT_NATIVE(func) Java_org_eclipse_swt_awt_SWT_1AWT_##func
+
+#ifndef NO_getAWTHandle
+JNIEXPORT jintLong JNICALL SWT_AWT_NATIVE(getAWTHandle)
+       (JNIEnv *env, jclass that, jobject canvas)
+{
+       JAWT awt;
+       JAWT_DrawingSurface* ds;
+       JAWT_DrawingSurfaceInfo* dsi;
+       JAWT_Win32DrawingSurfaceInfo* dsi_win;
+       jintLong result = 0;
+       jint lock;
+
+       awt.version = JAWT_VERSION_1_3;
+       if (JAWT_GetAWT(env, &awt) != 0) {
+               ds = awt.GetDrawingSurface(env, canvas);
+               if (ds != NULL) {
+                       lock = ds->Lock(ds);
+                       if ((lock & JAWT_LOCK_ERROR) == 0) {
+                               dsi = ds->GetDrawingSurfaceInfo(ds);
+                               dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
+                               result = (jintLong)dsi_win->hwnd;
+                               ds->FreeDrawingSurfaceInfo(dsi);
+                               ds->Unlock(ds);
+                       }
+               }
+               awt.FreeDrawingSurface(ds);
+       }
+       return result;
+}
+#endif
+
+#ifndef NO_initFrame
+JNIEXPORT jobject JNICALL SWT_AWT_NATIVE(initFrame)
+       (JNIEnv *env, jclass that, jintLong handle, jstring className)
+{
+       jobject object;
+       jmethodID constructor;
+       
+       jclass cls = (*env)->FindClass(env, "sun/awt/windows/WEmbeddedFrame");
+       if (NULL == cls) return NULL;
+       constructor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
+       object = (*env)->NewObject(env, cls, constructor, handle);
+       return object;
+}
+#endif
+
+#ifndef NO_synthesizeWindowActivation
+JNIEXPORT void JNICALL SWT_AWT_NATIVE(synthesizeWindowActivation)
+(JNIEnv *env, jclass that, jobject frame, jboolean doActivate)
+{
+       jmethodID midInit;
+    jclass cls = (*env)->FindClass(env, "sun/awt/windows/WEmbeddedFrame");
+    if (NULL == cls) return;
+    midInit = (*env)->GetMethodID(env, cls, "synthesizeWindowActivation", "(Z)V");
+    (*env)->CallVoidMethod(env, frame, midInit, doActivate);
+}
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_awt.rc b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_awt.rc
new file mode 100644 (file)
index 0000000..5686c8c
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+#include "windows.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SWT_COMMA_VERSION
+ PRODUCTVERSION 0,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName", "Eclipse Foundation\0"
+            VALUE "FileDescription", "SWT for Windows native library\0"
+            VALUE "FileVersion", SWT_FILE_VERSION
+            VALUE "InternalName", "SWT\0"
+            VALUE "LegalCopyright", "Copyright (c) 2000, 2006 IBM Corp.  All Rights Reserved.\0"
+            VALUE "OriginalFilename", SWT_ORG_FILENAME
+            VALUE "ProductName", "Standard Widget Toolkit\0"
+            VALUE "ProductVersion", "0,0,0,0\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_gdip.rc b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_gdip.rc
new file mode 100644 (file)
index 0000000..365e686
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+#include "windows.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SWT_COMMA_VERSION
+ PRODUCTVERSION 0,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName", "Eclipse Foundation\0"
+            VALUE "FileDescription", "SWT for Windows native library\0"
+            VALUE "FileVersion", SWT_FILE_VERSION
+            VALUE "InternalName", "SWT\0"
+            VALUE "LegalCopyright", "Copyright (c) 2000, 2011 IBM Corp.  All Rights Reserved.\0"
+            VALUE "OriginalFilename", SWT_ORG_FILENAME
+            VALUE "ProductName", "Standard Widget Toolkit\0"
+            VALUE "ProductVersion", "0,0,0,0\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_webkit.rc b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_webkit.rc
new file mode 100644 (file)
index 0000000..1a97590
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+#include "windows.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SWT_COMMA_VERSION
+ PRODUCTVERSION 0,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName", "Eclipse Foundation\0"
+            VALUE "FileDescription", "SWT for Windows native library\0"
+            VALUE "FileVersion", SWT_FILE_VERSION
+            VALUE "InternalName", "SWT\0"
+            VALUE "LegalCopyright", "Copyright (c) 2010 IBM Corp.  All Rights Reserved.\0"
+            VALUE "OriginalFilename", SWT_ORG_FILENAME
+            VALUE "ProductName", "Standard Widget Toolkit\0"
+            VALUE "ProductVersion", "0,0,0,0\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_wgl.rc b/bundles/org.eclipse.swt.win32.win32.x86_64/library/swt_wgl.rc
new file mode 100644 (file)
index 0000000..5686c8c
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+#include "windows.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SWT_COMMA_VERSION
+ PRODUCTVERSION 0,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName", "Eclipse Foundation\0"
+            VALUE "FileDescription", "SWT for Windows native library\0"
+            VALUE "FileVersion", SWT_FILE_VERSION
+            VALUE "InternalName", "SWT\0"
+            VALUE "LegalCopyright", "Copyright (c) 2000, 2006 IBM Corp.  All Rights Reserved.\0"
+            VALUE "OriginalFilename", SWT_ORG_FILENAME
+            VALUE "ProductName", "Standard Widget Toolkit\0"
+            VALUE "ProductVersion", "0,0,0,0\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32.cpp
new file mode 100644 (file)
index 0000000..2382805
--- /dev/null
@@ -0,0 +1,786 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 IBM Corporation and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html.  If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "webkit_win32_structs.h"
+#include "webkit_win32_stats.h"
+
+#ifndef WebKit_win32_NATIVE
+#define WebKit_win32_NATIVE(func) Java_org_eclipse_swt_internal_webkit_WebKit_1win32_##func
+#endif
+
+#ifndef NO_CFArrayGetCount
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFArrayGetCount)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFArrayGetCount)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFArrayGetCount_FUNC);
+       rc = (jint)CFArrayGetCount((CFArrayRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFArrayGetCount_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFArrayGetValueAtIndex
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFArrayGetValueAtIndex)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFArrayGetValueAtIndex)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFArrayGetValueAtIndex_FUNC);
+       rc = (jlong)CFArrayGetValueAtIndex((CFArrayRef)arg0, (CFIndex)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFArrayGetValueAtIndex_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFDataCreate
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFDataCreate)(JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jint arg2);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFDataCreate)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jint arg2)
+{
+       jbyte *lparg1=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFDataCreate_FUNC);
+       if (arg1) if ((lparg1 = env->GetByteArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jlong)CFDataCreate((CFAllocatorRef)arg0, (const UInt8 *)lparg1, (CFIndex)arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseByteArrayElements(arg1, lparg1, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFDataCreate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFDataGetBytePtr
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFDataGetBytePtr)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFDataGetBytePtr)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFDataGetBytePtr_FUNC);
+       rc = (jlong)CFDataGetBytePtr((CFDataRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFDataGetBytePtr_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFDataGetLength
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFDataGetLength)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFDataGetLength)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFDataGetLength_FUNC);
+       rc = (jint)CFDataGetLength((CFDataRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFDataGetLength_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFDictionaryCreate
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFDictionaryCreate)(JNIEnv *env, jclass that, jlong arg0, jlongArray arg1, jlongArray arg2, jint arg3, jlong arg4, jlong arg5);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFDictionaryCreate)
+       (JNIEnv *env, jclass that, jlong arg0, jlongArray arg1, jlongArray arg2, jint arg3, jlong arg4, jlong arg5)
+{
+       jlong *lparg1=NULL;
+       jlong *lparg2=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFDictionaryCreate_FUNC);
+       if (arg1) if ((lparg1 = env->GetLongArrayElements(arg1, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = env->GetLongArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jlong)CFDictionaryCreate((CFAllocatorRef)arg0, (const void **)lparg1, (const void **)lparg2, (CFIndex)arg3, (const CFDictionaryKeyCallBacks *)arg4, (const CFDictionaryValueCallBacks *)arg5);
+fail:
+       if (arg2 && lparg2) env->ReleaseLongArrayElements(arg2, lparg2, 0);
+       if (arg1 && lparg1) env->ReleaseLongArrayElements(arg1, lparg1, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFDictionaryCreate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieCreateWithResponseHeaderFields
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieCreateWithResponseHeaderFields)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieCreateWithResponseHeaderFields)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieCreateWithResponseHeaderFields_FUNC);
+       rc = (jlong)CFHTTPCookieCreateWithResponseHeaderFields((CFAllocatorRef)arg0, (CFDictionaryRef)arg1, (CFURLRef)arg2);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieCreateWithResponseHeaderFields_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieGetFlags
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFHTTPCookieGetFlags)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFHTTPCookieGetFlags)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieGetFlags_FUNC);
+       rc = (jint)CFHTTPCookieGetFlags((CFHTTPCookieRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieGetFlags_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieGetName
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieGetName)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieGetName)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieGetName_FUNC);
+       rc = (jlong)CFHTTPCookieGetName((CFHTTPCookieRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieGetName_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieGetValue
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieGetValue)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieGetValue)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieGetValue_FUNC);
+       rc = (jlong)CFHTTPCookieGetValue((CFHTTPCookieRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieGetValue_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieStorageCopyCookies
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageCopyCookies)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageCopyCookies)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieStorageCopyCookies_FUNC);
+       rc = (jlong)CFHTTPCookieStorageCopyCookies((CFHTTPCookieStorageRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieStorageCopyCookies_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieStorageCopyCookiesForURL
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageCopyCookiesForURL)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageCopyCookiesForURL)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jboolean arg2)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieStorageCopyCookiesForURL_FUNC);
+       rc = (jlong)CFHTTPCookieStorageCopyCookiesForURL((CFHTTPCookieStorageRef)arg0, (CFURLRef)arg1, (Boolean)arg2);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieStorageCopyCookiesForURL_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFHTTPCookieStorageDeleteCookie
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageDeleteCookie)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageDeleteCookie)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieStorageDeleteCookie_FUNC);
+       CFHTTPCookieStorageDeleteCookie((CFHTTPCookieStorageRef)arg0, (CFHTTPCookieRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieStorageDeleteCookie_FUNC);
+}
+#endif
+
+#ifndef NO_CFHTTPCookieStorageSetCookie
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageSetCookie)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFHTTPCookieStorageSetCookie)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       WebKit_win32_NATIVE_ENTER(env, that, CFHTTPCookieStorageSetCookie_FUNC);
+       CFHTTPCookieStorageSetCookie((CFHTTPCookieStorageRef)arg0, (CFHTTPCookieRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFHTTPCookieStorageSetCookie_FUNC);
+}
+#endif
+
+#ifndef NO_CFRelease
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFRelease)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFRelease)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       WebKit_win32_NATIVE_ENTER(env, that, CFRelease_FUNC);
+       CFRelease((CFTypeRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFRelease_FUNC);
+}
+#endif
+
+#ifndef NO_CFStringCreateWithCharacters
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFStringCreateWithCharacters)(JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFStringCreateWithCharacters)
+       (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2)
+{
+       jchar *lparg1=NULL;
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFStringCreateWithCharacters_FUNC);
+       if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)CFStringCreateWithCharacters((CFAllocatorRef)arg0, (const UniChar *)lparg1, (CFIndex)arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseCharArrayElements(arg1, lparg1, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFStringCreateWithCharacters_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFStringGetCharacterAtIndex
+extern "C" JNIEXPORT jchar JNICALL WebKit_win32_NATIVE(CFStringGetCharacterAtIndex)(JNIEnv *env, jclass that, jlong arg0, jint arg1);
+JNIEXPORT jchar JNICALL WebKit_win32_NATIVE(CFStringGetCharacterAtIndex)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jchar rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFStringGetCharacterAtIndex_FUNC);
+       rc = (jchar)CFStringGetCharacterAtIndex((CFStringRef)arg0, (CFIndex)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFStringGetCharacterAtIndex_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFStringGetCharactersPtr
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFStringGetCharactersPtr)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFStringGetCharactersPtr)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFStringGetCharactersPtr_FUNC);
+       rc = (jlong)CFStringGetCharactersPtr((CFStringRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFStringGetCharactersPtr_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFStringGetLength
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFStringGetLength)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(CFStringGetLength)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFStringGetLength_FUNC);
+       rc = (jint)CFStringGetLength((CFStringRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFStringGetLength_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFURLCreateWithString
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFURLCreateWithString)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFURLCreateWithString)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFURLCreateWithString_FUNC);
+       rc = (jlong)CFURLCreateWithString((CFAllocatorRef)arg0, (CFStringRef)arg1, (CFURLRef)arg2);
+       WebKit_win32_NATIVE_EXIT(env, that, CFURLCreateWithString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFURLRequestCopyHTTPRequestBody
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFURLRequestCopyHTTPRequestBody)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFURLRequestCopyHTTPRequestBody)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFURLRequestCopyHTTPRequestBody_FUNC);
+       rc = (jlong)CFURLRequestCopyHTTPRequestBody((CFURLRequestRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, CFURLRequestCopyHTTPRequestBody_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFURLRequestCreateMutableCopy
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFURLRequestCreateMutableCopy)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(CFURLRequestCreateMutableCopy)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, CFURLRequestCreateMutableCopy_FUNC);
+       rc = (jlong)CFURLRequestCreateMutableCopy((CFAllocatorRef)arg0, (CFURLRequestRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFURLRequestCreateMutableCopy_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_CFURLRequestSetHTTPRequestBody
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFURLRequestSetHTTPRequestBody)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFURLRequestSetHTTPRequestBody)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       WebKit_win32_NATIVE_ENTER(env, that, CFURLRequestSetHTTPRequestBody_FUNC);
+       CFURLRequestSetHTTPRequestBody((CFMutableURLRequestRef)arg0, (CFDataRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFURLRequestSetHTTPRequestBody_FUNC);
+}
+#endif
+
+#ifndef NO_CFURLRequestSetURL
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFURLRequestSetURL)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(CFURLRequestSetURL)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       WebKit_win32_NATIVE_ENTER(env, that, CFURLRequestSetURL_FUNC);
+       CFURLRequestSetURL((CFMutableURLRequestRef)arg0, (CFURLRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, CFURLRequestSetURL_FUNC);
+}
+#endif
+
+#ifndef NO_JSClassCreate
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSClassCreate)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSClassCreate)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSClassCreate_FUNC);
+       rc = (jlong)JSClassCreate((const JSClassDefinition*)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSClassCreate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSClassDefinition_1sizeof
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSClassDefinition_1sizeof)(JNIEnv *env, jclass that);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSClassDefinition_1sizeof)
+       (JNIEnv *env, jclass that)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSClassDefinition_1sizeof_FUNC);
+       rc = (jint)JSClassDefinition_sizeof();
+       WebKit_win32_NATIVE_EXIT(env, that, JSClassDefinition_1sizeof_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSClassRetain
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSClassRetain)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSClassRetain)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSClassRetain_FUNC);
+       rc = (jlong)JSClassRetain((JSClassRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSClassRetain_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSContextGetGlobalObject
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSContextGetGlobalObject)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSContextGetGlobalObject)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSContextGetGlobalObject_FUNC);
+       rc = (jlong)JSContextGetGlobalObject((JSContextRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSContextGetGlobalObject_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSEvaluateScript
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSEvaluateScript)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jint arg4, jlongArray arg5);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSEvaluateScript)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jint arg4, jlongArray arg5)
+{
+       jlong *lparg5=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSEvaluateScript_FUNC);
+       if (arg5) if ((lparg5 = env->GetLongArrayElements(arg5, NULL)) == NULL) goto fail;
+       rc = (jlong)JSEvaluateScript((JSContextRef)arg0, (JSStringRef)arg1, (JSObjectRef)arg2, (JSStringRef)arg3, arg4, (JSValueRef *)lparg5);
+fail:
+       if (arg5 && lparg5) env->ReleaseLongArrayElements(arg5, lparg5, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSEvaluateScript_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSGlobalContextRetain
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSGlobalContextRetain)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSGlobalContextRetain)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSGlobalContextRetain_FUNC);
+       rc = (jint)JSGlobalContextRetain((JSGlobalContextRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSGlobalContextRetain_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectGetPrivate
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectGetPrivate)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectGetPrivate)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectGetPrivate_FUNC);
+       rc = (jlong)JSObjectGetPrivate((JSObjectRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectGetPrivate_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectGetProperty
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectGetProperty)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlongArray arg3);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectGetProperty)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlongArray arg3)
+{
+       jlong *lparg3=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectGetProperty_FUNC);
+       if (arg3) if ((lparg3 = env->GetLongArrayElements(arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)JSObjectGetProperty((JSContextRef)arg0, (JSObjectRef)arg1, (JSStringRef)arg2, (JSValueRef*)lparg3);
+fail:
+       if (arg3 && lparg3) env->ReleaseLongArrayElements(arg3, lparg3, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectGetProperty_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectGetPropertyAtIndex
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectGetPropertyAtIndex)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlongArray arg3);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectGetPropertyAtIndex)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jlongArray arg3)
+{
+       jlong *lparg3=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectGetPropertyAtIndex_FUNC);
+       if (arg3) if ((lparg3 = env->GetLongArrayElements(arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)JSObjectGetPropertyAtIndex((JSContextRef)arg0, (JSObjectRef)arg1, (unsigned)arg2, (JSValueRef*)lparg3);
+fail:
+       if (arg3 && lparg3) env->ReleaseLongArrayElements(arg3, lparg3, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectGetPropertyAtIndex_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectMake
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSObjectMake)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSObjectMake)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectMake_FUNC);
+       rc = (jint)JSObjectMake((JSContextRef)arg0, (JSClassRef)arg1, (void *)arg2);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectMake_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectMakeArray
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectMakeArray)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2, jlongArray arg3);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSObjectMakeArray)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2, jlongArray arg3)
+{
+       jlong *lparg2=NULL;
+       jlong *lparg3=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectMakeArray_FUNC);
+       if (arg2) if ((lparg2 = env->GetLongArrayElements(arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = env->GetLongArrayElements(arg3, NULL)) == NULL) goto fail;
+       rc = (jlong)JSObjectMakeArray((JSContextRef)arg0, (size_t)arg1, (const struct OpaqueJSValue * const*)lparg2, (JSValueRef*)lparg3);
+fail:
+       if (arg3 && lparg3) env->ReleaseLongArrayElements(arg3, lparg3, 0);
+       if (arg2 && lparg2) env->ReleaseLongArrayElements(arg2, lparg2, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectMakeArray_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectMakeFunctionWithCallback
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSObjectMakeFunctionWithCallback)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSObjectMakeFunctionWithCallback)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectMakeFunctionWithCallback_FUNC);
+       rc = (jint)JSObjectMakeFunctionWithCallback((JSContextRef)arg0, (JSStringRef)arg1, (JSObjectCallAsFunctionCallback)arg2);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectMakeFunctionWithCallback_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSObjectSetProperty
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(JSObjectSetProperty)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4, jlongArray arg5);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(JSObjectSetProperty)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4, jlongArray arg5)
+{
+       jlong *lparg5=NULL;
+       WebKit_win32_NATIVE_ENTER(env, that, JSObjectSetProperty_FUNC);
+       if (arg5) if ((lparg5 = env->GetLongArrayElements(arg5, NULL)) == NULL) goto fail;
+       JSObjectSetProperty((JSContextRef)arg0, (JSObjectRef)arg1, (JSStringRef)arg2, (JSValueRef)arg3, (JSPropertyAttributes)arg4, (JSValueRef *)lparg5);
+fail:
+       if (arg5 && lparg5) env->ReleaseLongArrayElements(arg5, lparg5, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSObjectSetProperty_FUNC);
+}
+#endif
+
+#ifndef NO_JSStringCreateWithUTF8CString
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSStringCreateWithUTF8CString)(JNIEnv *env, jclass that, jbyteArray arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSStringCreateWithUTF8CString)
+       (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+       jbyte *lparg0=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSStringCreateWithUTF8CString_FUNC);
+       if (arg0) if ((lparg0 = env->GetByteArrayElements(arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)JSStringCreateWithUTF8CString((const char*)lparg0);
+fail:
+       if (arg0 && lparg0) env->ReleaseByteArrayElements(arg0, lparg0, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSStringCreateWithUTF8CString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSStringGetLength
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSStringGetLength)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSStringGetLength)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSStringGetLength_FUNC);
+       rc = (jint)JSStringGetLength((JSStringRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSStringGetLength_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSStringGetMaximumUTF8CStringSize
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSStringGetMaximumUTF8CStringSize)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSStringGetMaximumUTF8CStringSize)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSStringGetMaximumUTF8CStringSize_FUNC);
+       rc = (jlong)JSStringGetMaximumUTF8CStringSize((JSStringRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSStringGetMaximumUTF8CStringSize_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSStringGetUTF8CString
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSStringGetUTF8CString)(JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jlong arg2);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSStringGetUTF8CString)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jlong arg2)
+{
+       jbyte *lparg1=NULL;
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSStringGetUTF8CString_FUNC);
+       if (arg1) if ((lparg1 = env->GetByteArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)JSStringGetUTF8CString((JSStringRef)arg0, (char *)lparg1, (size_t)arg2);
+fail:
+       if (arg1 && lparg1) env->ReleaseByteArrayElements(arg1, lparg1, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSStringGetUTF8CString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSStringIsEqualToUTF8CString
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSStringIsEqualToUTF8CString)(JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSStringIsEqualToUTF8CString)
+       (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1)
+{
+       jbyte *lparg1=NULL;
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSStringIsEqualToUTF8CString_FUNC);
+       if (arg1) if ((lparg1 = env->GetByteArrayElements(arg1, NULL)) == NULL) goto fail;
+       rc = (jint)JSStringIsEqualToUTF8CString((JSStringRef)arg0, (const char *)lparg1);
+fail:
+       if (arg1 && lparg1) env->ReleaseByteArrayElements(arg1, lparg1, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSStringIsEqualToUTF8CString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSStringRelease
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(JSStringRelease)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(JSStringRelease)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       WebKit_win32_NATIVE_ENTER(env, that, JSStringRelease_FUNC);
+       JSStringRelease((JSStringRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSStringRelease_FUNC);
+}
+#endif
+
+#ifndef NO_JSValueGetType
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSValueGetType)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSValueGetType)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueGetType_FUNC);
+       rc = (jint)JSValueGetType((JSContextRef)arg0, (JSValueRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueGetType_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueIsObjectOfClass
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSValueIsObjectOfClass)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(JSValueIsObjectOfClass)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2)
+{
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueIsObjectOfClass_FUNC);
+       rc = (jint)JSValueIsObjectOfClass((JSContextRef)arg0, (JSValueRef)arg1, (JSClassRef)arg2);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueIsObjectOfClass_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueMakeBoolean
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeBoolean)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeBoolean)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueMakeBoolean_FUNC);
+       rc = (jlong)JSValueMakeBoolean((JSContextRef)arg0, (bool)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueMakeBoolean_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueMakeNull
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeNull)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeNull)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueMakeNull_FUNC);
+       rc = (jlong)JSValueMakeNull((JSContextRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueMakeNull_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueMakeNumber
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeNumber)(JNIEnv *env, jclass that, jlong arg0, jdouble arg1);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeNumber)
+       (JNIEnv *env, jclass that, jlong arg0, jdouble arg1)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueMakeNumber_FUNC);
+       rc = (jlong)JSValueMakeNumber((JSContextRef)arg0, (double)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueMakeNumber_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueMakeString
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeString)(JNIEnv *env, jclass that, jlong arg0, jlong arg1);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeString)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueMakeString_FUNC);
+       rc = (jlong)JSValueMakeString((JSContextRef)arg0, (JSStringRef)arg1);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueMakeString_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueMakeUndefined
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeUndefined)(JNIEnv *env, jclass that, jlong arg0);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueMakeUndefined)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueMakeUndefined_FUNC);
+       rc = (jlong)JSValueMakeUndefined((JSContextRef)arg0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueMakeUndefined_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueToNumber
+extern "C" JNIEXPORT jdouble JNICALL WebKit_win32_NATIVE(JSValueToNumber)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2);
+JNIEXPORT jdouble JNICALL WebKit_win32_NATIVE(JSValueToNumber)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2)
+{
+       jlong *lparg2=NULL;
+       jdouble rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueToNumber_FUNC);
+       if (arg2) if ((lparg2 = env->GetLongArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jdouble)JSValueToNumber((JSContextRef)arg0, (JSValueRef)arg1, (JSValueRef*)lparg2);
+fail:
+       if (arg2 && lparg2) env->ReleaseLongArrayElements(arg2, lparg2, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueToNumber_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_JSValueToStringCopy
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueToStringCopy)(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(JSValueToStringCopy)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlongArray arg2)
+{
+       jlong *lparg2=NULL;
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, JSValueToStringCopy_FUNC);
+       if (arg2) if ((lparg2 = env->GetLongArrayElements(arg2, NULL)) == NULL) goto fail;
+       rc = (jlong)JSValueToStringCopy((JSContextRef)arg0, (JSValueRef)arg1, (JSValueRef*)lparg2);
+fail:
+       if (arg2 && lparg2) env->ReleaseLongArrayElements(arg2, lparg2, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, JSValueToStringCopy_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_kCFCopyStringDictionaryKeyCallBacks
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(kCFCopyStringDictionaryKeyCallBacks)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(kCFCopyStringDictionaryKeyCallBacks)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, kCFCopyStringDictionaryKeyCallBacks_FUNC);
+       rc = (jlong)&kCFCopyStringDictionaryKeyCallBacks;
+       WebKit_win32_NATIVE_EXIT(env, that, kCFCopyStringDictionaryKeyCallBacks_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_kCFTypeDictionaryValueCallBacks
+extern "C" JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(kCFTypeDictionaryValueCallBacks)(JNIEnv *env, jclass that);
+JNIEXPORT jlong JNICALL WebKit_win32_NATIVE(kCFTypeDictionaryValueCallBacks)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, kCFTypeDictionaryValueCallBacks_FUNC);
+       rc = (jlong)&kCFTypeDictionaryValueCallBacks;
+       WebKit_win32_NATIVE_EXIT(env, that, kCFTypeDictionaryValueCallBacks_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_memmove
+extern "C" JNIEXPORT void JNICALL WebKit_win32_NATIVE(memmove)(JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2);
+JNIEXPORT void JNICALL WebKit_win32_NATIVE(memmove)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2)
+{
+       JSClassDefinition _arg1, *lparg1=NULL;
+       WebKit_win32_NATIVE_ENTER(env, that, memmove_FUNC);
+       if (arg1) if ((lparg1 = getJSClassDefinitionFields(env, arg1, &_arg1)) == NULL) goto fail;
+       memmove((void *)arg0, (const void *)lparg1, (size_t)arg2);
+fail:
+       WebKit_win32_NATIVE_EXIT(env, that, memmove_FUNC);
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32.h
new file mode 100644 (file)
index 0000000..23fab0c
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#ifndef INC_webkit_win32_H
+#define INC_webkit_win32_H
+
+#include <ole2.h>
+#include <JavaScriptCore/JSContextRef.h>
+#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <CFNetwork/CFHTTPCookiesPriv.h>
+#include <CFNetwork/CFURLRequestPriv.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <WebKitCOMAPI.h>
+#include "webkit_win32_custom.h"
+
+#define WebKit_LOAD_FUNCTION LOAD_FUNCTION
+
+#endif /* INC_webkit_win32_H */
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_custom.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_custom.cpp
new file mode 100644 (file)
index 0000000..2b9e173
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#include "swt.h"
+#include "webkit_win32.h"
+#include "webkit_win32_stats.h"
+
+#define WebKit_win32_NATIVE(func) Java_org_eclipse_swt_internal_webkit_WebKit_1win32_##func
+
+#ifndef NO_willPerformClientRedirectToURL_1CALLBACK
+static jintLong willPerformClientRedirectToURL_CALLBACK;
+static HRESULT CALLBACK willPerformClientRedirectToURL(void* ppVTable, jintLong webView, BSTR url, double delaySeconds, DATE fireDate, jintLong frame)
+{
+       return ((HRESULT (CALLBACK *)(void*, jintLong, BSTR, double*, DATE*, jintLong))willPerformClientRedirectToURL_CALLBACK)(ppVTable, webView, url, &delaySeconds, &fireDate, frame);
+}
+extern "C" JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(willPerformClientRedirectToURL_1CALLBACK) (JNIEnv *env, jclass that, jintLong func);
+JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(willPerformClientRedirectToURL_1CALLBACK) (JNIEnv *env, jclass that, jintLong func)
+{
+       willPerformClientRedirectToURL_CALLBACK = func;
+       return (jintLong)willPerformClientRedirectToURL;
+}
+#endif
+
+#ifndef NO_JSObjectCallAsFunctionProc_1CALLBACK
+static jintLong JSObjectCallAsFunctionProc_CALLBACK;
+static JSValueRef JSObjectCallAsFunctionProc(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+       return ((JSValueRef (CALLBACK *)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef*))JSObjectCallAsFunctionProc_CALLBACK)(ctx, function, thisObject, argumentCount, arguments, exception);
+}
+extern "C" JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(JSObjectCallAsFunctionProc_1CALLBACK) (JNIEnv *env, jclass that, jintLong func);
+JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(JSObjectCallAsFunctionProc_1CALLBACK) (JNIEnv *env, jclass that, jintLong func)
+{
+       JSObjectCallAsFunctionProc_CALLBACK = func;
+       return (jintLong)JSObjectCallAsFunctionProc;
+}
+#endif
+
+#ifndef NO_JSObjectGetPropertyProc_1CALLBACK
+static jintLong JSObjectGetPropertyProc_CALLBACK;
+static JSValueRef JSObjectGetPropertyProc(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+       return ((JSValueRef (CALLBACK *)(JSContextRef, JSObjectRef, JSStringRef, JSValueRef*))JSObjectGetPropertyProc_CALLBACK)(ctx, object, propertyName, exception);
+}
+extern "C" JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(JSObjectGetPropertyProc_1CALLBACK) (JNIEnv *env, jclass that, jintLong func);
+JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(JSObjectGetPropertyProc_1CALLBACK) (JNIEnv *env, jclass that, jintLong func)
+{
+       JSObjectGetPropertyProc_CALLBACK = func;
+       return (jintLong)JSObjectGetPropertyProc;
+}
+#endif
+
+#ifndef NO_JSObjectHasPropertyProc_1CALLBACK
+static jintLong JSObjectHasPropertyProc_CALLBACK;
+static bool JSObjectHasPropertyProc(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
+{
+       return ((bool (CALLBACK *)(JSContextRef, JSObjectRef, JSStringRef))JSObjectHasPropertyProc_CALLBACK)(ctx, object, propertyName);
+}
+extern "C" JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(JSObjectHasPropertyProc_1CALLBACK) (JNIEnv *env, jclass that, jintLong func);
+JNIEXPORT jintLong JNICALL WebKit_win32_NATIVE(JSObjectHasPropertyProc_1CALLBACK) (JNIEnv *env, jclass that, jintLong func)
+{
+       JSObjectHasPropertyProc_CALLBACK = func;
+       return (jintLong)JSObjectHasPropertyProc;
+}
+#endif
+
+#ifndef NO_WebKitCreateInstance
+extern "C" JNIEXPORT jint JNICALL WebKit_win32_NATIVE(WebKitCreateInstance)(JNIEnv *env, jclass that, jbyteArray arg0, jintLong arg1, jbyteArray arg2, jintLongArray arg3);
+JNIEXPORT jint JNICALL WebKit_win32_NATIVE(WebKitCreateInstance)
+       (JNIEnv *env, jclass that, jbyteArray arg0, jintLong arg1, jbyteArray arg2, jintLongArray arg3)
+{
+       jbyte *lparg0=NULL;
+       jbyte *lparg2=NULL;
+       jintLong *lparg3=NULL;
+       jint rc = 0;
+       WebKit_win32_NATIVE_ENTER(env, that, WebKitCreateInstance_FUNC);
+       if (arg0) if ((lparg0 = env->GetByteArrayElements(arg0, NULL)) == NULL) goto fail;
+       if (arg2) if ((lparg2 = env->GetByteArrayElements(arg2, NULL)) == NULL) goto fail;
+       if (arg3) if ((lparg3 = env->GetIntLongArrayElements(arg3, NULL)) == NULL) goto fail;
+/*
+       rc = (jint)WebKitCreateInstance(lparg0, arg1, lparg2, lparg3);
+*/
+       {
+               WebKit_LOAD_FUNCTION(fp, WebKitCreateInstance)
+               if (fp) {
+                       rc = (jint)((jint (*)(jbyte *, jintLong, jbyte *, jintLong *))fp)(lparg0, arg1, lparg2, lparg3);
+               }
+       }
+fail:
+       if (arg3 && lparg3) env->ReleaseIntLongArrayElements(arg3, lparg3, 0);
+       if (arg2 && lparg2) env->ReleaseByteArrayElements(arg2, lparg2, 0);
+       if (arg0 && lparg0) env->ReleaseByteArrayElements(arg0, lparg0, 0);
+       WebKit_win32_NATIVE_EXIT(env, that, WebKitCreateInstance_FUNC);
+       return rc;
+}
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_custom.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_custom.h
new file mode 100644 (file)
index 0000000..ae9b550
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Libraries for dynamic loaded functions */
+#define WebKitCreateInstance_LIB "webkit.dll"
+
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_stats.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_stats.cpp
new file mode 100644 (file)
index 0000000..df95d5f
--- /dev/null
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html.  If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "webkit_win32_stats.h"
+
+#ifdef NATIVE_STATS
+
+char * WebKit_win32_nativeFunctionNames[] = {
+       "CFArrayGetCount",
+       "CFArrayGetValueAtIndex",
+       "CFDataCreate",
+       "CFDataGetBytePtr",
+       "CFDataGetLength",
+       "CFDictionaryCreate",
+       "CFHTTPCookieCreateWithResponseHeaderFields",
+       "CFHTTPCookieGetFlags",
+       "CFHTTPCookieGetName",
+       "CFHTTPCookieGetValue",
+       "CFHTTPCookieStorageCopyCookies",
+       "CFHTTPCookieStorageCopyCookiesForURL",
+       "CFHTTPCookieStorageDeleteCookie",
+       "CFHTTPCookieStorageSetCookie",
+       "CFRelease",
+       "CFStringCreateWithCharacters",
+       "CFStringGetCharacterAtIndex",
+       "CFStringGetCharactersPtr",
+       "CFStringGetLength",
+       "CFURLCreateWithString",
+       "CFURLRequestCopyHTTPRequestBody",
+       "CFURLRequestCreateMutableCopy",
+       "CFURLRequestSetHTTPRequestBody",
+       "CFURLRequestSetURL",
+       "JSClassCreate",
+       "JSClassDefinition_1sizeof",
+       "JSClassRetain",
+       "JSContextGetGlobalObject",
+       "JSEvaluateScript",
+       "JSGlobalContextRetain",
+       "JSObjectCallAsFunctionProc_1CALLBACK",
+       "JSObjectGetPrivate",
+       "JSObjectGetProperty",
+       "JSObjectGetPropertyAtIndex",
+       "JSObjectGetPropertyProc_1CALLBACK",
+       "JSObjectHasPropertyProc_1CALLBACK",
+       "JSObjectMake",
+       "JSObjectMakeArray",
+       "JSObjectMakeFunctionWithCallback",
+       "JSObjectSetProperty",
+       "JSStringCreateWithUTF8CString",
+       "JSStringGetLength",
+       "JSStringGetMaximumUTF8CStringSize",
+       "JSStringGetUTF8CString",
+       "JSStringIsEqualToUTF8CString",
+       "JSStringRelease",
+       "JSValueGetType",
+       "JSValueIsObjectOfClass",
+       "JSValueMakeBoolean",
+       "JSValueMakeNull",
+       "JSValueMakeNumber",
+       "JSValueMakeString",
+       "JSValueMakeUndefined",
+       "JSValueToNumber",
+       "JSValueToStringCopy",
+       "WebKitCreateInstance",
+       "kCFCopyStringDictionaryKeyCallBacks",
+       "kCFTypeDictionaryValueCallBacks",
+       "memmove",
+       "willPerformClientRedirectToURL_1CALLBACK",
+};
+#define NATIVE_FUNCTION_COUNT sizeof(WebKit_win32_nativeFunctionNames) / sizeof(char*)
+int WebKit_win32_nativeFunctionCount = NATIVE_FUNCTION_COUNT;
+int WebKit_win32_nativeFunctionCallCount[NATIVE_FUNCTION_COUNT];
+
+#define STATS_NATIVE(func) Java_org_eclipse_swt_tools_internal_NativeStats_##func
+
+JNIEXPORT jint JNICALL STATS_NATIVE(WebKit_1win32_1GetFunctionCount)
+       (JNIEnv *env, jclass that)
+{
+       return WebKit_win32_nativeFunctionCount;
+}
+
+JNIEXPORT jstring JNICALL STATS_NATIVE(WebKit_1win32_1GetFunctionName)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return env->NewStringUTF(WebKit_win32_nativeFunctionNames[index]);
+}
+
+JNIEXPORT jint JNICALL STATS_NATIVE(WebKit_1win32_1GetFunctionCallCount)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return WebKit_win32_nativeFunctionCallCount[index];
+}
+
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_stats.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_stats.h
new file mode 100644 (file)
index 0000000..fedd666
--- /dev/null
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html.  If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#ifdef NATIVE_STATS
+extern int WebKit_win32_nativeFunctionCount;
+extern int WebKit_win32_nativeFunctionCallCount[];
+extern char* WebKit_win32_nativeFunctionNames[];
+#define WebKit_win32_NATIVE_ENTER(env, that, func) WebKit_win32_nativeFunctionCallCount[func]++;
+#define WebKit_win32_NATIVE_EXIT(env, that, func) 
+#else
+#ifndef WebKit_win32_NATIVE_ENTER
+#define WebKit_win32_NATIVE_ENTER(env, that, func) 
+#endif
+#ifndef WebKit_win32_NATIVE_EXIT
+#define WebKit_win32_NATIVE_EXIT(env, that, func) 
+#endif
+#endif
+
+typedef enum {
+       CFArrayGetCount_FUNC,
+       CFArrayGetValueAtIndex_FUNC,
+       CFDataCreate_FUNC,
+       CFDataGetBytePtr_FUNC,
+       CFDataGetLength_FUNC,
+       CFDictionaryCreate_FUNC,
+       CFHTTPCookieCreateWithResponseHeaderFields_FUNC,
+       CFHTTPCookieGetFlags_FUNC,
+       CFHTTPCookieGetName_FUNC,
+       CFHTTPCookieGetValue_FUNC,
+       CFHTTPCookieStorageCopyCookies_FUNC,
+       CFHTTPCookieStorageCopyCookiesForURL_FUNC,
+       CFHTTPCookieStorageDeleteCookie_FUNC,
+       CFHTTPCookieStorageSetCookie_FUNC,
+       CFRelease_FUNC,
+       CFStringCreateWithCharacters_FUNC,
+       CFStringGetCharacterAtIndex_FUNC,
+       CFStringGetCharactersPtr_FUNC,
+       CFStringGetLength_FUNC,
+       CFURLCreateWithString_FUNC,
+       CFURLRequestCopyHTTPRequestBody_FUNC,
+       CFURLRequestCreateMutableCopy_FUNC,
+       CFURLRequestSetHTTPRequestBody_FUNC,
+       CFURLRequestSetURL_FUNC,
+       JSClassCreate_FUNC,
+       JSClassDefinition_1sizeof_FUNC,
+       JSClassRetain_FUNC,
+       JSContextGetGlobalObject_FUNC,
+       JSEvaluateScript_FUNC,
+       JSGlobalContextRetain_FUNC,
+       JSObjectCallAsFunctionProc_1CALLBACK_FUNC,
+       JSObjectGetPrivate_FUNC,
+       JSObjectGetProperty_FUNC,
+       JSObjectGetPropertyAtIndex_FUNC,
+       JSObjectGetPropertyProc_1CALLBACK_FUNC,
+       JSObjectHasPropertyProc_1CALLBACK_FUNC,
+       JSObjectMake_FUNC,
+       JSObjectMakeArray_FUNC,
+       JSObjectMakeFunctionWithCallback_FUNC,
+       JSObjectSetProperty_FUNC,
+       JSStringCreateWithUTF8CString_FUNC,
+       JSStringGetLength_FUNC,
+       JSStringGetMaximumUTF8CStringSize_FUNC,
+       JSStringGetUTF8CString_FUNC,
+       JSStringIsEqualToUTF8CString_FUNC,
+       JSStringRelease_FUNC,
+       JSValueGetType_FUNC,
+       JSValueIsObjectOfClass_FUNC,
+       JSValueMakeBoolean_FUNC,
+       JSValueMakeNull_FUNC,
+       JSValueMakeNumber_FUNC,
+       JSValueMakeString_FUNC,
+       JSValueMakeUndefined_FUNC,
+       JSValueToNumber_FUNC,
+       JSValueToStringCopy_FUNC,
+       WebKitCreateInstance_FUNC,
+       kCFCopyStringDictionaryKeyCallBacks_FUNC,
+       kCFTypeDictionaryValueCallBacks_FUNC,
+       memmove_FUNC,
+       willPerformClientRedirectToURL_1CALLBACK_FUNC,
+} WebKit_win32_FUNCS;
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_structs.cpp b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_structs.cpp
new file mode 100644 (file)
index 0000000..782dc5e
--- /dev/null
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 IBM Corporation and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html.  If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "webkit_win32_structs.h"
+
+#ifndef NO_JSClassDefinition
+typedef struct JSClassDefinition_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID version, attributes, className, parentClass, staticValues, staticFunctions, initialize, finalize, hasProperty, getProperty, setProperty, deleteProperty, getPropertyNames, callAsFunction, callAsConstructor, hasInstance, convertToType;
+} JSClassDefinition_FID_CACHE;
+
+JSClassDefinition_FID_CACHE JSClassDefinitionFc;
+
+void cacheJSClassDefinitionFields(JNIEnv *env, jobject lpObject)
+{
+       if (JSClassDefinitionFc.cached) return;
+       JSClassDefinitionFc.clazz = env->GetObjectClass(lpObject);
+       JSClassDefinitionFc.version = env->GetFieldID(JSClassDefinitionFc.clazz, "version", "I");
+       JSClassDefinitionFc.attributes = env->GetFieldID(JSClassDefinitionFc.clazz, "attributes", "I");
+       JSClassDefinitionFc.className = env->GetFieldID(JSClassDefinitionFc.clazz, "className", "J");
+       JSClassDefinitionFc.parentClass = env->GetFieldID(JSClassDefinitionFc.clazz, "parentClass", "J");
+       JSClassDefinitionFc.staticValues = env->GetFieldID(JSClassDefinitionFc.clazz, "staticValues", "J");
+       JSClassDefinitionFc.staticFunctions = env->GetFieldID(JSClassDefinitionFc.clazz, "staticFunctions", "J");
+       JSClassDefinitionFc.initialize = env->GetFieldID(JSClassDefinitionFc.clazz, "initialize", "J");
+       JSClassDefinitionFc.finalize = env->GetFieldID(JSClassDefinitionFc.clazz, "finalize", "J");
+       JSClassDefinitionFc.hasProperty = env->GetFieldID(JSClassDefinitionFc.clazz, "hasProperty", "J");
+       JSClassDefinitionFc.getProperty = env->GetFieldID(JSClassDefinitionFc.clazz, "getProperty", "J");
+       JSClassDefinitionFc.setProperty = env->GetFieldID(JSClassDefinitionFc.clazz, "setProperty", "J");
+       JSClassDefinitionFc.deleteProperty = env->GetFieldID(JSClassDefinitionFc.clazz, "deleteProperty", "J");
+       JSClassDefinitionFc.getPropertyNames = env->GetFieldID(JSClassDefinitionFc.clazz, "getPropertyNames", "J");
+       JSClassDefinitionFc.callAsFunction = env->GetFieldID(JSClassDefinitionFc.clazz, "callAsFunction", "J");
+       JSClassDefinitionFc.callAsConstructor = env->GetFieldID(JSClassDefinitionFc.clazz, "callAsConstructor", "J");
+       JSClassDefinitionFc.hasInstance = env->GetFieldID(JSClassDefinitionFc.clazz, "hasInstance", "J");
+       JSClassDefinitionFc.convertToType = env->GetFieldID(JSClassDefinitionFc.clazz, "convertToType", "J");
+       JSClassDefinitionFc.cached = 1;
+}
+
+JSClassDefinition *getJSClassDefinitionFields(JNIEnv *env, jobject lpObject, JSClassDefinition *lpStruct)
+{
+       if (!JSClassDefinitionFc.cached) cacheJSClassDefinitionFields(env, lpObject);
+       lpStruct->version = env->GetIntField(lpObject, JSClassDefinitionFc.version);
+       lpStruct->attributes = (JSClassAttributes)env->GetIntField(lpObject, JSClassDefinitionFc.attributes);
+       lpStruct->className = (const char*)env->GetLongField(lpObject, JSClassDefinitionFc.className);
+       lpStruct->parentClass = (JSClassRef)env->GetLongField(lpObject, JSClassDefinitionFc.parentClass);
+       lpStruct->staticValues = (const JSStaticValue*)env->GetLongField(lpObject, JSClassDefinitionFc.staticValues);
+       lpStruct->staticFunctions = (const JSStaticFunction*)env->GetLongField(lpObject, JSClassDefinitionFc.staticFunctions);
+       lpStruct->initialize = (JSObjectInitializeCallback)env->GetLongField(lpObject, JSClassDefinitionFc.initialize);
+       lpStruct->finalize = (JSObjectFinalizeCallback)env->GetLongField(lpObject, JSClassDefinitionFc.finalize);
+       lpStruct->hasProperty = (JSObjectHasPropertyCallback)env->GetLongField(lpObject, JSClassDefinitionFc.hasProperty);
+       lpStruct->getProperty = (JSObjectGetPropertyCallback)env->GetLongField(lpObject, JSClassDefinitionFc.getProperty);
+       lpStruct->setProperty = (JSObjectSetPropertyCallback)env->GetLongField(lpObject, JSClassDefinitionFc.setProperty);
+       lpStruct->deleteProperty = (JSObjectDeletePropertyCallback)env->GetLongField(lpObject, JSClassDefinitionFc.deleteProperty);
+       lpStruct->getPropertyNames = (JSObjectGetPropertyNamesCallback)env->GetLongField(lpObject, JSClassDefinitionFc.getPropertyNames);
+       lpStruct->callAsFunction = (JSObjectCallAsFunctionCallback)env->GetLongField(lpObject, JSClassDefinitionFc.callAsFunction);
+       lpStruct->callAsConstructor = (JSObjectCallAsConstructorCallback)env->GetLongField(lpObject, JSClassDefinitionFc.callAsConstructor);
+       lpStruct->hasInstance = (JSObjectHasInstanceCallback)env->GetLongField(lpObject, JSClassDefinitionFc.hasInstance);
+       lpStruct->convertToType = (JSObjectConvertToTypeCallback)env->GetLongField(lpObject, JSClassDefinitionFc.convertToType);
+       return lpStruct;
+}
+
+void setJSClassDefinitionFields(JNIEnv *env, jobject lpObject, JSClassDefinition *lpStruct)
+{
+       if (!JSClassDefinitionFc.cached) cacheJSClassDefinitionFields(env, lpObject);
+       env->SetIntField(lpObject, JSClassDefinitionFc.version, (jint)lpStruct->version);
+       env->SetIntField(lpObject, JSClassDefinitionFc.attributes, (jint)lpStruct->attributes);
+       env->SetLongField(lpObject, JSClassDefinitionFc.className, (jlong)lpStruct->className);
+       env->SetLongField(lpObject, JSClassDefinitionFc.parentClass, (jlong)lpStruct->parentClass);
+       env->SetLongField(lpObject, JSClassDefinitionFc.staticValues, (jlong)lpStruct->staticValues);
+       env->SetLongField(lpObject, JSClassDefinitionFc.staticFunctions, (jlong)lpStruct->staticFunctions);
+       env->SetLongField(lpObject, JSClassDefinitionFc.initialize, (jlong)lpStruct->initialize);
+       env->SetLongField(lpObject, JSClassDefinitionFc.finalize, (jlong)lpStruct->finalize);
+       env->SetLongField(lpObject, JSClassDefinitionFc.hasProperty, (jlong)lpStruct->hasProperty);
+       env->SetLongField(lpObject, JSClassDefinitionFc.getProperty, (jlong)lpStruct->getProperty);
+       env->SetLongField(lpObject, JSClassDefinitionFc.setProperty, (jlong)lpStruct->setProperty);
+       env->SetLongField(lpObject, JSClassDefinitionFc.deleteProperty, (jlong)lpStruct->deleteProperty);
+       env->SetLongField(lpObject, JSClassDefinitionFc.getPropertyNames, (jlong)lpStruct->getPropertyNames);
+       env->SetLongField(lpObject, JSClassDefinitionFc.callAsFunction, (jlong)lpStruct->callAsFunction);
+       env->SetLongField(lpObject, JSClassDefinitionFc.callAsConstructor, (jlong)lpStruct->callAsConstructor);
+       env->SetLongField(lpObject, JSClassDefinitionFc.hasInstance, (jlong)lpStruct->hasInstance);
+       env->SetLongField(lpObject, JSClassDefinitionFc.convertToType, (jlong)lpStruct->convertToType);
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_structs.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/webkit_win32_structs.h
new file mode 100644 (file)
index 0000000..0bd04b0
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html.  If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "webkit_win32.h"
+
+#ifndef NO_JSClassDefinition
+void cacheJSClassDefinitionFields(JNIEnv *env, jobject lpObject);
+JSClassDefinition *getJSClassDefinitionFields(JNIEnv *env, jobject lpObject, JSClassDefinition *lpStruct);
+void setJSClassDefinitionFields(JNIEnv *env, jobject lpObject, JSClassDefinition *lpStruct);
+#define JSClassDefinition_sizeof() sizeof(JSClassDefinition)
+#else
+#define cacheJSClassDefinitionFields(a,b)
+#define getJSClassDefinitionFields(a,b,c) NULL
+#define setJSClassDefinitionFields(a,b,c)
+#define JSClassDefinition_sizeof() 0
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl.c
new file mode 100644 (file)
index 0000000..ff4ae9c
--- /dev/null
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "wgl_structs.h"
+#include "wgl_stats.h"
+
+#ifndef WGL_NATIVE
+#define WGL_NATIVE(func) Java_org_eclipse_swt_internal_opengl_win32_WGL_##func
+#endif
+
+#ifndef NO_ChoosePixelFormat
+JNIEXPORT jint JNICALL WGL_NATIVE(ChoosePixelFormat)
+       (JNIEnv *env, jclass that, jlong arg0, jobject arg1)
+{
+       PIXELFORMATDESCRIPTOR _arg1, *lparg1=NULL;
+       jint rc = 0;
+       WGL_NATIVE_ENTER(env, that, ChoosePixelFormat_FUNC);
+       if (arg1) if ((lparg1 = getPIXELFORMATDESCRIPTORFields(env, arg1, &_arg1)) == NULL) goto fail;
+       rc = (jint)ChoosePixelFormat((HDC)arg0, lparg1);
+fail:
+       if (arg1 && lparg1) setPIXELFORMATDESCRIPTORFields(env, arg1, lparg1);
+       WGL_NATIVE_EXIT(env, that, ChoosePixelFormat_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_DescribePixelFormat
+JNIEXPORT jint JNICALL WGL_NATIVE(DescribePixelFormat)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jobject arg3)
+{
+       PIXELFORMATDESCRIPTOR _arg3, *lparg3=NULL;
+       jint rc = 0;
+       WGL_NATIVE_ENTER(env, that, DescribePixelFormat_FUNC);
+       if (arg3) if ((lparg3 = getPIXELFORMATDESCRIPTORFields(env, arg3, &_arg3)) == NULL) goto fail;
+       rc = (jint)DescribePixelFormat((HDC)arg0, arg1, arg2, lparg3);
+fail:
+       if (arg3 && lparg3) setPIXELFORMATDESCRIPTORFields(env, arg3, lparg3);
+       WGL_NATIVE_EXIT(env, that, DescribePixelFormat_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_GetPixelFormat
+JNIEXPORT jint JNICALL WGL_NATIVE(GetPixelFormat)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jint rc = 0;
+       WGL_NATIVE_ENTER(env, that, GetPixelFormat_FUNC);
+       rc = (jint)GetPixelFormat((HDC)arg0);
+       WGL_NATIVE_EXIT(env, that, GetPixelFormat_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SetPixelFormat
+JNIEXPORT jboolean JNICALL WGL_NATIVE(SetPixelFormat)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jobject arg2)
+{
+       PIXELFORMATDESCRIPTOR _arg2, *lparg2=NULL;
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, SetPixelFormat_FUNC);
+       if (arg2) if ((lparg2 = getPIXELFORMATDESCRIPTORFields(env, arg2, &_arg2)) == NULL) goto fail;
+       rc = (jboolean)SetPixelFormat((HDC)arg0, arg1, lparg2);
+fail:
+       if (arg2 && lparg2) setPIXELFORMATDESCRIPTORFields(env, arg2, lparg2);
+       WGL_NATIVE_EXIT(env, that, SetPixelFormat_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_SwapBuffers
+JNIEXPORT jboolean JNICALL WGL_NATIVE(SwapBuffers)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, SwapBuffers_FUNC);
+       rc = (jboolean)SwapBuffers((HDC)arg0);
+       WGL_NATIVE_EXIT(env, that, SwapBuffers_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglCopyContext
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglCopyContext)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglCopyContext_FUNC);
+       rc = (jboolean)wglCopyContext((HGLRC)arg0, (HGLRC)arg1, arg2);
+       WGL_NATIVE_EXIT(env, that, wglCopyContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglCreateContext
+JNIEXPORT jlong JNICALL WGL_NATIVE(wglCreateContext)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jlong rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglCreateContext_FUNC);
+       rc = (jlong)wglCreateContext((HDC)arg0);
+       WGL_NATIVE_EXIT(env, that, wglCreateContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglCreateLayerContext
+JNIEXPORT jlong JNICALL WGL_NATIVE(wglCreateLayerContext)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jlong rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglCreateLayerContext_FUNC);
+       rc = (jlong)wglCreateLayerContext((HDC)arg0, arg1);
+       WGL_NATIVE_EXIT(env, that, wglCreateLayerContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglDeleteContext
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglDeleteContext)
+       (JNIEnv *env, jclass that, jlong arg0)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglDeleteContext_FUNC);
+       rc = (jboolean)wglDeleteContext((HGLRC)arg0);
+       WGL_NATIVE_EXIT(env, that, wglDeleteContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglDescribeLayerPlane
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglDescribeLayerPlane)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jobject arg4)
+{
+       LAYERPLANEDESCRIPTOR _arg4, *lparg4=NULL;
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglDescribeLayerPlane_FUNC);
+       if (arg4) if ((lparg4 = getLAYERPLANEDESCRIPTORFields(env, arg4, &_arg4)) == NULL) goto fail;
+       rc = (jboolean)wglDescribeLayerPlane((HDC)arg0, arg1, arg2, arg3, lparg4);
+fail:
+       if (arg4 && lparg4) setLAYERPLANEDESCRIPTORFields(env, arg4, lparg4);
+       WGL_NATIVE_EXIT(env, that, wglDescribeLayerPlane_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglGetCurrentContext
+JNIEXPORT jlong JNICALL WGL_NATIVE(wglGetCurrentContext)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglGetCurrentContext_FUNC);
+       rc = (jlong)wglGetCurrentContext();
+       WGL_NATIVE_EXIT(env, that, wglGetCurrentContext_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglGetCurrentDC
+JNIEXPORT jlong JNICALL WGL_NATIVE(wglGetCurrentDC)
+       (JNIEnv *env, jclass that)
+{
+       jlong rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglGetCurrentDC_FUNC);
+       rc = (jlong)wglGetCurrentDC();
+       WGL_NATIVE_EXIT(env, that, wglGetCurrentDC_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglGetLayerPaletteEntries
+JNIEXPORT jint JNICALL WGL_NATIVE(wglGetLayerPaletteEntries)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jintArray arg4)
+{
+       jint *lparg4=NULL;
+       jint rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglGetLayerPaletteEntries_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)wglGetLayerPaletteEntries((HDC)arg0, arg1, arg2, arg3, (COLORREF *)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       WGL_NATIVE_EXIT(env, that, wglGetLayerPaletteEntries_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglGetProcAddress
+JNIEXPORT jlong JNICALL WGL_NATIVE(wglGetProcAddress)
+       (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+       jbyte *lparg0=NULL;
+       jlong rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglGetProcAddress_FUNC);
+       if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+       rc = (jlong)wglGetProcAddress(lparg0);
+fail:
+       if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+       WGL_NATIVE_EXIT(env, that, wglGetProcAddress_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglMakeCurrent
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglMakeCurrent)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglMakeCurrent_FUNC);
+       rc = (jboolean)wglMakeCurrent((HDC)arg0, (HGLRC)arg1);
+       WGL_NATIVE_EXIT(env, that, wglMakeCurrent_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglRealizeLayerPalette
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglRealizeLayerPalette)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jboolean arg2)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglRealizeLayerPalette_FUNC);
+       rc = (jboolean)wglRealizeLayerPalette((HDC)arg0, arg1, arg2);
+       WGL_NATIVE_EXIT(env, that, wglRealizeLayerPalette_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglSetLayerPaletteEntries
+JNIEXPORT jint JNICALL WGL_NATIVE(wglSetLayerPaletteEntries)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jintArray arg4)
+{
+       jint *lparg4=NULL;
+       jint rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglSetLayerPaletteEntries_FUNC);
+       if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
+       rc = (jint)wglSetLayerPaletteEntries((HDC)arg0, arg1, arg2, arg3, (COLORREF *)lparg4);
+fail:
+       if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
+       WGL_NATIVE_EXIT(env, that, wglSetLayerPaletteEntries_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglShareLists
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglShareLists)
+       (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglShareLists_FUNC);
+       rc = (jboolean)wglShareLists((HGLRC)arg0, (HGLRC)arg1);
+       WGL_NATIVE_EXIT(env, that, wglShareLists_FUNC);
+       return rc;
+}
+#endif
+
+#ifndef NO_wglSwapLayerBuffers
+JNIEXPORT jboolean JNICALL WGL_NATIVE(wglSwapLayerBuffers)
+       (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+       jboolean rc = 0;
+       WGL_NATIVE_ENTER(env, that, wglSwapLayerBuffers_FUNC);
+       rc = (jboolean)wglSwapLayerBuffers((HDC)arg0, arg1);
+       WGL_NATIVE_EXIT(env, that, wglSwapLayerBuffers_FUNC);
+       return rc;
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl.h
new file mode 100644 (file)
index 0000000..bbf8387
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#ifndef SWT_WGL_H_INCLUDED
+#define SWT_WGL_H_INCLUDED
+
+#include <windows.h>
+
+#endif /* SWT_WGL_H_INCLUDED */
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_stats.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_stats.c
new file mode 100644 (file)
index 0000000..0d9a780
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "wgl_stats.h"
+
+#ifdef NATIVE_STATS
+
+char * WGL_nativeFunctionNames[] = {
+       "ChoosePixelFormat",
+       "DescribePixelFormat",
+       "GetPixelFormat",
+       "SetPixelFormat",
+       "SwapBuffers",
+       "wglCopyContext",
+       "wglCreateContext",
+       "wglCreateLayerContext",
+       "wglDeleteContext",
+       "wglDescribeLayerPlane",
+       "wglGetCurrentContext",
+       "wglGetCurrentDC",
+       "wglGetLayerPaletteEntries",
+       "wglGetProcAddress",
+       "wglMakeCurrent",
+       "wglRealizeLayerPalette",
+       "wglSetLayerPaletteEntries",
+       "wglShareLists",
+       "wglSwapLayerBuffers",
+};
+#define NATIVE_FUNCTION_COUNT sizeof(WGL_nativeFunctionNames) / sizeof(char*)
+int WGL_nativeFunctionCount = NATIVE_FUNCTION_COUNT;
+int WGL_nativeFunctionCallCount[NATIVE_FUNCTION_COUNT];
+
+#define STATS_NATIVE(func) Java_org_eclipse_swt_tools_internal_NativeStats_##func
+
+JNIEXPORT jint JNICALL STATS_NATIVE(WGL_1GetFunctionCount)
+       (JNIEnv *env, jclass that)
+{
+       return WGL_nativeFunctionCount;
+}
+
+JNIEXPORT jstring JNICALL STATS_NATIVE(WGL_1GetFunctionName)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return (*env)->NewStringUTF(env, WGL_nativeFunctionNames[index]);
+}
+
+JNIEXPORT jint JNICALL STATS_NATIVE(WGL_1GetFunctionCallCount)
+       (JNIEnv *env, jclass that, jint index)
+{
+       return WGL_nativeFunctionCallCount[index];
+}
+
+#endif
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_stats.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_stats.h
new file mode 100644 (file)
index 0000000..0975156
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#ifdef NATIVE_STATS
+extern int WGL_nativeFunctionCount;
+extern int WGL_nativeFunctionCallCount[];
+extern char* WGL_nativeFunctionNames[];
+#define WGL_NATIVE_ENTER(env, that, func) WGL_nativeFunctionCallCount[func]++;
+#define WGL_NATIVE_EXIT(env, that, func) 
+#else
+#ifndef WGL_NATIVE_ENTER
+#define WGL_NATIVE_ENTER(env, that, func) 
+#endif
+#ifndef WGL_NATIVE_EXIT
+#define WGL_NATIVE_EXIT(env, that, func) 
+#endif
+#endif
+
+typedef enum {
+       ChoosePixelFormat_FUNC,
+       DescribePixelFormat_FUNC,
+       GetPixelFormat_FUNC,
+       SetPixelFormat_FUNC,
+       SwapBuffers_FUNC,
+       wglCopyContext_FUNC,
+       wglCreateContext_FUNC,
+       wglCreateLayerContext_FUNC,
+       wglDeleteContext_FUNC,
+       wglDescribeLayerPlane_FUNC,
+       wglGetCurrentContext_FUNC,
+       wglGetCurrentDC_FUNC,
+       wglGetLayerPaletteEntries_FUNC,
+       wglGetProcAddress_FUNC,
+       wglMakeCurrent_FUNC,
+       wglRealizeLayerPalette_FUNC,
+       wglSetLayerPaletteEntries_FUNC,
+       wglShareLists_FUNC,
+       wglSwapLayerBuffers_FUNC,
+} WGL_FUNCS;
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_structs.c b/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_structs.c
new file mode 100644 (file)
index 0000000..675de35
--- /dev/null
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "swt.h"
+#include "wgl_structs.h"
+
+#ifndef NO_LAYERPLANEDESCRIPTOR
+typedef struct LAYERPLANEDESCRIPTOR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID nSize, nVersion, dwFlags, iPixelType, cColorBits, cRedBits, cRedShift, cGreenBits, cGreenShift, cBlueBits, cBlueShift, cAlphaBits, cAlphaShift, cAccumBits, cAccumRedBits, cAccumGreenBits, cAccumBlueBits, cAccumAlphaBits, cDepthBits, cStencilBits, cAuxBuffers, iLayerPlane, bReserved, crTransparent;
+} LAYERPLANEDESCRIPTOR_FID_CACHE;
+
+LAYERPLANEDESCRIPTOR_FID_CACHE LAYERPLANEDESCRIPTORFc;
+
+void cacheLAYERPLANEDESCRIPTORFields(JNIEnv *env, jobject lpObject)
+{
+       if (LAYERPLANEDESCRIPTORFc.cached) return;
+       LAYERPLANEDESCRIPTORFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       LAYERPLANEDESCRIPTORFc.nSize = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "nSize", "S");
+       LAYERPLANEDESCRIPTORFc.nVersion = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "nVersion", "S");
+       LAYERPLANEDESCRIPTORFc.dwFlags = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "dwFlags", "I");
+       LAYERPLANEDESCRIPTORFc.iPixelType = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "iPixelType", "B");
+       LAYERPLANEDESCRIPTORFc.cColorBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cColorBits", "B");
+       LAYERPLANEDESCRIPTORFc.cRedBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cRedBits", "B");
+       LAYERPLANEDESCRIPTORFc.cRedShift = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cRedShift", "B");
+       LAYERPLANEDESCRIPTORFc.cGreenBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cGreenBits", "B");
+       LAYERPLANEDESCRIPTORFc.cGreenShift = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cGreenShift", "B");
+       LAYERPLANEDESCRIPTORFc.cBlueBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cBlueBits", "B");
+       LAYERPLANEDESCRIPTORFc.cBlueShift = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cBlueShift", "B");
+       LAYERPLANEDESCRIPTORFc.cAlphaBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAlphaBits", "B");
+       LAYERPLANEDESCRIPTORFc.cAlphaShift = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAlphaShift", "B");
+       LAYERPLANEDESCRIPTORFc.cAccumBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAccumBits", "B");
+       LAYERPLANEDESCRIPTORFc.cAccumRedBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAccumRedBits", "B");
+       LAYERPLANEDESCRIPTORFc.cAccumGreenBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAccumGreenBits", "B");
+       LAYERPLANEDESCRIPTORFc.cAccumBlueBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAccumBlueBits", "B");
+       LAYERPLANEDESCRIPTORFc.cAccumAlphaBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAccumAlphaBits", "B");
+       LAYERPLANEDESCRIPTORFc.cDepthBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cDepthBits", "B");
+       LAYERPLANEDESCRIPTORFc.cStencilBits = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cStencilBits", "B");
+       LAYERPLANEDESCRIPTORFc.cAuxBuffers = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "cAuxBuffers", "B");
+       LAYERPLANEDESCRIPTORFc.iLayerPlane = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "iLayerPlane", "B");
+       LAYERPLANEDESCRIPTORFc.bReserved = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "bReserved", "B");
+       LAYERPLANEDESCRIPTORFc.crTransparent = (*env)->GetFieldID(env, LAYERPLANEDESCRIPTORFc.clazz, "crTransparent", "I");
+       LAYERPLANEDESCRIPTORFc.cached = 1;
+}
+
+LAYERPLANEDESCRIPTOR *getLAYERPLANEDESCRIPTORFields(JNIEnv *env, jobject lpObject, LAYERPLANEDESCRIPTOR *lpStruct)
+{
+       if (!LAYERPLANEDESCRIPTORFc.cached) cacheLAYERPLANEDESCRIPTORFields(env, lpObject);
+       lpStruct->nSize = (*env)->GetShortField(env, lpObject, LAYERPLANEDESCRIPTORFc.nSize);
+       lpStruct->nVersion = (*env)->GetShortField(env, lpObject, LAYERPLANEDESCRIPTORFc.nVersion);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, LAYERPLANEDESCRIPTORFc.dwFlags);
+       lpStruct->iPixelType = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.iPixelType);
+       lpStruct->cColorBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cColorBits);
+       lpStruct->cRedBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cRedBits);
+       lpStruct->cRedShift = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cRedShift);
+       lpStruct->cGreenBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cGreenBits);
+       lpStruct->cGreenShift = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cGreenShift);
+       lpStruct->cBlueBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cBlueBits);
+       lpStruct->cBlueShift = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cBlueShift);
+       lpStruct->cAlphaBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAlphaBits);
+       lpStruct->cAlphaShift = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAlphaShift);
+       lpStruct->cAccumBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumBits);
+       lpStruct->cAccumRedBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumRedBits);
+       lpStruct->cAccumGreenBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumGreenBits);
+       lpStruct->cAccumBlueBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumBlueBits);
+       lpStruct->cAccumAlphaBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumAlphaBits);
+       lpStruct->cDepthBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cDepthBits);
+       lpStruct->cStencilBits = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cStencilBits);
+       lpStruct->cAuxBuffers = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAuxBuffers);
+       lpStruct->iLayerPlane = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.iLayerPlane);
+       lpStruct->bReserved = (*env)->GetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.bReserved);
+       lpStruct->crTransparent = (*env)->GetIntField(env, lpObject, LAYERPLANEDESCRIPTORFc.crTransparent);
+       return lpStruct;
+}
+
+void setLAYERPLANEDESCRIPTORFields(JNIEnv *env, jobject lpObject, LAYERPLANEDESCRIPTOR *lpStruct)
+{
+       if (!LAYERPLANEDESCRIPTORFc.cached) cacheLAYERPLANEDESCRIPTORFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, LAYERPLANEDESCRIPTORFc.nSize, (jshort)lpStruct->nSize);
+       (*env)->SetShortField(env, lpObject, LAYERPLANEDESCRIPTORFc.nVersion, (jshort)lpStruct->nVersion);
+       (*env)->SetIntField(env, lpObject, LAYERPLANEDESCRIPTORFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.iPixelType, (jbyte)lpStruct->iPixelType);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cColorBits, (jbyte)lpStruct->cColorBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cRedBits, (jbyte)lpStruct->cRedBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cRedShift, (jbyte)lpStruct->cRedShift);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cGreenBits, (jbyte)lpStruct->cGreenBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cGreenShift, (jbyte)lpStruct->cGreenShift);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cBlueBits, (jbyte)lpStruct->cBlueBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cBlueShift, (jbyte)lpStruct->cBlueShift);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAlphaBits, (jbyte)lpStruct->cAlphaBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAlphaShift, (jbyte)lpStruct->cAlphaShift);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumBits, (jbyte)lpStruct->cAccumBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumRedBits, (jbyte)lpStruct->cAccumRedBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumGreenBits, (jbyte)lpStruct->cAccumGreenBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumBlueBits, (jbyte)lpStruct->cAccumBlueBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAccumAlphaBits, (jbyte)lpStruct->cAccumAlphaBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cDepthBits, (jbyte)lpStruct->cDepthBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cStencilBits, (jbyte)lpStruct->cStencilBits);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.cAuxBuffers, (jbyte)lpStruct->cAuxBuffers);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.iLayerPlane, (jbyte)lpStruct->iLayerPlane);
+       (*env)->SetByteField(env, lpObject, LAYERPLANEDESCRIPTORFc.bReserved, (jbyte)lpStruct->bReserved);
+       (*env)->SetIntField(env, lpObject, LAYERPLANEDESCRIPTORFc.crTransparent, (jint)lpStruct->crTransparent);
+}
+#endif
+
+#ifndef NO_PIXELFORMATDESCRIPTOR
+typedef struct PIXELFORMATDESCRIPTOR_FID_CACHE {
+       int cached;
+       jclass clazz;
+       jfieldID nSize, nVersion, dwFlags, iPixelType, cColorBits, cRedBits, cRedShift, cGreenBits, cGreenShift, cBlueBits, cBlueShift, cAlphaBits, cAlphaShift, cAccumBits, cAccumRedBits, cAccumGreenBits, cAccumBlueBits, cAccumAlphaBits, cDepthBits, cStencilBits, cAuxBuffers, iLayerType, bReserved, dwLayerMask, dwVisibleMask, dwDamageMask;
+} PIXELFORMATDESCRIPTOR_FID_CACHE;
+
+PIXELFORMATDESCRIPTOR_FID_CACHE PIXELFORMATDESCRIPTORFc;
+
+void cachePIXELFORMATDESCRIPTORFields(JNIEnv *env, jobject lpObject)
+{
+       if (PIXELFORMATDESCRIPTORFc.cached) return;
+       PIXELFORMATDESCRIPTORFc.clazz = (*env)->GetObjectClass(env, lpObject);
+       PIXELFORMATDESCRIPTORFc.nSize = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "nSize", "S");
+       PIXELFORMATDESCRIPTORFc.nVersion = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "nVersion", "S");
+       PIXELFORMATDESCRIPTORFc.dwFlags = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "dwFlags", "I");
+       PIXELFORMATDESCRIPTORFc.iPixelType = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "iPixelType", "B");
+       PIXELFORMATDESCRIPTORFc.cColorBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cColorBits", "B");
+       PIXELFORMATDESCRIPTORFc.cRedBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cRedBits", "B");
+       PIXELFORMATDESCRIPTORFc.cRedShift = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cRedShift", "B");
+       PIXELFORMATDESCRIPTORFc.cGreenBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cGreenBits", "B");
+       PIXELFORMATDESCRIPTORFc.cGreenShift = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cGreenShift", "B");
+       PIXELFORMATDESCRIPTORFc.cBlueBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cBlueBits", "B");
+       PIXELFORMATDESCRIPTORFc.cBlueShift = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cBlueShift", "B");
+       PIXELFORMATDESCRIPTORFc.cAlphaBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAlphaBits", "B");
+       PIXELFORMATDESCRIPTORFc.cAlphaShift = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAlphaShift", "B");
+       PIXELFORMATDESCRIPTORFc.cAccumBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAccumBits", "B");
+       PIXELFORMATDESCRIPTORFc.cAccumRedBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAccumRedBits", "B");
+       PIXELFORMATDESCRIPTORFc.cAccumGreenBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAccumGreenBits", "B");
+       PIXELFORMATDESCRIPTORFc.cAccumBlueBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAccumBlueBits", "B");
+       PIXELFORMATDESCRIPTORFc.cAccumAlphaBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAccumAlphaBits", "B");
+       PIXELFORMATDESCRIPTORFc.cDepthBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cDepthBits", "B");
+       PIXELFORMATDESCRIPTORFc.cStencilBits = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cStencilBits", "B");
+       PIXELFORMATDESCRIPTORFc.cAuxBuffers = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "cAuxBuffers", "B");
+       PIXELFORMATDESCRIPTORFc.iLayerType = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "iLayerType", "B");
+       PIXELFORMATDESCRIPTORFc.bReserved = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "bReserved", "B");
+       PIXELFORMATDESCRIPTORFc.dwLayerMask = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "dwLayerMask", "I");
+       PIXELFORMATDESCRIPTORFc.dwVisibleMask = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "dwVisibleMask", "I");
+       PIXELFORMATDESCRIPTORFc.dwDamageMask = (*env)->GetFieldID(env, PIXELFORMATDESCRIPTORFc.clazz, "dwDamageMask", "I");
+       PIXELFORMATDESCRIPTORFc.cached = 1;
+}
+
+PIXELFORMATDESCRIPTOR *getPIXELFORMATDESCRIPTORFields(JNIEnv *env, jobject lpObject, PIXELFORMATDESCRIPTOR *lpStruct)
+{
+       if (!PIXELFORMATDESCRIPTORFc.cached) cachePIXELFORMATDESCRIPTORFields(env, lpObject);
+       lpStruct->nSize = (*env)->GetShortField(env, lpObject, PIXELFORMATDESCRIPTORFc.nSize);
+       lpStruct->nVersion = (*env)->GetShortField(env, lpObject, PIXELFORMATDESCRIPTORFc.nVersion);
+       lpStruct->dwFlags = (*env)->GetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwFlags);
+       lpStruct->iPixelType = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.iPixelType);
+       lpStruct->cColorBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cColorBits);
+       lpStruct->cRedBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cRedBits);
+       lpStruct->cRedShift = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cRedShift);
+       lpStruct->cGreenBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cGreenBits);
+       lpStruct->cGreenShift = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cGreenShift);
+       lpStruct->cBlueBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cBlueBits);
+       lpStruct->cBlueShift = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cBlueShift);
+       lpStruct->cAlphaBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAlphaBits);
+       lpStruct->cAlphaShift = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAlphaShift);
+       lpStruct->cAccumBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumBits);
+       lpStruct->cAccumRedBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumRedBits);
+       lpStruct->cAccumGreenBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumGreenBits);
+       lpStruct->cAccumBlueBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumBlueBits);
+       lpStruct->cAccumAlphaBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumAlphaBits);
+       lpStruct->cDepthBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cDepthBits);
+       lpStruct->cStencilBits = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cStencilBits);
+       lpStruct->cAuxBuffers = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAuxBuffers);
+       lpStruct->iLayerType = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.iLayerType);
+       lpStruct->bReserved = (*env)->GetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.bReserved);
+       lpStruct->dwLayerMask = (*env)->GetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwLayerMask);
+       lpStruct->dwVisibleMask = (*env)->GetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwVisibleMask);
+       lpStruct->dwDamageMask = (*env)->GetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwDamageMask);
+       return lpStruct;
+}
+
+void setPIXELFORMATDESCRIPTORFields(JNIEnv *env, jobject lpObject, PIXELFORMATDESCRIPTOR *lpStruct)
+{
+       if (!PIXELFORMATDESCRIPTORFc.cached) cachePIXELFORMATDESCRIPTORFields(env, lpObject);
+       (*env)->SetShortField(env, lpObject, PIXELFORMATDESCRIPTORFc.nSize, (jshort)lpStruct->nSize);
+       (*env)->SetShortField(env, lpObject, PIXELFORMATDESCRIPTORFc.nVersion, (jshort)lpStruct->nVersion);
+       (*env)->SetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwFlags, (jint)lpStruct->dwFlags);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.iPixelType, (jbyte)lpStruct->iPixelType);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cColorBits, (jbyte)lpStruct->cColorBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cRedBits, (jbyte)lpStruct->cRedBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cRedShift, (jbyte)lpStruct->cRedShift);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cGreenBits, (jbyte)lpStruct->cGreenBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cGreenShift, (jbyte)lpStruct->cGreenShift);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cBlueBits, (jbyte)lpStruct->cBlueBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cBlueShift, (jbyte)lpStruct->cBlueShift);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAlphaBits, (jbyte)lpStruct->cAlphaBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAlphaShift, (jbyte)lpStruct->cAlphaShift);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumBits, (jbyte)lpStruct->cAccumBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumRedBits, (jbyte)lpStruct->cAccumRedBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumGreenBits, (jbyte)lpStruct->cAccumGreenBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumBlueBits, (jbyte)lpStruct->cAccumBlueBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAccumAlphaBits, (jbyte)lpStruct->cAccumAlphaBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cDepthBits, (jbyte)lpStruct->cDepthBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cStencilBits, (jbyte)lpStruct->cStencilBits);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.cAuxBuffers, (jbyte)lpStruct->cAuxBuffers);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.iLayerType, (jbyte)lpStruct->iLayerType);
+       (*env)->SetByteField(env, lpObject, PIXELFORMATDESCRIPTORFc.bReserved, (jbyte)lpStruct->bReserved);
+       (*env)->SetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwLayerMask, (jint)lpStruct->dwLayerMask);
+       (*env)->SetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwVisibleMask, (jint)lpStruct->dwVisibleMask);
+       (*env)->SetIntField(env, lpObject, PIXELFORMATDESCRIPTORFc.dwDamageMask, (jint)lpStruct->dwDamageMask);
+}
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_structs.h b/bundles/org.eclipse.swt.win32.win32.x86_64/library/wgl_structs.h
new file mode 100644 (file)
index 0000000..7c1d3ec
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/* Note: This file was auto-generated by org.eclipse.swt.tools.internal.JNIGenerator */
+/* DO NOT EDIT - your changes will be lost. */
+
+#include "wgl.h"
+
+#ifndef NO_LAYERPLANEDESCRIPTOR
+void cacheLAYERPLANEDESCRIPTORFields(JNIEnv *env, jobject lpObject);
+LAYERPLANEDESCRIPTOR *getLAYERPLANEDESCRIPTORFields(JNIEnv *env, jobject lpObject, LAYERPLANEDESCRIPTOR *lpStruct);
+void setLAYERPLANEDESCRIPTORFields(JNIEnv *env, jobject lpObject, LAYERPLANEDESCRIPTOR *lpStruct);
+#define LAYERPLANEDESCRIPTOR_sizeof() sizeof(LAYERPLANEDESCRIPTOR)
+#else
+#define cacheLAYERPLANEDESCRIPTORFields(a,b)
+#define getLAYERPLANEDESCRIPTORFields(a,b,c) NULL
+#define setLAYERPLANEDESCRIPTORFields(a,b,c)
+#define LAYERPLANEDESCRIPTOR_sizeof() 0
+#endif
+
+#ifndef NO_PIXELFORMATDESCRIPTOR
+void cachePIXELFORMATDESCRIPTORFields(JNIEnv *env, jobject lpObject);
+PIXELFORMATDESCRIPTOR *getPIXELFORMATDESCRIPTORFields(JNIEnv *env, jobject lpObject, PIXELFORMATDESCRIPTOR *lpStruct);
+void setPIXELFORMATDESCRIPTORFields(JNIEnv *env, jobject lpObject, PIXELFORMATDESCRIPTOR *lpStruct);
+#define PIXELFORMATDESCRIPTOR_sizeof() sizeof(PIXELFORMATDESCRIPTOR)
+#else
+#define cachePIXELFORMATDESCRIPTORFields(a,b)
+#define getPIXELFORMATDESCRIPTORFields(a,b,c) NULL
+#define setPIXELFORMATDESCRIPTORFields(a,b,c)
+#define PIXELFORMATDESCRIPTOR_sizeof() 0
+#endif
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/pom.xml b/bundles/org.eclipse.swt.win32.win32.x86_64/pom.xml
new file mode 100644 (file)
index 0000000..df131e2
--- /dev/null
@@ -0,0 +1,34 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+        <modelVersion>4.0.0</modelVersion>
+        <artifactId>org.eclipse.swt.win32.win32.x86_64</artifactId>
+        <groupId>org.eclipse</groupId>
+        <packaging>eclipse-plugin</packaging>
+        <version>3.113.0.v20191204-0601</version>
+
+        <parent>
+                <groupId>org.simantics</groupId>
+                <artifactId>org.simantics.root.bundles</artifactId>
+                <version>1.0.0-SNAPSHOT</version>
+                <relativePath>..</relativePath>
+        </parent>
+
+        <build>
+                <plugins>
+                        <plugin>
+                                <groupId>org.eclipse.tycho</groupId>
+                                <artifactId>target-platform-configuration</artifactId>
+                                <configuration>
+                                        <environments>
+                                                <environment>
+                                                        <os>win32</os>
+                                                        <ws>win32</ws>
+                                                        <arch>x86_64</arch>
+                                                </environment>
+                                        </environments>
+                                </configuration>
+                        </plugin>
+                </plugins>
+        </build>
+
+</project>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWT.java
new file mode 100644 (file)
index 0000000..5629185
--- /dev/null
@@ -0,0 +1,4785 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 455263
+ *******************************************************************************/
+package org.eclipse.swt;
+
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 final
+ *   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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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.widgets.Control#addDragDetectListener
+        * @see org.eclipse.swt.events.DragDetectListener#dragDetected
+        * @see org.eclipse.swt.events.DragDetectEvent
+        * @see org.eclipse.swt.dnd.DragSource
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final 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
+        *
+        * @see org.eclipse.swt.widgets.Control#addMenuDetectListener
+        * @see org.eclipse.swt.widgets.TrayItem#addMenuDetectListener
+        * @see org.eclipse.swt.events.MenuDetectListener#menuDetected
+        * @see org.eclipse.swt.events.MenuDetectEvent
+        *
+        * @since 3.0
+        */
+       public static final 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 final int SetData = 36;
+
+       /**
+        * The mouse vertical wheel event type (value is 37).
+        *
+        * @see org.eclipse.swt.widgets.Control#addMouseWheelListener
+        * @see org.eclipse.swt.widgets.Display#addFilter
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.6
+        */
+       public static final int MouseVerticalWheel = 37;
+
+       /**
+        * The mouse horizontal wheel event type (value is 38).
+        *
+        * @see org.eclipse.swt.widgets.Widget#addListener
+        * @see org.eclipse.swt.widgets.Display#addFilter
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.6
+        */
+       public static final int MouseHorizontalWheel = 38;
+
+       /**
+        * The mouse wheel event type (value is 37).
+        * This is a synonym for {@link #MouseVerticalWheel} (value is 37).
+        * Newer applications should use {@link #MouseVerticalWheel} instead
+        * of {@link #MouseWheel} to make code more understandable.
+        *
+        * @see org.eclipse.swt.widgets.Control#addMouseWheelListener
+        * @see org.eclipse.swt.widgets.Display#addFilter
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.1
+        */
+       public static final int MouseWheel = MouseVerticalWheel;
+
+       /**
+        * 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 final 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 final 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 final 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 final 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:
+        * <ul>
+        * <li>{@link SWT#COMPOSITION_CHANGED}</li>
+        * <li>{@link SWT#COMPOSITION_OFFSET}</li>
+        * <li>{@link SWT#COMPOSITION_SELECTION}</li>
+        * </ul>
+        *
+        * @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 final int ImeComposition = 43;
+
+       /**
+        * The orientation change event type (value is 44).
+        * <p>
+        * On some platforms the orientation of text widgets
+        * can be changed by keyboard shortcut.
+        * The application can use the <code>doit</code> field
+        * of the event to stop the change from happening.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Widget#addListener
+        * @see org.eclipse.swt.widgets.Display#addFilter
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.6
+        */
+       public static final int OrientationChange = 44;
+
+       /**
+        * The skin event type (value is 45).
+        *
+        * <p>
+        * The skin event is sent by the display when a widget needs to
+        * be skinned.
+        * </p>
+        *
+        * @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.Widget#reskin(int)
+        *
+        * @since 3.6
+        */
+       public static final int Skin = 45;
+
+       /**
+        * The open document event type (value is 46).
+        *
+        * <p>
+        * This event is sent when SWT receives notification that a document
+        * should be opened.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Display#addListener
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.6
+        */
+       public static final int OpenDocument = 46;
+
+       /**
+        * The touch event type (value is 47).
+        *
+        * <p>
+        * This event is sent when a touch has been performed
+        * on a touch-based input source.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Display#addListener
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.7
+        */
+       public static final int Touch = 47;
+
+       /**
+        * The gesture event type (value is 48).
+        *
+        * <p>
+        * This event is sent when a gesture has been performed.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Display#addListener
+        * @see org.eclipse.swt.widgets.Event
+        * @see SWT#GESTURE_MAGNIFY
+        * @see SWT#GESTURE_PAN
+        * @see SWT#GESTURE_ROTATE
+        * @see SWT#GESTURE_SWIPE
+        *
+        * @since 3.7
+        */
+       public static final int Gesture = 48;
+
+       /**
+        * The segments event type (value is 49).
+        *
+        * <p>
+        * This event is sent when text content has been changed.
+        * </p>
+        *
+        * @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.Text#addSegmentListener
+        * @see org.eclipse.swt.events.SegmentEvent
+        *
+        * @since 3.8
+        */
+       public static final int Segments = 49;
+
+       /**
+        * The PreEvent event type (value is 50).
+        *
+        * <p>
+        * This event is sent before an event other than {@link #PreExternalEventDispatch} or
+        * {@link #PostExternalEventDispatch} is dispatched.
+        * </p>
+        * <p>
+        * The detail field of the event contains the type of the following event.
+        * </p>
+        *
+        * @since 3.103
+        */
+       public static final int PreEvent = 50;
+
+       /**
+        * The PostEvent event type (value is 51).
+        *
+        * <p>
+        * This event is sent after an event other than {@link #PreExternalEventDispatch} or
+        * {@link #PostExternalEventDispatch} is dispatched.
+        * </p>
+        * <p>
+        * The detail field of the event contains the type of the prior event.
+        * </p>
+        *
+        * @since 3.103
+        */
+       public static final int PostEvent = 51;
+
+       /**
+        * The PreExternalEventDispatch event type (value is 52).
+        *
+        * <p>
+        * This event is sent before calling a blocking method that does its own event dispatch outside
+        * of the SWT code.
+        * </p>
+        *
+        * @since 3.104
+        */
+       public static final int PreExternalEventDispatch = 52;
+
+       /**
+        * The PostExternalEventDispatch event type (value is 53).
+        *
+        * <p>
+        * This event is sent after calling a blocking method that does its own event dispatch outside
+        * of the SWT code.
+        * </p>
+        *
+        * @since 3.104
+        */
+       public static final int PostExternalEventDispatch = 53;
+
+       /**
+        * @deprecated The same as PreExternalEventDispatch (value is 52).
+        * @since 3.103
+        */
+       @Deprecated
+       public static final int Sleep = PreExternalEventDispatch;
+
+       /**
+        * @deprecated The same as PostExternalEventDispatch (value is 53).
+        * @since 3.103
+        */
+       @Deprecated
+       public static final int Wakeup = PostExternalEventDispatch;
+
+       /**
+        * The open URL event type (value is 54).
+        *
+        * <p>
+        * This event is sent when SWT receives notification that a URL
+        * should be opened.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Display#addListener
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.107
+        */
+       public static final int OpenUrl = 54;
+
+       /**
+        * The SWT zoom change event type (value is 55).
+        *
+        * <p>
+        * This event is sent on <code>Shell</code> when the SWT zoom has changed. The SWT
+        * zoom changes when the operating system DPI or scale factor changes dynamically.
+        * </p>
+        * <p>
+        * Note that this is a <em>HINT</em> and is not sent on platforms that do not
+        * support dynamic DPI changes. This event is currently sent on Windows 10 and GTK
+        * only.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Widget#addListener
+        * @see org.eclipse.swt.widgets.Display#addFilter
+        * @see org.eclipse.swt.widgets.Event
+        *
+        * @since 3.108
+        */
+       public static final int ZoomChanged = 55;
+
+       /* 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final int HOT = 1 << 5;
+
+       /* This code is intentionally commented */
+       //public static final int PRESSED = 1 << 3;
+       //public static final int ACTIVE = 1 << 4;
+       //public static final int DISABLED = 1 << 5;
+       //public static final int HOT = 1 << 6;
+       //public static final int DEFAULTED = 1 << 7;
+
+       /**
+        * Traversal event detail field value indicating that no
+        * traversal action should be taken
+        * (value is 0).
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final int TRAVERSE_PAGE_NEXT = 1 << 9;
+
+       /**
+        * Gesture event detail field value indicating that a continuous
+        * gesture is about to begin.
+        *
+        * @since 3.7
+        */
+       public static final int GESTURE_BEGIN = 1 << 1;
+
+       /**
+        * Gesture event detail field value indicating that a continuous
+        * gesture has ended.
+        *
+        * @since 3.7
+        */
+       public static final int GESTURE_END = 1 << 2;
+
+       /**
+        * Gesture event detail field value indicating that a
+        * rotation gesture has happened. Only the rotation field
+        * of the event is valid.
+        *
+        * @since 3.7
+        */
+       public static final int GESTURE_ROTATE = 1 << 3;
+
+       /**
+        * Gesture event detail field value indicating that a
+        * swipe gesture has happened.
+        *
+        * @since 3.7
+        */
+       public static final int GESTURE_SWIPE = 1 << 4;
+
+       /**
+        * Gesture event detail field value indicating that a
+        * magnification gesture has happened.
+        *
+        * @since 3.7
+        */
+       public static final int GESTURE_MAGNIFY = 1 << 5;
+
+       /**
+        * Gesture event detail field value indicating that a
+        * panning (two-finger scroll) gesture has happened.
+        *
+        * @since 3.7
+        */
+       public static final int GESTURE_PAN = 1 << 6;
+
+       /**
+        * A constant indicating that a finger touched the device.
+        *
+        * @see org.eclipse.swt.widgets.Touch#state
+        *
+        * @since 3.7
+        */
+       public static final int TOUCHSTATE_DOWN = 1 << 0;
+
+       /**
+        * A constant indicating that a finger moved on the device.
+        *
+        * @see org.eclipse.swt.widgets.Touch#state
+        *
+        * @since 3.7
+        */
+       public static final int TOUCHSTATE_MOVE = 1 << 1;
+
+       /**
+        * A constant indicating that a finger was lifted from the device.
+        *
+        * @see org.eclipse.swt.widgets.Touch#state
+        *
+        * @since 3.7
+        */
+       public static final int TOUCHSTATE_UP = 1 << 2;
+
+       /**
+        * MenuDetect event detail value indicating that a context menu
+        * was requested by a mouse or other pointing device (value is 0).
+        *
+        * @since 3.8
+        */
+       public static final int MENU_MOUSE = 0;
+
+       /**
+        * MenuDetect event detail value indicating that a context menu
+        * was requested by a keyboard or other focus-based device (value is 1).
+        *
+        * @since 3.8
+        */
+       public static final int MENU_KEYBOARD = 1;
+
+       /**
+        * A constant indicating that widgets have changed.
+        * (value is 1&lt;&lt;1).
+        *
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Composite</code> layout</li>
+        * </ul>
+        *
+        * @see org.eclipse.swt.widgets.Composite#layout(org.eclipse.swt.widgets.Control[], int)
+        *
+        * @since 3.6
+        */
+       public static final int CHANGED = 1 << 1;
+
+       /**
+        * A constant indicating that a given operation should be deferred.
+        * (value is 1&lt;&lt;2).
+        *
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Composite</code> layout</li>
+        * </ul>
+        *
+        * @see org.eclipse.swt.widgets.Composite#layout(org.eclipse.swt.widgets.Control[], int)
+        *
+        * @since 3.6
+        */
+       public static final int DEFER = 1 << 2;
+
+       /**
+        * A constant known to be zero (0), typically used in operations
+        * which take bit flags to indicate that "no bits are set".
+        */
+       public static final int NONE = 0;
+
+       /**
+        * A constant known to be zero (0), used in operations which
+        * take pointers to indicate a null argument.
+        */
+       public static final int NULL = 0;
+
+       /**
+        * Indicates that a default should be used (value is -1).
+        */
+       public static final int DEFAULT = -1;
+
+       /**
+        * Indicates that a property is off (value is 0).
+        *
+        * @since 3.1
+        */
+       public static final int OFF = 0;
+
+       /**
+        * Indicates that a property is on (value is 1).
+        *
+        * @since 3.1
+        */
+       public static final int ON = 1;
+
+       /**
+        * Indicates low quality (value is 1).
+        *
+        * @since 3.1
+        */
+       public static final int LOW = 1;
+
+       /**
+        * Indicates high quality (value is 2).
+        *
+        * @since 3.1
+        */
+       public static final int HIGH = 2;
+
+       /**
+        * Style constant for menu bar behavior (value is 1&lt;&lt;1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Menu</code></li>
+        * </ul>
+        */
+       public static final int BAR = 1 << 1;
+
+       /**
+        * Style constant for drop down menu/list behavior (value is 1&lt;&lt;2).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Menu</code></li>
+        * <li><code>ToolItem</code></li>
+        * <li><code>CoolItem</code></li>
+        * <li><code>Combo</code></li>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        */
+       public static final int DROP_DOWN = 1 << 2;
+
+       /**
+        * Style constant for pop up menu behavior (value is 1&lt;&lt;3).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Menu</code></li>
+        * </ul>
+        */
+       public static final int POP_UP = 1 << 3;
+
+       /**
+        * Style constant for line separator behavior (value is 1&lt;&lt;1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Label</code></li>
+        * <li><code>MenuItem</code></li>
+        * <li><code>ToolItem</code></li>
+        * </ul>
+        */
+       public static final int SEPARATOR = 1 << 1;
+
+       /**
+        * Constant representing a flexible space separator in a ToolBar.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>ToolItem.setWidth()</code></li>
+        * </ul>
+        *
+        * @since 3.7
+        */
+       public static final int SEPARATOR_FILL = -2;
+
+       /**
+        * Style constant for toggle button behavior (value is 1&lt;&lt;1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * </ul>
+        */
+       public static final int TOGGLE = 1 << 1;
+
+       /**
+        * Style constant for arrow button behavior (value is 1&lt;&lt;2).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * </ul>
+        */
+       public static final int ARROW = 1 << 2;
+
+       /**
+        * Style constant for push button behavior (value is 1&lt;&lt;3).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * <li><code>MenuItem</code></li>
+        * <li><code>ToolItem</code></li>
+        * </ul>
+        */
+       public static final int PUSH = 1 << 3;
+
+       /**
+        * Style constant for radio button behavior (value is 1&lt;&lt;4).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * <li><code>MenuItem</code></li>
+        * <li><code>ToolItem</code></li>
+        * </ul>
+        */
+       public static final int RADIO = 1 << 4;
+
+       /**
+        * Style constant for check box behavior (value is 1&lt;&lt;5).
+        * <p><b>Used By:</b></p>
+        * <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>
+        */
+       public static final int CHECK = 1 << 5;
+
+       /**
+        * Style constant for cascade behavior (value is 1&lt;&lt;6).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>MenuItem</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Text</code></li>
+        * <li><code>List</code></li>
+        * <li><code>Table</code></li>
+        * <li><code>Tree</code></li>
+        * <li><code>FileDialog</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Text</code></li>
+        * <li><code>List</code></li>
+        * <li><code>Table</code></li>
+        * <li><code>Tree</code></li>
+        * </ul>
+        */
+       public static final int SINGLE = 1 << 2;
+
+       /**
+        * Style constant for read-only behavior (value is 1&lt;&lt;3).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Combo</code></li>
+        * <li><code>Text</code></li>
+        * </ul>
+        */
+       public static final int READ_ONLY = 1 << 3;
+
+       /**
+        * Style constant for automatic line wrap behavior (value is 1&lt;&lt;6).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * <li><code>Label</code></li>
+        * <li><code>Text</code></li>
+        * <li><code>ToolBar</code></li>
+        * <li><code>Spinner</code></li>
+        * </ul>
+        */
+       public static final int WRAP = 1 << 6;
+
+       /**
+        * Style constant for search behavior (value is 1&lt;&lt;7).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Text</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final int SEARCH = 1 << 7;
+
+       /**
+        * Style constant for simple (not drop down) behavior (value is 1&lt;&lt;6).
+        * <br>Note that this is a <em>HINT</em>.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Combo</code></li>
+        * </ul>
+        */
+       public static final int SIMPLE = 1 << 6;
+
+       /**
+        * Style constant for password behavior (value is 1&lt;&lt;22).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Text</code></li>
+        * </ul>
+        *
+        * @since 3.0
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Label</code></li>
+        * <li><code>Group</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Label</code></li>
+        * <li><code>Group</code></li>
+        * <li><code>ToolBar</code></li>
+        * </ul>
+        */
+       public static final 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 currently ignored on all platforms.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Group</code></li>
+        * </ul>
+        */
+       public static final 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 currently ignored on all platforms.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Group</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Label</code></li>
+        * <li><code>Group</code></li>
+        * </ul>
+        */
+       public static final int SHADOW_NONE = 1 << 5;
+
+       /**
+        * Style constant for progress bar behavior (value is 1&lt;&lt;1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>ProgressBar</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final int NO_TRIM = 1 << 3;
+
+       /**
+        * Style constant for resize box trim (value is 1&lt;&lt;4).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * <li><code>Tracker</code></li>
+        * </ul>
+        */
+       public static final int RESIZE = 1 << 4;
+
+       /**
+        * Style constant for title area trim (value is 1&lt;&lt;5).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final int MENU = CLOSE;
+
+       /**
+        * Style constant for minimize box trim (value is 1&lt;&lt;7).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final int MIN = 1 << 7;
+
+       /**
+        * Style constant for maximize box trim (value is 1&lt;&lt;10).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Decorations</code> and subclasses</li>
+        * </ul>
+        */
+       public static final int MAX = 1 << 10;
+
+       /**
+        * Style constant for the no move behavior (value is 1&lt;&lt;23).
+        * Creates the title trim when no other trim style is specified.
+        * Doesn't create the title trim when NO_TRIM is specified.
+        * <p>Note that this is a <em>HINT</em>.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Shell</code></li>
+        * </ul>
+        * @since 3.105
+        */
+       public static final int NO_MOVE = 1 << 23;
+
+       /**
+        * Style constant for horizontal scrollbar behavior (value is 1&lt;&lt;8).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Scrollable</code> and subclasses</li>
+        * </ul>
+        */
+       public static final int H_SCROLL = 1 << 8;
+
+       /**
+        * Style constant for vertical scrollbar behavior (value is 1&lt;&lt;9).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Scrollable</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Tree</code></li>
+        * <li><code>Table</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Control</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Control</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Control</code> and subclasses</li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Shell</code> and subclasses</li>
+        * </ul>
+        */
+       public static final int ON_TOP = 1 << 14;
+
+       /**
+        * Style constant for sheet window behavior (value is 1&lt;&lt;28).
+        * <p>
+        * A sheet window is a window intended to be used as a temporary modal
+        * dialog that is attached to a parent window. It is typically used to
+        * prompt the user before proceeding. The window trim, positioning and
+        * general look of a sheet window is platform specific. For example,
+        * on the Macintosh, at the time this documentation was written, the
+        * window title is not visible.
+        * <br>Note that this is a <em>HINT</em>.
+        * </p><p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Dialog</code> and subclasses</li>
+        * <li><code>Shell</code> and subclasses</li>
+        * </ul>
+        *
+        * @since 3.5
+        */
+       public static final int SHEET = 1 << 28;
+
+       /**
+        * Trim style convenience constant for the most common top level shell appearance
+        * (value is CLOSE|TITLE|MIN|MAX|RESIZE).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Shell</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Shell</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Dialog</code></li>
+        * <li><code>Shell</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Dialog</code></li>
+        * <li><code>Shell</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Dialog</code></li>
+        * <li><code>Shell</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Dialog</code></li>
+        * <li><code>Shell</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Table</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Table</code></li>
+        * <li><code>Tree</code></li>
+        * <li><code>StyledText</code></li>
+        * <li><code>TextLayout</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * <li><code>ToolBar</code></li>
+        * </ul>
+        */
+       public static final 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></p><ul>
+        * <li><code>ProgressBar</code></li>
+        * <li><code>Sash</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * <li><code>Menu</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * <li><code>Menu</code></li>
+        * <li><code>GC</code></li>
+        * </ul>
+        *
+        * @since 2.1.2
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * <li><code>Menu</code></li>
+        * <li><code>GC</code></li>
+        * </ul>
+        *
+        * @since 2.1.2
+        */
+       public static final int RIGHT_TO_LEFT = 1 << 26;
+
+       /**
+        * Style constant to indicate coordinate mirroring (value is 1&lt;&lt;27).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * <li><code>Menu</code></li>
+        * </ul>
+        *
+        * @since 2.1.2
+        */
+       public static final int MIRRORED = 1 << 27;
+
+       /**
+        * Style constant to allow embedding (value is 1&lt;&lt;24).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * </ul>
+        *
+        * @since 3.0
+        */
+       public static final int EMBEDDED = 1 << 24;
+
+       /**
+        * Style constant to allow virtual data (value is 1&lt;&lt;28).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Table</code></li>
+        * <li><code>Tree</code></li>
+        * </ul>
+        *
+        * @since 3.0
+        */
+       public static final int VIRTUAL = 1 << 28;
+
+       /**
+        * Style constant to indicate double buffering (value is 1&lt;&lt;29).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * </ul>
+        *
+        * @since 3.1
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>Composite</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        *
+        * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+        */
+       public static final int TRANSPARENT = 1 << 30;
+
+       /**
+        * Style constant to indicate base text direction (value is 1&lt;&lt;31).
+        * <p>
+        * When the bit is set, text direction mismatches the widget orientation.
+        * <br>Note that this is a <em>HINT</em>.
+        * </p>
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * </ul>
+        *
+        * @see org.eclipse.swt.widgets.Control#setTextDirection(int)
+        * @see org.eclipse.swt.widgets.Control#getTextDirection()
+        *
+        * @since 3.102
+        */
+       public static final int FLIP_TEXT_DIRECTION = 1 << 31;
+
+       /**
+        * A bit mask to indicate Bidi "auto" text direction.
+        * <p>
+        * When the bit is set, text direction is derived from the direction of the
+        * first strong Bidi character.
+        * </p>
+        * <br>Note that this is a <em>HINT</em> and it works on Windows only.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * <li><code>TextLayout</code></li>
+        * </ul>
+        *
+        * @see org.eclipse.swt.widgets.Control#setTextDirection(int)
+        * @see org.eclipse.swt.graphics.TextLayout#setTextDirection(int)
+        *
+        * @since 3.105
+       */
+       public static final int AUTO_TEXT_DIRECTION = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+
+       /**
+        * 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></p>
+        * <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>
+        */
+       public static final int UP = 1 << 7;
+
+       /**
+        * Style constant to indicate single underline (value is 0).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int UNDERLINE_SINGLE = 0;
+
+       /**
+        * Style constant to indicate double underline (value is 1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int UNDERLINE_DOUBLE = 1;
+
+       /**
+        * Style constant to indicate error underline (value is 2).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int UNDERLINE_ERROR = 2;
+
+       /**
+        * Style constant to indicate squiggle underline (value is 3).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int UNDERLINE_SQUIGGLE = 3;
+
+       /**
+        * Style constant to indicate link underline (value is 0).
+        * <p>
+        * If the text color or the underline color are not set in the range
+        * the usage of <code>UNDERLINE_LINK</code> will change these colors
+        * to the preferred link color of the platform.<br>
+        * Note that clients that use this style, such as <code>StyledText</code>,
+        * will include code to track the mouse and change the cursor to the hand
+        * cursor when mouse is over the link.
+        * </p>
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.5
+        */
+       public static final int UNDERLINE_LINK = 4;
+
+       /**
+        * Style constant to indicate solid border (value is 1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int BORDER_SOLID = 1;
+
+       /**
+        * Style constant to indicate dashed border (value is 2).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int BORDER_DASH = 2;
+
+       /**
+        * Style constant to indicate dotted border (value is 4).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>TextStyle</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+        * </ul>
+        */
+       public static final 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></p>
+        * <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>
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+        * <li><code>TabFolder</code></li>
+        * </ul>
+        */
+       public static final int BOTTOM             = DOWN;
+
+       /**
+        * Style constant for leading alignment (value is 1&lt;&lt;14).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * <li><code>Label</code></li>
+        * <li><code>Text</code></li>
+        * <li><code>TableColumn</code></li>
+        * <li><code>TreeColumn</code></li>
+        * <li><code>Tracker</code></li>
+        * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+        * </ul>
+        *
+        * @since 2.1.2
+        */
+       public static final int LEAD               = 1 << 14;
+
+       /**
+        * Style constant for align left behavior (value is 1&lt;&lt;14).
+        * This is a synonym for {@link #LEAD} (value is 1&lt;&lt;14).  Newer
+        * applications should use {@link #LEAD} instead of {@link #LEFT} to make code more
+        * understandable on right-to-left platforms.
+        * <p>
+        * This constant can also be used to representing the left keyboard
+        * location during a key event.
+        * </p>
+        */
+       public static final int LEFT               = LEAD;
+
+       /**
+        * Style constant for trailing alignment (value is 1&lt;&lt;17).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Button</code></li>
+        * <li><code>Label</code></li>
+        * <li><code>Text</code></li>
+        * <li><code>TableColumn</code></li>
+        * <li><code>TreeColumn</code></li>
+        * <li><code>Tracker</code></li>
+        * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+        * </ul>
+        *
+        * @since 2.1.2
+        */
+       public static final int TRAIL              = 1 << 17;
+
+       /**
+        * Style constant for align right behavior (value is 1&lt;&lt;17).
+        * This is a synonym for {@link #TRAIL} (value is 1&lt;&lt;17).  Newer
+        * applications should use {@link #TRAIL} instead of {@link #RIGHT} to make code more
+        * understandable on right-to-left platforms.
+        * <p>
+        * This constant can also be used to representing the right keyboard
+        * location during a key event.
+        * </p>
+        */
+       public static final int RIGHT              = TRAIL;
+
+       /**
+        * Style constant for align center behavior (value is 1&lt;&lt;24).
+        * <p><b>Used By:</b></p>
+        * <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>
+        */
+       public static final int CENTER = 1 << 24;
+
+       /**
+        * Style constant for horizontal alignment or orientation behavior (value is 1&lt;&lt;8).
+        * <p><b>Used By:</b></p>
+        * <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>
+        */
+       public static final int HORIZONTAL = 1 << 8;
+
+       /**
+        * Style constant for vertical alignment or orientation behavior (value is 1&lt;&lt;9).
+        * <p><b>Used By:</b></p>
+        * <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>
+        */
+       public static final int VERTICAL = 1 << 9;
+
+       /**
+        * Style constant for date display (value is 1&lt;&lt;5).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final int DATE = 1 << 5;
+
+       /**
+        * Style constant for time display (value is 1&lt;&lt;7).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final int TIME = 1 << 7;
+
+       /**
+        * Style constant for calendar display (value is 1&lt;&lt;10).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final int CALENDAR = 1 << 10;
+
+       /**
+        * Style constant for displaying week numbers in the calendar.
+        * <br>Note that this is a <em>HINT</em> and is supported on Windows &amp; GTK platforms only.
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.108
+        */
+       public static final int CALENDAR_WEEKNUMBERS = 1 << 14;
+
+       /**
+        * 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></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>DateTime</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        */
+       public static final 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><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Browser</code></li>
+        * </ul>
+        *
+        * @since 3.3
+        * @deprecated This style is deprecated and will be removed in the future.
+        *             XULRunner as a browser renderer is no longer supported. Use
+        *             <code>SWT.WEBKIT</code> or <code>SWT.NONE</code> instead.
+        */
+       @Deprecated
+       public static final int MOZILLA = 1 << 15;
+
+       /**
+        * Style constant specifying that a Browser should use WebKit
+        * for rendering its content (value is 1&lt;&lt;16).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Browser</code></li>
+        * </ul>
+        *
+        * @since 3.7
+        */
+       public static final int WEBKIT = 1 << 16;
+
+       /**
+        * Style constant for balloon behavior (value is 1&lt;&lt;12).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>ToolTip</code></li>
+        * </ul>
+        *
+        * @since 3.2
+        */
+       public static final int BALLOON = 1 << 12;
+
+       /**
+        * Style constant for vertical alignment or orientation behavior (value is 1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>GridLayout</code> type</li>
+        * </ul>
+        */
+       public static final int BEGINNING = 1;
+
+       /**
+        * Style constant for vertical alignment or orientation behavior (value is 4).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>GridLayout</code> type</li>
+        * </ul>
+        */
+       public static final int FILL = 4;
+
+       /**
+        * Input Method Editor style constant for double byte
+        * input behavior (value is 1&lt;&lt;1).
+        */
+       public static final int DBCS = 1 << 1;
+
+       /**
+        * Input Method Editor style constant for alpha
+        * input behavior (value is 1&lt;&lt;2).
+        */
+       public static final int ALPHA = 1 << 2;
+
+       /**
+        * Input Method Editor style constant for native
+        * input behavior (value is 1&lt;&lt;3).
+        */
+       public static final int NATIVE = 1 << 3;
+
+       /**
+        * Input Method Editor style constant for phonetic
+        * input behavior (value is 1&lt;&lt;4).
+        */
+       public static final int PHONETIC = 1 << 4;
+
+       /**
+        * Input Method Editor style constant for romanicized
+        * input behavior (value is 1&lt;&lt;5).
+        */
+       public static final int ROMAN = 1 << 5;
+
+       /**
+        * ASCII character convenience constant for the backspace character
+        * (value is the <code>char</code> '\b').
+        */
+       public static final char BS = '\b';
+
+       /**
+        * ASCII character convenience constant for the carriage return character
+        * (value is the <code>char</code> '\r').
+        */
+       public static final char CR = '\r';
+
+       /**
+        * ASCII character convenience constant for the delete character
+        * (value is the <code>char</code> with value 127).
+        */
+       public static final char DEL = 0x7F;
+
+       /**
+        * ASCII character convenience constant for the escape character
+        * (value is the <code>char</code> with value 27).
+        */
+       public static final char ESC = 0x1B;
+
+       /**
+        * ASCII character convenience constant for the line feed character
+        * (value is the <code>char</code> '\n').
+        */
+       public static final char LF = '\n';
+
+       /**
+        * ASCII character convenience constant for the tab character
+        * (value is the <code>char</code> '\t').
+        *
+        * @since 2.1
+        */
+       public static final char TAB = '\t';
+
+       /**
+        * ASCII character convenience constant for the space character
+        * (value is the <code>char</code> ' ').
+        *
+        * @since 3.7
+        */
+       public static final char SPACE = ' ';
+
+       /**
+        * Keyboard and/or mouse event mask indicating that the ALT_GR key
+        * was pushed on the keyboard when the event was generated
+        * (value is 1 &lt;&lt; 15).
+        *
+        * @since 3.108
+        */
+       public static final int ALT_GR = 1 << 15;
+
+       /**
+        * 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 final 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 final 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 final 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 final 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 final 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 &amp; SWT.MODIFIER_MASK) != 0</code>.
+        *
+        * @since 2.1
+        */
+       public static final int MODIFIER_MASK;
+
+       /**
+        * Keyboard and/or mouse event mask indicating that mouse button one (usually 'left')
+        * was pushed when the event was generated. (value is 1&lt;&lt;19).
+        */
+       public static final int BUTTON1 = 1 << 19;
+
+       /**
+        * Keyboard and/or mouse event mask indicating that mouse button two (usually 'middle')
+        * was pushed when the event was generated. (value is 1&lt;&lt;20).
+        */
+       public static final int BUTTON2 = 1 << 20;
+
+       /**
+        * Keyboard and/or mouse event mask indicating that mouse button three (usually 'right')
+        * was pushed when the event was generated. (value is 1&lt;&lt;21).
+        */
+       public static final 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 final 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 final 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 &amp; SWT.BUTTON_MASK) != 0</code>.
+        *
+        * @since 2.1
+        */
+       public static final int BUTTON_MASK;
+
+       /**
+        * 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.
+        * <p>
+        * {@link #CTRL} on most platforms ({@link #COMMAND} on the Mac).
+        * </p>
+        *
+        * @since 2.1
+        */
+       public static final int MOD1;
+
+       /**
+        * 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.
+        * <p>
+        * {@link #SHIFT} on most platforms.
+        * </p>
+        *
+        * @since 2.1
+        */
+       public static final int MOD2;
+
+       /**
+        * Keyboard and/or mouse event mask indicating that the MOD3 key
+        * was pushed on the keyboard when the event was generated.
+        * <p>
+        * {@link #ALT} on most platforms.
+        * </p>
+        *
+        * @since 2.1
+        */
+       public static final int MOD3;
+
+       /**
+        * Keyboard and/or mouse event mask indicating that the MOD4 key
+        * was pushed on the keyboard when the event was generated.
+        * <p>
+        * Undefined on most platforms ({@link #CTRL} on the Mac).
+        * </p>
+        *
+        * @since 2.1
+        */
+       public static final int MOD4;
+
+       /**
+        * Constants to indicate line scrolling (value is 1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * </ul>
+        *
+        * @since 3.1
+        */
+       public static final int SCROLL_LINE = 1;
+
+       /**
+        * Constants to indicate page scrolling (value is 2).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Control</code></li>
+        * </ul>
+        *
+        * @since 3.1
+        */
+       public static final 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') &amp; SWT.KEYCODE_BIT) != 0</code>.
+        *
+        * The following expression is true:
+        *
+        * <code>((SWT.MOD3 | SWT.F2) &amp; SWT.KEYCODE_BIT) != 0</code>.
+        *
+        * (value is (1&lt;&lt;24))
+        *
+        * @since 2.1
+        */
+       public static final 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 final int KEY_MASK = KEYCODE_BIT + 0xFFFF;
+
+       /**
+        * Keyboard event constant representing the UP ARROW key
+        * (value is (1&lt;&lt;24)+1).
+        */
+       public static final int ARROW_UP = KEYCODE_BIT + 1;
+
+       /**
+        * Keyboard event constant representing the DOWN ARROW key
+        * (value is (1&lt;&lt;24)+2).
+        */
+       public static final int ARROW_DOWN = KEYCODE_BIT + 2;
+
+       /**
+        * Keyboard event constant representing the LEFT ARROW key
+        * (value is (1&lt;&lt;24)+3).
+        */
+       public static final int ARROW_LEFT = KEYCODE_BIT + 3;
+
+       /**
+        * Keyboard event constant representing the RIGHT ARROW key
+        * (value is (1&lt;&lt;24)+4).
+        */
+       public static final int ARROW_RIGHT = KEYCODE_BIT + 4;
+
+       /**
+        * Keyboard event constant representing the PAGE UP key
+        * (value is (1&lt;&lt;24)+5).
+        */
+       public static final int PAGE_UP = KEYCODE_BIT + 5;
+
+       /**
+        * Keyboard event constant representing the PAGE DOWN key
+        * (value is (1&lt;&lt;24)+6).
+        */
+       public static final int PAGE_DOWN = KEYCODE_BIT + 6;
+
+       /**
+        * Keyboard event constant representing the HOME key
+        * (value is (1&lt;&lt;24)+7).
+        */
+       public static final int HOME = KEYCODE_BIT + 7;
+
+       /**
+        * Keyboard event constant representing the END key
+        * (value is (1&lt;&lt;24)+8).
+        */
+       public static final int END = KEYCODE_BIT + 8;
+
+       /**
+        * Keyboard event constant representing the INSERT key
+        * (value is (1&lt;&lt;24)+9).
+        */
+       public static final int INSERT = KEYCODE_BIT + 9;
+
+       /**
+        * Keyboard event constant representing the F1 key
+        * (value is (1&lt;&lt;24)+10).
+        */
+       public static final int F1 = KEYCODE_BIT + 10;
+
+       /**
+        * Keyboard event constant representing the F2 key
+        * (value is (1&lt;&lt;24)+11).
+        */
+       public static final int F2 = KEYCODE_BIT + 11;
+
+       /**
+        * Keyboard event constant representing the F3 key
+        * (value is (1&lt;&lt;24)+12).
+        */
+       public static final int F3 = KEYCODE_BIT + 12;
+
+       /**
+        * Keyboard event constant representing the F4 key
+        * (value is (1&lt;&lt;24)+13).
+        */
+       public static final int F4 = KEYCODE_BIT + 13;
+
+       /**
+        * Keyboard event constant representing the F5 key
+        * (value is (1&lt;&lt;24)+14).
+        */
+       public static final int F5 = KEYCODE_BIT + 14;
+
+       /**
+        * Keyboard event constant representing the F6 key
+        * (value is (1&lt;&lt;24)+15).
+        */
+       public static final int F6 = KEYCODE_BIT + 15;
+
+       /**
+        * Keyboard event constant representing the F7 key
+        * (value is (1&lt;&lt;24)+16).
+        */
+       public static final int F7 = KEYCODE_BIT + 16;
+
+       /**
+        * Keyboard event constant representing the F8 key
+        * (value is (1&lt;&lt;24)+17).
+        */
+       public static final int F8 = KEYCODE_BIT + 17;
+
+       /**
+        * Keyboard event constant representing the F9 key
+        * (value is (1&lt;&lt;24)+18).
+        */
+       public static final int F9 = KEYCODE_BIT + 18;
+
+       /**
+        * Keyboard event constant representing the F10 key
+        * (value is (1&lt;&lt;24)+19).
+        */
+       public static final int F10 = KEYCODE_BIT + 19;
+
+       /**
+        * Keyboard event constant representing the F11 key
+        * (value is (1&lt;&lt;24)+20).
+        */
+       public static final int F11 = KEYCODE_BIT + 20;
+
+       /**
+        * Keyboard event constant representing the F12 key
+        * (value is (1&lt;&lt;24)+21).
+        */
+       public static final int F12 = KEYCODE_BIT + 21;
+
+       /**
+        * Keyboard event constant representing the F13 key
+        * (value is (1&lt;&lt;24)+22).
+        *
+        * @since 3.0
+        */
+       public static final int F13 = KEYCODE_BIT + 22;
+
+       /**
+        * Keyboard event constant representing the F14 key
+        * (value is (1&lt;&lt;24)+23).
+        *
+        * @since 3.0
+        */
+       public static final int F14 = KEYCODE_BIT + 23;
+
+       /**
+        * Keyboard event constant representing the F15 key
+        * (value is (1&lt;&lt;24)+24).
+        *
+        * @since 3.0
+        */
+       public static final int F15 = KEYCODE_BIT + 24;
+
+       /**
+        * Keyboard event constant representing the F16 key
+        * (value is (1&lt;&lt;25)+25).
+        *
+        * @since 3.6
+        */
+       public static final int F16 = KEYCODE_BIT + 25;
+
+
+       /**
+        * Keyboard event constant representing the F17 key
+        * (value is (1&lt;&lt;26)+26).
+        *
+        * @since 3.6
+        */
+       public static final int F17 = KEYCODE_BIT + 26;
+
+
+       /**
+        * Keyboard event constant representing the F18 key
+        * (value is (1&lt;&lt;27)+27).
+        *
+        * @since 3.6
+        */
+       public static final int F18 = KEYCODE_BIT + 27;
+
+
+       /**
+        * Keyboard event constant representing the F19 key
+        * (value is (1&lt;&lt;28)+28).
+        *
+        * @since 3.6
+        */
+       public static final int F19 = KEYCODE_BIT + 28;
+
+       /**
+        * Keyboard event constant representing the F20 key
+        * (value is (1&lt;&lt;29)+29).
+        *
+        * @since 3.6
+        */
+       public static final int F20 = KEYCODE_BIT + 29;
+
+       /**
+        * Keyboard event constant representing the keypad location.
+        * (value is 1&lt;&lt;1).
+        *
+        * @since 3.6
+        */
+       public static final int KEYPAD = 1 << 1;
+
+       /**
+        * Keyboard event constant representing the numeric key
+        * pad multiply key (value is (1&lt;&lt;24)+42).
+        *
+        * @since 3.0
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final int PAUSE = KEYCODE_BIT + 85;
+
+       /**
+        * Keyboard event constant representing the break
+        * key (value is (1&lt;&lt;24)+86).
+        *
+        * @since 3.0
+        */
+       public static final 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 final int PRINT_SCREEN = KEYCODE_BIT + 87;
+
+       /**
+        * The <code>MessageBox</code> style constant for error icon
+        * behavior (value is 1).
+        */
+       public static final int ICON_ERROR = 1;
+
+       /**
+        * The <code>MessageBox</code> style constant for information icon
+        * behavior (value is 1&lt;&lt;1).
+        */
+       public static final int ICON_INFORMATION = 1 << 1;
+
+       /**
+        * The <code>MessageBox</code> style constant for question icon
+        * behavior (value is 1&lt;&lt;2).
+        */
+       public static final int ICON_QUESTION = 1 << 2;
+
+       /**
+        * The <code>MessageBox</code> style constant for warning icon
+        * behavior (value is 1&lt;&lt;3).
+        */
+       public static final int ICON_WARNING = 1 << 3;
+
+       /**
+        * The <code>MessageBox</code> style constant for "working" icon
+        * behavior (value is 1&lt;&lt;4).
+        */
+       public static final int ICON_WORKING = 1 << 4;
+
+       /**
+        * The style constant for "search" icon. This style constant is
+        * used with <code>Text</code> in combination with <code>SWT.SEARCH
+        * </code> (value is 1&lt;&lt;9).
+        *
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Text</code></li>
+        * </ul>
+        *
+        * @see #SEARCH
+        * @see #ICON_CANCEL
+        *
+        * @since 3.5
+        */
+       public static final int ICON_SEARCH = 1 << 9;
+
+       /**
+        * The style constant for "cancel" icon. This style constant is
+        * used with <code>Text</code> in combination with <code>SWT.SEARCH
+        * </code> (value is 1&lt;&lt;8).
+        *
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Text</code></li>
+        * </ul>
+        *
+        * @see #SEARCH
+        * @see #ICON_SEARCH
+        *
+        * @since 3.5
+        */
+       public static final int ICON_CANCEL = 1 << 8;
+
+
+       /**
+        * The <code>MessageBox</code> style constant for an OK button;
+        * valid combinations are OK, OK|CANCEL
+        * (value is 1&lt;&lt;5).
+        */
+       public static final 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 final 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 final 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).
+        *
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>MessageBox</code></li>
+        * </ul>
+        */
+       public static final 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 final 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 final 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 final int IGNORE = 1 << 11;
+
+       /**
+        * The <code>FileDialog</code> style constant for open file dialog behavior
+        * (value is 1&lt;&lt;12).
+        */
+       public static final int OPEN = 1 << 12;
+
+       /**
+        * The <code>FileDialog</code> style constant for save file dialog behavior
+        * (value is 1&lt;&lt;13).
+        */
+       public static final 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 final 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 final 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 final int INHERIT_FORCE = 2;
+
+       /**
+        * Default color white (value is 1).
+        */
+       public static final int COLOR_WHITE = 1;
+
+       /**
+        * Default color black (value is 2).
+        */
+       public static final int COLOR_BLACK = 2;
+
+       /**
+        * Default color red (value is 3).
+        */
+       public static final int COLOR_RED = 3;
+
+       /**
+        * Default color dark red (value is 4).
+        */
+       public static final int COLOR_DARK_RED = 4;
+
+       /**
+        * Default color green (value is 5).
+        */
+       public static final int COLOR_GREEN = 5;
+
+       /**
+        * Default color dark green (value is 6).
+        */
+       public static final int COLOR_DARK_GREEN = 6;
+
+       /**
+        * Default color yellow (value is 7).
+        */
+       public static final int COLOR_YELLOW = 7;
+
+       /**
+        * Default color dark yellow (value is 8).
+        */
+       public static final int COLOR_DARK_YELLOW = 8;
+
+       /**
+        * Default color blue (value is 9).
+        */
+       public static final int COLOR_BLUE = 9;
+
+       /**
+        * Default color dark blue (value is 10).
+        */
+       public static final int COLOR_DARK_BLUE = 10;
+
+       /**
+        * Default color magenta (value is 11).
+        */
+       public static final int COLOR_MAGENTA = 11;
+
+       /**
+        * Default color dark magenta (value is 12).
+        */
+       public static final int COLOR_DARK_MAGENTA = 12;
+
+       /**
+        * Default color cyan (value is 13).
+        */
+       public static final int COLOR_CYAN = 13;
+
+       /**
+        * Default color dark cyan (value is 14).
+        */
+       public static final int COLOR_DARK_CYAN = 14;
+
+       /**
+        * Default color gray (value is 15).
+        */
+       public static final int COLOR_GRAY = 15;
+
+       /**
+        * Default color dark gray (value is 16).
+        */
+       public static final 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 final int COLOR_WIDGET_DARK_SHADOW = 17;
+
+       /**
+        * System color used to paint normal shadow areas (value is 18).
+        */
+       public static final int COLOR_WIDGET_NORMAL_SHADOW = 18;
+
+       /**
+        * System color used to paint light shadow areas (value is 19).
+        */
+       public static final int COLOR_WIDGET_LIGHT_SHADOW = 19;
+
+       /**
+        * System color used to paint highlight shadow areas (value is 20).
+        */
+       public static final int COLOR_WIDGET_HIGHLIGHT_SHADOW = 20;
+
+       /**
+        * System color used to paint foreground areas (value is 21).
+        */
+       public static final int COLOR_WIDGET_FOREGROUND = 21;
+
+       /**
+        * System color used to paint background areas (value is 22).
+        */
+       public static final int COLOR_WIDGET_BACKGROUND = 22;
+
+       /**
+        * System color used to paint border areas (value is 23).
+        */
+       public static final int COLOR_WIDGET_BORDER = 23;
+
+       /**
+        * System color used to paint list foreground areas (value is 24).
+        */
+       public static final int COLOR_LIST_FOREGROUND = 24;
+
+       /**
+        * System color used to paint list background areas (value is 25).
+        */
+       public static final int COLOR_LIST_BACKGROUND = 25;
+
+       /**
+        * System color used to paint list selection background areas (value is 26).
+        */
+       public static final int COLOR_LIST_SELECTION = 26;
+
+       /**
+        * System color used to paint list selected text (value is 27).
+        */
+       public static final int COLOR_LIST_SELECTION_TEXT = 27;
+
+       /**
+        * System color used to paint tooltip text (value is 28).
+        */
+       public static final int COLOR_INFO_FOREGROUND = 28;
+
+       /**
+        * System color used to paint tooltip background areas (value is 29).
+        */
+       public static final int COLOR_INFO_BACKGROUND = 29;
+
+       /**
+        * System color used to paint title text (value is 30).
+        */
+       public static final int COLOR_TITLE_FOREGROUND = 30;
+
+       /**
+        * System color used to paint title background areas (value is 31).
+        */
+       public static final int COLOR_TITLE_BACKGROUND = 31;
+
+       /**
+        * System color used to paint title background gradient (value is 32).
+        */
+       public static final int COLOR_TITLE_BACKGROUND_GRADIENT = 32;
+
+       /**
+        * System color used to paint inactive title text (value is 33).
+        */
+       public static final int COLOR_TITLE_INACTIVE_FOREGROUND = 33;
+
+       /**
+        * System color used to paint inactive title background areas (value is 34).
+        */
+       public static final int COLOR_TITLE_INACTIVE_BACKGROUND = 34;
+
+       /**
+        * System color used to paint inactive title background gradient (value is 35).
+        */
+       public static final int COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = 35;
+
+       /**
+        * System color used to paint link text (value is 36).
+        *
+        * @since 3.102
+        */
+       public static final int COLOR_LINK_FOREGROUND = 36;
+
+       /**
+        * System color used to paint with alpha 0 (value is 37).
+        * <p>
+        * This pseudo-color can be used to set a transparent background on SWT
+        * controls. <br>
+        * Note that this is a <em>HINT</em> and may be overridden by the platform.
+        * For example:
+        * <ul>
+        * <li>{@link org.eclipse.swt.widgets.Combo Combo},
+        * {@link org.eclipse.swt.widgets.List List} and
+        * {@link org.eclipse.swt.widgets.Tree Tree} support transparent background
+        * on GTK3 and Windows only.</li>
+        * <li>{@link org.eclipse.swt.widgets.Text Text} supports transparent
+        * background on Windows only whereas {@link org.eclipse.swt.widgets.Table
+        * Table} supports transparent background on GTK3 only.</li>
+        * </ul>
+        *
+        * @since 3.104
+        */
+       public static final int COLOR_TRANSPARENT = 37;
+
+       /**
+        * System color used to paint disabled text background areas (value is 38).
+        *
+        * @since 3.112
+        */
+       public static final int COLOR_TEXT_DISABLED_BACKGROUND = 38;
+
+       /**
+        * System color used to paint disabled foreground areas (value is 39).
+        *
+        * @since 3.112
+        */
+       public static final int COLOR_WIDGET_DISABLED_FOREGROUND = 39;
+
+       /**
+        * Draw constant indicating whether the drawing operation
+        * should fill the background (value is 1&lt;&lt;0).
+        */
+       public static final 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 final 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 final int DRAW_TAB = 1 << 2;
+
+       /**
+        * Draw constant indicating whether the string drawing operation
+        * should handle mnemonics (value is 1&lt;&lt;3).
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>TextLayout</code></li>
+        * </ul>
+        *
+        * @see #FULL_SELECTION
+        * @see #LAST_LINE_SELECTION
+        *
+        * @since 3.3
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>TextLayout</code></li>
+        * </ul>
+        *
+        * @see #DELIMITER_SELECTION
+        * @see #FULL_SELECTION
+        *
+        * @since 3.3
+        */
+       public static final int LAST_LINE_SELECTION = 1 << 20;
+
+       /**
+        * SWT error constant indicating that no error number was specified
+        * (value is 1).
+        */
+       public static final int ERROR_UNSPECIFIED = 1;
+
+       /**
+        * SWT error constant indicating that no more handles for an
+        * operating system resource are available
+        * (value is 2).
+        */
+       public static final int ERROR_NO_HANDLES = 2;
+
+       /**
+        * SWT error constant indicating that no more callback resources are available
+        * (value is 3).
+        */
+       public static final int ERROR_NO_MORE_CALLBACKS = 3;
+
+       /**
+        * SWT error constant indicating that a null argument was passed in
+        * (value is 4).
+        */
+       public static final int ERROR_NULL_ARGUMENT = 4;
+
+       /**
+        * SWT error constant indicating that an invalid argument was passed in
+        * (value is 5).
+        */
+       public static final 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 final 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 final 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 final 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 final int ERROR_CANNOT_GET_SELECTION = 9;
+
+       /**
+        * SWT error constant indicating that the matrix is not invertible
+        * (value is 10).
+        *
+        * @since 3.1
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final int ERROR_ITEM_NOT_REMOVED = 15;
+
+       /**
+        * SWT error constant indicating that the graphics library
+        * is not available
+        * (value is 16).
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final 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 final int ERROR_DEVICE_DISPOSED = 45;
+
+       /**
+        * SWT error constant indicating that an exception happened
+        * when executing a runnable
+        * (value is 46).
+        */
+       public static final 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 final int ERROR_FAILED_LOAD_LIBRARY = 47;
+
+       /**
+        * SWT error constant indicating that a font is not valid
+        * (value is 48).
+        *
+        * @since 3.1
+        */
+       public static final int ERROR_INVALID_FONT = 48;
+
+       /**
+        * SWT error constant indicating that an attempt was made to
+        * use an BrowserFunction object which had already been disposed
+        * (value is 49).
+        *
+        * @since 3.5
+        */
+       public static final int ERROR_FUNCTION_DISPOSED = 49;
+
+       /**
+        * SWT error constant indicating that an exception happened
+        * when evaluating a javascript expression
+        * (value is 50).
+        *
+        * @since 3.5
+        */
+       public static final int ERROR_FAILED_EVALUATE = 50;
+
+       /**
+        * SWT error constant indicating that an invalid value was returned
+        * (value is 51).
+        *
+        * @since 3.5
+        */
+       public static final int ERROR_INVALID_RETURN_VALUE = 51;
+
+       /**
+        * Constant indicating that an image or operation is of type bitmap  (value is 0).
+        */
+       public static final int BITMAP = 0;
+
+       /**
+        * Constant indicating that an image or operation is of type icon  (value is 1).
+        */
+       public static final 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 final 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 final 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 final int IMAGE_GRAY = 2;
+
+       /**
+        * Constant to indicate an error state (value is 1).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>ProgressBar</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final int ERROR = 1;
+
+       /**
+        * Constant to a indicate a paused state (value is 4).
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>ProgressBar</code></li>
+        * </ul>
+        *
+        * @since 3.4
+        */
+       public static final 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></p>
+        * <ul>
+        * <li><code>ProgressBar</code></li>
+        * </ul>
+        */
+       public static final int NORMAL = 0;
+
+       /**
+        * The font style constant indicating a bold weight font
+        * (value is 1&lt;&lt;0).
+        */
+       public static final int BOLD = 1 << 0;
+
+       /**
+        * The font style constant indicating an italic font
+        * (value is 1&lt;&lt;1).
+        */
+       public static final int ITALIC = 1 << 1;
+
+       /**
+        * System arrow cursor  (value is 0).
+        */
+       public static final int CURSOR_ARROW = 0;
+
+       /**
+        * System wait cursor  (value is 1).
+        */
+       public static final int CURSOR_WAIT = 1;
+
+       /**
+        * System cross hair cursor  (value is 2).
+        */
+       public static final int CURSOR_CROSS = 2;
+
+       /**
+        * System app startup cursor  (value is 3).
+        */
+       public static final int CURSOR_APPSTARTING = 3;
+
+       /**
+        * System help cursor  (value is 4).
+        */
+       public static final int CURSOR_HELP = 4;
+
+       /**
+        * System resize all directions cursor (value is 5).
+        */
+       public static final int CURSOR_SIZEALL = 5;
+
+       /**
+        * System resize north-east-south-west cursor  (value is 6).
+        */
+       public static final int CURSOR_SIZENESW = 6;
+
+       /**
+        * System resize north-south cursor  (value is 7).
+        */
+       public static final int CURSOR_SIZENS = 7;
+
+       /**
+        * System resize north-west-south-east cursor  (value is 8).
+        */
+       public static final int CURSOR_SIZENWSE = 8;
+
+       /**
+        * System resize west-east cursor  (value is 9).
+        */
+       public static final int CURSOR_SIZEWE = 9;
+
+       /**
+        * System resize north cursor  (value is 10).
+        */
+       public static final int CURSOR_SIZEN = 10;
+
+       /**
+        * System resize south cursor  (value is 11).
+        */
+       public static final int CURSOR_SIZES = 11;
+
+       /**
+        * System resize east cursor  (value is 12).
+        */
+       public static final int CURSOR_SIZEE = 12;
+
+       /**
+        * System resize west cursor  (value is 13).
+        */
+       public static final int CURSOR_SIZEW = 13;
+
+       /**
+        * System resize north-east cursor (value is 14).
+        */
+       public static final int CURSOR_SIZENE = 14;
+
+       /**
+        * System resize south-east cursor (value is 15).
+        */
+       public static final int CURSOR_SIZESE = 15;
+
+       /**
+        * System resize south-west cursor (value is 16).
+        */
+       public static final int CURSOR_SIZESW = 16;
+
+       /**
+        * System resize north-west cursor (value is 17).
+        */
+       public static final int CURSOR_SIZENW = 17;
+
+       /**
+        * System up arrow cursor  (value is 18).
+        */
+       public static final int CURSOR_UPARROW = 18;
+
+       /**
+        * System i-beam cursor (value is 19).
+        */
+       public static final int CURSOR_IBEAM = 19;
+
+       /**
+        * System "not allowed" cursor (value is 20).
+        */
+       public static final int CURSOR_NO = 20;
+
+       /**
+        * System hand cursor (value is 21).
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final 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 final int JOIN_BEVEL = 3;
+
+       /**
+        * Line drawing style for solid lines  (value is 1).
+        */
+       public static final int LINE_SOLID = 1;
+
+       /**
+        * Line drawing style for dashed lines (value is 2).
+        */
+       public static final int LINE_DASH = 2;
+
+       /**
+        * Line drawing style for dotted lines (value is 3).
+        */
+       public static final int LINE_DOT = 3;
+
+       /**
+        * Line drawing style for alternating dash-dot lines (value is 4).
+        */
+       public static final int LINE_DASHDOT = 4;
+
+       /**
+        * Line drawing style for dash-dot-dot lines (value is 5).
+        */
+       public static final 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 final int LINE_CUSTOM = 6;
+
+       /**
+        * Path constant that represents a "move to" operation (value is 1).
+        *
+        * @since 3.1
+        */
+       public static final int PATH_MOVE_TO = 1;
+
+       /**
+        * Path constant that represents a "line to" operation (value is 2).
+        *
+        * @since 3.1
+        */
+       public static final int PATH_LINE_TO = 2;
+
+       /**
+        * Path constant that represents a "quadratic curve to" operation (value is 3).
+        *
+        * @since 3.1
+        */
+       public static final int PATH_QUAD_TO = 3;
+
+       /**
+        * Path constant that represents a "cubic curve to" operation (value is 4).
+        *
+        * @since 3.1
+        */
+       public static final int PATH_CUBIC_TO = 4;
+
+       /**
+        * Path constant that represents a "close" operation (value is 5).
+        *
+        * @since 3.1
+        */
+       public static final int PATH_CLOSE = 5;
+
+       /**
+        * Even odd rule for filling operations (value is 1).
+        *
+        * @since 3.1
+        */
+       public static final int FILL_EVEN_ODD = 1;
+
+       /**
+        * Winding rule for filling operations (value is 2).
+        *
+        * @since 3.1
+        */
+       public static final int FILL_WINDING = 2;
+
+       /**
+        * Image format constant indicating an unknown image type (value is -1).
+        */
+       public static final int IMAGE_UNDEFINED = -1;
+
+       /**
+        * Image format constant indicating a Windows BMP format image (value is 0).
+        */
+       public static final int IMAGE_BMP = 0;
+
+       /**
+        * Image format constant indicating a run-length encoded
+        * Windows BMP format image (value is 1).
+        */
+       public static final int IMAGE_BMP_RLE = 1;
+
+       /**
+        * Image format constant indicating a GIF format image (value is 2).
+        */
+       public static final int IMAGE_GIF = 2;
+
+       /**
+        * Image format constant indicating a ICO format image (value is 3).
+        */
+       public static final int IMAGE_ICO = 3;
+
+       /**
+        * Image format constant indicating a JPEG format image (value is 4).
+        */
+       public static final int IMAGE_JPEG = 4;
+
+       /**
+        * Image format constant indicating a PNG format image (value is 5).
+        */
+       public static final int IMAGE_PNG = 5;
+
+       /**
+        * Image format constant indicating a TIFF format image (value is 6).
+        */
+       public static final int IMAGE_TIFF = 6;
+
+       /**
+        * Image format constant indicating an OS/2 BMP format image (value is 7).
+        */
+       public static final int IMAGE_OS2_BMP = 7;
+
+       /**
+        * Image format constant indicating a SVG format image (value is 8).
+        * <br>Note that this is a <em>HINT</em> and is currently only supported on GTK.
+        *
+        * @since 3.113
+        */
+       public static final int IMAGE_SVG = 8;
+
+       /**
+        * GIF image disposal method constants indicating that the
+        * disposal method is unspecified (value is 0).
+        */
+       public static final 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 final 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 final 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 final int DM_FILL_PREVIOUS = 0x3;
+
+       /**
+        * Image transparency constant indicating that the image
+        * contains no transparency information (value is 0).
+        */
+       public static final int TRANSPARENCY_NONE = 0x0;
+
+       /**
+        * Image transparency constant indicating that the image
+        * contains alpha transparency information (value is 1&lt;&lt;0).
+        */
+       public static final int TRANSPARENCY_ALPHA = 1 << 0;
+
+       /**
+        * Image transparency constant indicating that the image
+        * contains a transparency mask (value is 1&lt;&lt;1).
+        */
+       public static final int TRANSPARENCY_MASK = 1 << 1;
+
+       /**
+        * Image transparency constant indicating that the image
+        * contains a transparent pixel (value is 1&lt;&lt;2).
+        */
+       public static final 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 final 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 final 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 final 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 final 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 final int MOVEMENT_WORD_START = 1 << 4;
+
+       /**
+        * A constant indicating that a given operation should be performed on
+        * all widgets (value is 1&lt;&lt;0).
+        *
+        * <p><b>Used By:</b></p>
+        * <ul>
+        * <li><code>Composite</code> layout</li>
+        * </ul>
+        *
+        * @see org.eclipse.swt.widgets.Composite#layout(org.eclipse.swt.widgets.Control[], int)
+        *
+        * @since 3.6
+        */
+       public static final int ALL = 1 << 0;
+
+       /**
+        * ID for the About menu item (value is -1).
+        *
+        * @see org.eclipse.swt.widgets.MenuItem#setID(int)
+        * @see org.eclipse.swt.widgets.MenuItem#getID()
+        *
+        * @since 3.7
+        */
+       public static final int ID_ABOUT = -1;
+
+       /**
+        * ID for the Preferences menu item (value is -2).
+        *
+        * @see org.eclipse.swt.widgets.MenuItem#setID(int)
+        * @see org.eclipse.swt.widgets.MenuItem#getID()
+        *
+        * @since 3.7
+        */
+       public static final int ID_PREFERENCES = -2;
+
+       /**
+        * ID for the Hide menu item (value is -3).
+        *
+        * @see org.eclipse.swt.widgets.MenuItem#setID(int)
+        * @see org.eclipse.swt.widgets.MenuItem#getID()
+        *
+        * @since 3.7
+        */
+       public static final int ID_HIDE = -3;
+
+       /**
+        * ID for the Hide Others menu item (value is -4).
+        *
+        * @see org.eclipse.swt.widgets.MenuItem#setID(int)
+        * @see org.eclipse.swt.widgets.MenuItem#getID()
+        *
+        * @since 3.7
+        */
+       public static final int ID_HIDE_OTHERS = -4;
+
+       /**
+        * ID for the Show All menu item (value is -5).
+        *
+        * @see org.eclipse.swt.widgets.MenuItem#setID(int)
+        * @see org.eclipse.swt.widgets.MenuItem#getID()
+        *
+        * @since 3.7
+        */
+       public static final int ID_SHOW_ALL = -5;
+
+       /**
+        * ID for the Quit menu item (value is -6).
+        *
+        * @see org.eclipse.swt.widgets.MenuItem#setID(int)
+        * @see org.eclipse.swt.widgets.MenuItem#getID()
+        *
+        * @since 3.7
+        */
+       public static final int ID_QUIT = -6;
+
+       /**
+        * Key name for setting and getting the skin class of a widget.
+        * <p>
+        * Note: SWT currently doesn't read or process this property. The only
+        * effect of setting this property is to trigger a call to
+        * {@link Widget#reskin(int) Widget#reskin(SWT.ALL)}.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Widget#getData(String)
+        * @see org.eclipse.swt.widgets.Widget#setData(String, Object)
+        *
+        * @since 3.6
+        */
+       public static final String SKIN_CLASS = "org.eclipse.swt.skin.class"; //$NON-NLS-1$
+
+       /**
+        * Key name for setting and getting the skin id of a widget.
+        * <p>
+        * Note: SWT currently doesn't read or process this property. The only
+        * effect of setting this property is to trigger a call to
+        * {@link Widget#reskin(int) Widget#reskin(SWT.ALL)}.
+        * </p>
+        *
+        * @see org.eclipse.swt.widgets.Widget#getData(String)
+        * @see org.eclipse.swt.widgets.Widget#setData(String, Object)
+        *
+        * @since 3.6
+        */
+       public static final String SKIN_ID = "org.eclipse.swt.skin.id"; //$NON-NLS-1$
+
+       /**
+        * The <code>Scrollable</code> constant to indicate that
+        * the receiver is using overlay scrollbars. (value is 1)
+        *
+        * @since 3.8
+        */
+       public static final int SCROLLBAR_OVERLAY = 1 << 1;
+
+
+/**
+ * Returns a boolean indicating whether this SWT implementation can
+ * be loaded.  Examples of criteria that may be used to determine this
+ * include the OS and architecture of the JRE that is being used.
+ *
+ * @return <code>true</code> if this SWT implementation can be loaded
+ * and <code>false</code> otherwise
+ *
+ * @since 3.8
+ */
+public static boolean isLoadable () {
+       return Platform.isLoadable ();
+}
+
+/**
+ * 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_RETURN_VALUE:   return "Return value 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_FUNCTION_DISPOSED:      return "BrowserFunction is disposed"; //$NON-NLS-1$
+               case ERROR_FAILED_EXEC:            return "Failed to execute runnable"; //$NON-NLS-1$
+               case ERROR_FAILED_EVALUATE:        return "Failed to evaluate javascript expression"; //$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$
+       }
+       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 NLS'ed message for the given arguments.
+ *
+ * @param key the key to look up
+ * @param args the parameters to insert into the message
+ * @return the message for the given parameterized key
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the key or args are null</li>
+ * </ul>
+ *
+ * @since 3.8
+ */
+public static String getMessage(String key, Object[] args) {
+       return Compatibility.getMessage(key, args);
+}
+
+/**
+ * Returns the SWT platform name.
+ * Examples: "win32", "gtk", "cocoa"
+ *
+ * @return the SWT platform name
+ */
+public static String getPlatform () {
+       return Platform.PLATFORM;
+}
+
+/**
+ * Returns the SWT version number as an integer.
+ * Example: "SWT051" == 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 (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:
+ * </p>
+ * <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.
+ *
+ * @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, Throwable 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:
+ * </p>
+ * <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.
+ *
+ * @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, Throwable 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 != SWT.ERROR_FAILED_EXEC) {
+               if (throwable instanceof SWTError) throw (SWTError) throwable;
+               if (throwable instanceof SWTException) throw (SWTException) throwable;
+       }
+
+       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_FUNCTION_DISPOSED:
+               case ERROR_INVALID_IMAGE:
+               case ERROR_UNSUPPORTED_DEPTH:
+               case ERROR_UNSUPPORTED_FORMAT:
+               case ERROR_FAILED_EXEC:
+               case ERROR_FAILED_EVALUATE:
+               case ERROR_CANNOT_INVERT_MATRIX:
+               case ERROR_NO_GRAPHICS_LIBRARY:
+               case ERROR_INVALID_RETURN_VALUE:
+               case ERROR_IO: {
+                       SWTException 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: {
+                       SWTError error = new SWTError (code, message);
+                       error.throwable = throwable;
+                       throw error;
+               }
+       }
+
+       /* Unknown/Undefined Error */
+       SWTError error = new SWTError (code, message);
+       error.throwable = throwable;
+       throw error;
+}
+
+static {
+       /*
+       * These values represent bit masks that may need to
+       * expand in the future.  Therefore they are not initialized
+       * in the declaration to stop the compiler from inlining.
+       */
+       BUTTON_MASK = BUTTON1 | BUTTON2 | BUTTON3 | BUTTON4 | BUTTON5;
+       MODIFIER_MASK = ALT | SHIFT | CTRL | COMMAND | ALT_GR;
+
+       /*
+       * These values can be different on different platforms.
+       * Therefore they are not initialized in the declaration
+       * to stop the compiler from inlining.
+       */
+       String platform = getPlatform ();
+       if ("cocoa".equals (platform)) { //$NON-NLS-1$
+               MOD1 = COMMAND;
+               MOD2 = SHIFT;
+               MOD3 = ALT;
+               MOD4 = CONTROL;
+       } else {
+               MOD1 = CONTROL;
+               MOD2 = SHIFT;
+               MOD3 = ALT;
+               MOD4 = 0;
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWTError.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWTError.java
new file mode 100644 (file)
index 0000000..03fc353
--- /dev/null
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt;
+
+/**
+ * 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 extends Error {
+       /**
+        * 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 Throwable throwable;
+
+       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 SWTError () {
+       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 SWTError (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 SWTError (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 SWTError (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
+ */
+@Override
+public Throwable 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
+ */
+@Override
+public String getMessage () {
+       if (throwable == null) return super.getMessage ();
+       return super.getMessage () + " (" + 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>
+ */
+@Override
+public void printStackTrace () {
+       super.printStackTrace ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWTException.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/SWTException.java
new file mode 100644 (file)
index 0000000..2c7ab43
--- /dev/null
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt;
+
+/**
+ * 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 extends RuntimeException {
+       /**
+        * 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 Throwable throwable;
+
+       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 SWTException () {
+       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 SWTException (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 SWTException (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 SWTException (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
+ */
+@Override
+public Throwable 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
+ */
+@Override
+public String getMessage () {
+       if (throwable == null) return super.getMessage ();
+       return super.getMessage () + " (" + 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>
+ */
+@Override
+public void printStackTrace () {
+       super.printStackTrace ();
+}
+
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/ACC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/ACC.java
new file mode 100644 (file)
index 0000000..3fe7f0d
--- /dev/null
@@ -0,0 +1,731 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+/**
+ * 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 final int STATE_NORMAL =                  0x00000000;
+       public static final int STATE_SELECTED =                0x00000002;
+       public static final int STATE_SELECTABLE =              0x00200000;
+       public static final int STATE_MULTISELECTABLE = 0x01000000;
+       public static final int STATE_FOCUSED =                 0x00000004;
+       public static final int STATE_FOCUSABLE =               0x00100000;
+       public static final int STATE_PRESSED =                 0x00000008;
+       public static final int STATE_CHECKED =                 0x00000010;
+       public static final int STATE_EXPANDED =                0x00000200;
+       public static final int STATE_COLLAPSED =               0x00000400;
+       public static final int STATE_HOTTRACKED =              0x00000080;
+       public static final int STATE_BUSY =                    0x00000800;
+       public static final int STATE_READONLY =                0x00000040;
+       public static final int STATE_INVISIBLE =               0x00008000;
+       public static final int STATE_OFFSCREEN =               0x00010000;
+       public static final int STATE_SIZEABLE =                0x00020000;
+       public static final int STATE_LINKED =                  0x00400000;
+       /** @since 3.6 */
+       public static final int STATE_DISABLED =                0x00000001;
+       /** @since 3.6 */
+       public static final int STATE_ACTIVE =                  0x04000000;
+       /** @since 3.6 */
+       public static final int STATE_SINGLELINE =              0x08000000;
+       /** @since 3.6 */
+       public static final int STATE_MULTILINE =               0x10000000;
+       /** @since 3.6 */
+       public static final int STATE_REQUIRED =                0x02000000;
+       /** @since 3.6 */
+       public static final int STATE_INVALID_ENTRY =   0x20000000;
+       /** @since 3.6 */
+       public static final int STATE_SUPPORTS_AUTOCOMPLETION = 0x40000000;
+
+       public static final int ROLE_CLIENT_AREA = 0xa;
+       public static final int ROLE_WINDOW = 0x9;
+       public static final int ROLE_MENUBAR = 0x2;
+       public static final int ROLE_MENU = 0xb;
+       public static final int ROLE_MENUITEM = 0xc;
+       public static final int ROLE_SEPARATOR = 0x15;
+       public static final int ROLE_TOOLTIP = 0xd;
+       public static final int ROLE_SCROLLBAR = 0x3;
+       public static final int ROLE_DIALOG = 0x12;
+       public static final int ROLE_LABEL = 0x29;
+       public static final int ROLE_PUSHBUTTON = 0x2b;
+       public static final int ROLE_CHECKBUTTON = 0x2c;
+       public static final int ROLE_RADIOBUTTON = 0x2d;
+       /** @since 3.5 */
+       public static final int ROLE_SPLITBUTTON = 0x3e;
+       public static final int ROLE_COMBOBOX = 0x2e;
+       public static final int ROLE_TEXT = 0x2a;
+       public static final int ROLE_TOOLBAR = 0x16;
+       public static final int ROLE_LIST = 0x21;
+       public static final int ROLE_LISTITEM = 0x22;
+       public static final int ROLE_TABLE = 0x18;
+       public static final int ROLE_TABLECELL = 0x1d;
+       public static final int ROLE_TABLECOLUMNHEADER = 0x19;
+       /** @deprecated use ROLE_TABLECOLUMNHEADER */
+       @Deprecated
+       public static final int ROLE_TABLECOLUMN = ROLE_TABLECOLUMNHEADER;
+       public static final int ROLE_TABLEROWHEADER = 0x1a;
+       public static final int ROLE_TREE = 0x23;
+       public static final int ROLE_TREEITEM = 0x24;
+       public static final int ROLE_TABFOLDER = 0x3c;
+       public static final int ROLE_TABITEM = 0x25;
+       public static final int ROLE_PROGRESSBAR = 0x30;
+       public static final int ROLE_SLIDER = 0x33;
+       public static final int ROLE_LINK = 0x1e;
+       /** @since 3.6 */
+       public static final int ROLE_ALERT = 0x08;
+       /** @since 3.6 */
+       public static final int ROLE_ANIMATION = 0x36;
+       /** @since 3.6 */
+       public static final int ROLE_CANVAS = 0x401;
+       /** @since 3.6 */
+       public static final int ROLE_COLUMN = 0x1b;
+       /** @since 3.6 */
+       public static final int ROLE_DOCUMENT = 0x0f;
+       /** @since 3.6 */
+       public static final int ROLE_GRAPHIC = 0x28;
+       /** @since 3.6 */
+       public static final int ROLE_GROUP = 0x14;
+       /** @since 3.6 */
+       public static final int ROLE_ROW = 0x1c;
+       /** @since 3.6 */
+       public static final int ROLE_SPINBUTTON = 0x34;
+       /** @since 3.6 */
+       public static final int ROLE_STATUSBAR = 0x17;
+       /** @since 3.6 */
+       public static final int ROLE_CHECKMENUITEM = 0x403;
+       /** @since 3.6 */
+       public static final int ROLE_RADIOMENUITEM = 0x431;
+       /** @since 3.6 */
+       public static final int ROLE_CLOCK = 0x3d;
+       /** @since 3.6 */
+       public static final int ROLE_CALENDAR = 0x2f;
+       /** @since 3.6 */
+       public static final int ROLE_DATETIME = 0x405;
+       /** @since 3.6 */
+       public static final int ROLE_FOOTER = 0x40E;
+       /** @since 3.6 */
+       public static final int ROLE_FORM = 0x410;
+       /** @since 3.6 */
+       public static final int ROLE_HEADER = 0x413;
+       /** @since 3.6 */
+       public static final int ROLE_HEADING = 0x414;
+       /** @since 3.6 */
+       public static final int ROLE_PAGE = 0x41D;
+       /** @since 3.6 */
+       public static final int ROLE_PARAGRAPH = 0x41E;
+       /** @since 3.6 */
+       public static final int ROLE_SECTION = 0x424;
+
+       public static final int CHILDID_SELF = -1;
+       public static final int CHILDID_NONE = -2;
+       public static final int CHILDID_MULTIPLE = -3;
+
+       /**
+        * An AT is requesting the accessible child object at the specified index.
+        *
+        * @see AccessibleControlListener#getChild
+        *
+        * @since 3.6
+        */
+       public static final int CHILDID_CHILD_AT_INDEX = -4;
+
+       /**
+        * An AT is requesting the index of this accessible in its parent.
+        *
+        * @see AccessibleControlListener#getChild
+        *
+        * @since 3.6
+        */
+       public static final int CHILDID_CHILD_INDEX = -5;
+
+       /**
+        * A detail constant indicating visible accessible objects.
+        *
+        * @since 3.6
+        */
+       public static final int VISIBLE = 0x01;
+
+       /**
+        * A type constant specifying that insertion occurred.
+        *
+        * @since 3.6
+        */
+       public static final int INSERT = 0;
+
+       /**
+        * A type constant specifying that deletion occurred.
+        *
+        * @since 3.6
+        */
+       public static final int DELETE = 1;
+
+       public static final int TEXT_INSERT = INSERT;
+       public static final int TEXT_DELETE = DELETE;
+
+       /**
+        * A constant specifying that an operation succeeded.
+        *
+        * @since 3.6
+        */
+       public static final String OK = "OK"; //$NON-NLS-1$
+
+       /**
+        * Typically, a single character is returned. In some cases more than one
+        * character is returned, for example, when a document contains field data
+        * such as a field containing a date, time, or footnote reference. In this
+        * case the caret can move over several characters in one movement of the
+        * caret. Note that after the caret moves, the caret offset changes by the
+        * number of characters in the field, e.g. by 8 characters in the following
+        * date: 03/26/07.
+        *
+        * @since 3.6
+        */
+       public static final int TEXT_BOUNDARY_CHAR = 0;
+
+       /**
+        * The range provided matches the range observed when the application
+        * processes the Ctrl + left arrow and Ctrl + right arrow key sequences.
+        * Typically this is from the start of one word to the start of the next,
+        * but various applications are inconsistent in the handling of the end of a
+        * line.
+        *
+        * @since 3.6
+        */
+       public static final int TEXT_BOUNDARY_WORD = 1;
+
+       /**
+        * Range is from start of one sentence to the start of another sentence.
+        *
+        * @since 3.6
+        */
+       public static final int TEXT_BOUNDARY_SENTENCE = 2;
+
+       /**
+        * Range is from start of one paragraph to the start of another paragraph.
+        *
+        * @since 3.6
+        */
+       public static final int TEXT_BOUNDARY_PARAGRAPH = 3;
+
+       /**
+        * Range is from start of one line to the start of another line. This often
+        * means that an end-of-line character will appear at the end of the range.
+        * However in the case of some applications an end-of-line character
+        * indicates the end of a paragraph and the lines composing the paragraph,
+        * other than the last line, do not contain an end of line character.
+        *
+        * @since 3.6
+        */
+       public static final int TEXT_BOUNDARY_LINE = 4;
+
+       /**
+        * Using this value will cause all text to be returned.
+        *
+        * @since 3.6
+        */
+       public static final int TEXT_BOUNDARY_ALL = 5;
+
+       /**
+        * Scroll the top left corner of the object or substring such that the top
+        * left corner (and as much as possible of the rest of the object or
+        * substring) is within the top level window. In cases where the entire
+        * object or substring fits within the top level window, the placement of
+        * the object or substring is dependent on the application. For example, the
+        * object or substring may be scrolled to the closest edge, the furthest
+        * edge, or midway between those two edges. In cases where there is a
+        * hierarchy of nested scrollable controls, more than one control may have
+        * to be scrolled.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_TOP_LEFT = 0;
+
+       /**
+        * Scroll the bottom right corner of the object or substring such that the
+        * bottom right corner (and as much as possible of the rest of the object or
+        * substring) is within the top level window. In cases where the entire
+        * object or substring fits within the top level window, the placement of
+        * the object or substring is dependent on the application. For example, the
+        * object or substring may be scrolled to the closest edge, the furthest
+        * edge, or midway between those two edges. In cases where there is a
+        * hierarchy of nested scrollable controls, more than one control may have
+        * to be scrolled.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_BOTTOM_RIGHT = 1;
+
+       /**
+        * Scroll the top edge of the object or substring such that the top edge
+        * (and as much as possible of the rest of the object or substring) is
+        * within the top level window. In cases where the entire object or substring
+        * fits within the top level window, the placement of the object or
+        * substring is dependent on the application. For example, the object or
+        * substring may be scrolled to the closest edge, the furthest edge, or
+        * midway between those two edges. In cases where there is a hierarchy of
+        * nested scrollable controls, more than one control may have to be
+        * scrolled.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_TOP_EDGE = 2;
+
+       /**
+        * Scroll the bottom edge of the object or substring such that the bottom
+        * edge (and as much as possible of the rest of the object or substring) is
+        * within the top level window. In cases where the entire object or
+        * substring fits within the top level window, the placement of the object
+        * or substring is dependent on the application. For example, the object or
+        * substring may be scrolled to the closest edge, the furthest edge, or
+        * midway between those two edges. In cases where there is a hierarchy of
+        * nested scrollable controls, more than one control may have to be
+        * scrolled.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_BOTTOM_EDGE = 3;
+
+       /**
+        * Scroll the left edge of the object or substring such that the left edge
+        * (and as much as possible of the rest of the object or substring) is
+        * within the top level window. In cases where the entire object or substring
+        * fits within the top level window, the placement of the object or
+        * substring is dependent on the application. For example, the object or
+        * substring may be scrolled to the closest edge, the furthest edge, or
+        * midway between those two edges. In cases where there is a hierarchy of
+        * nested scrollable controls, more than one control may have to be
+        * scrolled.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_LEFT_EDGE = 4;
+
+       /**
+        * Scroll the right edge of the object or substring such that the right edge
+        * (and as much as possible of the rest of the object or substring) is
+        * within the top level window. In cases where the entire object or
+        * substring fits within the top level window, the placement of the object
+        * or substring is dependent on the application. For example, the object or
+        * substring may be scrolled to the closest edge, the furthest edge, or
+        * midway between those two edges. In cases where there is a hierarchy of
+        * nested scrollable controls, more than one control may have to be
+        * scrolled.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_RIGHT_EDGE =  5;
+
+       /**
+        * Scroll the object or substring such that as much as possible of the
+        * object or substring is within the top level window. The placement of the
+        * object is dependent on the application. For example, the object or
+        * substring may be scrolled to to closest edge, the furthest edge, or
+        * midway between those two edges.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_ANYWHERE = 6;
+
+       /**
+        * Scroll the top left corner of the object or substring to the specified point.
+        *
+        * @since 3.6
+        */
+       public static final int SCROLL_TYPE_POINT = 7;
+
+       /**
+        * Send when the selection within a container has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_SELECTION_CHANGED = 0x8009;
+
+       /**
+        * Send when an object's text selection has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TEXT_SELECTION_CHANGED = 0x8014;
+
+       /**
+        * Send when an object's state has changed, for example enabled/disabled, pressed/released, or checked/unchecked.
+        * <p>
+        * The eventData object is an array of 2 ints specifying the following:</p><ul>
+        * <li>state - the STATE_* constant identifying the state that changed</li>
+        * <li>newValue - either 1 or 0, indicating whether the state has changed to true or false</li>
+        * </ul>
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_STATE_CHANGED = 0x800A;
+
+       /**
+        * Send when an object has moved.
+        * <p>
+        * Note: only send one notification for the topmost object that has changed.
+        * </p>
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_LOCATION_CHANGED = 0x800B;
+
+       /**
+        * Send when an object's name has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_NAME_CHANGED = 0x800C;
+
+       /**
+        * Send when an object's description has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_DESCRIPTION_CHANGED = 0x800D;
+
+       /**
+        * Send when an object's value has changed.
+        * <p>
+        * The eventData object is an array of 2 Numbers specifying the following:</p>
+        * <ul>
+        * <li>oldValue - the object's old value</li>
+        * <li>newValue - the object's new value</li>
+        * </ul>
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_VALUE_CHANGED = 0x800E;
+
+       /**
+        * Send when the loading of a document has completed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_DOCUMENT_LOAD_COMPLETE = 0x105;
+
+       /**
+        * Send when the loading of a document was interrupted.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_DOCUMENT_LOAD_STOPPED = 0x106;
+
+       /**
+        * Send when the document contents are being reloaded.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_DOCUMENT_RELOAD = 0x107;
+
+       /**
+        * Send when a slide changed in a presentation document
+        * or a page boundary was crossed in a word processing document.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_PAGE_CHANGED = 0x111;
+
+       /**
+        * Send when the caret moved from one section to the next.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_SECTION_CHANGED = 0x112;
+
+       /**
+        * Send when the count or attributes of an accessible object's actions have changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_ACTION_CHANGED = 0x100;
+
+       /**
+        * Send when the starting index of this link within the containing string has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERLINK_START_INDEX_CHANGED = 0x10d;
+
+       /**
+        * Send when the ending index of this link within the containing string has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERLINK_END_INDEX_CHANGED = 0x108;
+
+       /**
+        * Send when the number of anchors associated with this hyperlink object has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED = 0x109;
+
+       /**
+        * Send when the hyperlink selected state changed from selected to unselected
+        * or from unselected to selected.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERLINK_SELECTED_LINK_CHANGED = 0x10a;
+
+       /**
+        * Send when the hyperlink has been activated.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERLINK_ACTIVATED = 0x10b;
+
+       /**
+        * Send when one of the links associated with the hypertext object has been selected.
+        * <p>
+        * The eventData object is an Integer that represents the index of the selected link
+        * in the hypertext object.
+        * </p>
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERTEXT_LINK_SELECTED = 0x10c;
+
+       /**
+        * Send when the number of hyperlinks associated with a hypertext object has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_HYPERTEXT_LINK_COUNT_CHANGED = 0x10f;
+
+       /**
+        * Send when an object's attributes have changed.
+        *
+        * @see #EVENT_TEXT_ATTRIBUTE_CHANGED
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_ATTRIBUTE_CHANGED = 0x200;
+
+       /**
+        * Send when a table caption has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_CAPTION_CHANGED = 0x203;
+
+       /**
+        * Send when a table's column description has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED = 0x204;
+
+       /**
+        * Send when a table's column header has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_COLUMN_HEADER_CHANGED = 0x205;
+
+       /**
+        * Send when a table's data has changed.
+        * <p>
+        * The eventData object is an array of 5 ints specifying the following:</p>
+        * <ul>
+        * <li>type - {@link ACC#INSERT} or {@link ACC#DELETE} - the type of change</li>
+        * <li>rowStart - the index of the first row that changed</li>
+        * <li>rowCount - the number of contiguous rows that changed, or 0 if no rows changed</li>
+        * <li>columnStart - the index of the first column that changed</li>
+        * <li>columnCount - the number of contiguous columns that changed, or 0 if no columns changed</li>
+        * </ul>
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_CHANGED = 0x206;
+
+       /**
+        * Send when a table's row description has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_ROW_DESCRIPTION_CHANGED = 0x207;
+
+       /**
+        * Send when a table's row header has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_ROW_HEADER_CHANGED = 0x208;
+
+       /**
+        * Send when a table's summary has changed.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TABLE_SUMMARY_CHANGED = 0x209;
+
+       /**
+        * Send when a text object's attributes have changed.
+        *
+        * @see #EVENT_ATTRIBUTE_CHANGED
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TEXT_ATTRIBUTE_CHANGED = 0x20a;
+
+       /**
+        * Send when the caret has moved to a new position.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TEXT_CARET_MOVED = 0x11b;
+
+       /**
+        * Send when the caret has moved from one column to the next.
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TEXT_COLUMN_CHANGED = 0x11d;
+
+       /**
+        * Send when text was inserted or deleted.
+        * <p>
+        * The eventData object is an array of 4 objects specifying the following:</p>
+        * <ul>
+        * <li>type - {@link ACC#INSERT} or {@link ACC#DELETE} - the type of change</li>
+        * <li>start - the index of the first character that changed</li>
+        * <li>end - the index of the last character that changed</li>
+        * <li>text - the text string that was inserted or deleted</li>
+        * </ul>
+        *
+        * @since 3.6
+        */
+       public static final int EVENT_TEXT_CHANGED = 0x20c;
+
+       /**
+        * Some attribute of this object is affected by a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_CONTROLLED_BY = 0;
+
+       /**
+        * This object is interactive and controls some attribute of a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_CONTROLLER_FOR = 1;
+
+       /**
+        * This object is described by the target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_DESCRIBED_BY = 2;
+
+       /**
+        * This object is describes the target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_DESCRIPTION_FOR = 3;
+
+       /**
+        * This object is embedded by a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_EMBEDDED_BY = 4;
+
+       /**
+        * This object embeds a target object. This relation can be used on a
+        * control's accessible to show where the content areas are.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_EMBEDS = 5;
+
+       /**
+        * Content flows to this object from a target object.
+        * This relation and RELATION_FLOWS_TO are useful to tie text and non-text
+        * objects together in order to allow assistive technology to follow the
+        * intended reading order.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_FLOWS_FROM = 6;
+
+       /**
+        * Content flows from this object to a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_FLOWS_TO = 7;
+
+       /**
+        * This object is label for a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_LABEL_FOR = 8;
+
+       /**
+        * This object is labelled by a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_LABELLED_BY = 9;
+
+       /**
+        * This object is a member of a group of one or more objects. When
+        * there is more than one object in the group each member may have one and the
+        * same target, e.g. a grouping object.  It is also possible that each member has
+        * multiple additional targets, e.g. one for every other member in the group.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_MEMBER_OF = 10;
+
+       /**
+        * This object is a child of a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_NODE_CHILD_OF = 11;
+
+       /**
+        * This object is a parent window of the target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_PARENT_WINDOW_OF = 12;
+
+       /**
+        * This object is a transient component related to the target object.
+        * When this object is activated the target object doesn't lose focus.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_POPUP_FOR = 13;
+
+       /**
+        * This object is a sub window of a target object.
+        *
+        * @since 3.6
+        */
+       public static final int RELATION_SUBWINDOW_OF = 14;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java
new file mode 100644 (file)
index 0000000..05f6930
--- /dev/null
@@ -0,0 +1,5556 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.ole.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 {
+       static final int MAX_RELATION_TYPES = 15;
+       static final int TABLE_MODEL_CHANGE_SIZE = 5;
+       static final int TEXT_CHANGE_SIZE = 4;
+       static final int SCROLL_RATE = 100;
+       static final boolean DEBUG = false;
+       static final String PROPERTY_USEIA2 = "org.eclipse.swt.accessibility.UseIA2"; //$NON-NLS-1$
+       static boolean UseIA2 = true;
+       static int UniqueID = -0x10;
+       int refCount = 0, enumIndex = 0;
+       Runnable timer;
+       COMObject objIAccessible, objIEnumVARIANT, objIServiceProvider,
+               objIAccessibleApplication, /*objIAccessibleComponent,*/ objIAccessibleEditableText, objIAccessibleHyperlink,
+               objIAccessibleHypertext, /*objIAccessibleImage,*/ objIAccessibleTable2, objIAccessibleTableCell,
+               objIAccessibleValue; /* objIAccessibleRelation is defined in Relation class */
+       IAccessible iaccessible;
+       List<AccessibleListener> accessibleListeners;
+       List<AccessibleControlListener> accessibleControlListeners;
+       List<AccessibleTextListener> accessibleTextListeners;
+       List<AccessibleActionListener> accessibleActionListeners;
+       List<AccessibleEditableTextListener> accessibleEditableTextListeners;
+       List<AccessibleHyperlinkListener> accessibleHyperlinkListeners;
+       List<AccessibleTableListener> accessibleTableListeners;
+       List<AccessibleTableCellListener> accessibleTableCellListeners;
+       List<AccessibleTextExtendedListener> accessibleTextExtendedListeners;
+       List<AccessibleValueListener> accessibleValueListeners;
+       List<AccessibleAttributeListener> accessibleAttributeListeners;
+       Relation relations[] = new Relation[MAX_RELATION_TYPES];
+       Object[] variants;
+       Accessible parent;
+       List<Accessible> children = new ArrayList<>();
+       Control control;
+       int uniqueID = -1;
+       int [] tableChange; // type, rowStart, rowCount, columnStart, columnCount
+       Object [] textDeleted; // type, start, end, text
+       Object [] textInserted; // type, start, end, text
+       ToolItem item;
+
+       static {
+               String property = System.getProperty (PROPERTY_USEIA2);
+               if (property != null && property.equalsIgnoreCase ("false")) { //$NON-NLS-1$
+                       UseIA2 = false;
+               }
+       }
+
+       /**
+        * Constructs a new instance of this class given its parent.
+        *
+        * @param parent the Accessible parent, which must not be null
+        *
+        * @exception IllegalArgumentException <ul>
+        *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+        * </ul>
+        *
+        * @see #dispose
+        * @see Control#getAccessible
+        *
+        * @since 3.6
+        */
+       public Accessible(Accessible parent) {
+               this.parent = checkNull(parent);
+               this.control = parent.control;
+               parent.children.add(this);
+               AddRef();
+       }
+
+       /**
+        * @since 3.5
+        * @deprecated
+        */
+       @Deprecated
+       protected Accessible() {
+       }
+
+       Accessible(Control control) {
+               this.control = control;
+               long[] ppvObject = new 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.
+                */
+               int result = (int)COM.CreateStdAccessibleObject(control.handle, OS.OBJID_CLIENT, COM.IIDIAccessible, ppvObject);
+               /* The object needs to be checked, because if the CreateStdAccessibleObject()
+                * symbol is not found, the return value is S_OK.
+                */
+               if (ppvObject[0] == 0) return;
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+               iaccessible = new IAccessible(ppvObject[0]);
+               createIAccessible();
+               AddRef();
+       }
+
+       Accessible(Accessible parent, long iaccessible_address) {
+               this(parent);
+               iaccessible = new IAccessible(iaccessible_address);
+       }
+
+       static Accessible checkNull (Accessible parent) {
+               if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+               return parent;
+       }
+
+       void createIAccessible() {
+               objIAccessible = new COMObject(new int[] {2,0,0,/*IA>>*/1,3,5,8,1,1,2,2,2,2,2,2,2,3,2,1,1,2,2,5,3,3,1,2,2,/*<<IA*/1,2,3,1,1,3,3,1,1,1,1,3,3,1,1,1,1,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       // method3 GetTypeInfoCount - not implemented
+                       // method4 GetTypeInfo - not implemented
+                       // method5 GetIDsOfNames - not implemented
+                       // method6 Invoke - not implemented
+                       @Override
+                       public long method7(long[] args) {return get_accParent(args[0]);}
+                       @Override
+                       public long method8(long[] args) {return get_accChildCount(args[0]);}
+                       @Override
+                       public long method9(long[] args) {return get_accChild(args[0], args[1]);}
+                       @Override
+                       public long method10(long[] args) {return get_accName(args[0], args[1]);}
+                       @Override
+                       public long method11(long[] args) {return get_accValue(args[0], args[1]);}
+                       @Override
+                       public long method12(long[] args) {return get_accDescription(args[0], args[1]);}
+                       @Override
+                       public long method13(long[] args) {return get_accRole(args[0], args[1]);}
+                       @Override
+                       public long method14(long[] args) {return get_accState(args[0], args[1]);}
+                       @Override
+                       public long method15(long[] args) {return get_accHelp(args[0], args[1]);}
+                       @Override
+                       public long method16(long[] args) {return get_accHelpTopic(args[0], args[1], args[2]);}
+                       @Override
+                       public long method17(long[] args) {return get_accKeyboardShortcut(args[0], args[1]);}
+                       @Override
+                       public long method18(long[] args) {return get_accFocus(args[0]);}
+                       @Override
+                       public long method19(long[] args) {return get_accSelection(args[0]);}
+                       @Override
+                       public long method20(long[] args) {return get_accDefaultAction(args[0], args[1]);}
+                       @Override
+                       public long method21(long[] args) {return accSelect((int)args[0], args[1]);}
+                       @Override
+                       public long method22(long[] args) {return accLocation(args[0], args[1], args[2], args[3], args[4]);}
+                       @Override
+                       public long method23(long[] args) {return accNavigate((int)args[0], args[1], args[2]);}
+                       @Override
+                       public long method24(long[] args) {return accHitTest((int)args[0], (int)args[1], args[2]);}
+                       @Override
+                       public long method25(long[] args) {return accDoDefaultAction(args[0]);}
+                       @Override
+                       public long method26(long[] args) {return put_accName(args[0], args[1]);}
+                       @Override
+                       public long method27(long[] args) {return put_accValue(args[0], args[1]);}
+
+                       // IAccessible2 methods
+                       @Override
+                       public long method28(long[] args) {return get_nRelations(args[0]);}
+                       @Override
+                       public long method29(long[] args) {return get_relation((int)args[0], args[1]);}
+                       @Override
+                       public long method30(long[] args) {return get_relations((int)args[0], args[1], args[2]);}
+                       @Override
+                       public long method31(long[] args) {return get_role(args[0]);}
+                       @Override
+                       public long method32(long[] args) {return scrollTo((int)args[0]);}
+                       @Override
+                       public long method33(long[] args) {return scrollToPoint((int)args[0], (int)args[1], (int)args[2]);}
+                       @Override
+                       public long method34(long[] args) {return get_groupPosition(args[0], args[1], args[2]);}
+                       @Override
+                       public long method35(long[] args) {return get_states(args[0]);}
+                       @Override
+                       public long method36(long[] args) {return get_extendedRole(args[0]);}
+                       @Override
+                       public long method37(long[] args) {return get_localizedExtendedRole(args[0]);}
+                       @Override
+                       public long method38(long[] args) {return get_nExtendedStates(args[0]);}
+                       @Override
+                       public long method39(long[] args) {return get_extendedStates((int)args[0], args[1], args[2]);}
+                       @Override
+                       public long method40(long[] args) {return get_localizedExtendedStates((int)args[0], args[1], args[2]);}
+                       @Override
+                       public long method41(long[] args) {return get_uniqueID(args[0]);}
+                       @Override
+                       public long method42(long[] args) {return get_windowHandle(args[0]);}
+                       @Override
+                       public long method43(long[] args) {return get_indexInParent(args[0]);}
+                       @Override
+                       public long method44(long[] args) {return get_locale(args[0]);}
+                       @Override
+                       public long method45(long[] args) {return get_attributes(args[0]);}
+               };
+       }
+
+       void createIAccessibleApplication() {
+               objIAccessibleApplication = new COMObject(new int[] {2,0,0,1,1,1,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return get_appName(args[0]);}
+                       @Override
+                       public long method4(long[] args) {return get_appVersion(args[0]);}
+                       @Override
+                       public long method5(long[] args) {return get_toolkitName(args[0]);}
+                       @Override
+                       public long method6(long[] args) {return get_toolkitVersion(args[0]);}
+               };
+       }
+
+       // This method is intentionally commented. We are not providing IAccessibleComponent at this time.
+//     void createIAccessibleComponent() {
+//             objIAccessibleComponent = new COMObject(new int[] {2,0,0,2,1,1}) {
+//                     public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+//                     public long method1(long[] args) {return AddRef();}
+//                     public long method2(long[] args) {return Release();}
+//                     public long method3(long[] args) {return get_locationInParent(args[0], args[1]);}
+//                     public long method4(long[] args) {return get_foreground(args[0]);}
+//                     public long method5(long[] args) {return get_background(args[0]);}
+//             };
+//     }
+
+       void createIAccessibleEditableText() {
+               objIAccessibleEditableText = new COMObject(new int[] {2,0,0,2,2,2,2,1,3,3}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return copyText((int)args[0], (int)args[1]);}
+                       @Override
+                       public long method4(long[] args) {return deleteText((int)args[0], (int)args[1]);}
+                       @Override
+                       public long method5(long[] args) {return insertText((int)args[0], args[1]);}
+                       @Override
+                       public long method6(long[] args) {return cutText((int)args[0], (int)args[1]);}
+                       @Override
+                       public long method7(long[] args) {return pasteText((int)args[0]);}
+                       @Override
+                       public long method8(long[] args) {return replaceText((int)args[0], (int)args[1], args[2]);}
+                       @Override
+                       public long method9(long[] args) {return setAttributes((int)args[0], (int)args[1], args[2]);}
+               };
+       }
+
+       void createIAccessibleHyperlink() {
+               objIAccessibleHyperlink = new COMObject(new int[] {2,0,0,/*IAA>>*/1,1,2,4,2,2,/*<<IAA*/2,2,1,1,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       // IAccessibleAction
+                       @Override
+                       public long method3(long[] args) {return get_nActions(args[0]);}
+                       @Override
+                       public long method4(long[] args) {return doAction((int)args[0]);}
+                       @Override
+                       public long method5(long[] args) {return get_description((int)args[0], args[1]);}
+                       @Override
+                       public long method6(long[] args) {return get_keyBinding((int)args[0], (int)args[1], args[2], args[3]);}
+                       @Override
+                       public long method7(long[] args) {return get_name((int)args[0], args[1]);}
+                       @Override
+                       public long method8(long[] args) {return get_localizedName((int)args[0], args[1]);}
+                       // IAccessibleHyperlink
+                       @Override
+                       public long method9(long[] args) {return get_anchor((int)args[0], args[1]);}
+                       @Override
+                       public long method10(long[] args) {return get_anchorTarget((int)args[0], args[1]);}
+                       @Override
+                       public long method11(long[] args) {return get_startIndex(args[0]);}
+                       @Override
+                       public long method12(long[] args) {return get_endIndex(args[0]);}
+                       @Override
+                       public long method13(long[] args) {return get_valid(args[0]);}
+               };
+       }
+
+       void createIAccessibleHypertext() {
+               objIAccessibleHypertext = new COMObject(new int[] {2,0,0,/*IAT>>*/2,4,1,6,1,4,3,3,5,5,5,1,1,3,1,3,5,1,1,/*<<IAT*/1,2,2}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       // IAccessibleText
+                       @Override
+                       public long method3(long[] args) {return addSelection((int)args[0], (int)args[1]);}
+                       @Override
+                       public long method4(long[] args) {return get_attributes((int)args[0], args[1], args[2], args[3]);}
+                       @Override
+                       public long method5(long[] args) {return get_caretOffset(args[0]);}
+                       @Override
+                       public long method6(long[] args) {return get_characterExtents((int)args[0], (int)args[1], args[2], args[3], args[4], args[5]);}
+                       @Override
+                       public long method7(long[] args) {return get_nSelections(args[0]);}
+                       @Override
+                       public long method8(long[] args) {return get_offsetAtPoint((int)args[0], (int)args[1], (int)args[2], args[3]);}
+                       @Override
+                       public long method9(long[] args) {return get_selection((int)args[0], args[1], args[2]);}
+                       @Override
+                       public long method10(long[] args) {return get_text((int)args[0], (int)args[1], args[2]);}
+                       @Override
+                       public long method11(long[] args) {return get_textBeforeOffset((int)args[0], (int)args[1], args[2], args[3], args[4]);}
+                       @Override
+                       public long method12(long[] args) {return get_textAfterOffset((int)args[0], (int)args[1], args[2], args[3], args[4]);}
+                       @Override
+                       public long method13(long[] args) {return get_textAtOffset((int)args[0], (int)args[1], args[2], args[3], args[4]);}
+                       @Override
+                       public long method14(long[] args) {return removeSelection((int)args[0]);}
+                       @Override
+                       public long method15(long[] args) {return setCaretOffset((int)args[0]);}
+                       @Override
+                       public long method16(long[] args) {return setSelection((int)args[0], (int)args[1], (int)args[2]);}
+                       @Override
+                       public long method17(long[] args) {return get_nCharacters(args[0]);}
+                       @Override
+                       public long method18(long[] args) {return scrollSubstringTo((int)args[0], (int)args[1], (int)args[2]);}
+                       @Override
+                       public long method19(long[] args) {return scrollSubstringToPoint((int)args[0], (int)args[1], (int)args[2], (int)args[3], (int)args[4]);}
+                       @Override
+                       public long method20(long[] args) {return get_newText(args[0]);}
+                       @Override
+                       public long method21(long[] args) {return get_oldText(args[0]);}
+                       // IAccessibleHypertext
+                       @Override
+                       public long method22(long[] args) {return get_nHyperlinks(args[0]);}
+                       @Override
+                       public long method23(long[] args) {return get_hyperlink((int)args[0], args[1]);}
+                       @Override
+                       public long method24(long[] args) {return get_hyperlinkIndex((int)args[0], args[1]);}
+               };
+       }
+
+       // This method is intentionally commented. We are not providing IAccessibleImage at this time.
+//     void createIAccessibleImage() {
+//             objIAccessibleImage = new COMObject(new int[] {2,0,0,1,3,2}) {
+//                     public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+//                     public long method1(long[] args) {return AddRef();}
+//                     public long method2(long[] args) {return Release();}
+//                     public long method3(long[] args) {return get_description(args[0]);}
+//                     public long method4(long[] args) {return get_imagePosition((int)args[0], args[1], args[2]);}
+//                     public long method5(long[] args) {return get_imageSize(args[0], args[1]);}
+//             };
+//     }
+
+       void createIAccessibleTable2() {
+               objIAccessibleTable2 = new COMObject(new int[] {2,0,0,3,1,2,1,1,1,1,1,2,2,2,2,1,2,2,1,1,1,1,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return get_cellAt((int)args[0], (int)args[1], args[2]);}
+                       @Override
+                       public long method4(long[] args) {return get_caption(args[0]);}
+                       @Override
+                       public long method5(long[] args) {return get_columnDescription((int)args[0], args[1]);}
+                       @Override
+                       public long method6(long[] args) {return get_nColumns(args[0]);}
+                       @Override
+                       public long method7(long[] args) {return get_nRows(args[0]);}
+                       @Override
+                       public long method8(long[] args) {return get_nSelectedCells(args[0]);}
+                       @Override
+                       public long method9(long[] args) {return get_nSelectedColumns(args[0]);}
+                       @Override
+                       public long method10(long[] args) {return get_nSelectedRows(args[0]);}
+                       @Override
+                       public long method11(long[] args) {return get_rowDescription((int)args[0], args[1]);}
+                       @Override
+                       public long method12(long[] args) {return get_selectedCells(args[0], args[1]);}
+                       @Override
+                       public long method13(long[] args) {return get_selectedColumns(args[0], args[1]);}
+                       @Override
+                       public long method14(long[] args) {return get_selectedRows(args[0], args[1]);}
+                       @Override
+                       public long method15(long[] args) {return get_summary(args[0]);}
+                       @Override
+                       public long method16(long[] args) {return get_isColumnSelected((int)args[0], args[1]);}
+                       @Override
+                       public long method17(long[] args) {return get_isRowSelected((int)args[0], args[1]);}
+                       @Override
+                       public long method18(long[] args) {return selectRow((int)args[0]);}
+                       @Override
+                       public long method19(long[] args) {return selectColumn((int)args[0]);}
+                       @Override
+                       public long method20(long[] args) {return unselectRow((int)args[0]);}
+                       @Override
+                       public long method21(long[] args) {return unselectColumn((int)args[0]);}
+                       @Override
+                       public long method22(long[] args) {return get_modelChange(args[0]);}
+               };
+       }
+
+       void createIAccessibleTableCell() {
+               objIAccessibleTableCell = new COMObject(new int[] {2,0,0,1,2,1,1,2,1,1,5,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return get_columnExtent(args[0]);}
+                       @Override
+                       public long method4(long[] args) {return get_columnHeaderCells(args[0], args[1]);}
+                       @Override
+                       public long method5(long[] args) {return get_columnIndex(args[0]);}
+                       @Override
+                       public long method6(long[] args) {return get_rowExtent(args[0]);}
+                       @Override
+                       public long method7(long[] args) {return get_rowHeaderCells(args[0], args[1]);}
+                       @Override
+                       public long method8(long[] args) {return get_rowIndex(args[0]);}
+                       @Override
+                       public long method9(long[] args) {return get_isSelected(args[0]);}
+                       @Override
+                       public long method10(long[] args) {return get_rowColumnExtents(args[0], args[1], args[2], args[3], args[4]);}
+                       @Override
+                       public long method11(long[] args) {return get_table(args[0]);}
+               };
+       }
+
+       void createIAccessibleValue() {
+               objIAccessibleValue = new COMObject(new int[] {2,0,0,1,1,1,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return get_currentValue(args[0]);}
+                       @Override
+                       public long method4(long[] args) {return setCurrentValue(args[0]);}
+                       @Override
+                       public long method5(long[] args) {return get_maximumValue(args[0]);}
+                       @Override
+                       public long method6(long[] args) {return get_minimumValue(args[0]);}
+               };
+       }
+
+       void createIEnumVARIANT() {
+               objIEnumVARIANT = new COMObject(new int[] {2,0,0,3,1,0,1}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return Next((int)args[0], args[1], args[2]);}
+                       @Override
+                       public long method4(long[] args) {return Skip((int)args[0]);}
+                       @Override
+                       public long method5(long[] args) {return Reset();}
+                       @Override
+                       public long method6(long[] args) {return Clone(args[0]);}
+               };
+       }
+
+       void createIServiceProvider() {
+               objIServiceProvider = new COMObject(new int[] {2,0,0,3}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return QueryService(args[0], args[1], args[2]);}
+               };
+       }
+
+       /**
+        * 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
+        *
+        * @noreference This method is not intended to be referenced by clients.
+        */
+       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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleListeners == null) accessibleListeners = new ArrayList<>();
+               accessibleListeners.add(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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleControlListeners == null) accessibleControlListeners = new ArrayList<>();
+               accessibleControlListeners.add(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>
+        * and <code>AccessibleTextExtendedListener</code> interfaces.
+        *
+        * @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 AccessibleTextExtendedListener
+        * @see #removeAccessibleTextListener
+        *
+        * @since 3.0
+        */
+       public void addAccessibleTextListener (AccessibleTextListener listener) {
+               checkWidget ();
+               if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+               if (listener instanceof AccessibleTextExtendedListener) {
+                       if (accessibleTextExtendedListeners == null) accessibleTextExtendedListeners = new ArrayList<>();
+                       accessibleTextExtendedListeners.add ((AccessibleTextExtendedListener) listener);
+               } else {
+                       if (accessibleTextListeners == null) accessibleTextListeners = new ArrayList<>();
+                       accessibleTextListeners.add (listener);
+               }
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleActionListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleActionListener</code> interface properties
+        *
+        * @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 AccessibleActionListener
+        * @see #removeAccessibleActionListener
+        *
+        * @since 3.6
+        */
+       public void addAccessibleActionListener(AccessibleActionListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleActionListeners == null) accessibleActionListeners = new ArrayList<>();
+               accessibleActionListeners.add(listener);
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleEditableTextListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleEditableTextListener</code> interface properties
+        *
+        * @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 AccessibleEditableTextListener
+        * @see #removeAccessibleEditableTextListener
+        *
+        * @since 3.7
+        */
+       public void addAccessibleEditableTextListener(AccessibleEditableTextListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleEditableTextListeners == null) accessibleEditableTextListeners = new ArrayList<>();
+               accessibleEditableTextListeners.add(listener);
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleHyperlinkListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleHyperlinkListener</code> interface properties
+        *
+        * @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 AccessibleHyperlinkListener
+        * @see #removeAccessibleHyperlinkListener
+        *
+        * @since 3.6
+        */
+       public void addAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleHyperlinkListeners == null) accessibleHyperlinkListeners = new ArrayList<>();
+               accessibleHyperlinkListeners.add(listener);
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleTableListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleTableListener</code> interface properties
+        *
+        * @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 AccessibleTableListener
+        * @see #removeAccessibleTableListener
+        *
+        * @since 3.6
+        */
+       public void addAccessibleTableListener(AccessibleTableListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleTableListeners == null) accessibleTableListeners = new ArrayList<>();
+               accessibleTableListeners.add(listener);
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleTableCellListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleTableCellListener</code> interface properties
+        *
+        * @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 AccessibleTableCellListener
+        * @see #removeAccessibleTableCellListener
+        *
+        * @since 3.6
+        */
+       public void addAccessibleTableCellListener(AccessibleTableCellListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleTableCellListeners == null) accessibleTableCellListeners = new ArrayList<>();
+               accessibleTableCellListeners.add(listener);
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleValueListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleValueListener</code> interface properties
+        *
+        * @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 AccessibleValueListener
+        * @see #removeAccessibleValueListener
+        *
+        * @since 3.6
+        */
+       public void addAccessibleValueListener(AccessibleValueListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleValueListeners == null) accessibleValueListeners = new ArrayList<>();
+               accessibleValueListeners.add(listener);
+       }
+
+       /**
+        * Adds the listener to the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleAttributeListener</code> interface.
+        *
+        * @param listener the listener that should be notified when the receiver
+        * is asked for <code>AccessibleAttributeListener</code> interface properties
+        *
+        * @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 AccessibleAttributeListener
+        * @see #removeAccessibleAttributeListener
+        *
+        * @since 3.6
+        */
+       public void addAccessibleAttributeListener(AccessibleAttributeListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleAttributeListeners == null) accessibleAttributeListeners = new ArrayList<>();
+               accessibleAttributeListeners.add(listener);
+       }
+
+       /**
+        * Adds a relation with the specified type and target
+        * to the receiver's set of relations.
+        *
+        * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation
+        * @param target the accessible that is the target for this relation
+        * @exception IllegalArgumentException ERROR_NULL_ARGUMENT - if the Accessible target is null
+        * @since 3.6
+        */
+       public void addRelation(int type, Accessible target) {
+               checkWidget();
+               if (target == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+               if (relations[type] == null) {
+                       relations[type] = new Relation(this, type);
+               }
+               relations[type].addTarget(target);
+       }
+
+       /**
+        * Disposes of the operating system resources associated with
+        * the receiver, and removes the receiver from its parent's
+        * list of children.
+        * <p>
+        * This method should be called when an accessible that was created
+        * with the public constructor <code>Accessible(Accessible parent)</code>
+        * is no longer needed. You do not need to call this when the receiver's
+        * control is disposed, because all <code>Accessible</code> instances
+        * associated with a control are released when the control is disposed.
+        * It is also not necessary to call this for instances of <code>Accessible</code>
+        * that were retrieved with <code>Control.getAccessible()</code>.
+        * </p>
+        *
+        * @since 3.6
+        */
+       public void dispose () {
+               if (parent == null) return;
+               Release();
+               parent.children.remove(this);
+               parent = null;
+       }
+
+       long getAddress() {
+               /* The address of an Accessible is the address of its IAccessible COMObject. */
+               if (objIAccessible == null) createIAccessible();
+               return objIAccessible.getAddress();
+       }
+
+       /**
+        * 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>
+        *
+        * @noreference This method is not intended to be referenced by clients.
+        */
+       public void internal_dispose_Accessible() {
+               if (iaccessible != null) {
+                       iaccessible.Release();
+               }
+               iaccessible = null;
+               Release();
+               for (int i = 0; i < children.size(); i++) {
+                       Accessible child = children.get(i);
+                       child.dispose();
+               }
+       }
+
+       /**
+        * 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>
+        *
+        * @noreference This method is not intended to be referenced by clients.
+        */
+       public long internal_WM_GETOBJECT (long wParam, long lParam) {
+               if (objIAccessible == null) return 0;
+               if ((int)lParam == OS.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, objIAccessible.getAddress());
+               }
+               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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleListeners != null) {
+                       accessibleListeners.remove(listener);
+                       if (accessibleListeners.isEmpty()) accessibleListeners = null;
+               }
+       }
+
+       /**
+        * 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleControlListeners != null) {
+                       accessibleControlListeners.remove(listener);
+                       if (accessibleControlListeners.isEmpty()) accessibleControlListeners = null;
+               }
+       }
+
+       /**
+        * 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 AccessibleTextExtendedListener
+        * @see #addAccessibleTextListener
+        *
+        * @since 3.0
+        */
+       public void removeAccessibleTextListener (AccessibleTextListener listener) {
+               checkWidget ();
+               if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+               if (listener instanceof AccessibleTextExtendedListener) {
+                       if (accessibleTextExtendedListeners != null) {
+                               accessibleTextExtendedListeners.remove (listener);
+                               if (accessibleTextExtendedListeners.isEmpty()) accessibleTextExtendedListeners = null;
+                       }
+               } else {
+                       if (accessibleTextListeners != null) {
+                               accessibleTextListeners.remove (listener);
+                               if (accessibleTextListeners.isEmpty()) accessibleTextListeners = null;
+                       }
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleActionListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleActionListener</code> interface properties
+        *
+        * @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 AccessibleActionListener
+        * @see #addAccessibleActionListener
+        *
+        * @since 3.6
+        */
+       public void removeAccessibleActionListener(AccessibleActionListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleActionListeners != null) {
+                       accessibleActionListeners.remove(listener);
+                       if (accessibleActionListeners.isEmpty()) accessibleActionListeners = null;
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleEditableTextListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleEditableTextListener</code> interface properties
+        *
+        * @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 AccessibleEditableTextListener
+        * @see #addAccessibleEditableTextListener
+        *
+        * @since 3.7
+        */
+       public void removeAccessibleEditableTextListener(AccessibleEditableTextListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleEditableTextListeners != null) {
+                       accessibleEditableTextListeners.remove(listener);
+                       if (accessibleEditableTextListeners.isEmpty()) accessibleEditableTextListeners = null;
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleHyperlinkListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleHyperlinkListener</code> interface properties
+        *
+        * @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 AccessibleHyperlinkListener
+        * @see #addAccessibleHyperlinkListener
+        *
+        * @since 3.6
+        */
+       public void removeAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleHyperlinkListeners != null) {
+                       accessibleHyperlinkListeners.remove(listener);
+                       if (accessibleHyperlinkListeners.isEmpty()) accessibleHyperlinkListeners = null;
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleTableListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleTableListener</code> interface properties
+        *
+        * @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 AccessibleTableListener
+        * @see #addAccessibleTableListener
+        *
+        * @since 3.6
+        */
+       public void removeAccessibleTableListener(AccessibleTableListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleTableListeners != null) {
+                       accessibleTableListeners.remove(listener);
+                       if (accessibleTableListeners.isEmpty()) accessibleTableListeners = null;
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleTableCellListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleTableCellListener</code> interface properties
+        *
+        * @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 AccessibleTableCellListener
+        * @see #addAccessibleTableCellListener
+        *
+        * @since 3.6
+        */
+       public void removeAccessibleTableCellListener(AccessibleTableCellListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleTableCellListeners != null) {
+                       accessibleTableCellListeners.remove(listener);
+                       if (accessibleTableCellListeners.isEmpty()) accessibleTableCellListeners = null;
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleValueListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleValueListener</code> interface properties
+        *
+        * @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 AccessibleValueListener
+        * @see #addAccessibleValueListener
+        *
+        * @since 3.6
+        */
+       public void removeAccessibleValueListener(AccessibleValueListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleValueListeners != null) {
+                       accessibleValueListeners.remove(listener);
+                       if (accessibleValueListeners.isEmpty()) accessibleValueListeners = null;
+               }
+       }
+
+       /**
+        * Removes the listener from the collection of listeners that will be
+        * notified when an accessible client asks for any of the properties
+        * defined in the <code>AccessibleAttributeListener</code> interface.
+        *
+        * @param listener the listener that should no longer be notified when the receiver
+        * is asked for <code>AccessibleAttributeListener</code> interface properties
+        *
+        * @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 AccessibleAttributeListener
+        * @see #addAccessibleAttributeListener
+        *
+        * @since 3.6
+        */
+       public void removeAccessibleAttributeListener(AccessibleAttributeListener listener) {
+               checkWidget();
+               if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (accessibleAttributeListeners != null) {
+                       accessibleAttributeListeners.remove(listener);
+                       if (accessibleAttributeListeners.isEmpty()) accessibleAttributeListeners = null;
+               }
+       }
+
+       /**
+        * Removes the relation with the specified type and target
+        * from the receiver's set of relations.
+        *
+        * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation
+        * @param target the accessible that is the target for this relation
+        * @exception IllegalArgumentException ERROR_NULL_ARGUMENT - if the Accessible target is null
+        * @since 3.6
+        */
+       public void removeRelation(int type, Accessible target) {
+               checkWidget();
+               if (target == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+               Relation relation = relations[type];
+               if (relation != null) {
+                       relation.removeTarget(target);
+                       if (!relation.hasTargets()) {
+                               relations[type].Release();
+                               relations[type] = null;
+                       }
+               }
+       }
+
+       /**
+        * Sends a message with event-specific data to accessible clients
+        * indicating that something has changed within a custom control.
+        *
+        * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send
+        * @param eventData an object containing event-specific data, or null if there is no event-specific data
+        * (eventData is specified in the documentation for individual ACC.EVENT_* constants)
+        *
+        * @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#EVENT_ACTION_CHANGED
+        * @see ACC#EVENT_ATTRIBUTE_CHANGED
+        * @see ACC#EVENT_DESCRIPTION_CHANGED
+        * @see ACC#EVENT_DOCUMENT_LOAD_COMPLETE
+        * @see ACC#EVENT_DOCUMENT_LOAD_STOPPED
+        * @see ACC#EVENT_DOCUMENT_RELOAD
+        * @see ACC#EVENT_HYPERLINK_ACTIVATED
+        * @see ACC#EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED
+        * @see ACC#EVENT_HYPERLINK_END_INDEX_CHANGED
+        * @see ACC#EVENT_HYPERLINK_SELECTED_LINK_CHANGED
+        * @see ACC#EVENT_HYPERLINK_START_INDEX_CHANGED
+        * @see ACC#EVENT_HYPERTEXT_LINK_COUNT_CHANGED
+        * @see ACC#EVENT_HYPERTEXT_LINK_SELECTED
+        * @see ACC#EVENT_LOCATION_CHANGED
+        * @see ACC#EVENT_NAME_CHANGED
+        * @see ACC#EVENT_PAGE_CHANGED
+        * @see ACC#EVENT_SECTION_CHANGED
+        * @see ACC#EVENT_SELECTION_CHANGED
+        * @see ACC#EVENT_STATE_CHANGED
+        * @see ACC#EVENT_TABLE_CAPTION_CHANGED
+        * @see ACC#EVENT_TABLE_CHANGED
+        * @see ACC#EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED
+        * @see ACC#EVENT_TABLE_COLUMN_HEADER_CHANGED
+        * @see ACC#EVENT_TABLE_ROW_DESCRIPTION_CHANGED
+        * @see ACC#EVENT_TABLE_ROW_HEADER_CHANGED
+        * @see ACC#EVENT_TABLE_SUMMARY_CHANGED
+        * @see ACC#EVENT_TEXT_ATTRIBUTE_CHANGED
+        * @see ACC#EVENT_TEXT_CARET_MOVED
+        * @see ACC#EVENT_TEXT_CHANGED
+        * @see ACC#EVENT_TEXT_COLUMN_CHANGED
+        * @see ACC#EVENT_TEXT_SELECTION_CHANGED
+        * @see ACC#EVENT_VALUE_CHANGED
+        *
+        * @since 3.6
+        */
+       public void sendEvent(int event, Object eventData) {
+               checkWidget();
+               if (!isATRunning ()) return;
+               if (!UseIA2) return;
+               if (DEBUG) print(this + ".NotifyWinEvent " + getEventString(event) + " hwnd=" + control.handle + " childID=" + eventChildID());
+               switch (event) {
+                       case ACC.EVENT_TABLE_CHANGED: {
+                               if (!(eventData instanceof int[] && ((int[])eventData).length == TABLE_MODEL_CHANGE_SIZE)) break;
+                               tableChange = (int[])eventData;
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID());
+                               break;
+                       }
+                       case ACC.EVENT_TEXT_CHANGED: {
+                               if (!(eventData instanceof Object[] && ((Object[])eventData).length == TEXT_CHANGE_SIZE)) break;
+                               Object[] data = (Object[])eventData;
+                               int type = ((Integer)data[0]).intValue();
+                               switch (type) {
+                                       case ACC.DELETE:
+                                               textDeleted = (Object[])eventData;
+                                               OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_REMOVED, control.handle, OS.OBJID_CLIENT, eventChildID());
+                                               break;
+                                       case ACC.INSERT:
+                                               textInserted = (Object[])eventData;
+                                               OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_INSERTED, control.handle, OS.OBJID_CLIENT, eventChildID());
+                                               break;
+                               }
+                               break;
+                       }
+                       case ACC.EVENT_HYPERTEXT_LINK_SELECTED: {
+                               if (!(eventData instanceof Integer)) break;
+       //                      int index = ((Integer)eventData).intValue();
+                               // TODO: IA2 currently does not use the index, however the plan is to use it in future
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERTEXT_LINK_SELECTED, control.handle, OS.OBJID_CLIENT, eventChildID());
+                               break;
+                       }
+                       case ACC.EVENT_VALUE_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_STATE_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_STATECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_SELECTION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TEXT_SELECTION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_LOCATION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_NAME_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_NAMECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_DESCRIPTION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_DESCRIPTIONCHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_DOCUMENT_LOAD_COMPLETE:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_DOCUMENT_LOAD_COMPLETE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_DOCUMENT_LOAD_STOPPED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_DOCUMENT_LOAD_STOPPED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_DOCUMENT_RELOAD:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_DOCUMENT_RELOAD, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_PAGE_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_PAGE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_SECTION_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_SECTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_ACTION_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_ACTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_START_INDEX_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_END_INDEX_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_HYPERLINK_ACTIVATED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_ACTIVATED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_ATTRIBUTE_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_ATTRIBUTE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TABLE_CAPTION_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_CAPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TABLE_ROW_HEADER_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_ROW_HEADER_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TABLE_SUMMARY_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_SUMMARY_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_ATTRIBUTE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TEXT_CARET_MOVED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_CARET_MOVED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+                       case ACC.EVENT_TEXT_COLUMN_CHANGED:
+                               OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_COLUMN_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
+               }
+       }
+
+       /**
+        * Sends a message with event-specific data and a childID
+        * to accessible clients, indicating that something has changed
+        * within a custom control.
+        *
+        * NOTE: This API is intended for applications that are still using childIDs.
+        * Moving forward, applications should use accessible objects instead of childIDs.
+        *
+        * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send
+        * @param eventData an object containing event-specific data, or null if there is no event-specific data
+        * (eventData is specified in the documentation for individual ACC.EVENT_* constants)
+        * @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>
+        *
+        * @see ACC#EVENT_DESCRIPTION_CHANGED
+        * @see ACC#EVENT_LOCATION_CHANGED
+        * @see ACC#EVENT_NAME_CHANGED
+        * @see ACC#EVENT_SELECTION_CHANGED
+        * @see ACC#EVENT_STATE_CHANGED
+        * @see ACC#EVENT_TEXT_SELECTION_CHANGED
+        * @see ACC#EVENT_VALUE_CHANGED
+        *
+        * @since 3.8
+        */
+       public void sendEvent(int event, Object eventData, int childID) {
+               checkWidget();
+               if (!isATRunning ()) return;
+               if (!UseIA2) return;
+               int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID);
+               if (DEBUG) print(this + ".NotifyWinEvent " + getEventString(event) + " hwnd=" + control.handle + " childID=" + osChildID);
+               switch (event) {
+                       case ACC.EVENT_STATE_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_STATECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
+                       case ACC.EVENT_NAME_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_NAMECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
+                       case ACC.EVENT_VALUE_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
+                       case ACC.EVENT_LOCATION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
+                       case ACC.EVENT_SELECTION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, osChildID); break;
+                       case ACC.EVENT_TEXT_SELECTION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, osChildID); break;
+                       case ACC.EVENT_DESCRIPTION_CHANGED:
+                               OS.NotifyWinEvent (COM.EVENT_OBJECT_DESCRIPTIONCHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
+               }
+       }
+
+
+       /**
+        * 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();
+               if (!isATRunning ()) return;
+               if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_SELECTIONWITHIN hwnd=" + control.handle + " childID=" + eventChildID());
+               OS.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, eventChildID());
+       }
+
+       /**
+        * 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();
+               if (!isATRunning ()) return;
+               int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID);
+               if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_FOCUS hwnd=" + control.handle + " childID=" + osChildID);
+               OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, control.handle, OS.OBJID_CLIENT, osChildID);
+       }
+
+       /**
+        * 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();
+               if (timer == null) {
+                       timer = new Runnable() {
+                               @Override
+                               public void run() {
+                                       if (!isATRunning ()) return;
+                                       if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_LOCATIONCHANGE hwnd=" + control.handle + " childID=" + eventChildID());
+                                       OS.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CARET, eventChildID());
+                                       if (!UseIA2) return;
+                                       if (DEBUG) print(this + ".NotifyWinEvent IA2_EVENT_TEXT_CARET_MOVED hwnd=" + control.handle + " childID=" + eventChildID());
+                                       OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_CARET_MOVED, control.handle, OS.OBJID_CLIENT, eventChildID());
+                               }
+                       };
+               }
+               control.getDisplay ().timerExec(SCROLL_RATE, timer);
+       }
+
+       /**
+        * 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.TEXT_INSERT</code>
+        * or <code>ACC.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();
+               if (!isATRunning ()) return;
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.start = startIndex;
+               event.end = startIndex + length;
+               event.count = 0;
+               event.type = ACC.TEXT_BOUNDARY_ALL;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getText(event);
+               }
+               if (event.result != null) {
+                       Object[] eventData = new Object[] {
+                                       Integer.valueOf(type),
+                                       Integer.valueOf(startIndex),
+                                       Integer.valueOf(startIndex + length),
+                                       event.result};
+                       sendEvent(ACC.EVENT_TEXT_CHANGED, eventData);
+                       return;
+               }
+               if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_VALUECHANGE hwnd=" + control.handle + " childID=" + eventChildID());
+               OS.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID());
+       }
+
+       /**
+        * 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();
+               if (!isATRunning ()) return;
+               if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_TEXTSELECTIONCHANGED hwnd=" + control.handle + " childID=" + eventChildID());
+               OS.NotifyWinEvent (COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, eventChildID());
+       }
+
+       /* 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.
+        */
+       int QueryInterface(long iid, long ppvObject) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               OS.MoveMemory(ppvObject, new long[] { 0 }, C.PTR_SIZEOF);
+               GUID guid = new GUID();
+               COM.MoveMemory(guid, iid, GUID.sizeof);
+
+               if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) || COM.IsEqualGUID(guid, COM.IIDIAccessible)) {
+                       if (objIAccessible == null) createIAccessible();
+                       OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF);
+                       AddRef();
+                       if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIAccessible.getAddress() + hresult(COM.S_OK));
+                       return COM.S_OK;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) {
+                       if (objIEnumVARIANT == null) createIEnumVARIANT();
+                       OS.MoveMemory(ppvObject, new long[] { objIEnumVARIANT.getAddress() }, C.PTR_SIZEOF);
+                       AddRef();
+                       enumIndex = 0;
+                       if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIEnumVARIANT.getAddress() + hresult(COM.S_OK));
+                       return COM.S_OK;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) {
+                       if (!UseIA2) return COM.E_NOINTERFACE;
+                       if (accessibleActionListenersSize() > 0 || accessibleAttributeListenersSize() > 0 ||
+                               accessibleHyperlinkListenersSize() > 0 || accessibleTableListenersSize() > 0 ||
+                               accessibleTableCellListenersSize() > 0 || accessibleTextExtendedListenersSize() > 0 ||
+                               accessibleValueListenersSize() > 0 || accessibleControlListenersSize() > 0 || getRelationCount() > 0
+                               || (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) || (control instanceof Composite)) {
+                               if (objIServiceProvider == null) createIServiceProvider();
+                               OS.MoveMemory(ppvObject, new long[] { objIServiceProvider.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIServiceProvider.getAddress() + hresult(COM.S_OK));
+                               return COM.S_OK;
+                       }
+                       if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE));
+                       return COM.E_NOINTERFACE;
+               }
+
+               int code = queryAccessible2Interfaces(guid, ppvObject);
+               if (code != COM.S_FALSE) {
+                       if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning" + hresult(code));
+                       return code;
+               }
+
+               if (iaccessible != null) {
+                       /* Forward any other GUIDs to the OS proxy. */
+                       long[] ppv = new long[1];
+                       code = iaccessible.QueryInterface(guid, ppv);
+                       OS.MoveMemory(ppvObject, ppv, C.PTR_SIZEOF);
+                       if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning super" + hresult(code));
+                       return code;
+               }
+
+               if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE));
+               return COM.E_NOINTERFACE;
+       }
+
+       int accessibleListenersSize() {
+               return accessibleListeners == null ? 0 : accessibleListeners.size();
+       }
+
+       int accessibleControlListenersSize() {
+               return accessibleControlListeners == null ? 0 : accessibleControlListeners.size();
+       }
+
+       int accessibleValueListenersSize() {
+               return accessibleValueListeners == null ? 0 : accessibleValueListeners.size();
+       }
+
+       int accessibleTextExtendedListenersSize() {
+               return accessibleTextExtendedListeners == null ? 0 : accessibleTextExtendedListeners.size();
+       }
+
+       int accessibleTextListenersSize() {
+               return accessibleTextListeners == null ? 0 : accessibleTextListeners.size();
+       }
+
+       int accessibleTableCellListenersSize() {
+               return accessibleTableCellListeners == null ? 0 : accessibleTableCellListeners.size();
+       }
+
+       int accessibleTableListenersSize() {
+               return accessibleTableListeners == null ? 0 : accessibleTableListeners.size();
+       }
+
+       int accessibleHyperlinkListenersSize() {
+               return accessibleHyperlinkListeners == null ? 0 : accessibleHyperlinkListeners.size();
+       }
+
+       int accessibleEditableTextListenersSize() {
+               return accessibleEditableTextListeners == null ? 0 : accessibleEditableTextListeners.size();
+       }
+
+       int accessibleAttributeListenersSize() {
+               return accessibleAttributeListeners == null ? 0 : accessibleAttributeListeners.size();
+       }
+
+       int accessibleActionListenersSize() {
+               return accessibleActionListeners == null ? 0 : accessibleActionListeners.size();
+       }
+
+       int AddRef() {
+               refCount++;
+               return refCount;
+       }
+
+       int Release() {
+               refCount--;
+
+               if (refCount == 0) {
+                       if (objIAccessible != null)
+                               objIAccessible.dispose();
+                       objIAccessible = null;
+
+                       if (objIEnumVARIANT != null)
+                               objIEnumVARIANT.dispose();
+                       objIEnumVARIANT = null;
+
+                       if (objIServiceProvider != null)
+                               objIServiceProvider.dispose();
+                       objIServiceProvider = null;
+
+                       if (objIAccessibleApplication != null)
+                               objIAccessibleApplication.dispose();
+                       objIAccessibleApplication = null;
+
+                       // The following lines are intentionally commented. We are not providing IAccessibleComponent at this time.
+//                     if (objIAccessibleComponent != null)
+//                             objIAccessibleComponent.dispose();
+//                     objIAccessibleComponent = null;
+
+                       if (objIAccessibleEditableText != null)
+                               objIAccessibleEditableText.dispose();
+                       objIAccessibleEditableText = null;
+
+                       if (objIAccessibleHyperlink != null)
+                               objIAccessibleHyperlink.dispose();
+                       objIAccessibleHyperlink = null;
+
+                       if (objIAccessibleHypertext != null)
+                               objIAccessibleHypertext.dispose();
+                       objIAccessibleHypertext = null;
+
+                       // The following lines are intentionally commented. We are not providing IAccessibleImage at this time.
+//                     if (objIAccessibleImage != null)
+//                             objIAccessibleImage.dispose();
+//                     objIAccessibleImage = null;
+
+                       if (objIAccessibleTable2 != null)
+                               objIAccessibleTable2.dispose();
+                       objIAccessibleTable2 = null;
+
+                       if (objIAccessibleTableCell != null)
+                               objIAccessibleTableCell.dispose();
+                       objIAccessibleTableCell = null;
+
+                       if (objIAccessibleValue != null)
+                               objIAccessibleValue.dispose();
+                       objIAccessibleValue = null;
+
+                       for (int i = 0; i < relations.length; i++) {
+                               if (relations[i] != null) relations[i].Release();
+                       }
+                       // TODO: also remove all relations for which 'this' is a target??
+               }
+               return refCount;
+       }
+
+       /* QueryService([in] guidService, [in] riid, [out] ppvObject) */
+       int QueryService(long guidService, long riid, long ppvObject) {
+               OS.MoveMemory(ppvObject, new long[] { 0 }, C.PTR_SIZEOF);
+               GUID service = new GUID();
+               COM.MoveMemory(service, guidService, GUID.sizeof);
+               GUID guid = new GUID();
+               COM.MoveMemory(guid, riid, GUID.sizeof);
+
+               if (COM.IsEqualGUID(service, COM.IIDIAccessible)) {
+                       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) || COM.IsEqualGUID(guid, COM.IIDIAccessible)) {
+                               if (objIAccessible == null) createIAccessible();
+                               if (DEBUG) print(this + ".QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning " + objIAccessible.getAddress() + hresult(COM.S_OK));
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       int code = queryAccessible2Interfaces(guid, ppvObject);
+                       if (code != COM.S_FALSE) {
+                               if (DEBUG) print(this + ".QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(code));
+                               return code;
+                       }
+               }
+
+               if (COM.IsEqualGUID(service, COM.IIDIAccessible2)) {
+                       int code = queryAccessible2Interfaces(guid, ppvObject);
+                       if (code != COM.S_FALSE) {
+                               if (DEBUG) print(this + ".*QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(code));
+                               return code;
+                       }
+               }
+
+               if (iaccessible != null) {
+                       /* Forward any other GUIDs to the OS proxy. */
+                       long [] ppv = new long [1];
+                       int code = iaccessible.QueryInterface(COM.IIDIServiceProvider, ppv);
+                       if (code == COM.S_OK) {
+                               IServiceProvider iserviceProvider = new IServiceProvider(ppv[0]);
+                               long [] ppvx = new long [1];
+                               code = iserviceProvider.QueryService(service, guid, ppvx);
+                               OS.MoveMemory(ppvObject, ppvx, C.PTR_SIZEOF);
+                               if (DEBUG) if (interesting(service) && interesting(guid)) print("QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning super" + hresult(code));
+                               return code;
+                       }
+               }
+
+               if (DEBUG) if (interesting(service) && interesting(guid)) print("QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE));
+               return COM.E_NOINTERFACE;
+       }
+
+       int queryAccessible2Interfaces(GUID guid, long ppvObject) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) {
+                       if (accessibleActionListenersSize() > 0 || accessibleAttributeListenersSize() > 0 ||
+                                       accessibleHyperlinkListenersSize() > 0 || accessibleTableListenersSize() > 0 ||
+                                       accessibleTableCellListenersSize() > 0 || accessibleTextExtendedListenersSize() > 0 ||
+                                       accessibleValueListenersSize() > 0 || accessibleControlListenersSize() > 0 || getRelationCount() > 0
+                                       || (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) || (control instanceof Composite)) {
+                               // NOTE: IAccessible2 vtable is shared with IAccessible
+                               if (objIAccessible == null) createIAccessible();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) {
+                       if (accessibleActionListenersSize() > 0) {
+                               // NOTE: IAccessibleAction vtable is shared with IAccessibleHyperlink
+                               if (objIAccessibleHyperlink == null) createIAccessibleHyperlink();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleHyperlink.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) {
+                       if (objIAccessibleApplication == null) createIAccessibleApplication();
+                       OS.MoveMemory(ppvObject, new long[] { objIAccessibleApplication.getAddress() }, C.PTR_SIZEOF);
+                       AddRef();
+                       return COM.S_OK;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) {
+                       // The following lines are intentionally commented. We are not supporting IAccessibleComponent at this time.
+//                     if (accessibleControlListenersSize() > 0) { // TO DO: can we reduce the scope of this somehow?
+//                             if (objIAccessibleComponent == null) createIAccessibleComponent();
+//                             COM.MoveMemory(ppvObject, new long[] { objIAccessibleComponent.getAddress() }, OS.PTR_SIZEOF);
+//                             AddRef();
+//                             return COM.S_OK;
+//                     }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) {
+                       if (accessibleEditableTextListenersSize() > 0) {
+                               if (objIAccessibleEditableText == null) createIAccessibleEditableText();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleEditableText.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) {
+                       if (accessibleHyperlinkListenersSize() > 0) {
+                               if (objIAccessibleHyperlink == null) createIAccessibleHyperlink();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleHyperlink.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) {
+                       if (accessibleTextExtendedListenersSize() > 0) {
+                               if (objIAccessibleHypertext == null) createIAccessibleHypertext();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleHypertext.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) {
+                       // The following lines are intentionally commented. We are not supporting IAccessibleImage at this time.
+//                     if (getRole() == ACC.ROLE_GRAPHIC && (accessibleAccessibleListenersSize() > 0 || accessibleControlListenersSize() > 0)) {
+//                             if (objIAccessibleImage == null) createIAccessibleImage();
+//                             COM.MoveMemory(ppvObject, new long[] { objIAccessibleImage.getAddress() }, OS.PTR_SIZEOF);
+//                             AddRef();
+//                             return COM.S_OK;
+//                     }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) {
+                       // We are not supporting IAccessibleTable at this time.
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) {
+                       if (accessibleTableListenersSize() > 0) {
+                               if (objIAccessibleTable2 == null) createIAccessibleTable2();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleTable2.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) {
+                       if (accessibleTableCellListenersSize() > 0) {
+                               if (objIAccessibleTableCell == null) createIAccessibleTableCell();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleTableCell.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) {
+                       if (accessibleTextExtendedListenersSize() > 0 || accessibleAttributeListenersSize() > 0) {
+                               // NOTE: IAccessibleText vtable is shared with IAccessibleHypertext
+                               if (objIAccessibleHypertext == null) createIAccessibleHypertext();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleHypertext.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) {
+                       if (accessibleValueListenersSize() > 0) {
+                               if (objIAccessibleValue == null) createIAccessibleValue();
+                               OS.MoveMemory(ppvObject, new long[] { objIAccessibleValue.getAddress() }, C.PTR_SIZEOF);
+                               AddRef();
+                               return COM.S_OK;
+                       }
+                       return COM.E_NOINTERFACE;
+               }
+
+               return COM.S_FALSE;
+       }
+
+       /* IAccessible::accDoDefaultAction([in] varChild) */
+       int accDoDefaultAction(long varChild) {
+               if (DEBUG) print(this + ".IAccessible::accDoDefaultAction");
+               if (accessibleActionListenersSize() > 0) {
+                       VARIANT v = getVARIANT(varChild);
+                       if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+                       if (v.lVal == COM.CHILDID_SELF) return doAction(0);
+               }
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               if (iaccessible != null) {
+                       /* If there were no action listeners, forward to the proxy. */
+                       code = iaccessible.accDoDefaultAction(varChild);
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+               }
+               return code;
+       }
+
+       /* IAccessible::accHitTest([in] xLeft, [in] yTop, [out] pvarChild) */
+       int accHitTest(int xLeft, int yTop, long pvarChild) {
+               int osChild = ACC.CHILDID_NONE;
+               long osChildObject = 0;
+               if (iaccessible != null) {
+                       /* Get the default child at point (left, top) from the OS. */
+                       int code = iaccessible.accHitTest(xLeft, yTop, pvarChild);
+                       if (code == COM.S_OK) {
+                               VARIANT v = getVARIANT(pvarChild);
+                               if (v.vt == COM.VT_I4) osChild = v.lVal;
+                               else if (v.vt == COM.VT_DISPATCH) {
+                                       osChildObject = v.lVal; // TODO: don't use struct. lVal is an int.
+                                       if (DEBUG) print(this + ".IAccessible::accHitTest() super returned VT_DISPATCH");
+                               }
+                       }
+                       if (accessibleControlListenersSize() == 0) {
+                               if (DEBUG) print(this + ".IAccessible::accHitTest returning childID=" + osChild + " from super" + hresult(code));
+                               return code;
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = osChild == ACC.CHILDID_NONE ? ACC.CHILDID_NONE : osToChildID(osChild);
+               // TODO: event.accessible = Accessible for osChildObject;
+               event.x = xLeft;
+               event.y = yTop;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getChildAtPoint(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible != null) {
+                       if (DEBUG) print(this + ".IAccessible::accHitTest returning " + accessible.getAddress() + hresult(COM.S_OK));
+                       accessible.AddRef();
+                       setPtrVARIANT(pvarChild, COM.VT_DISPATCH, accessible.getAddress());
+                       return COM.S_OK;
+               }
+               int childID = event.childID;
+               if (childID == ACC.CHILDID_NONE) {
+                       if (osChildObject != 0) {
+                               if (DEBUG) print(this + ".IAccessible::accHitTest returning osChildObject " + osChildObject + " from super" + hresult(COM.S_OK));
+                               return COM.S_OK;
+                       }
+                       if (DEBUG) print(this + ".IAccessible::accHitTest returning VT_EMPTY" + hresult(COM.S_FALSE));
+                       setIntVARIANT(pvarChild, COM.VT_EMPTY, 0);
+                       return COM.S_FALSE;
+               }
+               if (DEBUG) print(this + ".IAccessible::accHitTest returning " + childIDToOs(childID) + hresult(COM.S_OK));
+               setIntVARIANT(pvarChild, COM.VT_I4, childIDToOs(childID));
+               return COM.S_OK;
+       }
+
+       /* IAccessible::accLocation([out] pxLeft, [out] pyTop, [out] pcxWidth, [out] pcyHeight, [in] varChild) */
+       int accLocation(long pxLeft, long pyTop, long pcxWidth, long pcyHeight, long varChild) {
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int osLeft = 0, osTop = 0, osWidth = 0, osHeight = 0;
+               if (iaccessible != null) {
+                       /* Get the default location from the OS. */
+                       int code = iaccessible.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild);
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+                       if (accessibleControlListenersSize() == 0) {
+                               if (DEBUG) print(this + ".IAccessible::accLocation returning from super" + hresult(code));
+                               return code;
+                       }
+                       if (code == COM.S_OK) {
+                               int[] pLeft = new int[1], pTop = new int[1], pWidth = new int[1], pHeight = new int[1];
+                               OS.MoveMemory(pLeft, pxLeft, 4);
+                               OS.MoveMemory(pTop, pyTop, 4);
+                               OS.MoveMemory(pWidth, pcxWidth, 4);
+                               OS.MoveMemory(pHeight, 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 < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getLocation(event);
+               }
+               if (DEBUG) print(this + ".IAccessible::accLocation(" + v.lVal + ") returning x=" + event.x + " y=" + event.y + "w=" + event.width + "h=" + event.height + hresult(COM.S_OK));
+               OS.MoveMemory(pxLeft, new int[] { event.x }, 4);
+               OS.MoveMemory(pyTop, new int[] { event.y }, 4);
+               OS.MoveMemory(pcxWidth, new int[] { event.width }, 4);
+               OS.MoveMemory(pcyHeight, new int[] { event.height }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::accNavigate([in] navDir, [in] varStart, [out] pvarEndUpAt) */
+       int accNavigate(int navDir, long varStart, long pvarEndUpAt) {
+               if (DEBUG) print(this + ".IAccessible::accNavigate");
+               /* MSAA: "The accNavigate method is deprecated and should not be used." */
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               if (iaccessible != null) {
+                       /* Since many of the native controls still handle accNavigate,
+                        * we will continue to send this through to the proxy. */
+                       code = iaccessible.accNavigate(navDir, varStart, pvarEndUpAt);
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+               }
+               return code;
+       }
+
+       // TODO: Consider supporting this in future.
+       /* IAccessible::accSelect([in] flagsSelect, [in] varChild) */
+       int accSelect(int flagsSelect, long varChild) {
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               if (iaccessible != null) {
+                       /* Currently, we don't expose this as API. Forward to the proxy. */
+                       code = iaccessible.accSelect(flagsSelect, varChild);
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+               }
+               if (DEBUG) print(this + ".IAccessible::accSelect(" + flagsSelect + ") returning" + hresult(code));
+               return code;
+       }
+
+       /* IAccessible::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.
+        */
+       int get_accChild(long varChild, long ppdispChild) {
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               if (v.lVal == COM.CHILDID_SELF) {
+                       if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning " + getAddress() + hresult(COM.S_OK));
+                       AddRef();
+                       OS.MoveMemory(ppdispChild, new long[] { getAddress() }, C.PTR_SIZEOF);
+                       return COM.S_OK;
+               }
+               final int childID = osToChildID(v.lVal);
+               int code = COM.S_FALSE;
+               Accessible osAccessible = null;
+               if (iaccessible != null) {
+                       /* Get the default child from the OS. */
+                       code = iaccessible.get_accChild(varChild, ppdispChild);
+                       if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+                       if (code == COM.S_OK && control instanceof ToolBar) {
+                               ToolBar toolBar = (ToolBar) control;
+                               final ToolItem item = toolBar.getItem(childID);
+                               if (item != null && (item.getStyle() & SWT.DROP_DOWN) != 0) {
+                                       long[] addr = new long[1];
+                                       OS.MoveMemory(addr, ppdispChild, C.PTR_SIZEOF);
+                                       boolean found = false;
+                                       for (int i = 0; i < children.size(); i++) {
+                                               Accessible accChild = children.get(i);
+                                               if (accChild.item == item) {
+                                                       /*
+                                                        * MSAA uses a new accessible for the child
+                                                        * so we dispose the old and use the new.
+                                                        */
+                                                       accChild.dispose();
+                                                       accChild.item = null;
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                                       osAccessible = new Accessible(this, addr[0]);
+                                       osAccessible.item = item;
+                                       if (!found) {
+                                               item.addListener(SWT.Dispose, e -> {
+                                                       for (int i = 0; i < children.size(); i++) {
+                                                               Accessible accChild = children.get(i);
+                                                               if (accChild.item == item) {
+                                                                       accChild.dispose();
+                                                               }
+                                                       }
+                                               });
+                                       }
+                                       osAccessible.addAccessibleListener(new AccessibleAdapter() {
+                                               @Override
+                                               public void getName(AccessibleEvent e) {
+                                                       if (e.childID == ACC.CHILDID_SELF) {
+                                                               AccessibleEvent event = new AccessibleEvent(Accessible.this);
+                                                               event.childID = childID;
+                                                               for (int i = 0; i < accessibleListenersSize(); i++) {
+                                                                       AccessibleListener listener = accessibleListeners.get(i);
+                                                                       listener.getName(event);
+                                                               }
+                                                               e.result = event.result;
+                                                       }
+                                               }
+                                       });
+                               }
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = childID;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getChild(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible == null) accessible = osAccessible;
+               if (accessible != null) {
+                       if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning " + accessible.getAddress() + hresult(COM.S_OK));
+                       accessible.AddRef();
+                       OS.MoveMemory(ppdispChild, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+                       return COM.S_OK;
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning from super" + hresult(code));
+               return code;
+       }
+
+       /* IAccessible::get_accChildCount([out] pcountChildren) */
+       int get_accChildCount(long pcountChildren) {
+               int osChildCount = 0;
+               if (iaccessible != null) {
+                       /* Get the default child count from the OS. */
+                       int code = iaccessible.get_accChildCount(pcountChildren);
+                       if (code == COM.S_OK) {
+                               int[] pChildCount = new int[1];
+                               OS.MoveMemory(pChildCount, pcountChildren, 4);
+                               osChildCount = pChildCount[0];
+                       }
+                       if (accessibleControlListenersSize() == 0) {
+                               if (DEBUG) print(this + ".IAccessible::get_accChildCount() returning " + osChildCount + " from super" + hresult(code));
+                               return code;
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = ACC.CHILDID_SELF;
+               event.detail = osChildCount;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getChildCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accChildCount() returning " + event.detail + hresult(COM.S_OK));
+               OS.MoveMemory(pcountChildren, new int[] { event.detail }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accDefaultAction([in] varChild, [out] pszDefaultAction) */
+       int get_accDefaultAction(long varChild, long pszDefaultAction) {
+               if (DEBUG) print(this + ".IAccessible::get_accDefaultAction");
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               String osDefaultAction = null;
+               if (iaccessible != null) {
+                       /* Get the default defaultAction from the OS. */
+                       code = iaccessible.get_accDefaultAction(varChild, pszDefaultAction);
+                       if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+                       if (accessibleControlListenersSize() == 0) return code;
+                       if (code == COM.S_OK) {
+                               long[] pDefaultAction = new long[1];
+                               OS.MoveMemory(pDefaultAction, pszDefaultAction, C.PTR_SIZEOF);
+                               int size = COM.SysStringByteLen(pDefaultAction[0]);
+                               if (size > 0) {
+                                       char[] buffer = new char[(size + 1) /2];
+                                       OS.MoveMemory(buffer, pDefaultAction[0], size);
+                                       osDefaultAction = new String(buffer);
+                               }
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = osToChildID(v.lVal);
+               event.result = osDefaultAction;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getDefaultAction(event);
+               }
+               if ((event.result == null || event.result.length() == 0) && v.lVal == COM.CHILDID_SELF) {
+                       code = get_name(0, pszDefaultAction);
+               }
+               if (event.result == null) return code;
+               if (event.result.length() == 0) return COM.S_FALSE;
+               setString(pszDefaultAction, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accDescription([in] varChild, [out] pszDescription) */
+       int get_accDescription(long varChild, long pszDescription) {
+               /*
+                * MSAA: "The accDescription property is not supported in the transition to
+                * UI Automation. MSAA servers and applications should not use it."
+                *
+                * TODO: Description was exposed as SWT API. We will need to either deprecate this (?),
+                * or find a suitable replacement. Also, check description property on other platforms.
+                * If it is truly deprecated for MSAA, then perhaps it can be reused for IAccessibleImage.
+                * Note that the trick to expose tree columns (below) was not supported by screen readers,
+                * so it should be replaced.
+                */
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               String osDescription = null;
+               if (iaccessible != null) {
+                       /* Get the default description from the OS. */
+                       code = iaccessible.get_accDescription(varChild, pszDescription);
+                       if (code == 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 (accessibleListenersSize() == 0 && !(control instanceof Tree)) {
+                               if (DEBUG) print(this + ".IAccessible::get_accDescription(" + v.lVal + ") returning super" + hresult(code));
+                               return code;
+                       }
+                       if (code == COM.S_OK) {
+                               long[] pDescription = new long[1];
+                               OS.MoveMemory(pDescription, pszDescription, C.PTR_SIZEOF);
+                               int size = COM.SysStringByteLen(pDescription[0]);
+                               if (size > 0) {
+                                       char[] buffer = new char[(size + 1) /2];
+                                       OS.MoveMemory(buffer, pDescription[0], size);
+                                       osDescription = new String(buffer);
+                               }
+                       }
+               }
+
+               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 != COM.CHILDID_SELF) {
+                       if (control instanceof Tree) {
+                               Tree tree = (Tree) control;
+                               int columnCount = tree.getColumnCount ();
+                               if (columnCount > 1) {
+                                       long hwnd = control.handle, hItem = 0;
+                                       hItem = OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
+                                       Widget widget = tree.getDisplay ().findWidget (hwnd, hItem);
+                                       event.result = "";
+                                       if (widget != null && widget instanceof TreeItem) {
+                                               TreeItem item = (TreeItem) widget;
+                                               for (int i = 1; i < columnCount; i++) {
+                                                       if (tree.isDisposed() || item.isDisposed()) {
+                                                               event.result = "";
+                                                               return COM.S_OK;
+                                                       }
+                                                       event.result += tree.getColumn(i).getText() + ": " + item.getText(i);
+                                                       if (i + 1 < columnCount) event.result += ", ";
+                                               }
+                                       }
+                               }
+                       }
+               }
+               for (int i = 0; i < accessibleListenersSize(); i++) {
+                       AccessibleListener listener = accessibleListeners.get(i);
+                       listener.getDescription(event);
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accDescription(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               if (event.result == null) return code;
+               if (event.result.length() == 0) return COM.S_FALSE;
+               setString(pszDescription, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accFocus([out] 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.
+        */
+       int get_accFocus(long pvarChild) {
+               int osChild = ACC.CHILDID_NONE;
+               if (iaccessible != null) {
+                       /* Get the default focus child from the OS. */
+                       int code = iaccessible.get_accFocus(pvarChild);
+                       if (code == COM.S_OK) {
+                               VARIANT v = getVARIANT(pvarChild);
+                               if (v.vt == COM.VT_I4) osChild = v.lVal;
+                               // TODO: need to check VT_DISPATCH (don't use struct)
+                               if (DEBUG) if (v.vt == COM.VT_DISPATCH) print("IAccessible::get_accFocus() super returned VT_DISPATCH");
+                       }
+                       if (accessibleControlListenersSize() == 0) {
+                               if (DEBUG) print(this + ".IAccessible::get_accFocus() returning childID=" + osChild + " from super" + hresult(code));
+                               return code;
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = osChild == ACC.CHILDID_NONE ? ACC.CHILDID_NONE : osToChildID(osChild);
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getFocus(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible != null) {
+                       if (DEBUG) print(this + ".IAccessible::get_accFocus() returning accessible " + accessible.getAddress() + hresult(COM.S_OK));
+                       accessible.AddRef();
+                       setPtrVARIANT(pvarChild, COM.VT_DISPATCH, accessible.getAddress());
+                       return COM.S_OK;
+               }
+               int childID = event.childID;
+               if (childID == ACC.CHILDID_NONE) {
+                       if (DEBUG) print(this + ".IAccessible::get_accFocus() returning VT_EMPTY" + hresult(COM.S_FALSE));
+                       setIntVARIANT(pvarChild, COM.VT_EMPTY, 0);
+                       return COM.S_FALSE;
+               }
+               if (childID == ACC.CHILDID_SELF) {
+                       if (DEBUG) print(this + ".IAccessible::get_accFocus() returning CHILDID_SELF " + hresult(COM.S_OK));
+                       AddRef();
+                       setIntVARIANT(pvarChild, COM.VT_I4, COM.CHILDID_SELF);
+                       return COM.S_OK;
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accFocus() returning childID " + childIDToOs(childID) + hresult(COM.S_OK));
+               setIntVARIANT(pvarChild, COM.VT_I4, childIDToOs(childID));
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accHelp([in] varChild, [out] pszHelp) */
+       int get_accHelp(long varChild, long pszHelp) {
+               if (DEBUG) print(this + ".IAccessible::get_accHelp");
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               String osHelp = null;
+               if (iaccessible != null) {
+                       /* Get the default help string from the OS. */
+                       code = iaccessible.get_accHelp(varChild, pszHelp);
+                       if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+                       if (accessibleListenersSize() == 0) return code;
+                       if (code == COM.S_OK) {
+                               long[] pHelp = new long[1];
+                               OS.MoveMemory(pHelp, pszHelp, C.PTR_SIZEOF);
+                               int size = COM.SysStringByteLen(pHelp[0]);
+                               if (size > 0) {
+                                       char[] buffer = new char[(size + 1) /2];
+                                       OS.MoveMemory(buffer, pHelp[0], size);
+                                       osHelp = new String(buffer);
+                               }
+                       }
+               }
+
+               AccessibleEvent event = new AccessibleEvent(this);
+               event.childID = osToChildID(v.lVal);
+               event.result = osHelp;
+               for (int i = 0; i < accessibleListenersSize(); i++) {
+                       AccessibleListener listener = accessibleListeners.get(i);
+                       listener.getHelp(event);
+               }
+               if (event.result == null) return code;
+               if (event.result.length() == 0) return COM.S_FALSE;
+               setString(pszHelp, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accHelpTopic([out] pszHelpFile, [in] varChild, [out] pidTopic) */
+       int get_accHelpTopic(long pszHelpFile, long varChild, long pidTopic) {
+               if (DEBUG) print(this + ".IAccessible::get_accHelpTopic");
+               /* MSAA: "The accHelpTopic property is deprecated and should not be used." */
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               if (iaccessible != null) {
+                       /* Since it is possible that a native control might still handle get_accHelpTopic,
+                        * we will continue to send this through to the proxy. */
+                       code = iaccessible.get_accHelpTopic(pszHelpFile, varChild, pidTopic);
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+               }
+               return code;
+       }
+
+       /* IAccessible::get_accKeyboardShortcut([in] varChild, [out] pszKeyboardShortcut) */
+       int get_accKeyboardShortcut(long varChild, long pszKeyboardShortcut) {
+               if (DEBUG) print(this + ".IAccessible::get_accKeyboardShortcut");
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               String osKeyboardShortcut = null;
+               if (iaccessible != null) {
+                       /* Get the default keyboard shortcut from the OS. */
+                       code = iaccessible.get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
+                       if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+                       /* Process TabFolder even if there are no apps listening. */
+                       if (accessibleListenersSize() == 0 && !(control instanceof TabFolder)) return code;
+                       if (code == COM.S_OK) {
+                               long[] pKeyboardShortcut = new long[1];
+                               OS.MoveMemory(pKeyboardShortcut, pszKeyboardShortcut, C.PTR_SIZEOF);
+                               int size = COM.SysStringByteLen(pKeyboardShortcut[0]);
+                               if (size > 0) {
+                                       char[] buffer = new char[(size + 1) /2];
+                                       OS.MoveMemory(buffer, pKeyboardShortcut[0], size);
+                                       osKeyboardShortcut = new String(buffer);
+                               }
+                       }
+               }
+
+               AccessibleEvent event = new AccessibleEvent(this);
+               event.childID = osToChildID(v.lVal);
+               event.result = osKeyboardShortcut;
+               /* SWT TabFolders use Ctrl+PageDown to switch pages (not Ctrl+Tab). */
+               if (v.lVal == COM.CHILDID_SELF && control instanceof TabFolder) {
+                       event.result = SWT.getMessage ("SWT_SwitchPage_Shortcut"); //$NON-NLS-1$
+               }
+               for (int i = 0; i < accessibleListenersSize(); i++) {
+                       AccessibleListener listener = accessibleListeners.get(i);
+                       listener.getKeyboardShortcut(event);
+               }
+               if (event.result == null) return code;
+               if (event.result.length() == 0) return COM.S_FALSE;
+               setString(pszKeyboardShortcut, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accName([in] varChild, [out] pszName) */
+       int get_accName(long varChild, long pszName) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.S_FALSE;
+               String osName = null;
+               if (iaccessible != null) {
+                       /* Get the default name from the OS. */
+                       code = iaccessible.get_accName(varChild, pszName);
+                       if (code == COM.S_OK) {
+                               long[] pName = new long[1];
+                               OS.MoveMemory(pName, pszName, C.PTR_SIZEOF);
+                               int size = COM.SysStringByteLen(pName[0]);
+                               if (size > 0) {
+                                       char[] buffer = new char[(size + 1) /2];
+                                       OS.MoveMemory(buffer, pName[0], size);
+                                       osName = new String(buffer);
+                               }
+                       }
+                       if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+                       /* Process Text even if there are no apps listening. */
+                       if (accessibleListenersSize() == 0 && !(control instanceof Text)) {
+                               if (DEBUG) print(this + ".IAccessible::get_accName(" + v.lVal + ") returning name=" + osName + " from super" + hresult(code));
+                               return code;
+                       }
+               }
+
+               AccessibleEvent event = new AccessibleEvent(this);
+               event.childID = osToChildID(v.lVal);
+               event.result = osName;
+               /*
+               * Bug in Windows:  A Text with SWT.SEARCH style uses EM_SETCUEBANNER
+               * to set the message text. This text should be used as the control's
+               * accessible name, however it is not. The fix is to return the message
+               * text here as the accName (unless there is a preceding label).
+               */
+               if (control instanceof Text && (control.getStyle() & SWT.SEARCH) != 0 && osName == null) {
+                       event.result = ((Text) control).getMessage();
+               }
+               for (int i = 0; i < accessibleListenersSize(); i++) {
+                       AccessibleListener listener = accessibleListeners.get(i);
+                       listener.getName(event);
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accName(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               if (event.result == null) return code;
+               if (event.result.length() == 0) return COM.S_FALSE;
+               setString(pszName, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::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.
+        */
+       int get_accParent(long ppdispParent) {
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               if (iaccessible != null) {
+                       /* Currently, we don't expose this as API. Forward to the proxy. */
+                       code = iaccessible.get_accParent(ppdispParent);
+               }
+               if (parent != null) {
+                       /* For lightweight accessibles, return the accessible's parent. */
+                       parent.AddRef();
+                       OS.MoveMemory(ppdispParent, new long[] { parent.getAddress() }, C.PTR_SIZEOF);
+                       code = COM.S_OK;
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accParent() returning" + (parent != null ? " " + parent.getAddress() : " from super") + hresult(code));
+               return code;
+       }
+
+       /* IAccessible::get_accRole([in] varChild, [out] pvarRole) */
+       int get_accRole(long varChild, long pvarRole) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int osRole = COM.ROLE_SYSTEM_CLIENT;
+               if (iaccessible != null) {
+                       /* Get the default role from the OS. */
+                       int code = iaccessible.get_accRole(varChild, pvarRole);
+                       if (code == COM.S_OK) {
+                               VARIANT v2 = getVARIANT(pvarRole);
+                               if (v2.vt == COM.VT_I4) osRole = v2.lVal;
+                       }
+               }
+
+               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 (control instanceof Tree || control instanceof Table) {
+                       if (v.lVal != COM.CHILDID_SELF && (control.getStyle() & SWT.CHECK) != 0) event.detail = ACC.ROLE_CHECKBUTTON;
+               }
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getRole(event);
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accRole(" + v.lVal + ") returning " + getRoleString(roleToOs(event.detail)) + hresult(COM.S_OK));
+               setIntVARIANT(pvarRole, COM.VT_I4, roleToOs(event.detail));
+               return COM.S_OK;
+       }
+
+       /* IAccessible::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.
+        */
+       int get_accSelection(long pvarChildren) {
+               if (DEBUG) print(this + ".IAccessible::get_accSelection");
+               int osChild = ACC.CHILDID_NONE;
+               long osChildObject = 0;
+               if (iaccessible != null) {
+                       /* Get the default selection from the OS. */
+                       int code = iaccessible.get_accSelection(pvarChildren);
+                       if (accessibleControlListenersSize() == 0) return code;
+                       if (code == COM.S_OK) {
+                               VARIANT v = getVARIANT(pvarChildren);
+                               if (v.vt == COM.VT_I4) {
+                                       osChild = osToChildID(v.lVal);
+                               } else if (v.vt == COM.VT_DISPATCH) {
+                                       osChildObject = v.lVal; // TODO: don't use struct; lVal is an int
+                               } else if (v.vt == COM.VT_UNKNOWN) {
+                                       osChild = ACC.CHILDID_MULTIPLE;
+                                       // TODO: Should get IEnumVARIANT from punkVal field, and enumerate children...
+                               }
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = osChild;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getSelection(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible != null) {
+                       accessible.AddRef();
+                       setPtrVARIANT(pvarChildren, COM.VT_DISPATCH, accessible.getAddress());
+                       return COM.S_OK;
+               }
+               int childID = event.childID;
+               if (childID == ACC.CHILDID_NONE) {
+                       if (osChildObject != 0) return COM.S_OK;
+                       setIntVARIANT(pvarChildren, COM.VT_EMPTY, 0);
+                       return COM.S_FALSE;
+               }
+               if (childID == ACC.CHILDID_MULTIPLE) {
+                       // TODO: return an enumeration for event.children (currently just returns enumeration from proxy)
+                       //AddRef();
+                       //setPtrVARIANT(pvarChildren, COM.VT_UNKNOWN, getAddress());
+                       return COM.S_OK;
+               }
+               if (childID == ACC.CHILDID_SELF) {
+                       AddRef();
+                       setPtrVARIANT(pvarChildren, COM.VT_DISPATCH, getAddress());
+                       return COM.S_OK;
+               }
+               setIntVARIANT(pvarChildren, COM.VT_I4, childIDToOs(childID));
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accState([in] varChild, [out] pvarState) */
+       int get_accState(long varChild, long pvarState) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int osState = 0;
+               if (iaccessible != null) {
+                       /* Get the default state from the OS. */
+                       int code = iaccessible.get_accState(varChild, pvarState);
+                       if (code == COM.S_OK) {
+                               VARIANT v2 = getVARIANT(pvarState);
+                               if (v2.vt == COM.VT_I4) osState = v2.lVal;
+                       }
+               }
+
+               boolean 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 != COM.CHILDID_SELF) {
+                       if (control instanceof Tree && (control.getStyle() & SWT.CHECK) != 0) {
+                               long hwnd = control.handle;
+                               TVITEM tvItem = new TVITEM ();
+                               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                               tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+                               tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
+                               long result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+                               boolean checked = (result != 0) && (((tvItem.state >> 12) & 1) == 0);
+                               if (checked) event.detail |= ACC.STATE_CHECKED;
+                               grayed = tvItem.state >> 12 > 2;
+                       } else if (control instanceof Table && (control.getStyle() & SWT.CHECK) != 0) {
+                               Table table = (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 < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getState(event);
+               }
+               int state = stateToOs(event.detail);
+               if ((state & ACC.STATE_CHECKED) != 0 && grayed) {
+                       state &= ~ COM.STATE_SYSTEM_CHECKED;
+                       state |= COM.STATE_SYSTEM_MIXED;
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accState(" + v.lVal + ") returning" + getStateString(state) + hresult(COM.S_OK));
+               setIntVARIANT(pvarState, COM.VT_I4, state);
+               return COM.S_OK;
+       }
+
+       /* IAccessible::get_accValue([in] varChild, [out] pszValue) */
+       int get_accValue(long varChild, long pszValue) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               String osValue = null;
+               if (iaccessible != null) {
+                       /* Get the default value string from the OS. */
+                       code = iaccessible.get_accValue(varChild, pszValue);
+                       if (code == COM.S_OK) {
+                               long[] pValue = new long[1];
+                               OS.MoveMemory(pValue, pszValue, C.PTR_SIZEOF);
+                               int size = COM.SysStringByteLen(pValue[0]);
+                               if (size > 0) {
+                                       char[] buffer = new char[(size + 1) /2];
+                                       OS.MoveMemory(buffer, pValue[0], size);
+                                       osValue = new String(buffer);
+                               }
+                       }
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+                       /* Process Text even if there are no apps listening. */
+                       if (accessibleControlListenersSize() == 0 && !(control instanceof Text)) {
+                               if (DEBUG) print(this + ".IAccessible::get_accValue(" + v.lVal + ") returning value=" + osValue + " from super" + hresult(code));
+                               return code;
+                       }
+               }
+
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = osToChildID(v.lVal);
+               event.result = osValue;
+               /*
+               * Bug in Windows:  A Text with SWT.SEARCH style uses EM_SETCUEBANNER
+               * to set the message text. This text should be used as the control's
+               * accessible value when the control does not have focus, however it
+               * is not. The fix is to return the message text here as the accValue.
+               */
+               if (control instanceof Text && (control.getStyle() & SWT.SEARCH) != 0 && !control.isFocusControl()) {
+                       event.result = ((Text) control).getMessage();
+               }
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getValue(event);
+               }
+               if (DEBUG) print(this + ".IAccessible::get_accValue(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : COM.S_OK));
+               if (event.result == null) return code;
+               // empty string is a valid value, so do not test for it
+               setString(pszValue, event.result);
+               return COM.S_OK;
+       }
+
+       /* put_accName([in] varChild, [in] szName) */
+       int put_accName(long varChild, long szName) {
+               /* MSAA: "The IAccessible::put_accName method is no longer supported. Servers should return E_NOTIMPL." */
+               return COM.E_NOTIMPL;
+       }
+
+       /* put_accValue([in] varChild, [in] szValue) */
+       int put_accValue(long varChild, long szValue) {
+               /* MSAA: this method is supported for some UI elements (usually edit controls). */
+               VARIANT v = getVARIANT(varChild);
+               if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
+               int code = COM.DISP_E_MEMBERNOTFOUND;
+               if (v.lVal == COM.CHILDID_SELF && accessibleEditableTextListenersSize() > 0) {
+                       /*
+                        * If the object supports AccessibleEditableTextListener.replaceText,
+                        * then give the object a chance to handle this event.
+                        */
+                       AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+                       event.start = 0;
+                       event.end = getCharacterCount();
+                       if (event.end >= 0) {
+                               int size = COM.SysStringByteLen(szValue);
+                               char [] buffer = new char [(size + 1) / 2];
+                               OS.MoveMemory (buffer, szValue, size);
+                               event.string = new String (buffer);
+                               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                                       listener.replaceText(event);
+                               }
+                               if (event.result != null && event.result.equals(ACC.OK)) code = COM.S_OK;
+                               if (DEBUG) print(this + ".IAccessible::put_accValue(" + v.lVal + ", \"" + event.string + "\") returning " + hresult(code));
+                       }
+               }
+               if (code != COM.S_OK && iaccessible != null) {
+                       /* If the object did not handle the event, then forward to the proxy. */
+                       code = iaccessible.put_accValue(varChild, szValue);
+                       if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
+                       if (DEBUG) print(this + ".IAccessible::put_accValue(" + v.lVal + ") returning " + hresult(code) + " from proxy");
+               }
+               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).
+        */
+
+       /* IEnumVARIANT::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.
+        */
+       int Next(int celt, long rgvar, long pceltFetched) {
+               if (DEBUG) print(this + ".IEnumVARIANT::Next");
+               /* If there are no listeners, query the proxy for
+                * its IEnumVariant, and get the Next items from it.
+                */
+               if (iaccessible != null && accessibleControlListenersSize() == 0) {
+                       long[] ppvObject = new long[1];
+                       int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
+                       if (code != COM.S_OK) return code;
+                       IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
+                       int[] celtFetched = new int[1];
+                       code = ienumvariant.Next(celt, rgvar, celtFetched);
+                       ienumvariant.Release();
+                       OS.MoveMemory(pceltFetched, celtFetched, 4);
+                       return code;
+               }
+
+               if (rgvar == 0) return COM.E_INVALIDARG;
+               if (pceltFetched == 0 && celt != 1) return COM.E_INVALIDARG;
+               if (enumIndex == 0) {
+                       AccessibleControlEvent event = new AccessibleControlEvent(this);
+                       event.childID = ACC.CHILDID_SELF;
+                       for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                               AccessibleControlListener listener = accessibleControlListeners.get(i);
+                               listener.getChildren(event);
+                       }
+                       variants = event.children;
+               }
+               Object[] nextItems = null;
+               if (variants != 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 (child instanceof Integer) {
+                                               nextItems[i] = Integer.valueOf(childIDToOs(((Integer)child).intValue()));
+                                       } else {
+                                               nextItems[i] = child;
+                                       }
+                                       enumIndex++;
+                               }
+                       }
+               }
+               if (nextItems != null) {
+                       for (int i = 0; i < nextItems.length; i++) {
+                               Object nextItem = nextItems[i];
+                               if (nextItem instanceof Integer) {
+                                       int item = ((Integer) nextItem).intValue();
+                                       setIntVARIANT(rgvar + i * VARIANT.sizeof, COM.VT_I4, item);
+                               } else {
+                                       Accessible accessible = (Accessible) nextItem;
+                                       accessible.AddRef();
+                                       setPtrVARIANT(rgvar + i * VARIANT.sizeof, COM.VT_DISPATCH, accessible.getAddress());
+                               }
+                       }
+                       if (pceltFetched != 0)
+                               OS.MoveMemory(pceltFetched, new int[] {nextItems.length}, 4);
+                       if (nextItems.length == celt) return COM.S_OK;
+               } else {
+                       if (pceltFetched != 0)
+                               OS.MoveMemory(pceltFetched, new int[] {0}, 4);
+               }
+               return COM.S_FALSE;
+       }
+
+       /* IEnumVARIANT::Skip([in] celt) over the specified number of elements in the enumeration sequence. */
+       int Skip(int celt) {
+               if (DEBUG) print(this + ".IEnumVARIANT::Skip");
+               /* If there are no listeners, query the proxy
+                * for its IEnumVariant, and tell it to Skip.
+                */
+               if (iaccessible != null && accessibleControlListenersSize() == 0) {
+                       long[] ppvObject = new long[1];
+                       int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
+                       if (code != COM.S_OK) return code;
+                       IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
+                       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;
+       }
+
+       /* IEnumVARIANT::Reset() the enumeration sequence to the beginning. */
+       int Reset() {
+               if (DEBUG) print(this + ".IEnumVARIANT::Reset");
+               /* If there are no listeners, query the proxy
+                * for its IEnumVariant, and tell it to Reset.
+                */
+               if (iaccessible != null && accessibleControlListenersSize() == 0) {
+                       long[] ppvObject = new long[1];
+                       int code = (int)iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
+                       if (code != COM.S_OK) return code;
+                       IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
+                       code = ienumvariant.Reset();
+                       ienumvariant.Release();
+                       return code;
+               }
+
+               enumIndex = 0;
+               return COM.S_OK;
+       }
+
+       /* IEnumVARIANT::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(long ppEnum) {
+               if (DEBUG) print(this + ".IEnumVARIANT::Clone");
+               /* If there are no listeners, query the proxy for
+                * its IEnumVariant, and get the Clone from it.
+                */
+               if (iaccessible != null && accessibleControlListenersSize() == 0) {
+                       long[] ppvObject = new long[1];
+                       int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
+                       if (code != COM.S_OK) return code;
+                       IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
+                       long [] pEnum = new long [1];
+                       code = ienumvariant.Clone(pEnum);
+                       ienumvariant.Release();
+                       OS.MoveMemory(ppEnum, pEnum, C.PTR_SIZEOF);
+                       return code;
+               }
+
+               if (ppEnum == 0) return COM.E_INVALIDARG;
+               OS.MoveMemory(ppEnum, new long[] { objIEnumVARIANT.getAddress() }, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_nRelations([out] pNRelations) */
+       int get_nRelations(long pNRelations) {
+               int count = getRelationCount();
+               if (DEBUG) print(this + ".IAccessible2::get_nRelations returning " + count + hresult(COM.S_OK));
+               OS.MoveMemory(pNRelations, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_relation([in] relationIndex, [out] ppRelation) */
+       int get_relation(int relationIndex, long ppRelation) {
+               int i = -1;
+               for (int type = 0; type < MAX_RELATION_TYPES; type++) {
+                       Relation relation = relations[type];
+                       if (relation != null) i++;
+                       if (i == relationIndex) {
+                               if (DEBUG) print(this + ".IAccessible2::get_relation(" + relationIndex + ") returning " + relation.getAddress() + hresult(COM.S_OK));
+                               relation.AddRef();
+                               OS.MoveMemory(ppRelation, new long[] { relation.getAddress() }, C.PTR_SIZEOF);
+                               return COM.S_OK;
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessible2::get_relation(" + relationIndex + ") returning" + hresult(COM.E_INVALIDARG));
+               return COM.E_INVALIDARG;
+       }
+
+       /* IAccessible2::get_relations([in] maxRelations, [out] ppRelations, [out] pNRelations) */
+       int get_relations(int maxRelations, long ppRelations, long pNRelations) {
+               int count = 0;
+               for (int type = 0; type < MAX_RELATION_TYPES; type++) {
+                       if (count == maxRelations) break;
+                       Relation relation = relations[type];
+                       if (relation != null) {
+                               relation.AddRef();
+                               OS.MoveMemory(ppRelations + count * C.PTR_SIZEOF, new long[] { relation.getAddress() }, C.PTR_SIZEOF);
+                               count++;
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessible2::get_relations(" + maxRelations + ") returning " + count + hresult(COM.S_OK));
+               OS.MoveMemory(pNRelations, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_role([out] pRole) */
+       int get_role(long pRole) {
+               int role = getRole();
+               if (role == 0) role = getDefaultRole();
+               if (DEBUG) print(this + ".IAccessible2::get_role() returning " + getRoleString(role) + hresult(COM.S_OK));
+               OS.MoveMemory(pRole, new int [] { role }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::scrollTo([in] scrollType) */
+       int scrollTo(int scrollType) {
+               if (DEBUG) print(this + ".IAccessible2::scrollTo");
+               if (scrollType < ACC.SCROLL_TYPE_LEFT_EDGE || scrollType > ACC.SCROLL_TYPE_ANYWHERE) return COM.E_INVALIDARG;
+               return COM.E_NOTIMPL;
+       }
+
+       /* IAccessible2::scrollToPoint([in] coordinateType, [in] x, [in] y) */
+       int scrollToPoint(int coordinateType, int x, int y) {
+               if (DEBUG) print(this + ".IAccessible2::scrollToPoint");
+               if (coordinateType != COM.IA2_COORDTYPE_SCREEN_RELATIVE) return COM.E_INVALIDARG;
+               return COM.E_NOTIMPL;
+       }
+
+       /* IAccessible2::get_groupPosition([out] pGroupLevel, [out] pSimilarItemsInGroup, [out] pPositionInGroup) */
+       int get_groupPosition(long pGroupLevel, long pSimilarItemsInGroup, long pPositionInGroup) {
+               if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
+               AccessibleAttributeEvent event = new AccessibleAttributeEvent(this);
+               event.groupLevel = event.groupCount = event.groupIndex = -1;
+               for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
+                       AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
+                       listener.getAttributes(event);
+               }
+               int groupLevel = (event.groupLevel != -1) ? event.groupLevel : 0;
+               int similarItemsInGroup = (event.groupCount != -1) ? event.groupCount : 0;
+               int positionInGroup = (event.groupIndex != -1) ? event.groupIndex : 0;
+               if (similarItemsInGroup == 0 && positionInGroup == 0) {
+                       /* Determine position and count for radio buttons. */
+                       if (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) {
+                               Control [] children = control.getParent().getChildren();
+                               positionInGroup = 1;
+                               similarItemsInGroup = 1;
+                               for (int i = 0; i < children.length; i++) {
+                                       Control child = children[i];
+                                       if (child instanceof Button && ((child.getStyle() & SWT.RADIO) != 0)) {
+                                               if (child == control) positionInGroup = similarItemsInGroup;
+                                               else similarItemsInGroup++;
+                                       }
+                               }
+                       }
+               }
+               OS.MoveMemory(pGroupLevel, new int [] { groupLevel }, 4);
+               OS.MoveMemory(pSimilarItemsInGroup, new int [] { similarItemsInGroup }, 4);
+               OS.MoveMemory(pPositionInGroup, new int [] { positionInGroup }, 4);
+               if (DEBUG) print(this + ".IAccessible2::get_groupPosition() returning level=" + groupLevel + ", count=" + similarItemsInGroup + ", index=" + positionInGroup + hresult(groupLevel == 0 && similarItemsInGroup == 0 && positionInGroup == 0 ? COM.S_FALSE : COM.S_OK));
+               if (groupLevel == 0 && similarItemsInGroup == 0 && positionInGroup == 0) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_states([out] pStates) */
+       int get_states(long pStates) {
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = ACC.CHILDID_SELF;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getState(event);
+               }
+               int states = event.detail;
+               int ia2States = 0;
+               if ((states & ACC.STATE_ACTIVE) != 0) ia2States |= COM.IA2_STATE_ACTIVE;
+               if ((states & ACC.STATE_SINGLELINE) != 0) ia2States |= COM.IA2_STATE_SINGLE_LINE;
+               if ((states & ACC.STATE_MULTILINE) != 0) ia2States |= COM.IA2_STATE_MULTI_LINE;
+               if ((states & ACC.STATE_REQUIRED) != 0) ia2States |= COM.IA2_STATE_REQUIRED;
+               if ((states & ACC.STATE_INVALID_ENTRY) != 0) ia2States |= COM.IA2_STATE_INVALID_ENTRY;
+               if ((states & ACC.STATE_SUPPORTS_AUTOCOMPLETION) != 0) ia2States |= COM.IA2_STATE_SUPPORTS_AUTOCOMPLETION;
+
+               /* If the role is text and there are TextExtendedListeners, then set IA2_STATE_EDITABLE.
+                * Note that IA2_STATE_EDITABLE is not the opposite of STATE_READONLY.
+                * Instead, it means: "has a caret, supports IAccessibleText, and is a text editing environment".
+                */
+               if (getRole() == ACC.ROLE_TEXT && accessibleTextExtendedListenersSize() > 0) {
+                       ia2States |= COM.IA2_STATE_EDITABLE;
+               }
+               if (DEBUG) print(this + ".IAccessible2::get_states returning" + getIA2StatesString(ia2States) + hresult(COM.S_OK));
+               OS.MoveMemory(pStates, new int [] { ia2States }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_extendedRole([out] pbstrExtendedRole) */
+       int get_extendedRole(long pbstrExtendedRole) {
+               /* This feature is not supported. */
+               setString(pbstrExtendedRole, null);
+               return COM.S_FALSE;
+       }
+
+       /* IAccessible2::get_localizedExtendedRole([out] pbstrLocalizedExtendedRole) */
+       int get_localizedExtendedRole(long pbstrLocalizedExtendedRole) {
+               /* This feature is not supported. */
+               setString(pbstrLocalizedExtendedRole, null);
+               return COM.S_FALSE;
+       }
+
+       /* IAccessible2::get_nExtendedStates([out] pNExtendedStates) */
+       int get_nExtendedStates(long pNExtendedStates) {
+               /* This feature is not supported. */
+               OS.MoveMemory(pNExtendedStates, new int [] { 0 }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_extendedStates([in] maxExtendedStates, [out] ppbstrExtendedStates, [out] pNExtendedStates) */
+       int get_extendedStates(int maxExtendedStates, long ppbstrExtendedStates, long pNExtendedStates) {
+               /* This feature is not supported. */
+               setString(ppbstrExtendedStates, null);
+               OS.MoveMemory(pNExtendedStates, new int [] { 0 }, 4);
+               return COM.S_FALSE;
+       }
+
+       /* IAccessible2::get_localizedExtendedStates([in] maxLocalizedExtendedStates, [out] ppbstrLocalizedExtendedStates, [out] pNLocalizedExtendedStates) */
+       int get_localizedExtendedStates(int maxLocalizedExtendedStates, long ppbstrLocalizedExtendedStates, long pNLocalizedExtendedStates) {
+               /* This feature is not supported. */
+               setString(ppbstrLocalizedExtendedStates, null);
+               OS.MoveMemory(pNLocalizedExtendedStates, new int [] { 0 }, 4);
+               return COM.S_FALSE;
+       }
+
+       /* IAccessible2::get_uniqueID([out] pUniqueID) */
+       int get_uniqueID(long pUniqueID) {
+               if (uniqueID == -1) uniqueID = UniqueID--;
+               if (DEBUG) print(this + ".IAccessible2::get_uniqueID returning " + uniqueID + hresult(COM.S_OK));
+               OS.MoveMemory(pUniqueID, new long [] { uniqueID }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_windowHandle([out] pWindowHandle) */
+       int get_windowHandle(long pWindowHandle) {
+               if (DEBUG) print(this + ".IAccessible2::get_windowHandle returning " + control.handle + hresult(COM.S_OK));
+               OS.MoveMemory(pWindowHandle, new long [] { control.handle }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_indexInParent([out] pIndexInParent) */
+       int get_indexInParent(long pIndexInParent) {
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = ACC.CHILDID_CHILD_INDEX;
+               event.detail = -1;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getChild(event);
+               }
+               int indexInParent = event.detail;
+               if (indexInParent == -1) {
+//                     /* The application did not implement CHILDID_CHILD_INDEX,
+//                      * so determine the index by looping through the parent's
+//                      * children looking for this Accessible. This may be slow,
+//                      * so applications are strongly encouraged to implement
+//                      * getChild for CHILDID_CHILD_INDEX.
+//                      */
+//                     // TODO: finish this. See also get_groupPosition
+                       // this won't work because VARIANT.sizeof isn't big enough on 64-bit machines.
+                       // just create an  long [] ppdispParent - it's not a variant anyhow...
+//                     long ppdispParent = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+//                     int code = get_accParent(ppdispParent);
+//                     if (code == COM.S_OK) {
+//                             VARIANT v = getVARIANT(ppdispParent);
+//                             if (v.vt == COM.VT_DISPATCH) {
+//                                     IAccessible accParent = new IAccessible(v.lVal);
+//                                     long pcountChildren = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, 4);
+//                                     code = accParent.get_accChildCount(pcountChildren);
+//                                     if (code == COM.S_OK) {
+//                                             int [] childCount = new int[1];
+//                                             OS.MoveMemory(childCount, pcountChildren, 4);
+//                                             int[] pcObtained = new int[1];
+//                                             long rgVarChildren = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof * childCount[0]);
+//                                             System.out.println("Asking for AccessibleChildren");
+//                                             code = COM.AccessibleChildren(accParent.getAddress(), 0, childCount[0], rgVarChildren, pcObtained);
+//                                             if (code == COM.S_OK) {
+//                                                     System.out.println("Got this far - now what?");
+//                                             } else {
+//                                                     System.out.println("AccessibleChildren failed? code=" + code);
+//                                             }
+//                                             OS.GlobalFree(rgVarChildren);
+//                                     } else {
+//                                             System.out.println("get_accChildCount failed? code=" + code);
+//                                     }
+//                                     OS.GlobalFree (pcountChildren);
+//                             } else {
+//                                     System.out.println("get_accParent did not return VT_DISPATCH? It returned: " + v.vt);
+//                             }
+//                             COM.VariantClear(ppdispParent);
+//                             OS.GlobalFree (ppdispParent);
+//                     } else {
+//                             System.out.println("get_accParent failed? code=" + code);
+//                     }
+               }
+
+               if (DEBUG) print(this + ".IAccessible2::get_indexInParent returning " + indexInParent + hresult(indexInParent == -1 ? COM.S_FALSE : COM.S_OK));
+               OS.MoveMemory(pIndexInParent, new int [] { indexInParent }, 4);
+               return indexInParent == -1 ? COM.S_FALSE : COM.S_OK;
+       }
+
+       /* IAccessible2::get_locale([out] pLocale) */
+       int get_locale(long pLocale) {
+               /* Return the default locale for the JVM. */
+               Locale locale = Locale.getDefault();
+
+               char[] data = (locale.getLanguage()+"\0").toCharArray();
+               long ptr = COM.SysAllocString(data);
+               OS.MoveMemory(pLocale, new long[] {ptr}, C.PTR_SIZEOF);
+
+               data = (locale.getCountry()+"\0").toCharArray();
+               ptr = COM.SysAllocString(data);
+               OS.MoveMemory(pLocale + C.PTR_SIZEOF, new long[] {ptr}, C.PTR_SIZEOF);
+
+               data = (locale.getVariant()+"\0").toCharArray();
+               ptr = COM.SysAllocString(data);
+               OS.MoveMemory(pLocale + 2 * C.PTR_SIZEOF, new long[] {ptr}, C.PTR_SIZEOF);
+
+               if (DEBUG) print(this + ".IAccessible2::get_locale() returning" + hresult(COM.S_OK));
+               return COM.S_OK;
+       }
+
+       /* IAccessible2::get_attributes([out] pbstrAttributes) */
+       int get_attributes(long pbstrAttributes) {
+               AccessibleAttributeEvent event = new AccessibleAttributeEvent(this);
+               for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
+                       AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
+                       listener.getAttributes(event);
+               }
+               String attributes = "";
+               attributes += "margin-left:" + event.leftMargin + ";";
+               attributes += "margin-top:" + event.topMargin + ";";
+               attributes += "margin-right:" + event.rightMargin + ";";
+               attributes += "margin-bottom:" + event.bottomMargin + ";";
+               if (event.tabStops != null) {
+                       for (int i = 0; i < event.tabStops.length; i++) {
+                               attributes += "tab-stop:position=" + event.tabStops[i] + ";";
+                       }
+               }
+               if (event.justify) attributes += "text-align:justify;";
+               attributes += "text-align:" + (event.alignment == SWT.LEFT ? "left" : event.alignment == SWT.RIGHT ? "right" : "center") + ";";
+               attributes += "text-indent:" + event.indent + ";";
+               if (event.attributes != null) {
+                       for (int i = 0; i + 1 < event.attributes.length; i += 2) {
+                               attributes += event.attributes[i] + ":" + event.attributes[i+1] + ";";
+                       }
+               }
+
+               /* If the role is text, then specify the text model for JAWS. */
+               if (getRole() == ACC.ROLE_TEXT) {
+                       attributes += "text-model:a1;";
+               }
+               if (DEBUG) print(this + ".IAccessible2::get_attributes() returning " + attributes + hresult(attributes.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               setString(pbstrAttributes, attributes);
+               if (attributes.length() == 0) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleAction::get_nActions([out] pNActions) */
+       int get_nActions(long pNActions) {
+               AccessibleActionEvent event = new AccessibleActionEvent(this);
+               for (int i = 0; i < accessibleActionListenersSize(); i++) {
+                       AccessibleActionListener listener = accessibleActionListeners.get(i);
+                       listener.getActionCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleAction::get_nActions() returning " + event.count + hresult(COM.S_OK));
+               OS.MoveMemory(pNActions, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleAction::doAction([in] actionIndex) */
+       int doAction(int actionIndex) {
+               AccessibleActionEvent event = new AccessibleActionEvent(this);
+               event.index = actionIndex;
+               for (int i = 0; i < accessibleActionListenersSize(); i++) {
+                       AccessibleActionListener listener = accessibleActionListeners.get(i);
+                       listener.doAction(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleAction::doAction(" + actionIndex + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleAction::get_description([in] actionIndex, [out] pbstrDescription) */
+       int get_description(int actionIndex, long pbstrDescription) {
+               AccessibleActionEvent event = new AccessibleActionEvent(this);
+               event.index = actionIndex;
+               for (int i = 0; i < accessibleActionListenersSize(); i++) {
+                       AccessibleActionListener listener = accessibleActionListeners.get(i);
+                       listener.getDescription(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleAction::get_description(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               setString(pbstrDescription, event.result);
+               if (event.result == null || event.result.length() == 0) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleAction::get_keyBinding([in] actionIndex, [in] nMaxBindings, [out] ppbstrKeyBindings, [out] pNBindings) */
+       int get_keyBinding(int actionIndex, int nMaxBindings, long ppbstrKeyBindings, long pNBindings) {
+               AccessibleActionEvent event = new AccessibleActionEvent(this);
+               event.index = actionIndex;
+               for (int i = 0; i < accessibleActionListenersSize(); i++) {
+                       AccessibleActionListener listener = accessibleActionListeners.get(i);
+                       listener.getKeyBinding(event);
+               }
+               String keyBindings = event.result;
+               int length = 0;
+               if (keyBindings != null) length = keyBindings.length();
+               int i = 0, count = 0;
+               while (i < length) {
+                       if (count == nMaxBindings) break;
+                       int j = keyBindings.indexOf(';', i);
+                       if (j == -1) j = length;
+                       String keyBinding = keyBindings.substring(i, j);
+                       if (keyBinding.length() > 0) {
+                               setString(ppbstrKeyBindings + count * C.PTR_SIZEOF, keyBinding);
+                               count++;
+                       }
+                       i = j + 1;
+               }
+               if (DEBUG) print(this + ".IAccessibleAction::get_keyBinding(index=" + actionIndex + " max=" + nMaxBindings + ") returning count=" + count + hresult(count == 0 ? COM.S_FALSE : COM.S_OK));
+               OS.MoveMemory(pNBindings, new int [] { count }, 4);
+               if (count == 0) {
+                       setString(ppbstrKeyBindings, null);
+                       return COM.S_FALSE;
+               }
+               return COM.S_OK;
+       }
+
+       /* IAccessibleAction::get_name([in] actionIndex, [out] pbstrName) */
+       int get_name(int actionIndex, long pbstrName) {
+               AccessibleActionEvent event = new AccessibleActionEvent(this);
+               event.index = actionIndex;
+               event.localized = false;
+               for (int i = 0; i < accessibleActionListenersSize(); i++) {
+                       AccessibleActionListener listener = accessibleActionListeners.get(i);
+                       listener.getName(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleAction::get_name(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               if (event.result == null || event.result.length() == 0) {
+                       setString(pbstrName, null);
+                       return COM.S_FALSE;
+               }
+               setString(pbstrName, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleAction::get_localizedName([in] actionIndex, [out] pbstrLocalizedName) */
+       int get_localizedName(int actionIndex, long pbstrLocalizedName) {
+               AccessibleActionEvent event = new AccessibleActionEvent(this);
+               event.index = actionIndex;
+               event.localized = true;
+               for (int i = 0; i < accessibleActionListenersSize(); i++) {
+                       AccessibleActionListener listener = accessibleActionListeners.get(i);
+                       listener.getName(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleAction::get_localizedName(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               if (event.result == null || event.result.length() == 0) {
+                       setString(pbstrLocalizedName, null);
+                       return COM.S_FALSE;
+               }
+               setString(pbstrLocalizedName, event.result);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleApplication::get_appName([out] pbstrName) */
+       int get_appName(long pbstrName) {
+               String appName = Display.getAppName();
+               if (DEBUG) print(this + ".IAccessibleApplication::get_appName() returning " + appName + hresult(appName == null || appName.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               if (appName == null || appName.length() == 0) {
+                       setString(pbstrName, null);
+                       return COM.S_FALSE;
+               }
+               setString(pbstrName, appName);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleApplication::get_appVersion([out] pbstrVersion) */
+       int get_appVersion(long pbstrVersion) {
+               String appVersion = Display.getAppVersion();
+               if (DEBUG) print(this + ".IAccessibleApplication::get_appVersion() returning" + appVersion + hresult(appVersion == null || appVersion.length() == 0 ? COM.S_FALSE : COM.S_OK));
+               if (appVersion == null || appVersion.length() == 0) {
+                       setString(pbstrVersion, null);
+                       return COM.S_FALSE;
+               }
+               setString(pbstrVersion, appVersion);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleApplication::get_toolkitName([out] pbstrName) */
+       int get_toolkitName(long pbstrName) {
+               String toolkitName = "SWT";
+               if (DEBUG) print(this + ".IAccessibleApplication::get_toolkitName() returning" + toolkitName + hresult(COM.S_OK));
+               setString(pbstrName, toolkitName);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleApplication::get_toolkitVersion([out] pbstrVersion) */
+       int get_toolkitVersion(long pbstrVersion) {
+               String toolkitVersion = "" + SWT.getVersion(); //$NON-NLS-1$
+               if (DEBUG) print(this + ".IAccessibleApplication::get_toolkitVersion() returning" + toolkitVersion + hresult(COM.S_OK));
+               setString(pbstrVersion, toolkitVersion);
+               return COM.S_OK;
+       }
+
+       // The following 3 method are intentionally commented. We are not providing IAccessibleComponent at this time.
+//     /* IAccessibleComponent::get_locationInParent([out] pX, [out] pY) */
+//     int get_locationInParent(long pX, long pY) {
+//             if (DEBUG) print(this + ".IAccessibleComponent::get_locationInParent");
+//             // TO DO: support transparently (hard for lightweight parents - screen vs. parent coords)
+//             AccessibleControlEvent event = new AccessibleControlEvent(this);
+//             for (int i = 0; i < accessibleControlListenersSize(); i++) {
+//                     AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i);
+//                     listener.getLocation (event);
+//             }
+//             COM.MoveMemory(pX, new int [] { event.x }, 4);
+//             COM.MoveMemory(pY, new int [] { event.y }, 4);
+//             return COM.S_OK;
+//     }
+//
+//     /* IAccessibleComponent::get_foreground([out] pForeground) */
+//     int get_foreground(long pForeground) {
+//             Color color = control.getForeground();
+//             if (DEBUG) print(this + ".IAccessibleComponent::get_foreground returning " + color.handle);
+//             COM.MoveMemory(pForeground, new int [] { color.handle }, 4);
+//             return COM.S_OK;
+//     }
+//
+//     /* IAccessibleComponent::get_background([out] pBackground) */
+//     int get_background(long pBackground) {
+//             Color color = control.getBackground();
+//             if (DEBUG) print(this + ".IAccessibleComponent::get_background returning " + color.handle);
+//             COM.MoveMemory(pBackground, new int [] { color.handle }, 4);
+//             return COM.S_OK;
+//     }
+
+       /* IAccessibleEditableText::copyText([in] startOffset, [in] endOffset) */
+       int copyText(int startOffset, int endOffset) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::copyText, start=" + startOffset + ", end=" + endOffset);
+               AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                       listener.copyText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleEditableText::deleteText([in] startOffset, [in] endOffset) */
+       int deleteText(int startOffset, int endOffset) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::deleteText, start=" + startOffset + ", end=" + endOffset);
+               AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               event.string = "";
+               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                       listener.replaceText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleEditableText::insertText([in] offset, [in] pbstrText) */
+       int insertText(int offset, long pbstrText) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::insertText, offset=" + offset + ", pbstrText=" + pbstrText);
+               AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+               event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
+               event.end = event.start;
+               event.string = getString(pbstrText);
+               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                       listener.replaceText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleEditableText::cutText([in] startOffset, [in] endOffset) */
+       int cutText(int startOffset, int endOffset) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::cutText, start=" + startOffset + ", end=" + endOffset);
+               AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                       listener.cutText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleEditableText::pasteText([in] offset) */
+       int pasteText(int offset) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::pasteText, offset=" + offset);
+               AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+               event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
+               event.end = event.start;
+               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                       listener.pasteText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleEditableText::replaceText([in] startOffset, [in] endOffset, [in] pbstrText) */
+       int replaceText(int startOffset, int endOffset, long pbstrText) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::replaceText, start=" + startOffset + ", end=" + endOffset + ", pbstrText=" + pbstrText);
+               AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               event.string = getString(pbstrText);
+               for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                       AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                       listener.replaceText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleEditableText::setAttributes([in] startOffset, [in] endOffset, [in] pbstrAttributes) */
+       int setAttributes(int startOffset, int endOffset, long pbstrAttributes) {
+               if (DEBUG) print(this + ".IAccessibleEditableText::setAttributes, start=" + startOffset + ", end=" + endOffset + ", pbstrAttributes=" + pbstrAttributes);
+               AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this);
+               String string = getString(pbstrAttributes);
+               if (string != null && string.length() > 0) {
+                       event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+                       event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+                       TextStyle style = new TextStyle();
+                       FontData fontData = null;
+                       int points = 10; // used for default rise
+                       String [] attributes = new String [0];
+                       int begin = 0;
+                       int end = string.indexOf(';');
+                       while (end != -1 && end < string.length()) {
+                               String keyValue = string.substring(begin, end).trim();
+                               int colonIndex = keyValue.indexOf(':');
+                               if (colonIndex != -1 && colonIndex + 1 < keyValue.length()) {
+                                       String [] newAttributes = new String [attributes.length + 2];
+                                       System.arraycopy (attributes, 0, newAttributes, 0, attributes.length);
+                                       newAttributes[attributes.length] = keyValue.substring(0, colonIndex).trim();
+                                       newAttributes[attributes.length + 1] = keyValue.substring(colonIndex + 1).trim();
+                                       attributes = newAttributes;
+                               }
+                               begin = end + 1;
+                               end = string.indexOf(';', begin);
+                       }
+                       for (int i = 0; i+1 < attributes.length; i+=2) {
+                               String key = attributes[i];
+                               String value = attributes[i+1];
+                               if (key.equals("text-position")) {
+                                       if (value.equals("super")) style.rise = points / 2;
+                                       else if (value.equals("sub")) style.rise = - points / 2;
+                               } else if (key.equals("text-underline-type")) {
+                                       style.underline = true;
+                                       if (value.equals("double")) style.underlineStyle = SWT.UNDERLINE_DOUBLE;
+                                       else if (value.equals("single")) {
+                                               if (style.underlineStyle != SWT.UNDERLINE_SQUIGGLE && style.underlineStyle != SWT.UNDERLINE_ERROR) {
+                                                       style.underlineStyle = SWT.UNDERLINE_SINGLE;
+                                               }
+                                       }
+                               } else if (key.equals("text-underline-style") && value.equals("wave")) {
+                                       style.underline = true;
+                                       style.underlineStyle = SWT.UNDERLINE_SQUIGGLE;
+                               } else if (key.equals("invalid") && value.equals("true")) {
+                                       style.underline = true;
+                                       style.underlineStyle = SWT.UNDERLINE_ERROR;
+                               } else if (key.equals("text-line-through-type")) {
+                                       if (value.equals("single")) style.strikeout = true;
+                               } else if (key.equals("font-family")) {
+                                       if (fontData == null) fontData = new FontData ();
+                                       fontData.setName(value);
+                               } else if (key.equals("font-size")) {
+                                       try {
+                                               String pts = value.endsWith("pt") ? value.substring(0, value.length() - 2) : value;
+                                               points = Integer.parseInt(pts);
+                                               if (fontData == null) fontData = new FontData ();
+                                               fontData.setHeight(points);
+                                               if (style.rise > 0) style.rise = points / 2;
+                                               else if (style.rise < 0) style.rise = - points / 2;
+                                       } catch (NumberFormatException ex) {}
+                               } else if (key.equals("font-style")) {
+                                       if (value.equals("italic")) {
+                                               if (fontData == null) fontData = new FontData ();
+                                               fontData.setStyle(fontData.getStyle() | SWT.ITALIC);
+                                       }
+                               } else if (key.equals("font-weight")) {
+                                       if (value.equals("bold")) {
+                                               if (fontData == null) fontData = new FontData ();
+                                               fontData.setStyle(fontData.getStyle() | SWT.BOLD);
+                                       } else {
+                                               try {
+                                                       int weight = Integer.parseInt(value);
+                                                       if (fontData == null) fontData = new FontData ();
+                                                       if (weight > 400) fontData.setStyle(fontData.getStyle() | SWT.BOLD);
+                                               } catch (NumberFormatException ex) {}
+                                       }
+                               } else if (key.equals("color")) {
+                                       style.foreground = colorFromString(value);
+                               } else if (key.equals("background-color")) {
+                                       style.background = colorFromString(value);
+                               }
+                       }
+                       if (attributes.length > 0) {
+                               event.attributes = attributes;
+                               if (fontData != null) {
+                                       style.font = new Font(control.getDisplay(), fontData);
+                               }
+                               if (!style.equals(new TextStyle())) event.textStyle = style;
+                       }
+                       for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
+                               AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
+                               listener.setTextAttributes(event);
+                       }
+                       if (style.font != null) {
+                               style.font.dispose();
+                       }
+                       if (style.foreground != null) {
+                               style.foreground.dispose();
+                       }
+                       if (style.background != null) {
+                               style.background.dispose();
+                       }
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHyperlink::get_anchor([in] index, [out] pAnchor) */
+       int get_anchor(int index, long pAnchor) {
+               if (DEBUG) print(this + ".IAccessibleHyperlink::get_anchor");
+               AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
+               event.index = index;
+               for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
+                       AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
+                       listener.getAnchor(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible != null) {
+                       accessible.AddRef();
+                       setPtrVARIANT(pAnchor, COM.VT_DISPATCH, accessible.getAddress());
+                       return COM.S_OK;
+               }
+               setStringVARIANT(pAnchor, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHyperlink::get_anchorTarget([in] index, [out] pAnchorTarget) */
+       int get_anchorTarget(int index, long pAnchorTarget) {
+               if (DEBUG) print(this + ".IAccessibleHyperlink::get_anchorTarget");
+               AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
+               event.index = index;
+               for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
+                       AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
+                       listener.getAnchorTarget(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible != null) {
+                       accessible.AddRef();
+                       setPtrVARIANT(pAnchorTarget, COM.VT_DISPATCH, accessible.getAddress());
+                       return COM.S_OK;
+               }
+               setStringVARIANT(pAnchorTarget, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHyperlink::get_startIndex([out] pIndex) */
+       int get_startIndex(long pIndex) {
+               if (DEBUG) print(this + ".IAccessibleHyperlink::get_startIndex");
+               AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
+               for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
+                       AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
+                       listener.getStartIndex(event);
+               }
+               OS.MoveMemory(pIndex, new int [] { event.index }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHyperlink::get_endIndex([out] pIndex) */
+       int get_endIndex(long pIndex) {
+               if (DEBUG) print(this + ".IAccessibleHyperlink::get_endIndex");
+               AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
+               for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
+                       AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
+                       listener.getEndIndex(event);
+               }
+               OS.MoveMemory(pIndex, new int [] { event.index }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHyperlink::get_valid([out] pValid) */
+       int get_valid(long pValid) {
+               /* Deprecated. */
+               return COM.E_NOTIMPL;
+       }
+
+       /* IAccessibleHypertext::get_nHyperlinks([out] pHyperlinkCount) */
+       int get_nHyperlinks(long pHyperlinkCount) {
+               if (DEBUG) print(this + ".IAccessibleHypertext::get_nHyperlinks");
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getHyperlinkCount(event);
+               }
+               OS.MoveMemory(pHyperlinkCount, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHypertext::get_hyperlink([in] index, [out] ppHyperlink) */
+       int get_hyperlink(int index, long ppHyperlink) {
+               if (DEBUG) print(this + ".IAccessibleHypertext::get_hyperlink");
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.index = index;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getHyperlink(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible == null) {
+                       setIntVARIANT(ppHyperlink, COM.VT_EMPTY, 0);
+                       return COM.E_INVALIDARG;
+               }
+               accessible.AddRef();
+               OS.MoveMemory(ppHyperlink, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleHypertext::get_hyperlinkIndex([in] charIndex, [out] pHyperlinkIndex) */
+       int get_hyperlinkIndex(int charIndex, long pHyperlinkIndex) {
+               if (DEBUG) print(this + ".IAccessibleHypertext::get_hyperlinkIndex");
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.offset = charIndex;
+               event.index = -1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getHyperlinkIndex(event);
+               }
+               OS.MoveMemory(pHyperlinkIndex, new int [] { event.index }, 4);
+               if (event.index == -1) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       // The following 3 method are intentionally commented. We are not providing IAccessibleImage at this time.
+//     /* IAccessibleImage::get_description([out] pbstrDescription) */
+//     int get_description(long pbstrDescription) {
+//             if (DEBUG) print(this + ".IAccessibleImage::get_description");
+//             // TO DO: Does it make sense to just reuse description?
+//             AccessibleEvent event = new AccessibleEvent(this);
+//             event.childID = ACC.CHILDID_SELF;
+//             for (int i = 0; i < accessibleListenersSize(); i++) {
+//                     AccessibleListener listener = (AccessibleListener) accessibleListeners.get(i);
+//                     listener.getDescription(event);
+//             }
+//             setString(pbstrDescription, event.result);
+//             if (event.result == null) return COM.S_FALSE;
+//             return COM.S_OK;
+//     }
+//
+//     /* IAccessibleImage::get_imagePosition([in] coordinateType, [out] pX, [out] pY) */
+//     int get_imagePosition(int coordinateType, long pX, long pY) {
+//             if (DEBUG) print(this + ".IAccessibleImage::get_imagePosition");
+//             // TO DO: does it make sense to just reuse getLocation?
+//             AccessibleControlEvent event = new AccessibleControlEvent(this);
+//             event.childID = ACC.CHILDID_SELF;
+//             for (int i = 0; i < accessibleControlListenersSize(); i++) {
+//                     AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i);
+//                     listener.getLocation(event);
+//             }
+//             COM.MoveMemory(pX, new int [] { event.x }, 4);
+//             COM.MoveMemory(pY, new int [] { event.y }, 4);
+//             return COM.S_OK;
+//     }
+//
+//     /* IAccessibleImage::get_imageSize([out] pHeight, [out] pWidth) */
+//     int get_imageSize(long pHeight, long pWidth) {
+//             if (DEBUG) print(this + ".IAccessibleImage::get_imageSize");
+//             // TO DO: does it make sense to just reuse getLocation?
+//             AccessibleControlEvent event = new AccessibleControlEvent(this);
+//             for (int i = 0; i < accessibleControlListenersSize(); i++) {
+//                     AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i);
+//                     listener.getLocation(event);
+//             }
+//             COM.MoveMemory(pHeight, new int [] { event.height }, 4);
+//             COM.MoveMemory(pWidth, new int [] { event.width }, 4);
+//             return COM.S_OK;
+//     }
+
+       /* IAccessibleTable2::get_cellAt([in] row, [in] column, [out] ppCell) */
+       int get_cellAt(int row, int column, long ppCell) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.row = row;
+               event.column = column;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getCell(event);
+               }
+               Accessible accessible = event.accessible;
+               if (DEBUG) print(this + ".IAccessibleTable2::get_cellAt(row=" + row + ", column=" + column + ") returning " + accessible);
+               if (accessible == null) return COM.E_INVALIDARG;
+               accessible.AddRef();
+               OS.MoveMemory(ppCell, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_caption([out] ppAccessible) */
+       int get_caption(long ppAccessible) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getCaption(event);
+               }
+               Accessible accessible = event.accessible;
+               if (DEBUG) print(this + ".IAccessibleTable2::get_caption() returning " + accessible);
+               if (accessible == null) {
+                       OS.MoveMemory(ppAccessible, new long[] { 0 }, C.PTR_SIZEOF);
+                       return COM.S_FALSE;
+               }
+               accessible.AddRef();
+               OS.MoveMemory(ppAccessible, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_columnDescription([in] column, [out] pbstrDescription) */
+       int get_columnDescription(int column, long pbstrDescription) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.column = column;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getColumnDescription(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_columnDescription(column=" + column + ") returning " + event.result);
+               setString(pbstrDescription, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_nColumns([out] pColumnCount) */
+       int get_nColumns(long pColumnCount) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getColumnCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_nColumns() returning " + event.count);
+               OS.MoveMemory(pColumnCount, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_nRows([out] pRowCount) */
+       int get_nRows(long pRowCount) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getRowCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_nRows() returning " + event.count);
+               OS.MoveMemory(pRowCount, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_nSelectedCells([out] pCellCount) */
+       int get_nSelectedCells(long pCellCount) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSelectedCellCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedCells() returning " + event.count);
+               OS.MoveMemory(pCellCount, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_nSelectedColumns([out] pColumnCount) */
+       int get_nSelectedColumns(long pColumnCount) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSelectedColumnCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedColumns() returning " + event.count);
+               OS.MoveMemory(pColumnCount, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_nSelectedRows([out] pRowCount) */
+       int get_nSelectedRows(long pRowCount) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSelectedRowCount(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedRows() returning " + event.count);
+               OS.MoveMemory(pRowCount, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_rowDescription([in] row, [out] pbstrDescription) */
+       int get_rowDescription(int row, long pbstrDescription) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.row = row;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getRowDescription(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_rowDescription(row=" + row + ") returning " + event.result);
+               setString(pbstrDescription, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_selectedCells([out] ppCells, [out] pNSelectedCells) */
+       int get_selectedCells(long ppCells, long pNSelectedCells) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSelectedCells(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_selectedCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]"));
+               if (event.accessibles == null || event.accessibles.length == 0) {
+                       OS.MoveMemory(ppCells, new long[] { 0 }, C.PTR_SIZEOF);
+                       OS.MoveMemory(pNSelectedCells, new int [] { 0 }, 4);
+                       return COM.S_FALSE;
+               }
+               int length = event.accessibles.length;
+               long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF);
+               int count = 0;
+               for (int i = 0; i < length; i++) {
+                       Accessible accessible = event.accessibles[i];
+                       if (accessible != null) {
+                               accessible.AddRef();
+                               OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+                               count++;
+                       }
+               }
+               OS.MoveMemory(ppCells, new long [] { pv }, C.PTR_SIZEOF);
+               OS.MoveMemory(pNSelectedCells, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_selectedColumns([out] ppSelectedColumns, [out] pNColumns) */
+       int get_selectedColumns(long ppSelectedColumns, long pNColumns) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSelectedColumns(event);
+               }
+               int count = event.selected == null ? 0 : event.selected.length;
+               if (DEBUG) print(this + ".IAccessibleTable2::get_selectedColumns() returning " + (count == 0 ? "null" : "selected[" + count + "]"));
+               if (count == 0) {
+                       OS.MoveMemory(ppSelectedColumns, new long[] { 0 }, C.PTR_SIZEOF);
+                       OS.MoveMemory(pNColumns, new int [] { 0 }, 4);
+                       return COM.S_FALSE;
+               }
+               long pv = OS.CoTaskMemAlloc(count * 4);
+               OS.MoveMemory(pv, event.selected, count * 4);
+               OS.MoveMemory(ppSelectedColumns, new long [] { pv }, C.PTR_SIZEOF);
+               OS.MoveMemory(pNColumns, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_selectedRows([out] ppSelectedRows, [out] pNRows) */
+       int get_selectedRows(long ppSelectedRows, long pNRows) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSelectedRows(event);
+               }
+               int count = event.selected == null ? 0 : event.selected.length;
+               if (DEBUG) print(this + ".IAccessibleTable2::get_selectedRows() returning " + (count == 0 ? "null" : "selected[" + count + "]"));
+               if (count == 0) {
+                       OS.MoveMemory(ppSelectedRows, new long[] { 0 }, C.PTR_SIZEOF);
+                       OS.MoveMemory(pNRows, new int [] { 0 }, 4);
+                       return COM.S_FALSE;
+               }
+               long pv = OS.CoTaskMemAlloc(count * 4);
+               OS.MoveMemory(pv, event.selected, count * 4);
+               OS.MoveMemory(ppSelectedRows, new long [] { pv }, C.PTR_SIZEOF);
+               OS.MoveMemory(pNRows, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_summary([out] ppAccessible) */
+       int get_summary(long ppAccessible) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.getSummary(event);
+               }
+               Accessible accessible = event.accessible;
+               if (DEBUG) print(this + ".IAccessibleTable2::get_summary() returning " + accessible);
+               if (accessible == null) {
+                       OS.MoveMemory(ppAccessible, new long[] { 0 }, C.PTR_SIZEOF);
+                       return COM.S_FALSE;
+               }
+               accessible.AddRef();
+               OS.MoveMemory(ppAccessible, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_isColumnSelected([in] column, [out] pIsSelected) */
+       int get_isColumnSelected(int column, long pIsSelected) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.column = column;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.isColumnSelected(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_isColumnSelected() returning " + event.isSelected);
+               OS.MoveMemory(pIsSelected, new int [] {event.isSelected ? 1 : 0}, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_isRowSelected([in] row, [out] pIsSelected) */
+       int get_isRowSelected(int row, long pIsSelected) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.row = row;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.isRowSelected(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::get_isRowSelected() returning " + event.isSelected);
+               OS.MoveMemory(pIsSelected, new int [] {event.isSelected ? 1 : 0}, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::selectRow([in] row) */
+       int selectRow(int row) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.row = row;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.setSelectedRow(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::selectRow() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::selectColumn([in] column) */
+       int selectColumn(int column) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.column = column;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.setSelectedColumn(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::selectColumn() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::unselectRow([in] row) */
+       int unselectRow(int row) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.row = row;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.deselectRow(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::unselectRow() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::unselectColumn([in] column) */
+       int unselectColumn(int column) {
+               AccessibleTableEvent event = new AccessibleTableEvent(this);
+               event.column = column;
+               for (int i = 0; i < accessibleTableListenersSize(); i++) {
+                       AccessibleTableListener listener = accessibleTableListeners.get(i);
+                       listener.deselectColumn(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTable2::unselectColumn() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTable2::get_modelChange([out] pModelChange) */
+       int get_modelChange(long pModelChange) {
+               if (DEBUG) print(this + ".IAccessibleTable2::get_modelChange() returning " + (tableChange == null ? "null" : "tableChange=" + tableChange[0] + ", " + tableChange[1] + ", " + tableChange[2] + ", " + tableChange[3]));
+               if (tableChange == null) {
+                       OS.MoveMemory(pModelChange, new long [] { 0 }, C.PTR_SIZEOF);
+                       return COM.S_FALSE;
+               }
+               OS.MoveMemory(pModelChange, tableChange, tableChange.length * 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_columnExtent([out] pNColumnsSpanned) */
+       int get_columnExtent(long pNColumnsSpanned) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getColumnSpan(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_columnExtent() returning " + event.count);
+               OS.MoveMemory(pNColumnsSpanned, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_columnHeaderCells([out] ppCellAccessibles, [out] pNColumnHeaderCells) */
+       int get_columnHeaderCells(long ppCellAccessibles, long pNColumnHeaderCells) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getColumnHeaders(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_columnHeaderCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]"));
+               if (event.accessibles == null || event.accessibles.length == 0) {
+                       OS.MoveMemory(ppCellAccessibles, new long[] { 0 }, C.PTR_SIZEOF);
+                       OS.MoveMemory(pNColumnHeaderCells, new int [] { 0 }, 4);
+                       return COM.S_FALSE;
+               }
+               int length = event.accessibles.length;
+               long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF);
+               int count = 0;
+               for (int i = 0; i < length; i++) {
+                       Accessible accessible = event.accessibles[i];
+                       if (accessible != null) {
+                               accessible.AddRef();
+                               OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+                               count++;
+                       }
+               }
+               OS.MoveMemory(ppCellAccessibles, new long [] { pv }, C.PTR_SIZEOF);
+               OS.MoveMemory(pNColumnHeaderCells, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_columnIndex([out] pColumnIndex) */
+       int get_columnIndex(long pColumnIndex) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getColumnIndex(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_columnIndex() returning " + event.index);
+               OS.MoveMemory(pColumnIndex, new int [] { event.index }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_rowExtent([out] pNRowsSpanned) */
+       int get_rowExtent(long pNRowsSpanned) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getRowSpan(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_rowExtent() returning " + event.count);
+               OS.MoveMemory(pNRowsSpanned, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_rowHeaderCells([out] ppCellAccessibles, [out] pNRowHeaderCells) */
+       int get_rowHeaderCells(long ppCellAccessibles, long pNRowHeaderCells) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getRowHeaders(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_rowHeaderCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]"));
+               if (event.accessibles == null || event.accessibles.length == 0) {
+                       OS.MoveMemory(ppCellAccessibles, new long[] { 0 }, C.PTR_SIZEOF);
+                       OS.MoveMemory(pNRowHeaderCells, new int [] { 0 }, 4);
+                       return COM.S_FALSE;
+               }
+               int length = event.accessibles.length;
+               long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF);
+               int count = 0;
+               for (int i = 0; i < length; i++) {
+                       Accessible accessible = event.accessibles[i];
+                       if (accessible != null) {
+                               accessible.AddRef();
+                               OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+                               count++;
+                       }
+               }
+               OS.MoveMemory(ppCellAccessibles, new long [] { pv }, C.PTR_SIZEOF);
+               OS.MoveMemory(pNRowHeaderCells, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_rowIndex([out] pRowIndex) */
+       int get_rowIndex(long pRowIndex) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getRowIndex(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_rowIndex() returning " + event.index);
+               OS.MoveMemory(pRowIndex, new int [] { event.index }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_isSelected([out] pIsSelected) */
+       int get_isSelected(long pIsSelected) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.isSelected(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_isSelected() returning " + event.isSelected);
+               OS.MoveMemory(pIsSelected, new int [] {event.isSelected ? 1 : 0}, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_rowColumnExtents([out] pRow, [out] pColumn, [out] pRowExtents, [out] pColumnExtents, [out] pIsSelected) */
+       int get_rowColumnExtents(long pRow, long pColumn, long pRowExtents, long pColumnExtents, long pIsSelected) {
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_rowColumnExtents");
+               // TODO: should we implement this? It is just a convenience function.
+               return COM.DISP_E_MEMBERNOTFOUND;
+//             AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+//             for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+//                     AccessibleTableCellListener listener = (AccessibleTableCellListener) accessibleTableCellListeners.get(i);
+//                     listener.getRowColumnExtents(event);
+//             }
+//             COM.MoveMemory(pRow, new int [] { event.row }, 4);
+//             COM.MoveMemory(pColumn, new int [] { event.column }, 4);
+//             COM.MoveMemory(pRowExtents, new int [] { event.rowExtents }, 4);
+//             COM.MoveMemory(pColumnExtents, new int [] { event.columnExtents }, 4);
+//             return COM.S_OK;
+       }
+
+       /* IAccessibleTableCell::get_table([out] ppTable) */
+       int get_table(long ppTable) {
+               AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
+               for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
+                       AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
+                       listener.getTable(event);
+               }
+               Accessible accessible = event.accessible;
+               if (DEBUG) print(this + ".IAccessibleTableCell::get_table() returning " + accessible);
+               if (accessible == null) {
+                       // TODO: This is not supposed to return S_FALSE. We need to lookup the table role parent and return that.
+                       OS.MoveMemory(ppTable, new long[] { 0 }, C.PTR_SIZEOF);
+                       return COM.S_FALSE;
+               }
+               accessible.AddRef();
+               OS.MoveMemory(ppTable, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::addSelection([in] startOffset, [in] endOffset) */
+       int addSelection(int startOffset, int endOffset) {
+               if (DEBUG) print(this + ".IAccessibleText::addSelection(" + startOffset + ", " + endOffset + ")");
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.addSelection(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_attributes([in] offset, [out] pStartOffset, [out] pEndOffset, [out] pbstrTextAttributes) */
+       int get_attributes(int offset, long pStartOffset, long pEndOffset, long pbstrTextAttributes) {
+               AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this);
+               event.offset = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
+               for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
+                       AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
+                       listener.getTextAttributes(event);
+               }
+               String textAttributes = "";
+               TextStyle style = event.textStyle;
+               if (style != null) {
+                       if (style.rise != 0) {
+                               textAttributes += "text-position:";
+                               if (style.rise > 0) textAttributes += "super";
+                               else textAttributes += "sub";
+                       }
+                       if (style.underline) {
+                               textAttributes += "text-underline-type:";
+                               switch (style.underlineStyle) {
+                                       case SWT.UNDERLINE_SINGLE: textAttributes += "single;"; break;
+                                       case SWT.UNDERLINE_DOUBLE: textAttributes += "double;"; break;
+                                       case SWT.UNDERLINE_SQUIGGLE: textAttributes += "single;text-underline-style:wave;"; break;
+                                       case SWT.UNDERLINE_ERROR: textAttributes += "single;text-underline-style:wave;invalid:true;"; break;
+                                       default: textAttributes += "none;"; break;
+                               }
+                               // style.underlineColor is not currently part of the IA2 spec. If provided, it would be "text-underline-color:rgb(n,n,n);"
+                       }
+                       if (style.strikeout) {
+                               textAttributes += "text-line-through-type:single;";
+                               // style.strikeoutColor is not currently part of the IA2 spec. If provided, it would be "text-line-through-color:rgb(n,n,n);"
+                       }
+                       Font font = style.font;
+                       if (font != null && !font.isDisposed()) {
+                               FontData fontData = font.getFontData()[0];
+                               textAttributes += "font-family:" + fontData.getName() + ";";
+                               textAttributes += "font-size:" + fontData.getHeight() + "pt;";
+                               textAttributes += "font-style:" + (fontData.data.lfItalic != 0 ? "italic" : "normal") + ";";
+                               textAttributes += "font-weight:" + fontData.data.lfWeight + ";";
+                       }
+                       Color color = style.foreground;
+                       if (color != null && !color.isDisposed()) {
+                               textAttributes += "color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");";
+                       }
+                       color = style.background;
+                       if (color != null && !color.isDisposed()) {
+                               textAttributes += "background-color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");";
+                       }
+               }
+               if (event.attributes != null) {
+                       for (int i = 0; i + 1 < event.attributes.length; i += 2) {
+                               textAttributes += event.attributes[i] + ":" + event.attributes[i+1] + ";";
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_attributes(" + offset + ") returning start = " + event.start + ", end = " + event.end + ", attributes = " + textAttributes);
+               OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
+               OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
+               setString(pbstrTextAttributes, textAttributes);
+               if (textAttributes.length() == 0) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_caretOffset([out] pOffset) */
+       int get_caretOffset(long pOffset) {
+               int offset = getCaretOffset();
+               if (DEBUG) print(this + ".IAccessibleText::get_caretOffset returning " + offset + hresult(offset == -1 ? COM.S_FALSE : COM.S_OK));
+               OS.MoveMemory(pOffset, new int [] { offset }, 4);
+               if (offset == -1) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_characterExtents([in] offset, [in] coordType, [out] pX, [out] pY, [out] pWidth, [out] pHeight) */
+       int get_characterExtents(int offset, int coordType, long pX, long pY, long pWidth, long pHeight) {
+               int length = getCharacterCount();
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? length : offset < 0 ? 0 : offset;
+               event.end = offset == COM.IA2_TEXT_OFFSET_LENGTH || offset >= length ? length : offset + 1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getTextBounds(event);
+               }
+               /* Note: event.rectangles is not used here, because IAccessibleText::get_characterExtents is just for one character. */
+               if (DEBUG) print(this + ".IAccessibleText::get_characterExtents(" + offset + ") returning " + event.x + ", " + event.y + ", " + event.width + ", " + event.height);
+               OS.MoveMemory(pX, new int [] { event.x }, 4);
+               OS.MoveMemory(pY, new int [] { event.y }, 4);
+               OS.MoveMemory(pWidth, new int [] { event.width }, 4);
+               OS.MoveMemory(pHeight, new int [] { event.height }, 4);
+               if (event.width == 0 && event.height == 0) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_nSelections([out] pNSelections) */
+       int get_nSelections(long pNSelections) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.count = -1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getSelectionCount(event);
+               }
+               if (event.count == -1) {
+                       event.childID = ACC.CHILDID_SELF;
+                       event.offset = -1;
+                       event.length = 0;
+                       for (int i = 0; i < accessibleTextListenersSize(); i++) {
+                               AccessibleTextListener listener = accessibleTextListeners.get(i);
+                               listener.getSelectionRange (event);
+                       }
+                       event.count = event.offset != -1 && event.length > 0 ? 1 : 0;
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_nSelections returning " + event.count);
+               OS.MoveMemory(pNSelections, new int [] { event.count }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_offsetAtPoint([in] x, [in] y, [in] coordType, [out] pOffset) */
+       int get_offsetAtPoint(int x, int y, int coordType, long pOffset) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.x = x;
+               event.y = y;
+               event.offset = -1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getOffsetAtPoint(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_offsetAtPoint(" + x + ", " + y + ") returning " + event.offset + hresult(event.offset == -1 ? COM.S_FALSE : COM.S_OK));
+               /*
+                * Note that the current IA2 spec says to return 0 when there's nothing to return,
+                * but since 0 is a valid return value, the spec is going to be updated to return -1.
+                */
+               OS.MoveMemory(pOffset, new int [] { event.offset }, 4);
+               if (event.offset == -1) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_selection([in] selectionIndex, [out] pStartOffset, [out] pEndOffset) */
+       int get_selection(int selectionIndex, long pStartOffset, long pEndOffset) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.index = selectionIndex;
+               event.start = -1;
+               event.end = -1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getSelection(event);
+               }
+               if (event.start == -1 && selectionIndex == 0) {
+                       event.childID = ACC.CHILDID_SELF;
+                       event.offset = -1;
+                       event.length = 0;
+                       for (int i = 0; i < accessibleTextListenersSize(); i++) {
+                               AccessibleTextListener listener = accessibleTextListeners.get(i);
+                               listener.getSelectionRange (event);
+                       }
+                       event.start = event.offset;
+                       event.end = event.offset + event.length;
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_selection(" + selectionIndex + ") returning " + event.start + ", " + event.end);
+               OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
+               OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
+               /*
+                * Note that the current IA2 spec says to return 0,0 when there's nothing to return,
+                * but since 0 is a valid return value, the spec is going to be updated to return -1,-1.
+                */
+               if (event.start == -1) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_text([in] startOffset, [in] endOffset, [out] pbstrText) */
+       int get_text(int startOffset, int endOffset, long pbstrText) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               if (event.start > event.end) {
+                       /* IA2 spec says that indices can be exchanged. */
+                       int temp = event.start;
+                       event.start = event.end;
+                       event.end = temp;
+               }
+               event.count = 0;
+               event.type = ACC.TEXT_BOUNDARY_ALL;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getText(event);
+               }
+               if (event.result == null) {
+                       AccessibleControlEvent e = new AccessibleControlEvent(this);
+                       e.childID = ACC.CHILDID_SELF;
+                       for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                               AccessibleControlListener listener = accessibleControlListeners.get(i);
+                               listener.getRole(e);
+                               listener.getValue(e);
+                       }
+                       // TODO: Consider passing the value through for other roles as well (i.e. combo, etc). Keep in sync with get_nCharacters.
+                       if (e.detail == ACC.ROLE_TEXT) {
+                               event.result = e.result;
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_text(" + startOffset + ", " + endOffset + ") returning " + event.result + hresult(event.result == null ? COM.E_INVALIDARG : COM.S_OK));
+               setString(pbstrText, event.result);
+               if (event.result == null) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_textBeforeOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */
+       int get_textBeforeOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               int charCount = getCharacterCount();
+               event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset;
+               event.end = event.start;
+               event.count = -1;
+               switch (boundaryType) {
+                       case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
+                       case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break;
+                       case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
+                       case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break;
+                       case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break;
+                       default: return COM.E_INVALIDARG;
+               }
+               int eventStart = event.start;
+               int eventEnd = event.end;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getText(event);
+               }
+               if (event.end < charCount) {
+                       switch (boundaryType) {
+                               case COM.IA2_TEXT_BOUNDARY_WORD:
+                               case COM.IA2_TEXT_BOUNDARY_SENTENCE:
+                               case COM.IA2_TEXT_BOUNDARY_PARAGRAPH:
+                               case COM.IA2_TEXT_BOUNDARY_LINE:
+                                       int start = event.start;
+                                       event.start = eventStart;
+                                       event.end = eventEnd;
+                                       event.count = 0;
+                                       for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                                               AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                                               listener.getText(event);
+                                       }
+                                       event.end = event.start;
+                                       event.start = start;
+                                       event.type = ACC.TEXT_BOUNDARY_ALL;
+                                       event.count = 0;
+                                       for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                                               AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                                               listener.getText(event);
+                                       }
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_textBeforeOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK));
+               OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
+               OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
+               setString(pbstrText, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_textAfterOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */
+       int get_textAfterOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               int charCount = getCharacterCount();
+               event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset;
+               event.end = event.start;
+               event.count = 1;
+               switch (boundaryType) {
+                       case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
+                       case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break;
+                       case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
+                       case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break;
+                       case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break;
+                       default: return COM.E_INVALIDARG;
+               }
+               int eventStart = event.start;
+               int eventEnd = event.end;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getText(event);
+               }
+               if (event.end < charCount) {
+                       switch (boundaryType) {
+                               case COM.IA2_TEXT_BOUNDARY_WORD:
+                               case COM.IA2_TEXT_BOUNDARY_SENTENCE:
+                               case COM.IA2_TEXT_BOUNDARY_PARAGRAPH:
+                               case COM.IA2_TEXT_BOUNDARY_LINE:
+                                       int start = event.start;
+                                       event.start = eventStart;
+                                       event.end = eventEnd;
+                                       event.count = 2;
+                                       for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                                               AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                                               listener.getText(event);
+                                       }
+                                       event.end = event.start;
+                                       event.start = start;
+                                       event.type = ACC.TEXT_BOUNDARY_ALL;
+                                       event.count = 0;
+                                       for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                                               AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                                               listener.getText(event);
+                                       }
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_textAfterOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK));
+               OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
+               OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
+               setString(pbstrText, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_textAtOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */
+       int get_textAtOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               int charCount = getCharacterCount();
+               event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset;
+               event.end = event.start;
+               event.count = 0;
+               switch (boundaryType) {
+                       case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
+                       case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break;
+                       case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
+                       case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break;
+                       case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break;
+                       case COM.IA2_TEXT_BOUNDARY_ALL: {
+                               event.type = ACC.TEXT_BOUNDARY_ALL;
+                               event.start = 0;
+                               event.end = charCount;
+                               event.count = 0;
+                               break;
+                       }
+                       default: return COM.E_INVALIDARG;
+               }
+               int eventStart = event.start;
+               int eventEnd = event.end;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getText(event);
+               }
+               if (event.end < charCount) {
+                       switch (boundaryType) {
+                               case COM.IA2_TEXT_BOUNDARY_WORD:
+                               case COM.IA2_TEXT_BOUNDARY_SENTENCE:
+                               case COM.IA2_TEXT_BOUNDARY_PARAGRAPH:
+                               case COM.IA2_TEXT_BOUNDARY_LINE:
+                                       int start = event.start;
+                                       event.start = eventStart;
+                                       event.end = eventEnd;
+                                       event.count = 1;
+                                       for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                                               AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                                               listener.getText(event);
+                                       }
+                                       event.end = event.start;
+                                       event.start = start;
+                                       event.type = ACC.TEXT_BOUNDARY_ALL;
+                                       event.count = 0;
+                                       for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                                               AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                                               listener.getText(event);
+                                       }
+                       }
+               }
+               if (DEBUG) print(this + ".IAccessibleText::get_textAtOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK));
+               OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
+               OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
+               setString(pbstrText, event.result);
+               if (event.result == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::removeSelection([in] selectionIndex) */
+       int removeSelection(int selectionIndex) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.index = selectionIndex;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.removeSelection(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleText::removeSelection(" + selectionIndex + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::setCaretOffset([in] offset) */
+       int setCaretOffset(int offset) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.offset = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.setCaretOffset(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleText::setCaretOffset(" + offset + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; // TODO: @retval E_FAIL if the caret cannot be set ?
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::setSelection([in] selectionIndex, [in] startOffset, [in] endOffset) */
+       int setSelection(int selectionIndex, int startOffset, int endOffset) {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.index = selectionIndex;
+               event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
+               event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.setSelection(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleText::setSelection(index=" + selectionIndex + ", start=" + event.start + ", end=" + event.end + ") returning " + (event.result.equals(ACC.OK) ? "OK" : "INVALIDARG"));
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_nCharacters([out] pNCharacters) */
+       int get_nCharacters(long pNCharacters) {
+               int count = getCharacterCount();
+               OS.MoveMemory(pNCharacters, new int [] { count }, 4);
+               if (DEBUG) print(this + ".IAccessibleText::get_nCharacters returning " + count);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::scrollSubstringTo([in] startIndex, [in] endIndex, [in] scrollType) */
+       int scrollSubstringTo(int startIndex, int endIndex, int scrollType) {
+               if (DEBUG) print(this + ".IAccessibleText::scrollSubstringTo");
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.start = startIndex;
+               event.end = endIndex;
+               switch (scrollType) {
+                       case COM.IA2_SCROLL_TYPE_TOP_LEFT: event.type = ACC.SCROLL_TYPE_TOP_LEFT; break;
+                       case COM.IA2_SCROLL_TYPE_BOTTOM_RIGHT: event.type = ACC.SCROLL_TYPE_BOTTOM_RIGHT; break;
+                       case COM.IA2_SCROLL_TYPE_TOP_EDGE: event.type = ACC.SCROLL_TYPE_TOP_EDGE; break;
+                       case COM.IA2_SCROLL_TYPE_BOTTOM_EDGE: event.type = ACC.SCROLL_TYPE_BOTTOM_EDGE; break;
+                       case COM.IA2_SCROLL_TYPE_LEFT_EDGE: event.type = ACC.SCROLL_TYPE_LEFT_EDGE; break;
+                       case COM.IA2_SCROLL_TYPE_RIGHT_EDGE: event.type = ACC.SCROLL_TYPE_RIGHT_EDGE; break;
+                       case COM.IA2_SCROLL_TYPE_ANYWHERE: event.type = ACC.SCROLL_TYPE_ANYWHERE; break;
+               }
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.scrollText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::scrollSubstringToPoint([in] startIndex, [in] endIndex, [in] coordinateType, [in] x, [in] y) */
+       int scrollSubstringToPoint(int startIndex, int endIndex, int coordinateType, int x, int y) {
+               if (DEBUG) print(this + ".IAccessibleText::scrollSubstringToPoint");
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.start = startIndex;
+               event.end = endIndex;
+               event.type = ACC.SCROLL_TYPE_POINT;
+               event.x = x;
+               event.y = y;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.scrollText(event);
+               }
+               if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; // TODO: @retval S_FALSE if the object is already at the specified location.
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_newText([out] pNewText) */
+       int get_newText(long pNewText) {
+               if (DEBUG) print(this + ".IAccessibleText::get_newText");
+               String text = null;
+               int start = 0;
+               int end = 0;
+               if (textInserted != null) {
+                       text = (String) textInserted[3];
+                       start = ((Integer)textInserted[1]).intValue();
+                       end = ((Integer)textInserted[2]).intValue();
+               }
+               setString(pNewText, text);
+               OS.MoveMemory(pNewText + C.PTR_SIZEOF, new int [] {start}, 4);
+               OS.MoveMemory(pNewText + C.PTR_SIZEOF + 4, new int [] {end}, 4);
+               if (textInserted == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleText::get_oldText([out] pOldText) */
+       int get_oldText(long pOldText) {
+               if (DEBUG) print(this + ".IAccessibleText::get_oldText");
+               String text = null;
+               int start = 0;
+               int end = 0;
+               if (textDeleted != null) {
+                       text = (String) textDeleted[3];
+                       start = ((Integer)textDeleted[1]).intValue();
+                       end = ((Integer)textDeleted[2]).intValue();
+               }
+               setString(pOldText, text);
+               OS.MoveMemory(pOldText + C.PTR_SIZEOF, new int [] {start}, 4);
+               OS.MoveMemory(pOldText + C.PTR_SIZEOF + 4, new int [] {end}, 4);
+               if (textDeleted == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleValue::get_currentValue([out] pCurrentValue) */
+       int get_currentValue(long pCurrentValue) {
+               AccessibleValueEvent event = new AccessibleValueEvent(this);
+               for (int i = 0; i < accessibleValueListenersSize(); i++) {
+                       AccessibleValueListener listener = accessibleValueListeners.get(i);
+                       listener.getCurrentValue(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleValue::get_currentValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK));
+               setNumberVARIANT(pCurrentValue, event.value);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleValue::setCurrentValue([in] value) */
+       int setCurrentValue(long value) {
+               if (DEBUG) print(this + ".IAccessibleValue::setCurrentValue");
+               AccessibleValueEvent event = new AccessibleValueEvent(this);
+               event.value = getNumberVARIANT(value);
+               for (int i = 0; i < accessibleValueListenersSize(); i++) {
+                       AccessibleValueListener listener = accessibleValueListeners.get(i);
+                       listener.setCurrentValue(event);
+               }
+               //if (event.value == null) return COM.S_FALSE;
+               return COM.S_OK;
+       }
+
+       /* IAccessibleValue::get_maximumValue([out] pMaximumValue) */
+       int get_maximumValue(long pMaximumValue) {
+               AccessibleValueEvent event = new AccessibleValueEvent(this);
+               for (int i = 0; i < accessibleValueListenersSize(); i++) {
+                       AccessibleValueListener listener = accessibleValueListeners.get(i);
+                       listener.getMaximumValue(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleValue::get_maximumValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK));
+               setNumberVARIANT(pMaximumValue, event.value);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleValue::get_minimumValue([out] pMinimumValue) */
+       int get_minimumValue(long pMinimumValue) {
+               AccessibleValueEvent event = new AccessibleValueEvent(this);
+               for (int i = 0; i < accessibleValueListenersSize(); i++) {
+                       AccessibleValueListener listener = accessibleValueListeners.get(i);
+                       listener.getMinimumValue(event);
+               }
+               if (DEBUG) print(this + ".IAccessibleValue::get_minimumValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK));
+               setNumberVARIANT(pMinimumValue, event.value);
+               return COM.S_OK;
+       }
+
+       int eventChildID() {
+               if (parent == null) return COM.CHILDID_SELF;
+               if (uniqueID == -1) uniqueID = UniqueID--;
+               return uniqueID;
+       }
+
+       void checkUniqueID(int childID) {
+               /* If the application is using child ids, check whether there's a corresponding
+                * accessible, and if so, use the child id as that accessible's unique id. */
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = childID;
+               for (int l = 0; l < accessibleControlListenersSize(); l++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(l);
+                       listener.getChild(event);
+               }
+               Accessible accessible = event.accessible;
+               if (accessible != null && accessible.uniqueID == -1) {
+                       accessible.uniqueID = childID;
+               }
+       }
+
+       int childIDToOs(int childID) {
+               if (childID == ACC.CHILDID_SELF) return COM.CHILDID_SELF;
+               /* ChildIDs are 1-based indices. */
+               int osChildID = childID + 1;
+               if (control instanceof Tree) {
+                       osChildID = (int)OS.SendMessage (control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0);
+               }
+               checkUniqueID(osChildID);
+               return osChildID;
+       }
+
+       int osToChildID(int osChildID) {
+               if (osChildID == COM.CHILDID_SELF) return ACC.CHILDID_SELF;
+               /*
+               * Feature of Windows:
+               * Before Windows XP, tree item ids were 1-based indices.
+               * Windows XP and later use the tree item handle for the
+               * accessible child ID. For backward compatibility, we still
+               * take 1-based childIDs for tree items prior to Windows XP.
+               * All other childIDs are 1-based indices.
+               */
+               if (!(control instanceof Tree)) return osChildID - 1;
+               return (int)OS.SendMessage (control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0);
+       }
+
+       int stateToOs(int state) {
+               int osState = 0;
+               if ((state & ACC.STATE_SELECTED) != 0) osState |= COM.STATE_SYSTEM_SELECTED;
+               if ((state & ACC.STATE_SELECTABLE) != 0) osState |= COM.STATE_SYSTEM_SELECTABLE;
+               if ((state & ACC.STATE_MULTISELECTABLE) != 0) osState |= COM.STATE_SYSTEM_MULTISELECTABLE;
+               if ((state & ACC.STATE_FOCUSED) != 0) osState |= COM.STATE_SYSTEM_FOCUSED;
+               if ((state & ACC.STATE_FOCUSABLE) != 0) osState |= COM.STATE_SYSTEM_FOCUSABLE;
+               if ((state & ACC.STATE_PRESSED) != 0) osState |= COM.STATE_SYSTEM_PRESSED;
+               if ((state & ACC.STATE_CHECKED) != 0) osState |= COM.STATE_SYSTEM_CHECKED;
+               if ((state & ACC.STATE_EXPANDED) != 0) osState |= COM.STATE_SYSTEM_EXPANDED;
+               if ((state & ACC.STATE_COLLAPSED) != 0) osState |= COM.STATE_SYSTEM_COLLAPSED;
+               if ((state & ACC.STATE_HOTTRACKED) != 0) osState |= COM.STATE_SYSTEM_HOTTRACKED;
+               if ((state & ACC.STATE_BUSY) != 0) osState |= COM.STATE_SYSTEM_BUSY;
+               if ((state & ACC.STATE_READONLY) != 0) osState |= COM.STATE_SYSTEM_READONLY;
+               if ((state & ACC.STATE_INVISIBLE) != 0) osState |= COM.STATE_SYSTEM_INVISIBLE;
+               if ((state & ACC.STATE_OFFSCREEN) != 0) osState |= COM.STATE_SYSTEM_OFFSCREEN;
+               if ((state & ACC.STATE_SIZEABLE) != 0) osState |= COM.STATE_SYSTEM_SIZEABLE;
+               if ((state & ACC.STATE_LINKED) != 0) osState |= COM.STATE_SYSTEM_LINKED;
+               if ((state & ACC.STATE_DISABLED) != 0) osState |= COM.STATE_SYSTEM_UNAVAILABLE;
+               return osState;
+       }
+
+       int osToState(int osState) {
+               int state = ACC.STATE_NORMAL;
+               if ((osState & COM.STATE_SYSTEM_SELECTED) != 0) state |= ACC.STATE_SELECTED;
+               if ((osState & COM.STATE_SYSTEM_SELECTABLE) != 0) state |= ACC.STATE_SELECTABLE;
+               if ((osState & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) state |= ACC.STATE_MULTISELECTABLE;
+               if ((osState & COM.STATE_SYSTEM_FOCUSED) != 0) state |= ACC.STATE_FOCUSED;
+               if ((osState & COM.STATE_SYSTEM_FOCUSABLE) != 0) state |= ACC.STATE_FOCUSABLE;
+               if ((osState & COM.STATE_SYSTEM_PRESSED) != 0) state |= ACC.STATE_PRESSED;
+               if ((osState & COM.STATE_SYSTEM_CHECKED) != 0) state |= ACC.STATE_CHECKED;
+               if ((osState & COM.STATE_SYSTEM_EXPANDED) != 0) state |= ACC.STATE_EXPANDED;
+               if ((osState & COM.STATE_SYSTEM_COLLAPSED) != 0) state |= ACC.STATE_COLLAPSED;
+               if ((osState & COM.STATE_SYSTEM_HOTTRACKED) != 0) state |= ACC.STATE_HOTTRACKED;
+               if ((osState & COM.STATE_SYSTEM_BUSY) != 0) state |= ACC.STATE_BUSY;
+               if ((osState & COM.STATE_SYSTEM_READONLY) != 0) state |= ACC.STATE_READONLY;
+               if ((osState & COM.STATE_SYSTEM_INVISIBLE) != 0) state |= ACC.STATE_INVISIBLE;
+               if ((osState & COM.STATE_SYSTEM_OFFSCREEN) != 0) state |= ACC.STATE_OFFSCREEN;
+               if ((osState & COM.STATE_SYSTEM_SIZEABLE) != 0) state |= ACC.STATE_SIZEABLE;
+               if ((osState & COM.STATE_SYSTEM_LINKED) != 0) state |= ACC.STATE_LINKED;
+               if ((osState & COM.STATE_SYSTEM_UNAVAILABLE) != 0) state |= ACC.STATE_DISABLED;
+               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_SPLITBUTTON: return COM.ROLE_SYSTEM_SPLITBUTTON;
+                       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;
+                       case ACC.ROLE_ALERT: return COM.ROLE_SYSTEM_ALERT;
+                       case ACC.ROLE_ANIMATION: return COM.ROLE_SYSTEM_ANIMATION;
+                       case ACC.ROLE_COLUMN: return COM.ROLE_SYSTEM_COLUMN;
+                       case ACC.ROLE_DOCUMENT: return COM.ROLE_SYSTEM_DOCUMENT;
+                       case ACC.ROLE_GRAPHIC: return COM.ROLE_SYSTEM_GRAPHIC;
+                       case ACC.ROLE_GROUP: return COM.ROLE_SYSTEM_GROUPING;
+                       case ACC.ROLE_ROW: return COM.ROLE_SYSTEM_ROW;
+                       case ACC.ROLE_SPINBUTTON: return COM.ROLE_SYSTEM_SPINBUTTON;
+                       case ACC.ROLE_STATUSBAR: return COM.ROLE_SYSTEM_STATUSBAR;
+                       case ACC.ROLE_CLOCK: return COM.ROLE_SYSTEM_CLOCK;
+                       case ACC.ROLE_CALENDAR: return COM.ROLE_SYSTEM_DROPLIST;
+
+                       /* The rest are IA2 roles, so return the closest match. */
+                       case ACC.ROLE_CANVAS: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_CHECKMENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
+                       case ACC.ROLE_RADIOMENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
+                       case ACC.ROLE_DATETIME: return COM.ROLE_SYSTEM_DROPLIST;
+                       case ACC.ROLE_FOOTER: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_FORM: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_HEADER: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_HEADING: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_PAGE: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_PARAGRAPH: return COM.ROLE_SYSTEM_CLIENT;
+                       case ACC.ROLE_SECTION: return COM.ROLE_SYSTEM_CLIENT;
+               }
+               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_SPLITBUTTON: return ACC.ROLE_SPLITBUTTON;
+                       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;
+                       case COM.ROLE_SYSTEM_ALERT: return ACC.ROLE_ALERT;
+                       case COM.ROLE_SYSTEM_ANIMATION: return ACC.ROLE_ANIMATION;
+                       case COM.ROLE_SYSTEM_COLUMN: return ACC.ROLE_COLUMN;
+                       case COM.ROLE_SYSTEM_DOCUMENT: return ACC.ROLE_DOCUMENT;
+                       case COM.ROLE_SYSTEM_GRAPHIC: return ACC.ROLE_GRAPHIC;
+                       case COM.ROLE_SYSTEM_GROUPING: return ACC.ROLE_GROUP;
+                       case COM.ROLE_SYSTEM_ROW: return ACC.ROLE_ROW;
+                       case COM.ROLE_SYSTEM_SPINBUTTON: return ACC.ROLE_SPINBUTTON;
+                       case COM.ROLE_SYSTEM_STATUSBAR: return ACC.ROLE_STATUSBAR;
+                       case COM.ROLE_SYSTEM_CLOCK: return ACC.ROLE_CLOCK;
+                       case COM.ROLE_SYSTEM_DROPLIST: return ACC.ROLE_CALENDAR;
+               }
+               return ACC.ROLE_CLIENT_AREA;
+       }
+
+       /*
+        * Return a Color given a string of the form "rgb(n,n,n)".
+        */
+       Color colorFromString(String rgbString) {
+               try {
+                       int open = rgbString.indexOf('(');
+                       int comma1 = rgbString.indexOf(',');
+                       int comma2 = rgbString.indexOf(',', comma1 + 1);
+                       int close = rgbString.indexOf(')');
+                       int r = Integer.parseInt(rgbString.substring(open + 1, comma1));
+                       int g = Integer.parseInt(rgbString.substring(comma1 + 1, comma2));
+                       int b = Integer.parseInt(rgbString.substring(comma2 + 1, close));
+                       return new Color(control.getDisplay(), r, g, b);
+               } catch (NumberFormatException ex) {}
+               return null;
+       }
+
+       int getCaretOffset() {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.offset = -1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getCaretOffset (event);
+               }
+               if (event.offset == -1) {
+                       for (int i = 0; i < accessibleTextListenersSize(); i++) {
+                               event.childID = ACC.CHILDID_SELF;
+                               AccessibleTextListener listener = accessibleTextListeners.get(i);
+                               listener.getCaretOffset (event);
+                       }
+               }
+               return event.offset;
+       }
+
+       int getCharacterCount() {
+               AccessibleTextEvent event = new AccessibleTextEvent(this);
+               event.count = -1;
+               for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
+                       AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
+                       listener.getCharacterCount(event);
+               }
+               if (event.count == -1) {
+                       AccessibleControlEvent e = new AccessibleControlEvent(this);
+                       e.childID = ACC.CHILDID_SELF;
+                       for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                               AccessibleControlListener listener = accessibleControlListeners.get(i);
+                               listener.getRole(e);
+                               listener.getValue(e);
+                       }
+                       // TODO: Consider passing the value through for other roles as well (i.e. combo, etc). Keep in sync with get_text.
+                       event.count = e.detail == ACC.ROLE_TEXT && e.result != null ? e.result.length() : 0;
+               }
+               return event.count;
+       }
+
+       int getRelationCount() {
+               int count = 0;
+               for (int type = 0; type < MAX_RELATION_TYPES; type++) {
+                       if (relations[type] != null) count++;
+               }
+               return count;
+       }
+
+       int getRole() {
+               AccessibleControlEvent event = new AccessibleControlEvent(this);
+               event.childID = ACC.CHILDID_SELF;
+               for (int i = 0; i < accessibleControlListenersSize(); i++) {
+                       AccessibleControlListener listener = accessibleControlListeners.get(i);
+                       listener.getRole(event);
+               }
+               return event.detail;
+       }
+
+       int getDefaultRole() {
+               int role;
+               role = COM.ROLE_SYSTEM_CLIENT;
+               if (iaccessible != null) {
+                       /* Get the default role from the OS. */
+                       long varChild = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+                       setIntVARIANT(varChild, COM.VT_I4, COM.CHILDID_SELF);
+                       long pvarRole = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+                       int code = iaccessible.get_accRole(varChild, pvarRole);
+                       if (code == COM.S_OK) {
+                               VARIANT v = getVARIANT(pvarRole);
+                               if (v.vt == COM.VT_I4) role = v.lVal;
+                       }
+                       OS.GlobalFree(varChild);
+                       OS.GlobalFree(pvarRole);
+               }
+               return role;
+       }
+
+       String getString(long psz) {
+               long [] ptr = new long [1];
+               OS.MoveMemory (ptr, psz, C.PTR_SIZEOF);
+               int size = COM.SysStringByteLen(ptr [0]);
+               if (size == 0) return "";
+               char [] buffer = new char [(size + 1) / 2];
+               OS.MoveMemory (buffer, ptr [0], size);
+               return new String (buffer);
+       }
+
+       VARIANT getVARIANT(long variant) {
+               VARIANT v = new VARIANT();
+               COM.MoveMemory(v, variant, VARIANT.sizeof);
+               return v;
+       }
+
+       Number getNumberVARIANT(long variant) {
+               VARIANT v = new VARIANT();
+               COM.MoveMemory(v, variant, VARIANT.sizeof);
+               if (v.vt == COM.VT_I8) return Long.valueOf(v.lVal); // TODO: Fix this - v.lVal is an int - don't use struct
+               return Integer.valueOf(v.lVal);
+       }
+
+       void setIntVARIANT(long variant, short vt, int lVal) {
+               if (vt == COM.VT_I4 || vt == COM.VT_EMPTY) {
+                       OS.MoveMemory(variant, new short[] { vt }, 2);
+                       OS.MoveMemory(variant + 8, new int[] { lVal }, 4);
+               }
+       }
+
+       void setPtrVARIANT(long variant, short vt, long lVal) {
+               if (vt == COM.VT_DISPATCH || vt == COM.VT_UNKNOWN) {
+                       OS.MoveMemory(variant, new short[] { vt }, 2);
+                       OS.MoveMemory(variant + 8, new long [] { lVal }, C.PTR_SIZEOF);
+               }
+       }
+
+       void setNumberVARIANT(long variant, Number number) {
+               if (number == null) {
+                       OS.MoveMemory(variant, new short[] { COM.VT_EMPTY }, 2);
+                       OS.MoveMemory(variant + 8, new int[] { 0 }, 4);
+               } else if (number instanceof Double) {
+                       OS.MoveMemory(variant, new short[] { COM.VT_R8 }, 2);
+                       OS.MoveMemory(variant + 8, new double[] { number.doubleValue() }, 8);
+               } else if (number instanceof Float) {
+                       OS.MoveMemory(variant, new short[] { COM.VT_R4 }, 2);
+                       OS.MoveMemory(variant + 8, new float[] { number.floatValue() }, 4);
+               } else if (number instanceof Long) {
+                       OS.MoveMemory(variant, new short[] { COM.VT_I8 }, 2);
+                       OS.MoveMemory(variant + 8, new long[] { number.longValue() }, 8);
+               } else {
+                       OS.MoveMemory(variant, new short[] { COM.VT_I4 }, 2);
+                       OS.MoveMemory(variant + 8, new int[] { number.intValue() }, 4);
+               }
+       }
+
+       void setString(long psz, String string) {
+               long ptr = 0;
+               if (string != null) {
+                       char[] data = (string + "\0").toCharArray();
+                       ptr = COM.SysAllocString(data);
+               }
+               OS.MoveMemory(psz, new long [] { ptr }, C.PTR_SIZEOF);
+       }
+
+       void setStringVARIANT(long variant, String string) {
+               long ptr = 0;
+               if (string != null) {
+                       char[] data = (string + "\0").toCharArray();
+                       ptr = COM.SysAllocString(data);
+               }
+               OS.MoveMemory(variant, new short[] { ptr == 0 ? COM.VT_EMPTY : COM.VT_BSTR }, 2);
+               OS.MoveMemory(variant + 8, new long [] { ptr }, C.PTR_SIZEOF);
+       }
+
+       /* 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);
+       }
+
+       boolean isATRunning () {
+               /*
+                * Currently there is no accurate way to check if AT is running from 'refCount'.
+                * JAWS screen reader cannot be detected using 'refCount' approach,
+                * because 'refCount' continues to be 1 even when JAWS is running.
+                */
+               // if (refCount <= 1) return false;
+               return true;
+       }
+
+       /* isValidThread was copied from Widget, and rewritten to work in this package */
+       boolean isValidThread () {
+               return control.getDisplay ().getThread () == Thread.currentThread ();
+       }
+
+       // START DEBUG CODE
+       static void print (String str) {
+               if (DEBUG) System.out.println (str);
+       }
+       String getRoleString(int role) {
+               if (DEBUG) switch (role) {
+                       case COM.ROLE_SYSTEM_CLIENT: return "ROLE_SYSTEM_CLIENT";
+                       case COM.ROLE_SYSTEM_WINDOW: return "ROLE_SYSTEM_WINDOW";
+                       case COM.ROLE_SYSTEM_MENUBAR: return "ROLE_SYSTEM_MENUBAR";
+                       case COM.ROLE_SYSTEM_MENUPOPUP: return "ROLE_SYSTEM_MENUPOPUP";
+                       case COM.ROLE_SYSTEM_MENUITEM: return "ROLE_SYSTEM_MENUITEM";
+                       case COM.ROLE_SYSTEM_SEPARATOR: return "ROLE_SYSTEM_SEPARATOR";
+                       case COM.ROLE_SYSTEM_TOOLTIP: return "ROLE_SYSTEM_TOOLTIP";
+                       case COM.ROLE_SYSTEM_SCROLLBAR: return "ROLE_SYSTEM_SCROLLBAR";
+                       case COM.ROLE_SYSTEM_DIALOG: return "ROLE_SYSTEM_DIALOG";
+                       case COM.ROLE_SYSTEM_STATICTEXT: return "ROLE_SYSTEM_STATICTEXT";
+                       case COM.ROLE_SYSTEM_PUSHBUTTON: return "ROLE_SYSTEM_PUSHBUTTON";
+                       case COM.ROLE_SYSTEM_CHECKBUTTON: return "ROLE_SYSTEM_CHECKBUTTON";
+                       case COM.ROLE_SYSTEM_RADIOBUTTON: return "ROLE_SYSTEM_RADIOBUTTON";
+                       case COM.ROLE_SYSTEM_SPLITBUTTON: return "ROLE_SYSTEM_SPLITBUTTON";
+                       case COM.ROLE_SYSTEM_COMBOBOX: return "ROLE_SYSTEM_COMBOBOX";
+                       case COM.ROLE_SYSTEM_TEXT: return "ROLE_SYSTEM_TEXT";
+                       case COM.ROLE_SYSTEM_TOOLBAR: return "ROLE_SYSTEM_TOOLBAR";
+                       case COM.ROLE_SYSTEM_LIST: return "ROLE_SYSTEM_LIST";
+                       case COM.ROLE_SYSTEM_LISTITEM: return "ROLE_SYSTEM_LISTITEM";
+                       case COM.ROLE_SYSTEM_TABLE: return "ROLE_SYSTEM_TABLE";
+                       case COM.ROLE_SYSTEM_CELL: return "ROLE_SYSTEM_CELL";
+                       case COM.ROLE_SYSTEM_COLUMNHEADER: return "ROLE_SYSTEM_COLUMNHEADER";
+                       case COM.ROLE_SYSTEM_ROWHEADER: return "ROLE_SYSTEM_ROWHEADER";
+                       case COM.ROLE_SYSTEM_OUTLINE: return "ROLE_SYSTEM_OUTLINE";
+                       case COM.ROLE_SYSTEM_OUTLINEITEM: return "ROLE_SYSTEM_OUTLINEITEM";
+                       case COM.ROLE_SYSTEM_PAGETABLIST: return "ROLE_SYSTEM_PAGETABLIST";
+                       case COM.ROLE_SYSTEM_PAGETAB: return "ROLE_SYSTEM_PAGETAB";
+                       case COM.ROLE_SYSTEM_PROGRESSBAR: return "ROLE_SYSTEM_PROGRESSBAR";
+                       case COM.ROLE_SYSTEM_SLIDER: return "ROLE_SYSTEM_SLIDER";
+                       case COM.ROLE_SYSTEM_LINK: return "ROLE_SYSTEM_LINK";
+                       case COM.ROLE_SYSTEM_ALERT: return "ROLE_SYSTEM_ALERT";
+                       case COM.ROLE_SYSTEM_ANIMATION: return "ROLE_SYSTEM_ANIMATION";
+                       case COM.ROLE_SYSTEM_COLUMN: return "ROLE_SYSTEM_COLUMN";
+                       case COM.ROLE_SYSTEM_DOCUMENT: return "ROLE_SYSTEM_DOCUMENT";
+                       case COM.ROLE_SYSTEM_GRAPHIC: return "ROLE_SYSTEM_GRAPHIC";
+                       case COM.ROLE_SYSTEM_GROUPING: return "ROLE_SYSTEM_GROUPING";
+                       case COM.ROLE_SYSTEM_ROW: return "ROLE_SYSTEM_ROW";
+                       case COM.ROLE_SYSTEM_SPINBUTTON: return "ROLE_SYSTEM_SPINBUTTON";
+                       case COM.ROLE_SYSTEM_STATUSBAR: return "ROLE_SYSTEM_STATUSBAR";
+                       case COM.ROLE_SYSTEM_CLOCK: return "ROLE_SYSTEM_CLOCK";
+                       case COM.ROLE_SYSTEM_DROPLIST: return "ROLE_SYSTEM_DROPLIST";
+                       // IA2 roles
+                       case ACC.ROLE_CANVAS: return "IA2_ROLE_CANVAS";
+                       case ACC.ROLE_CHECKMENUITEM: return "IA2_ROLE_CHECKMENUITEM";
+                       case ACC.ROLE_RADIOMENUITEM: return "IA2_ROLE_RADIOMENUITEM";
+                       case ACC.ROLE_DATETIME: return "IA2_ROLE_DATETIME";
+                       case ACC.ROLE_FOOTER: return "IA2_ROLE_FOOTER";
+                       case ACC.ROLE_FORM: return "IA2_ROLE_FORM";
+                       case ACC.ROLE_HEADER: return "IA2_ROLE_HEADER";
+                       case ACC.ROLE_HEADING: return "IA2_ROLE_HEADING";
+                       case ACC.ROLE_PAGE: return "IA2_ROLE_PAGE";
+                       case ACC.ROLE_PARAGRAPH: return "IA2_ROLE_PARAGRAPH";
+                       case ACC.ROLE_SECTION: return "IA2_ROLE_SECTION";
+               }
+               return "Unknown role (" + role + ")";
+       }
+       String getStateString(int state) {
+               if (state == 0) return " no state bits set";
+               StringBuilder stateString = new StringBuilder();
+               if (DEBUG) {
+               if ((state & COM.STATE_SYSTEM_SELECTED) != 0) stateString.append(" STATE_SYSTEM_SELECTED");
+               if ((state & COM.STATE_SYSTEM_SELECTABLE) != 0) stateString.append(" STATE_SYSTEM_SELECTABLE");
+               if ((state & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) stateString.append(" STATE_SYSTEM_MULTISELECTABLE");
+               if ((state & COM.STATE_SYSTEM_FOCUSED) != 0) stateString.append(" STATE_SYSTEM_FOCUSED");
+               if ((state & COM.STATE_SYSTEM_FOCUSABLE) != 0) stateString.append(" STATE_SYSTEM_FOCUSABLE");
+               if ((state & COM.STATE_SYSTEM_PRESSED) != 0) stateString.append(" STATE_SYSTEM_PRESSED");
+               if ((state & COM.STATE_SYSTEM_CHECKED) != 0) stateString.append(" STATE_SYSTEM_CHECKED");
+               if ((state & COM.STATE_SYSTEM_EXPANDED) != 0) stateString.append(" STATE_SYSTEM_EXPANDED");
+               if ((state & COM.STATE_SYSTEM_COLLAPSED) != 0) stateString.append(" STATE_SYSTEM_COLLAPSED");
+               if ((state & COM.STATE_SYSTEM_HOTTRACKED) != 0) stateString.append(" STATE_SYSTEM_HOTTRACKED");
+               if ((state & COM.STATE_SYSTEM_BUSY) != 0) stateString.append(" STATE_SYSTEM_BUSY");
+               if ((state & COM.STATE_SYSTEM_READONLY) != 0) stateString.append(" STATE_SYSTEM_READONLY");
+               if ((state & COM.STATE_SYSTEM_INVISIBLE) != 0) stateString.append(" STATE_SYSTEM_INVISIBLE");
+               if ((state & COM.STATE_SYSTEM_OFFSCREEN) != 0) stateString.append(" STATE_SYSTEM_OFFSCREEN");
+               if ((state & COM.STATE_SYSTEM_SIZEABLE) != 0) stateString.append(" STATE_SYSTEM_SIZEABLE");
+               if ((state & COM.STATE_SYSTEM_LINKED) != 0) stateString.append(" STATE_SYSTEM_LINKED");
+               if ((state & COM.STATE_SYSTEM_UNAVAILABLE) != 0) stateString.append(" STATE_SYSTEM_UNAVAILABLE");
+               if (stateString.length() == 0) stateString.append(" Unknown state[s] (" + Integer.toHexString(state) + ")");
+               }
+               return stateString.toString();
+       }
+       String getIA2StatesString(int ia2States) {
+               if (ia2States == 0) return " no state bits set";
+               StringBuilder stateString = new StringBuilder();
+               if (DEBUG) {
+               if ((ia2States & COM.IA2_STATE_ACTIVE) != 0) stateString.append(" IA2_STATE_ACTIVE");
+               if ((ia2States & COM.IA2_STATE_EDITABLE) != 0) stateString.append(" IA2_STATE_EDITABLE");
+               if ((ia2States & COM.IA2_STATE_SINGLE_LINE) != 0) stateString.append(" IA2_STATE_SINGLE_LINE");
+               if ((ia2States & COM.IA2_STATE_MULTI_LINE) != 0) stateString.append(" IA2_STATE_MULTI_LINE");
+               if ((ia2States & COM.IA2_STATE_REQUIRED) != 0) stateString.append(" IA2_STATE_REQUIRED");
+               if ((ia2States & COM.IA2_STATE_INVALID_ENTRY) != 0) stateString.append(" IA2_STATE_INVALID_ENTRY");
+               if ((ia2States & COM.IA2_STATE_SUPPORTS_AUTOCOMPLETION) != 0) stateString.append(" IA2_STATE_SUPPORTS_AUTOCOMPLETION");
+               if (stateString.length() == 0) stateString.append(" Unknown IA2 state[s] (" + ia2States + ")");
+               }
+               return stateString.toString();
+       }
+       String getEventString(int event) {
+               if (DEBUG) switch (event) {
+                       case ACC.EVENT_TABLE_CHANGED: return "IA2_EVENT_TABLE_CHANGED";
+                       case ACC.EVENT_TEXT_CHANGED: return "IA2_EVENT_TEXT_REMOVED or IA2_EVENT_TEXT_INSERTED";
+                       case ACC.EVENT_HYPERTEXT_LINK_SELECTED: return "IA2_EVENT_HYPERTEXT_LINK_SELECTED";
+                       case ACC.EVENT_VALUE_CHANGED: return "EVENT_OBJECT_VALUECHANGE";
+                       case ACC.EVENT_STATE_CHANGED: return "EVENT_OBJECT_STATECHANGE";
+                       case ACC.EVENT_SELECTION_CHANGED: return "EVENT_OBJECT_SELECTIONWITHIN";
+                       case ACC.EVENT_TEXT_SELECTION_CHANGED: return "EVENT_OBJECT_TEXTSELECTIONCHANGED";
+                       case ACC.EVENT_LOCATION_CHANGED: return "EVENT_OBJECT_LOCATIONCHANGE";
+                       case ACC.EVENT_NAME_CHANGED: return "EVENT_OBJECT_NAMECHANGE";
+                       case ACC.EVENT_DESCRIPTION_CHANGED: return "EVENT_OBJECT_DESCRIPTIONCHANGE";
+                       case ACC.EVENT_DOCUMENT_LOAD_COMPLETE: return "IA2_EVENT_DOCUMENT_LOAD_COMPLETE";
+                       case ACC.EVENT_DOCUMENT_LOAD_STOPPED: return "IA2_EVENT_DOCUMENT_LOAD_STOPPED";
+                       case ACC.EVENT_DOCUMENT_RELOAD: return "IA2_EVENT_DOCUMENT_RELOAD";
+                       case ACC.EVENT_PAGE_CHANGED: return "IA2_EVENT_PAGE_CHANGED";
+                       case ACC.EVENT_SECTION_CHANGED: return "IA2_EVENT_SECTION_CHANGED";
+                       case ACC.EVENT_ACTION_CHANGED: return "IA2_EVENT_ACTION_CHANGED";
+                       case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED: return "IA2_EVENT_HYPERLINK_START_INDEX_CHANGED";
+                       case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED: return "IA2_EVENT_HYPERLINK_END_INDEX_CHANGED";
+                       case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED: return "IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED";
+                       case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED: return "IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED";
+                       case ACC.EVENT_HYPERLINK_ACTIVATED: return "IA2_EVENT_HYPERLINK_ACTIVATED";
+                       case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED: return "IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED";
+                       case ACC.EVENT_ATTRIBUTE_CHANGED: return "IA2_EVENT_ATTRIBUTE_CHANGED";
+                       case ACC.EVENT_TABLE_CAPTION_CHANGED: return "IA2_EVENT_TABLE_CAPTION_CHANGED";
+                       case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED: return "IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED";
+                       case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED: return "IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED";
+                       case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED: return "IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED";
+                       case ACC.EVENT_TABLE_ROW_HEADER_CHANGED: return "IA2_EVENT_TABLE_ROW_HEADER_CHANGED";
+                       case ACC.EVENT_TABLE_SUMMARY_CHANGED: return "IA2_EVENT_TABLE_SUMMARY_CHANGED";
+                       case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED: return "IA2_EVENT_TEXT_ATTRIBUTE_CHANGED";
+                       case ACC.EVENT_TEXT_CARET_MOVED: return "IA2_EVENT_TEXT_CARET_MOVED";
+                       case ACC.EVENT_TEXT_COLUMN_CHANGED: return "IA2_EVENT_TEXT_COLUMN_CHANGED";
+               }
+               return "Unknown event (" + event + ")";
+       }
+       private String hresult(int code) {
+               if (DEBUG) switch (code) {
+                       case COM.S_OK: return " S_OK";
+                       case COM.S_FALSE: return " S_FALSE";
+                       case COM.E_ACCESSDENIED: return " E_ACCESSDENIED";
+                       case COM.E_FAIL: return " E_FAIL";
+                       case COM.E_INVALIDARG: return " E_INVALIDARG";
+                       case COM.E_NOINTERFACE: return " E_NOINTERFACE";
+                       case COM.E_NOTIMPL: return " E_NOTIMPL";
+                       case COM.E_NOTSUPPORTED: return " E_NOTSUPPORTED";
+                       case COM.E_OUTOFMEMORY: return " E_OUTOFMEMORY";
+                       case OS.E_POINTER: return " E_POINTER";
+                       case COM.DISP_E_EXCEPTION: return " DISP_E_EXCEPTION";
+                       case COM.DISP_E_MEMBERNOTFOUND: return " DISP_E_MEMBERNOTFOUND";
+                       case COM.DISP_E_UNKNOWNINTERFACE: return " DISP_E_UNKNOWNINTERFACE";
+                       case COM.DISP_E_UNKNOWNNAME: return " DISP_E_UNKNOWNNAME";
+               }
+               return " HRESULT=" + code;
+       }
+       boolean interesting(GUID guid) {
+               if (DEBUG) {
+               if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) return true;
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleContext)) return true;
+               }
+               return false;
+       }
+       String guidString(GUID guid) {
+               if (DEBUG) {
+               final GUID IIDIAccessibleHandler = IIDFromString("{03022430-ABC4-11D0-BDE2-00AA001A1953}"); //$NON-NLS-1$
+               final GUID IIDIAccessor = IIDFromString("{0C733A8C-2A1C-11CE-ADE5-00AA0044773D}"); //$NON-NLS-1$
+               final GUID IIDIAdviseSink2 = IIDFromString("{00000125-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIBindCtx = IIDFromString("{0000000E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDICreateErrorInfo = IIDFromString("{22F03340-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
+               final GUID IIDICreateTypeInfo = IIDFromString("{00020405-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDICreateTypeLib = IIDFromString("{00020406-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIDataAdviseHolder = IIDFromString("{00000110-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIEnumConnectionPoints = IIDFromString("{B196B285-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+               final GUID IIDIEnumConnections = IIDFromString("{B196B287-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+               final GUID IIDIEnumMoniker = IIDFromString("{00000102-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIEnumOLEVERB = IIDFromString("{00000104-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIEnumSTATDATA = IIDFromString("{00000105-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIEnumSTATSTG = IIDFromString("{0000000D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIEnumString = IIDFromString("{00000101-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIEnumUnknown = IIDFromString("{00000100-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIErrorInfo = IIDFromString("{1CF2B120-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
+               final GUID IIDIErrorLog = IIDFromString("{3127CA40-446E-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
+               final GUID IIDIExternalConnection = IIDFromString("{00000019-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIFontDisp = IIDFromString("{BEF6E003-A874-101A-8BBA-00AA00300CAB}"); //$NON-NLS-1$
+               final GUID IIDILockBytes = IIDFromString("{0000000A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIMalloc = IIDFromString("{00000002-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIMallocSpy = IIDFromString("{0000001D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIMarshal = IIDFromString("{00000003-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIMessageFilter = IIDFromString("{00000016-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIMoniker = IIDFromString("{0000000F-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIOleAdviseHolder = IIDFromString("{00000111-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIOleCache = IIDFromString("{0000011E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIOleCache2 = IIDFromString("{00000128-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIOleCacheControl = IIDFromString("{00000129-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIOleItemContainer = IIDFromString("{0000011C-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIParseDisplayName = IIDFromString("{0000011A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIPerPropertyBrowsing = IIDFromString("{376BD3AA-3845-101B-84ED-08002B2EC713}"); //$NON-NLS-1$
+               final GUID IIDIPersistMemory = IIDFromString("{BD1AE5E0-A6AE-11CE-BD37-504200C10000}"); //$NON-NLS-1$
+               final GUID IIDIPersistPropertyBag = IIDFromString("{37D84F60-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
+               final GUID IIDIPicture = IIDFromString("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$
+               final GUID IIDIPictureDisp = IIDFromString("{7BF80981-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$
+               final GUID IIDIPropertyBag = IIDFromString("{55272A00-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
+               final GUID IIDIPropertyPage = IIDFromString("{B196B28D-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+               final GUID IIDIPropertyPage2 = IIDFromString("{01E44665-24AC-101B-84ED-08002B2EC713}"); //$NON-NLS-1$
+               final GUID IIDIPropertyPageSite = IIDFromString("{B196B28C-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+               final GUID IIDIPSFactoryBuffer = IIDFromString("{D5F569D0-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+               final GUID IIDIRootStorage = IIDFromString("{00000012-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIROTData = IIDFromString("{F29F6BC0-5021-11CE-AA15-00006901293F}"); //$NON-NLS-1$
+               final GUID IIDIRpcChannelBuffer = IIDFromString("{D5F56B60-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+               final GUID IIDIRpcProxyBuffer = IIDFromString("{D5F56A34-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+               final GUID IIDIRpcStubBuffer = IIDFromString("{D5F56AFC-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+               final GUID IIDIRunnableObject = IIDFromString("{00000126-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIRunningObjectTable = IIDFromString("{00000010-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDISimpleFrameSite = IIDFromString("{742B0E01-14E6-101B-914E-00AA00300CAB}"); //$NON-NLS-1$
+               final GUID IIDIStdMarshalInfo = IIDFromString("{00000018-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDISupportErrorInfo = IIDFromString("{DF0B3D60-548F-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
+               final GUID IIDITypeComp = IIDFromString("{00020403-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDITypeLib = IIDFromString("{00020402-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIViewObject = IIDFromString("{0000010D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDIdentityUnmarshal = IIDFromString("{0000001b-0000-0000-c000-000000000046}"); //$NON-NLS-1$
+               final GUID IIDInternalMSMarshaller = IIDFromString("{4c1e39e1-e3e3-4296-aa86-ec938d896e92}"); //$NON-NLS-1$
+               final GUID IIDIAccIdentity = IIDFromString("{7852B78D-1CFD-41C1-A615-9C0C85960B5F}"); //$NON-NLS-1$
+               final GUID IIDIAccPropServer = IIDFromString("{76C0DBBB-15E0-4E7B-B61B-20EEEA2001E0}"); //$NON-NLS-1$
+               final GUID IIDIAccPropServices = IIDFromString("{6E26E776-04F0-495D-80E4-3330352E3169}"); //$NON-NLS-1$
+               if (COM.IsEqualGUID(guid, COM.IID_IDropTargetHelper)) return "IID_IDropTargetHelper";
+               if (COM.IsEqualGUID(guid, COM.IIDJavaBeansBridge)) return "IIDJavaBeansBridge";
+               if (COM.IsEqualGUID(guid, COM.IIDShockwaveActiveXControl)) return "IIDShockwaveActiveXControl";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) return "IIDIAccessible";
+               if (COM.IsEqualGUID(guid, IIDIAccessibleHandler)) return "IIDIAccessibleHandler";
+               if (COM.IsEqualGUID(guid, IIDIAccessor)) return "IIDIAccessor";
+               if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) return "IIDIAdviseSink";
+               if (COM.IsEqualGUID(guid, IIDIAdviseSink2)) return "IIDIAdviseSink2";
+               if (COM.IsEqualGUID(guid, IIDIBindCtx)) return "IIDIBindCtx";
+               if (COM.IsEqualGUID(guid, COM.IIDIClassFactory)) return "IIDIClassFactory";
+               if (COM.IsEqualGUID(guid, COM.IIDIClassFactory2)) return "IIDIClassFactory2";
+               if (COM.IsEqualGUID(guid, COM.IIDIConnectionPointContainer)) return "IIDIConnectionPointContainer";
+               if (COM.IsEqualGUID(guid, IIDICreateErrorInfo)) return "IIDICreateErrorInfo";
+               if (COM.IsEqualGUID(guid, IIDICreateTypeInfo)) return "IIDICreateTypeInfo";
+               if (COM.IsEqualGUID(guid, IIDICreateTypeLib)) return "IIDICreateTypeLib";
+               if (COM.IsEqualGUID(guid, IIDIDataAdviseHolder)) return "IIDIDataAdviseHolder";
+               if (COM.IsEqualGUID(guid, COM.IIDIDataObject)) return "IIDIDataObject";
+               if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) return "IIDIDispatch";
+               if (COM.IsEqualGUID(guid, COM.IIDIDispatchEx)) return "IIDIDispatchEx";
+               if (COM.IsEqualGUID(guid, COM.IIDIDocHostUIHandler)) return "IIDIDocHostUIHandler";
+               if (COM.IsEqualGUID(guid, COM.IIDIDocHostShowUI)) return "IIDIDocHostShowUI";
+               if (COM.IsEqualGUID(guid, COM.IIDIDropSource)) return "IIDIDropSource";
+               if (COM.IsEqualGUID(guid, COM.IIDIDropTarget)) return "IIDIDropTarget";
+               if (COM.IsEqualGUID(guid, IIDIEnumConnectionPoints)) return "IIDIEnumConnectionPoints";
+               if (COM.IsEqualGUID(guid, IIDIEnumConnections)) return "IIDIEnumConnections";
+               if (COM.IsEqualGUID(guid, COM.IIDIEnumFORMATETC)) return "IIDIEnumFORMATETC";
+               if (COM.IsEqualGUID(guid, IIDIEnumMoniker)) return "IIDIEnumMoniker";
+               if (COM.IsEqualGUID(guid, IIDIEnumOLEVERB)) return "IIDIEnumOLEVERB";
+               if (COM.IsEqualGUID(guid, IIDIEnumSTATDATA)) return "IIDIEnumSTATDATA";
+               if (COM.IsEqualGUID(guid, IIDIEnumSTATSTG)) return "IIDIEnumSTATSTG";
+               if (COM.IsEqualGUID(guid, IIDIEnumString)) return "IIDIEnumString";
+               if (COM.IsEqualGUID(guid, IIDIEnumUnknown)) return "IIDIEnumUnknown";
+               if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) return "IIDIEnumVARIANT";
+               if (COM.IsEqualGUID(guid, IIDIErrorInfo)) return "IIDIErrorInfo";
+               if (COM.IsEqualGUID(guid, IIDIErrorLog)) return "IIDIErrorLog";
+               if (COM.IsEqualGUID(guid, IIDIExternalConnection)) return "IIDIExternalConnection";
+               if (COM.IsEqualGUID(guid, IIDIFontDisp)) return "IIDIFontDisp";
+       //      if (COM.IsEqualGUID(guid, COM.IIDIHTMLDocumentEvents2)) return "IIDIHTMLDocumentEvents2";
+               if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) return "IIDIInternetSecurityManager";
+               if (COM.IsEqualGUID(guid, COM.IIDIAuthenticate)) return "IIDIAuthenticate";
+               if (COM.IsEqualGUID(guid, COM.IIDIJScriptTypeInfo)) return "IIDIJScriptTypeInfo";
+               if (COM.IsEqualGUID(guid, IIDILockBytes)) return "IIDILockBytes";
+               if (COM.IsEqualGUID(guid, IIDIMalloc)) return "IIDIMalloc";
+               if (COM.IsEqualGUID(guid, IIDIMallocSpy)) return "IIDIMallocSpy";
+               if (COM.IsEqualGUID(guid, IIDIMarshal)) return "IIDIMarshal";
+               if (COM.IsEqualGUID(guid, IIDIMessageFilter)) return "IIDIMessageFilter";
+               if (COM.IsEqualGUID(guid, IIDIMoniker)) return "IIDIMoniker";
+               if (COM.IsEqualGUID(guid, IIDIOleAdviseHolder)) return "IIDIOleAdviseHolder";
+               if (COM.IsEqualGUID(guid, IIDIOleCache)) return "IIDIOleCache";
+               if (COM.IsEqualGUID(guid, IIDIOleCache2)) return "IIDIOleCache2";
+               if (COM.IsEqualGUID(guid, IIDIOleCacheControl)) return "IIDIOleCacheControl";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) return "IIDIOleClientSite";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleCommandTarget)) return "IIDIOleCommandTarget";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleControl)) return "IIDIOleControl";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleControlSite)) return "IIDIOleControlSite";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleDocument)) return "IIDIOleDocument";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite)) return "IIDIOleDocumentSite";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame)) return "IIDIOleInPlaceFrame";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceObject)) return "IIDIOleInPlaceObject";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) return "IIDIOleInPlaceSite";
+               if (COM.IsEqualGUID(guid, IIDIOleItemContainer)) return "IIDIOleItemContainer";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleLink)) return "IIDIOleLink";
+               if (COM.IsEqualGUID(guid, COM.IIDIOleObject)) return "IIDIOleObject";
+               if (COM.IsEqualGUID(guid, IIDIParseDisplayName)) return "IIDIParseDisplayName";
+               if (COM.IsEqualGUID(guid, IIDIPerPropertyBrowsing)) return "IIDIPerPropertyBrowsing";
+               if (COM.IsEqualGUID(guid, COM.IIDIPersist)) return "IIDIPersist";
+               if (COM.IsEqualGUID(guid, COM.IIDIPersistFile)) return "IIDIPersistFile";
+               if (COM.IsEqualGUID(guid, IIDIPersistMemory)) return "IIDIPersistMemory";
+               if (COM.IsEqualGUID(guid, IIDIPersistPropertyBag)) return "IIDIPersistPropertyBag";
+               if (COM.IsEqualGUID(guid, COM.IIDIPersistStorage)) return "IIDIPersistStorage";
+               if (COM.IsEqualGUID(guid, COM.IIDIPersistStreamInit)) return "IIDIPersistStreamInit";
+               if (COM.IsEqualGUID(guid, IIDIPicture)) return "IIDIPicture";
+               if (COM.IsEqualGUID(guid, IIDIPictureDisp)) return "IIDIPictureDisp";
+               if (COM.IsEqualGUID(guid, IIDIPropertyBag)) return "IIDIPropertyBag";
+               if (COM.IsEqualGUID(guid, COM.IIDIPropertyNotifySink)) return "IIDIPropertyNotifySink";
+               if (COM.IsEqualGUID(guid, IIDIPropertyPage)) return "IIDIPropertyPage";
+               if (COM.IsEqualGUID(guid, IIDIPropertyPage2)) return "IIDIPropertyPage2";
+               if (COM.IsEqualGUID(guid, IIDIPropertyPageSite)) return "IIDIPropertyPageSite";
+               if (COM.IsEqualGUID(guid, COM.IIDIProvideClassInfo)) return "IIDIProvideClassInfo";
+               if (COM.IsEqualGUID(guid, COM.IIDIProvideClassInfo2)) return "IIDIProvideClassInfo2";
+               if (COM.IsEqualGUID(guid, IIDIPSFactoryBuffer)) return "IIDIPSFactoryBuffer";
+               if (COM.IsEqualGUID(guid, IIDIRootStorage)) return "IIDIRootStorage";
+               if (COM.IsEqualGUID(guid, IIDIROTData)) return "IIDIROTData";
+               if (COM.IsEqualGUID(guid, IIDIRpcChannelBuffer)) return "IIDIRpcChannelBuffer";
+               if (COM.IsEqualGUID(guid, IIDIRpcProxyBuffer)) return "IIDIRpcProxyBuffer";
+               if (COM.IsEqualGUID(guid, IIDIRpcStubBuffer)) return "IIDIRpcStubBuffer";
+               if (COM.IsEqualGUID(guid, IIDIRunnableObject)) return "IIDIRunnableObject";
+               if (COM.IsEqualGUID(guid, IIDIRunningObjectTable)) return "IIDIRunningObjectTable";
+               if (COM.IsEqualGUID(guid, IIDISimpleFrameSite)) return "IIDISimpleFrameSite";
+               if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) return "IIDIServiceProvider";
+               if (COM.IsEqualGUID(guid, COM.IIDISpecifyPropertyPages)) return "IIDISpecifyPropertyPages";
+               if (COM.IsEqualGUID(guid, IIDIStdMarshalInfo)) return "IIDIStdMarshalInfo";
+               if (COM.IsEqualGUID(guid, IIDISupportErrorInfo)) return "IIDISupportErrorInfo";
+               if (COM.IsEqualGUID(guid, IIDITypeComp)) return "IIDITypeComp";
+               if (COM.IsEqualGUID(guid, IIDITypeLib)) return "IIDITypeLib";
+               if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) return "IIDIUnknown";
+               if (COM.IsEqualGUID(guid, IIDIViewObject)) return "IIDIViewObject";
+               if (COM.IsEqualGUID(guid, COM.IIDIViewObject2)) return "IIDIViewObject2";
+               if (COM.IsEqualGUID(guid, COM.CGID_DocHostCommandHandler)) return "CGID_DocHostCommandHandler";
+               if (COM.IsEqualGUID(guid, COM.CGID_Explorer)) return "CGID_Explorer";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) return "IIDIAccessible2";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) return "IIDIAccessibleRelation";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) return "IIDIAccessibleAction";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) return "IIDIAccessibleComponent";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) return "IIDIAccessibleValue";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) return "IIDIAccessibleText";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) return "IIDIAccessibleEditableText";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) return "IIDIAccessibleHyperlink";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) return "IIDIAccessibleHypertext";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) return "IIDIAccessibleTable";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) return "IIDIAccessibleTable2";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) return "IIDIAccessibleTableCell";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) return "IIDIAccessibleImage";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) return "IIDIAccessibleApplication";
+               if (COM.IsEqualGUID(guid, COM.IIDIAccessibleContext)) return "IIDIAccessibleContext";
+               if (COM.IsEqualGUID(guid, IIDIdentityUnmarshal)) return "IIDIdentityUnmarshal";
+               if (COM.IsEqualGUID(guid, IIDInternalMSMarshaller)) return "IIDInternalMSMarshaller";
+               if (COM.IsEqualGUID(guid, IIDIAccIdentity)) return "IIDIAccIdentity";
+               if (COM.IsEqualGUID(guid, IIDIAccPropServer)) return "IIDIAccPropServer";
+               if (COM.IsEqualGUID(guid, IIDIAccPropServices)) return "IIDIAccPropServices";
+               }
+               return guid.toString();
+       }
+       static GUID IIDFromString(String lpsz) {
+               if (DEBUG) {
+               int length = lpsz.length();
+               char[] buffer = new char[length + 1];
+               lpsz.getChars(0, length, buffer, 0);
+               GUID lpiid = new GUID();
+               if (COM.IIDFromString(buffer, lpiid) == COM.S_OK) return lpiid;
+               }
+               return null;
+       }
+       @Override
+       public String toString () {
+               String toString = super.toString();
+               if (DEBUG) {
+                       int role = getRole();
+                       if (role == 0) role = getDefaultRole();
+                       return toString.substring(toString.lastIndexOf('.') + 1) + "(" + getRoleString(role) + ")";
+               }
+               return toString;
+       }
+       // END DEBUG CODE
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionAdapter.java
new file mode 100644 (file)
index 0000000..68c78d5
--- /dev/null
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleActionListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleAction</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleActionListener
+ * @see AccessibleActionEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleActionAdapter implements AccessibleActionListener {
+       /**
+        * Returns the number of accessible actions available in this object.
+        * <p>
+        * If there are more than one, the first one (index 0) is considered the
+        * "default" action of the object.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of actions, or zero if there are no actions</li>
+        * </ul>
+        */
+       @Override
+       public void getActionCount(AccessibleActionEvent e) {}
+
+       /**
+        * Performs the specified action on the object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying the action to perform.
+        *              If the index lies outside the valid range no action is performed.</li>
+        * <li>[out] result - set to {@link ACC#OK} if the action was performed.</li>
+        * </ul>
+        */
+       @Override
+       public void doAction(AccessibleActionEvent e) {}
+
+       /**
+        * Returns a description of the specified action.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying which action's description to return</li>
+        * <li>[out] result - a localized string describing the specified action,
+        *              or null if the index lies outside the valid range</li>
+        * </ul>
+        */
+       @Override
+       public void getDescription(AccessibleActionEvent e) {}
+
+       /**
+        * Returns a string representing one or more key bindings, if there
+        * are any, associated with the specified action.
+        * <p>
+        * The returned string is of the following form: mnemonic;accelerator
+        * for example: "C;CTRL+C" for the Copy item in a typical Edit menu.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying which action's key bindings to return</li>
+        * <li>[out] result - a semicolon-delimited string of localized key bindings
+        *              (example: "C;CTRL+C"), or null if the index lies outside the valid range</li>
+        * </ul>
+        */
+       @Override
+       public void getKeyBinding(AccessibleActionEvent e) {}
+
+       /**
+        * Returns the name of the specified action.
+        * <p>
+        * There is no need to implement this method for single action controls
+        * since that would be redundant with AccessibleControlListener.getDefaultAction.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying which action's name to return</li>
+        * <li>[in] localized - a boolean indicating whether or not to return a localized name</li>
+        * <li>[out] result - the name of the specified action,
+        *              or null if the index lies outside the valid range</li>
+        * </ul>
+        */
+       @Override
+       public void getName(AccessibleActionEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionEvent.java
new file mode 100644 (file)
index 0000000..7781cf3
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleAction messages to an accessible object.
+ *
+ * @see AccessibleActionListener
+ * @see AccessibleActionAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleActionEvent extends EventObject {
+
+       /**
+        * The value of this field must be set in the accessible action listener method
+        * before returning. What to set it to depends on the listener method called.
+        */
+       public String result;
+       public int count;
+       public int index;
+       public boolean localized;
+
+       static final long serialVersionUID = 2849066792640153087L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleActionEvent(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 "AccessibleActionEvent {" //$NON-NLS-1$
+               + "string=" + result   //$NON-NLS-1$
+               + " count=" + count   //$NON-NLS-1$
+               + " index=" + index   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleActionListener.java
new file mode 100644 (file)
index 0000000..5e2e52a
--- /dev/null
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleAction events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleActionListener</code> method and removed using
+ * the <code>removeAccessibleActionListener</code> method.
+ * </p>
+ *
+ * @see AccessibleActionAdapter
+ * @see AccessibleActionEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleActionListener extends SWTEventListener {
+       /**
+        * Returns the number of accessible actions available in this object.
+        * <p>
+        * If there are more than one, the first one (index 0) is considered the
+        * "default" action of the object.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of actions, or zero if there are no actions</li>
+        * </ul>
+        */
+       public void getActionCount(AccessibleActionEvent e);
+
+       /**
+        * Performs the specified action on the object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying the action to perform.
+        *              If the index lies outside the valid range no action is performed.</li>
+        * <li>[out] result - set to {@link ACC#OK} if the action was performed.</li>
+        * </ul>
+        */
+       public void doAction(AccessibleActionEvent e);
+
+       /**
+        * Returns a description of the specified action.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying which action's description to return</li>
+        * <li>[out] result - a localized string describing the specified action,
+        *              or null if the index lies outside the valid range</li>
+        * </ul>
+        */
+       public void getDescription(AccessibleActionEvent e);
+
+       /**
+        * Returns a string representing one or more key bindings, if there
+        * are any, associated with the specified action.
+        * <p>
+        * The returned string is of the following form: mnemonic;accelerator
+        * for example: "C;CTRL+C" for the Copy item in a typical Edit menu.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying which action's key bindings to return</li>
+        * <li>[out] result - a semicolon-delimited string of localized key bindings
+        *              (example: "C;CTRL+C"), or null if the index lies outside the valid range</li>
+        * </ul>
+        */
+       public void getKeyBinding(AccessibleActionEvent e);
+
+       /**
+        * Returns the name of the specified action.
+        * <p>
+        * There is no need to implement this method for single action controls
+        * since that would be redundant with AccessibleControlListener.getDefaultAction.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index specifying which action's name to return</li>
+        * <li>[in] localized - a boolean indicating whether or not to return a localized name</li>
+        * <li>[out] result - the name of the specified action,
+        *              or null if the index lies outside the valid range</li>
+        * </ul>
+        */
+       public void getName(AccessibleActionEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAdapter.java
new file mode 100644 (file)
index 0000000..8a7d145
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+/**
+ * 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 implements 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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       public void getDescription(AccessibleEvent e) {
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeAdapter.java
new file mode 100644 (file)
index 0000000..895a9e0
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleAttributeListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleAttribute</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleAttributeListener
+ * @see AccessibleAttributeEvent
+ * @see AccessibleTextAttributeEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleAttributeAdapter implements AccessibleAttributeListener {
+       /**
+        * Returns attributes specific to this Accessible object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] topMargin - the top margin in pixels</li>
+        * <li>[out] bottomMargin - the bottom margin in pixels</li>
+        * <li>[out] leftMargin - the left margin in pixels</li>
+        * <li>[out] rightMargin - the right margin in pixels</li>
+        * <li>[out] tabStops - an array of pixel locations</li>
+        * <li>[out] justify - whether or not to justify the text</li>
+        * <li>[out] alignment - one of <code>SWT#LEFT</code>, <code>SWT#RIGHT</code> or <code>SWT#CENTER</code></li>
+        * <li>[out] indent - the indent in pixels</li>
+        * <li>[out] groupLevel - the level of this accessible in its group</li>
+        * <li>[out] groupCount - the number of similar children in this accessible's group</li>
+        * <li>[out] groupIndex - the index of this accessible in its group</li>
+        * <li>[out] attributes - an array of alternating key and value Strings
+        *              which represent additional (i.e. non predefined) attributes</li>
+        * </ul>
+        */
+       @Override
+       public void getAttributes(AccessibleAttributeEvent e) {}
+
+       /**
+        * Returns text attributes specific to this Accessible object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] offset - the 0 based text offset for which to return attribute information</li>
+        * <li>[out] start - the 0 based starting offset of the character range
+        *              over which all text attributes match those of offset</li>
+        * <li>[out] end - the 0 based offset after the last character of the character range
+        *              over which all text attributes match those of offset</li>
+        * <li>[out] textStyle - the TextStyle of the character range</li>
+        * <li>[out] attributes - an array of alternating key and value Strings
+        *              that represent additional attributes that do not correspond to TextStyle fields</li>
+        * </ul>
+        */
+       @Override
+       public void getTextAttributes(AccessibleTextAttributeEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeEvent.java
new file mode 100644 (file)
index 0000000..8de1451
--- /dev/null
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleAttribute messages to an accessible object.
+ *
+ * @see AccessibleAttributeListener
+ * @see AccessibleAttributeAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleAttributeEvent extends EventObject {
+
+       /**
+        * [out] the top margin in pixels
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int topMargin;
+
+       /**
+        * [out] the bottom margin in pixels
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int bottomMargin;
+
+       /**
+        * [out] the left margin in pixels
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int leftMargin;
+
+       /**
+        * [out] the right margin in pixels
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int rightMargin;
+
+       /**
+        * [out] an array of pixel locations representing tab stops
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int[] tabStops;
+
+       /**
+        * [out] whether or not to justify the text
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public boolean justify;
+
+       /**
+        * [out] the alignment, which is one of SWT#LEFT, SWT#RIGHT or SWT#CENTER
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int alignment;
+
+       /**
+        * [out] the indent in pixels
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public int indent;
+
+       /**
+        * [out] the 1-based level of this accessible in its group
+        *  (0 means "not applicable")
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        * @since 3.102
+        */
+       public int groupLevel;
+       /**
+        * [out] the 1-based number of similar children in this accessible's group,
+        * including this accessible (0 means "not applicable")
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        * @since 3.102
+        */
+       public int groupCount;
+       /**
+        * [out] the 1-based index of this accessible in its group
+        *  (0 means "not applicable")
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        * @since 3.102
+        */
+       public int groupIndex;
+
+       /**
+        * [out] an array of alternating key and value Strings which
+        * represent additional (i.e. non predefined) attributes
+        *
+        * @see AccessibleAttributeListener#getAttributes
+        */
+       public String [] attributes;
+
+       static final long serialVersionUID = -2894665777259297851L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleAttributeEvent(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 "AccessibleAttributeEvent {" //$NON-NLS-1$
+               + " topMargin=" + topMargin   //$NON-NLS-1$
+               + " bottomMargin=" + bottomMargin   //$NON-NLS-1$
+               + " leftMargin=" + leftMargin   //$NON-NLS-1$
+               + " rightMargin=" + rightMargin   //$NON-NLS-1$
+               + " tabStops=" + tabStops   //$NON-NLS-1$
+               + " justify=" + justify   //$NON-NLS-1$
+               + " alignment=" + alignment   //$NON-NLS-1$
+               + " indent=" + indent   //$NON-NLS-1$
+               + " groupLevel=" + groupLevel   //$NON-NLS-1$
+               + " groupCount=" + groupCount   //$NON-NLS-1$
+               + " groupIndex=" + groupIndex   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleAttributeListener.java
new file mode 100644 (file)
index 0000000..936f022
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleAttribute events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleAttributeListener</code> method and removed using
+ * the <code>removeAccessibleAttributeListener</code> method.
+ * </p>
+ *
+ * @see AccessibleAttributeAdapter
+ * @see AccessibleAttributeEvent
+ * @see AccessibleTextAttributeEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleAttributeListener extends SWTEventListener {
+       /**
+        * Returns attributes specific to this Accessible object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] topMargin - the top margin in pixels</li>
+        * <li>[out] bottomMargin - the bottom margin in pixels</li>
+        * <li>[out] leftMargin - the left margin in pixels</li>
+        * <li>[out] rightMargin - the right margin in pixels</li>
+        * <li>[out] tabStops - an array of pixel locations</li>
+        * <li>[out] justify - whether or not to justify the text</li>
+        * <li>[out] alignment - one of <code>SWT#LEFT</code>, <code>SWT#RIGHT</code> or <code>SWT#CENTER</code></li>
+        * <li>[out] indent - the indent in pixels</li>
+        * <li>[out] groupLevel - the level of this accessible in its group</li>
+        * <li>[out] groupCount - the number of similar children in this accessible's group</li>
+        * <li>[out] groupIndex - the index of this accessible in its group</li>
+        * <li>[out] attributes - an array of alternating key and value Strings
+        *              which represent additional (i.e. non predefined) attributes</li>
+        * </ul>
+        */
+       public void getAttributes(AccessibleAttributeEvent e);
+
+       /**
+        * Returns text attributes specific to this Accessible object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] offset - the 0 based text offset for which to return attribute information</li>
+        * <li>[out] start - the 0 based starting offset of the character range
+        *              over which all text attributes match those of offset</li>
+        * <li>[out] end - the 0 based offset after the last character of the character range
+        *              over which all text attributes match those of offset</li>
+        * <li>[out] textStyle - the TextStyle of the character range</li>
+        * <li>[out] attributes - an array of alternating key and value Strings
+        *              that represent additional attributes that do not correspond to TextStyle fields</li>
+        * </ul>
+        */
+       public void getTextAttributes(AccessibleTextAttributeEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlAdapter.java
new file mode 100644 (file)
index 0000000..b1de1ec
--- /dev/null
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+/**
+ * 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 implements 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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       public void getLocation(AccessibleControlEvent e) {
+       }
+
+       /**
+        * Sent when an accessibility client requests the accessible object
+        * for a child of the control by index or childID, or when a client
+        * requests the index of an accessible object in its parent.
+        * <p>
+        * The childID field in the event object can be one of the following:</p>
+        * <ul>
+        *    <li>an integer child ID - return the accessible object for the specified child ID,
+        *      or null if the specified child does not have its own accessible</li>
+        *    <li>{@link ACC#CHILDID_CHILD_AT_INDEX} - return the accessible child object at the specified index,
+        *      or null if this object has no children</li>
+        *    <li>{@link ACC#CHILDID_CHILD_INDEX} - return the index of this accessible in its parent</li>
+        * </ul>
+        *
+        * @param e an event object containing the following fields:<ul>
+        *    <li>childID [IN] - an identifier specifying a child of the control, or one of the predefined CHILDID constants</li>
+        *    <li>detail [Optional IN] - the index of the child accessible to be returned when childID = CHILDID_CHILD_AT_INDEX</li>
+        *    <li>detail [Optional OUT] - the index of this accessible in its parent when childID = CHILDID_CHILD_INDEX</li>
+        *    <li>accessible [Optional OUT] - an Accessible for the specified childID or index, or null if one does not exist</li>
+        * </ul>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>children [Optional OUT] - the array of childIDs for the selected children if CHILDID_MULTIPLE is returned</li>
+        *    <li>accessible [Optional OUT] - the accessible object for the control or child may be returned instead of the childID</li>
+        * </ul>
+        */
+       @Override
+       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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       public void getValue(AccessibleControlEvent e) {
+       }
+
+       /**
+        * Sent when an accessibility client requests the children, or visible children,
+        * of the control. The default behavior is to do nothing.
+        * <p>
+        * Return the children as an array of childIDs or accessibles in the
+        * <code>children</code> field of the event object.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        *    <li>detail [IN] - a flag that may have one of the following values:<ul>
+        *      <li>0 (default) - return all children</li>
+        *      <li>VISIBLE - return all visible children</li>
+        *    </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>
+        */
+       @Override
+       public void getChildren(AccessibleControlEvent e) {
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlEvent.java
new file mode 100644 (file)
index 0000000..8ca3ccc
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import java.util.*;
+
+/**
+ * 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 extends EventObject {
+       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 AccessibleControlEvent(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 "AccessibleControlEvent {childID=" + childID +  //$NON-NLS-1$
+               " accessible=" + accessible +  //$NON-NLS-1$
+               " x=" + x +  //$NON-NLS-1$
+               " y=" + y +  //$NON-NLS-1$
+               " width=" + width +  //$NON-NLS-1$
+               " height=" + height +  //$NON-NLS-1$
+               " detail=" + detail +  //$NON-NLS-1$
+               " result=" + result +  //$NON-NLS-1$
+               "}"; //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleControlListener.java
new file mode 100644 (file)
index 0000000..e938a35
--- /dev/null
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 extends 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 by index or childID, or when a client
+        * requests the index of an accessible object in its parent.
+        * <p>
+        * The childID field in the event object can be one of the following:</p>
+        * <ul>
+        *    <li>an integer child ID - return the accessible object for the specified child ID,
+        *      or null if the specified child does not have its own accessible</li>
+        *    <li>{@link ACC#CHILDID_CHILD_AT_INDEX} - return the accessible child object at the specified index,
+        *      or null if this object has no children</li>
+        *    <li>{@link ACC#CHILDID_CHILD_INDEX} - return the index of this accessible in its parent</li>
+        * </ul>
+        *
+        * @param e an event object containing the following fields:<ul>
+        *    <li>childID [IN] - an identifier specifying a child of the control, or one of the predefined CHILDID constants</li>
+        *    <li>detail [Optional IN] - the index of the child accessible to be returned when childID = CHILDID_CHILD_AT_INDEX</li>
+        *    <li>detail [Optional OUT] - the index of this accessible in its parent when childID = CHILDID_CHILD_INDEX</li>
+        *    <li>accessible [Optional OUT] - an Accessible for the specified childID or index, 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>children [Optional OUT] - the array of childIDs for the selected children if CHILDID_MULTIPLE is returned</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, or visible children,
+        * of the control.
+        * <p>
+        * Return the children as an array of childIDs or accessibles in the
+        * <code>children</code> field of the event object.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        *    <li>detail [IN] - a flag that may have one of the following values:<ul>
+        *      <li>0 (default) - return all children</li>
+        *      <li>VISIBLE - return all visible children</li>
+        *    </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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextAdapter.java
new file mode 100644 (file)
index 0000000..6c70b12
--- /dev/null
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleEditableTextListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleEditableText</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleEditableTextListener
+ * @see AccessibleEditableTextEvent
+ * @see AccessibleTextAttributeEvent
+ *
+ * @since 3.7
+ */
+public class AccessibleEditableTextAdapter implements AccessibleEditableTextListener {
+       /**
+        * Copies the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> to the clipboard.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              to be copied to the clipboard</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              to be copied to the clipboard</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       @Override
+       public void copyText(AccessibleEditableTextEvent e) {}
+
+       /**
+        * Moves the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> to the clipboard.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              to be moved to the clipboard</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              to be moved to the clipboard</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       @Override
+       public void cutText(AccessibleEditableTextEvent e) {}
+
+       /**
+        * Inserts the text in the clipboard at the leading edge of the specified <code>start</code> offset.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the offset at which to insert the text from the clipboard.
+        *              The valid range is 0..length</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       @Override
+       public void pasteText(AccessibleEditableTextEvent e) {}
+
+       /**
+        * Replaces the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> by the specified string.
+        * <p>
+        * This event notification is also used to delete text if <code>string</code> is an empty string,
+        * or to insert text at the leading edge of the specified offset if <code>start</code> and <code>end</code> are equal.
+        * </p>
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              to be replaced</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              to be replaced</li>
+        * <li>[in] string - the string that replaces the substring beginning at
+        *              <code>start</code> and extending to <code>end - 1</code></li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       @Override
+       public void replaceText(AccessibleEditableTextEvent e) {}
+
+       /**
+        * Replaces the set of attributes of the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> by the specified set of attributes.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              whose attributes are modified</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              whose attributes are modified</li>
+        * <li>[in] textStyle - the TextStyle which contains attributes that replace the old set of attributes.
+        *              The foreground, background, and font fields of this TextStyle are only valid for the duration of the event.
+        *              The value of this field may be null if none of the attributes to be set correspond to TextStyle fields.</li>
+        * <li>[in] attributes - an array of alternating key and value Strings that represent the complete
+        *              set of attributes to replace the old set of attributes.
+        *              The value of this field may be null if no attributes are to be set.</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       @Override
+       public void setTextAttributes(AccessibleTextAttributeEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextEvent.java
new file mode 100644 (file)
index 0000000..d874a0a
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleEditableText messages to an accessible object.
+ *
+ * @see AccessibleEditableTextListener
+ * @see AccessibleEditableTextAdapter
+ *
+ * @since 3.7
+ */
+public class AccessibleEditableTextEvent extends EventObject {
+
+       /**
+        * [in] 0-based start offset of the character range to perform
+        * the operation on
+        *
+        * @see AccessibleEditableTextListener#copyText
+        * @see AccessibleEditableTextListener#cutText
+        * @see AccessibleEditableTextListener#pasteText
+        * @see AccessibleEditableTextListener#replaceText
+        */
+       public int start;
+
+       /**
+        * [in] 0-based ending offset of the character range to perform
+        * the operation on
+        *
+        * @see AccessibleEditableTextListener#copyText
+        * @see AccessibleEditableTextListener#cutText
+        * @see AccessibleEditableTextListener#replaceText
+        */
+       public int end;
+
+       /**
+        * [in] a string that will replace the specified character range
+        *
+        * @see AccessibleEditableTextListener#replaceText
+        */
+       public String string;
+
+       /**
+        * [out] Set this field to {@link ACC#OK} if the operation
+        * was completed successfully, and <code>null</code> otherwise.
+        *
+        * @see AccessibleEditableTextListener#copyText
+        * @see AccessibleEditableTextListener#cutText
+        * @see AccessibleEditableTextListener#pasteText
+        * @see AccessibleEditableTextListener#replaceText
+        */
+       public String result;
+
+       static final long serialVersionUID = -5045447704486894646L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleEditableTextEvent(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 "AccessibleEditableTextEvent {" //$NON-NLS-1$
+               + "start=" + start   //$NON-NLS-1$
+               + " end=" + end   //$NON-NLS-1$
+               + " string=" + string   //$NON-NLS-1$
+               + " result=" + result   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEditableTextListener.java
new file mode 100644 (file)
index 0000000..c7a930b
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleEditableText events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleEditableTextListener</code> method and removed using
+ * the <code>removeAccessibleEditableTextListener</code> method.
+ * </p>
+ *
+ * @see AccessibleEditableTextAdapter
+ * @see AccessibleEditableTextEvent
+ * @see AccessibleTextAttributeEvent
+ *
+ * @since 3.7
+ */
+public interface AccessibleEditableTextListener extends SWTEventListener {
+       /**
+        * Copies the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> to the clipboard.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              to be copied to the clipboard</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              to be copied to the clipboard</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       public void copyText(AccessibleEditableTextEvent e);
+
+       /**
+        * Moves the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> to the clipboard.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              to be moved to the clipboard</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              to be moved to the clipboard</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       public void cutText(AccessibleEditableTextEvent e);
+
+       /**
+        * Inserts the text in the clipboard at the leading edge of the specified <code>start</code> offset.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the offset at which to insert the text from the clipboard.
+        *              The valid range is 0..length</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       public void pasteText(AccessibleEditableTextEvent e);
+
+       /**
+        * Replaces the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> by the specified string.
+        * <p>
+        * This event notification is also used to delete text if <code>string</code> is an empty string,
+        * or to insert text at the leading edge of the specified offset if <code>start</code> and <code>end</code> are equal.
+        * </p>
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              to be replaced</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              to be replaced</li>
+        * <li>[in] string - the string that replaces the substring beginning at
+        *              <code>start</code> and extending to <code>end - 1</code></li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       public void replaceText(AccessibleEditableTextEvent e);
+
+       /**
+        * Replaces the set of attributes of the substring beginning at the specified <code>start</code> offset
+        * and extending to the character at offset <code>end - 1</code> by the specified set of attributes.
+        *
+        * @param e an event object containing the following information:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring
+        *              whose attributes are modified</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring
+        *              whose attributes are modified</li>
+        * <li>[in] textStyle - the TextStyle which contains attributes that replace the old set of attributes.
+        *              The foreground, background, and font fields of this TextStyle are only valid for the duration of the event.
+        *              The value of this field may be null if none of the attributes to be set correspond to TextStyle fields.</li>
+        * <li>[in] attributes - an array of alternating key and value Strings that represent the complete
+        *              set of attributes to replace the old set of attributes.
+        *              The value of this field may be null if no attributes are to be set.</li>
+        * <li>[out] result - set to {@link ACC#OK} if the operation was completed successfully</li>
+        * </ul>
+        */
+       public void setTextAttributes(AccessibleTextAttributeEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleEvent.java
new file mode 100644 (file)
index 0000000..72c8ece
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import java.util.*;
+
+/**
+ * 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 extends EventObject {
+       /**
+        * 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 AccessibleEvent(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 "AccessibleEvent {childID=" + childID + " result=" + result + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkAdapter.java
new file mode 100644 (file)
index 0000000..18254f7
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleHyperlinkListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleHyperlink</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleHyperlinkListener
+ * @see AccessibleHyperlinkEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleHyperlinkAdapter implements AccessibleHyperlinkListener {
+       /**
+        * Returns the anchor for the link at the specified index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index identifying the anchor if this object
+        *              has more than one link, as in the case of an image map</li>
+        * <li>[typical out] result - the returned anchor</li>
+        * <li>[optional out] accessible - the returned anchor.
+        *              Note: The returned anchor can either be a string or an accessible.
+        *              For example, for a text link this could be the substring of the containing string
+        *              where the substring is overridden with link behavior, and for an image link this could be
+        *              the accessible for the image.</li>
+        * </ul>
+        */
+       @Override
+       public void getAnchor(AccessibleHyperlinkEvent e) {}
+
+       /**
+        * Returns the target of the link at the specified index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index identifying the anchor if this object
+        *              has more than one link, as in the case of an image map</li>
+        * <li>[typical out] result - the returned target</li>
+        * <li>[optional out] accessible - the returned target.
+        *              Note: The returned target can either be a string or an accessible.
+        *              For example, this could be a string URI, or the accessible for the target
+        *              object to be activated when the link is activated.</li>
+        * </ul>
+        */
+       @Override
+       public void getAnchorTarget(AccessibleHyperlinkEvent e) {}
+
+       /**
+        * Returns the 0 based character offset at which the textual representation of the hyperlink starts.
+        * <p>
+        * The returned value is related to the AccessibleTextExtended interface of the object that
+        * owns this hyperlink.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index</li>
+        * </ul>
+        */
+       @Override
+       public void getStartIndex(AccessibleHyperlinkEvent e) {}
+
+       /**
+        * Returns the 0 based character offset at which the textual representation of the hyperlink ends.
+        * <p>
+        * The returned value is related to the AccessibleTextExtended interface of the object that
+        * owns this hyperlink. The character at the index is not part of the hypertext.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index</li>
+        * </ul>
+        */
+       @Override
+       public void getEndIndex(AccessibleHyperlinkEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkEvent.java
new file mode 100644 (file)
index 0000000..7a5ca71
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleHyperlink messages to an accessible object.
+ *
+ * @see AccessibleHyperlinkListener
+ * @see AccessibleHyperlinkAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleHyperlinkEvent extends EventObject {
+
+       public Accessible accessible;
+
+       /**
+        * The value of this field must be set in the accessible hyperlink listener method
+        * before returning. What to set it to depends on the listener method called.
+        */
+       public String result;
+
+       public int index;
+
+       static final long serialVersionUID = 6253098373844074544L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleHyperlinkEvent(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 "AccessibleHyperlinkEvent {" //$NON-NLS-1$
+               + "accessible=" + accessible   //$NON-NLS-1$
+               + " string=" + result   //$NON-NLS-1$
+               + " index=" + index   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleHyperlinkListener.java
new file mode 100644 (file)
index 0000000..de02c6b
--- /dev/null
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleHyperlink events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleHyperlinkListener</code> method and removed using
+ * the <code>removeAccessibleHyperlinkListener</code> method.
+ * </p>
+ *
+ * @see AccessibleHyperlinkAdapter
+ * @see AccessibleHyperlinkEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleHyperlinkListener extends SWTEventListener {
+       /**
+        * Returns the anchor for the link at the specified index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index identifying the anchor if this object
+        *              has more than one link, as in the case of an image map</li>
+        * <li>[typical out] result - the returned anchor</li>
+        * <li>[optional out] accessible - the returned anchor.
+        *              Note: The returned anchor can either be a string or an accessible.
+        *              For example, for a text link this could be the substring of the containing string
+        *              where the substring is overridden with link behavior, and for an image link this could be
+        *              the accessible for the image.</li>
+        * </ul>
+        */
+       public void getAnchor(AccessibleHyperlinkEvent e);
+
+       /**
+        * Returns the target of the link at the specified index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - a 0 based index identifying the anchor if this object
+        *              has more than one link, as in the case of an image map</li>
+        * <li>[typical out] result - the returned target</li>
+        * <li>[optional out] accessible - the returned target.
+        *              Note: The returned target can either be a string or an accessible.
+        *              For example, this could be a string URI, or the accessible for the target
+        *              object to be activated when the link is activated.</li>
+        * </ul>
+        */
+       public void getAnchorTarget(AccessibleHyperlinkEvent e);
+
+       /**
+        * Returns the 0 based character offset at which the textual representation of the hyperlink starts.
+        * <p>
+        * The returned value is related to the AccessibleTextExtended interface of the object that
+        * owns this hyperlink.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index</li>
+        * </ul>
+        */
+       public void getStartIndex(AccessibleHyperlinkEvent e);
+
+       /**
+        * Returns the 0 based character offset at which the textual representation of the hyperlink ends.
+        * <p>
+        * The returned value is related to the AccessibleTextExtended interface of the object that
+        * owns this hyperlink. The character at the index is not part of the hypertext.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index</li>
+        * </ul>
+        */
+       public void getEndIndex(AccessibleHyperlinkEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleListener.java
new file mode 100644 (file)
index 0000000..a18dad8
--- /dev/null
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 extends 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);
+
+       /**
+        * Static helper method to create a <code>AccessibleListener</code> for the
+        * {@link #getName(AccessibleEvent e)}) method with a lambda expression.
+        *
+        * @param c the consumer of the event
+        * @return AccessibleListener
+        * @since 3.106
+       */
+       public static AccessibleListener getNameAdapter(Consumer<AccessibleEvent> c) {
+               return new AccessibleAdapter() {
+                       @Override
+                       public void getName(AccessibleEvent e) {
+                               c.accept(e);
+                       }
+               };
+       }
+
+       /**
+        * Static helper method to create a <code>AccessibleListener</code> for the
+        * {@link #getHelp(AccessibleEvent e)}) method with a lambda expression.
+        *
+        * @param c the consumer of the event
+        * @return AccessibleListener
+        * @since 3.106
+       */
+       public static AccessibleListener getHelpAdapter(Consumer<AccessibleEvent> c) {
+               return new AccessibleAdapter() {
+                       @Override
+                       public void getHelp(AccessibleEvent e) {
+                               c.accept(e);
+                       }
+               };
+       }
+
+       /**
+        * Static helper method to create a <code>AccessibleListener</code> for the
+        * {@link #getKeyboardShortcut(AccessibleEvent e)}) method with a lambda expression.
+        *
+        * @param c the consumer of the event
+        * @return AccessibleListener
+        * @since 3.106
+       */
+       public static AccessibleListener getKeyboardShortcutAdapter(Consumer<AccessibleEvent> c) {
+               return new AccessibleAdapter() {
+                       @Override
+                       public void getKeyboardShortcut(AccessibleEvent e) {
+                               c.accept(e);
+                       }
+               };
+       }
+
+       /**
+        * Static helper method to create a <code>AccessibleListener</code> for the
+        * {@link #getDescription(AccessibleEvent e)}) method with a lambda expression.
+        *
+        * @param c the consumer of the event
+        * @return AccessibleListener
+        * @since 3.106
+       */
+       public static AccessibleListener getDescriptionAdapter(Consumer<AccessibleEvent> c) {
+               return new AccessibleAdapter() {
+                       @Override
+                       public void getDescription(AccessibleEvent e) {
+                               c.accept(e);
+                       }
+               };
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableAdapter.java
new file mode 100644 (file)
index 0000000..e9ea737
--- /dev/null
@@ -0,0 +1,383 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleTableListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleTable</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p><p>
+ * Many methods in this adapter return cell accessible objects,
+ * which should implement <code>AccessibleTableCellListener</code>.
+ * </p>
+ *
+ * @see AccessibleTableAdapter
+ * @see AccessibleTableEvent
+ * @see AccessibleTableCellListener
+ * @see AccessibleTableCellEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleTableAdapter implements AccessibleTableListener {
+       /**
+        * Deselects one column, leaving other selected columns selected (if any).
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column to be unselected.</li>
+        * <li>[out] result - set to {@link ACC#OK} if the column was deselected.</li>
+        * </ul>
+        */
+       @Override
+       public void deselectColumn(AccessibleTableEvent e) {}
+
+       /**
+        * Deselects one row, leaving other selected rows selected (if any).
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row to be unselected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the row was deselected.</li>
+        * </ul>
+        */
+       @Override
+       public void deselectRow(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the caption for the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - the caption for the table, or null if the table does not have a caption</li>
+        * </ul>
+        *
+        * @deprecated IAccessibleTable2::caption is deprecated, instead use the
+        * IA2_RELATION_LABELED_BY relation to create a relation between the table and its caption.
+        */
+       @Deprecated
+       @Override
+       public void getCaption(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the accessible object at the specified row and column in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - the 0 based row index for which to retrieve the accessible cell</li>
+        * <li>[in] column - the 0 based column index for which to retrieve the accessible cell</li>
+        * <li>[out] accessible - the table cell at the specified row and column index,
+        *              or null if the row or column index are not valid</li>
+        * </ul>
+        */
+       @Override
+       public void getCell(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the accessible object for the specified column in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - the 0 based column index for which to retrieve the accessible column</li>
+        * <li>[out] accessible - the table column at the specified column index,
+        *              or null if the column index is not valid</li>
+        * </ul>
+        */
+       @Override
+       public void getColumn(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the total number of columns in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of columns in the table</li>
+        * </ul>
+        */
+       @Override
+       public void getColumnCount(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the description text of the specified column in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - the 0 based index of the column for which to retrieve the description</li>
+        * <li>[out] result - the description text of the specified column in the table,
+        *              or null if the column does not have a description</li>
+        * </ul>
+        */
+       @Override
+       public void getColumnDescription(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the accessible object for the column header.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - an accessible object representing the column header,
+        *              or null if there is no column header</li>
+        * </ul>
+        */
+       @Override
+       public void getColumnHeader(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the column header cells as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing column header cells,
+        *              or null if there are no column header cells</li>
+        * </ul>
+        */
+       @Override
+       public void getColumnHeaderCells(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the columns as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing columns,
+        *              or null if there are no columns</li>
+        * </ul>
+        */
+       @Override
+       public void getColumns(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the accessible object for the specified row in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - the 0 based row index for which to retrieve the accessible row</li>
+        * <li>[out] accessible - the table row at the specified row index,
+        *              or null if the row index is not valid</li>
+        * </ul>
+        */
+       @Override
+       public void getRow(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the total number of rows in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of rows in the table</li>
+        * </ul>
+        */
+       @Override
+       public void getRowCount(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the description text of the specified row in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - the 0 based index of the row for which to retrieve the description</li>
+        * <li>[out] result - the description text of the specified row in the table,
+        *              or null if the row does not have a description</li>
+        * </ul>
+        */
+       @Override
+       public void getRowDescription(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the accessible object for the row header.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - an accessible object representing the row header,
+        *              or null if there is no row header</li>
+        * </ul>
+        */
+       @Override
+       public void getRowHeader(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the row header cells as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing row header cells,
+        *              or null if there are no row header cells</li>
+        * </ul>
+        */
+       @Override
+       public void getRowHeaderCells(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the rows as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing rows,
+        *              or null if there are no rows</li>
+        * </ul>
+        */
+       @Override
+       public void getRows(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the number of selected cells.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count -  the number of cells currently selected</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectedCellCount(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the currently selected cells.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - array containing the selected accessible cells</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectedCells(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the number of selected columns.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of columns currently selected</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectedColumnCount(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the column indexes that are currently selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] selected - an array of 0 based column indexes of selected columns</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectedColumns(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the number of selected rows.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of rows currently selected</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectedRowCount(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the row indexes that are currently selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] selected - an array of 0 based row indexes of selected rows</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectedRows(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the summary description of the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - the summary for the table,
+        *              or null if the table does not have a summary</li>
+        * </ul>
+        *
+        * @deprecated IAccessibleTable2::summary is deprecated, instead use the
+        * IA2_RELATION_DESCRIBED_BY relation to create a relation between the table and its summary.
+        */
+       @Deprecated
+       @Override
+       public void getSummary(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the visible columns as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing visible columns,
+        *              or null if there are no visible columns</li>
+        * </ul>
+        */
+       @Override
+       public void getVisibleColumns(AccessibleTableEvent e) {}
+
+       /**
+        * Returns the visible rows as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing visible rows,
+        *              or null if there are no visible rows</li>
+        * </ul>
+        */
+       @Override
+       public void getVisibleRows(AccessibleTableEvent e) {}
+
+       /**
+        * Returns a boolean value indicating whether the specified column is
+        * completely selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column for which to determine whether it is selected</li>
+        * <li>[out] isSelected - true if the specified column is selected completely, and false otherwise</li>
+        * </ul>
+        */
+       @Override
+       public void isColumnSelected(AccessibleTableEvent e) {}
+
+       /**
+        * Returns a boolean value indicating whether the specified row is
+        * completely selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row for which to determine whether it is selected</li>
+        * <li>[out] isSelected - true if the specified row is selected completely, and false otherwise</li>
+        * </ul>
+        */
+       @Override
+       public void isRowSelected(AccessibleTableEvent e) {}
+
+       /**
+        * Selects a column.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the column was selected.</li>
+        * </ul>
+        */
+       @Override
+       public void selectColumn(AccessibleTableEvent e) {}
+
+       /**
+        * Selects a row.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the row was selected.</li>
+        * </ul>
+        */
+       @Override
+       public void selectRow(AccessibleTableEvent e) {}
+
+       /**
+        * Selects a column and deselects all previously selected columns.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the column was selected.</li>
+        * </ul>
+        */
+       @Override
+       public void setSelectedColumn(AccessibleTableEvent e) {}
+
+       /**
+        * Selects a row and deselects all previously selected rows.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the row was selected.</li>
+        * </ul>
+        */
+       @Override
+       public void setSelectedRow(AccessibleTableEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellAdapter.java
new file mode 100644 (file)
index 0000000..e6c6f44
--- /dev/null
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleTableCellListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleTableCell</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleTableCellListener
+ * @see AccessibleTableCellEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleTableCellAdapter implements AccessibleTableCellListener {
+       /**
+        * Returns the number of columns occupied by this cell accessible.
+        * <p>
+        * This is 1 if the specified cell is only in one column, or
+        * more than 1 if the specified cell spans multiple columns.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the 1 based number of columns spanned by the specified cell
+        * </ul>
+        */
+       @Override
+       public void getColumnSpan(AccessibleTableCellEvent e) {}
+
+       /**
+        * Returns the column headers as an array of cell accessibles.
+        * TODO: doc that this is a more efficient way to get headers of a cell than TableListener.getRow/ColHeaders
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of cell accessibles, or null if there are no column headers
+        * </ul>
+        */
+       @Override
+       public void getColumnHeaders(AccessibleTableCellEvent e) {}
+
+       /**
+        * Translates this cell accessible into the corresponding column index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index - the 0 based column index of the specified cell,
+        *              or the index of the first column if the cell spans multiple columns
+        * </ul>
+        */
+       @Override
+       public void getColumnIndex(AccessibleTableCellEvent e) {}
+
+       /**
+        * Returns the number of rows occupied by this cell accessible.
+        * <p>
+        * This is 1 if the specified cell is only in one row, or
+        * more than 1 if the specified cell spans multiple rows.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the 1 based number of rows spanned by the specified cell
+        * </ul>
+        */
+       @Override
+       public void getRowSpan(AccessibleTableCellEvent e) {}
+
+       /**
+        * Returns the row headers as an array of cell accessibles.
+        * TODO: doc that this is a more efficient way to get headers of a cell than TableListener.getRow/ColHeaders
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of cell accessibles, or null if there are no row headers
+        * </ul>
+        */
+       @Override
+       public void getRowHeaders(AccessibleTableCellEvent e) {}
+
+       /**
+        * Translates this cell accessible into the corresponding row index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index - the 0 based row index of the specified cell,
+        *              or the index of the first row if the cell spans multiple rows
+        * </ul>
+        */
+       @Override
+       public void getRowIndex(AccessibleTableCellEvent e) {}
+
+       /**
+        * Returns the accessible for the table containing this cell.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - the accessible for the containing table
+        * </ul>
+        */
+       @Override
+       public void getTable(AccessibleTableCellEvent e) {}
+
+       /**
+        * Returns a boolean value indicating whether this cell is selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] isSelected - true if the specified cell is selected and false otherwise
+        * </ul>
+        */
+       @Override
+       public void isSelected(AccessibleTableCellEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellEvent.java
new file mode 100644 (file)
index 0000000..03674e1
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleTableCell messages to an accessible object.
+ *
+ * @see AccessibleTableCellListener
+ * @see AccessibleTableCellAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleTableCellEvent extends EventObject {
+
+       public Accessible accessible;
+       public Accessible[] accessibles;
+       public boolean isSelected;
+       public int count;
+       public int index;
+
+       static final long serialVersionUID = 7231059449172889781L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleTableCellEvent(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 "AccessibleTableCellEvent {" //$NON-NLS-1$
+               + " accessibles=" + accessibles   //$NON-NLS-1$
+               + " isSelected=" + isSelected   //$NON-NLS-1$
+               + " count=" + count   //$NON-NLS-1$
+               + " index=" + index   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableCellListener.java
new file mode 100644 (file)
index 0000000..5533da3
--- /dev/null
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleTableCell events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleTableCellListener</code> method and removed using
+ * the <code>removeAccessibleTableCellListener</code> method.
+ * </p>
+ *
+ * @see AccessibleTableCellAdapter
+ * @see AccessibleTableCellEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleTableCellListener extends SWTEventListener {
+       /**
+        * Returns the number of columns occupied by this cell accessible.
+        * <p>
+        * This is 1 if the specified cell is only in one column, or
+        * more than 1 if the specified cell spans multiple columns.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the 1 based number of columns spanned by the specified cell
+        * </ul>
+        */
+       public void getColumnSpan(AccessibleTableCellEvent e);
+
+       /**
+        * Returns the column headers as an array of cell accessibles.
+        * TODO: doc that this is a more efficient way to get headers of a cell than TableListener.getRow/ColHeaders
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of cell accessibles, or null if there are no column headers
+        * </ul>
+        */
+       public void getColumnHeaders(AccessibleTableCellEvent e);
+
+       /**
+        * Translates this cell accessible into the corresponding column index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index - the 0 based column index of the specified cell,
+        *              or the index of the first column if the cell spans multiple columns
+        * </ul>
+        */
+       public void getColumnIndex(AccessibleTableCellEvent e);
+
+       /**
+        * Returns the number of rows occupied by this cell accessible.
+        * <p>
+        * This is 1 if the specified cell is only in one row, or
+        * more than 1 if the specified cell spans multiple rows.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the 1 based number of rows spanned by the specified cell
+        * </ul>
+        */
+       public void getRowSpan(AccessibleTableCellEvent e);
+
+       /**
+        * Returns the row headers as an array of cell accessibles.
+        * TODO: doc that this is a more efficient way to get headers of a cell than TableListener.getRow/ColHeaders
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of cell accessibles, or null if there are no row headers
+        * </ul>
+        */
+       public void getRowHeaders(AccessibleTableCellEvent e);
+
+       /**
+        * Translates this cell accessible into the corresponding row index.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] index - the 0 based row index of the specified cell,
+        *              or the index of the first row if the cell spans multiple rows
+        * </ul>
+        */
+       public void getRowIndex(AccessibleTableCellEvent e);
+
+       /**
+        * Returns the accessible for the table containing this cell.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - the accessible for the containing table
+        * </ul>
+        */
+       public void getTable(AccessibleTableCellEvent e);
+
+       /**
+        * Returns a boolean value indicating whether this cell is selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] isSelected - true if the specified cell is selected and false otherwise
+        * </ul>
+        */
+       public void isSelected(AccessibleTableCellEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableEvent.java
new file mode 100644 (file)
index 0000000..4f55261
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleTable messages to an accessible object.
+ *
+ * @see AccessibleTableListener
+ * @see AccessibleTableAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleTableEvent extends EventObject {
+
+       public Accessible accessible;
+       public Accessible[] accessibles;
+
+       /**
+        * The value of this field must be set in the accessible table listener method
+        * before returning. What to set it to depends on the listener method called.
+        */
+       public String result;
+
+       public int column;
+       public int row;
+       public int count;
+       public boolean isSelected;
+       public int[] selected;
+
+       static final long serialVersionUID = 1624586163666270447L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleTableEvent(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 "AccessibleTableEvent {" //$NON-NLS-1$
+               + "accessible=" + accessible   //$NON-NLS-1$
+               + " accessibles=" + accessibles   //$NON-NLS-1$
+               + " string=" + result   //$NON-NLS-1$
+               + " isSelected=" + isSelected   //$NON-NLS-1$
+               + " column=" + column   //$NON-NLS-1$
+               + " count=" + count   //$NON-NLS-1$
+               + " row=" + row   //$NON-NLS-1$
+               + " selected=" + selected   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTableListener.java
new file mode 100644 (file)
index 0000000..ec901d3
--- /dev/null
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleTable events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleTableListener</code> method and removed using
+ * the <code>removeAccessibleTableListener</code> method.
+ * </p><p>
+ * Many methods in this listener return cell accessible objects,
+ * which should implement <code>AccessibleTableCellListener</code>.
+ * </p>
+ *
+ * @see AccessibleTableAdapter
+ * @see AccessibleTableEvent
+ * @see AccessibleTableCellListener
+ * @see AccessibleTableCellEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleTableListener extends SWTEventListener {
+       /**
+        * Deselects one column, leaving other selected columns selected (if any).
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column to be unselected.</li>
+        * <li>[out] result - set to {@link ACC#OK} if the column was deselected.</li>
+        * </ul>
+        */
+       public void deselectColumn(AccessibleTableEvent e);
+
+       /**
+        * Deselects one row, leaving other selected rows selected (if any).
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row to be unselected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the row was deselected.</li>
+        * </ul>
+        */
+       public void deselectRow(AccessibleTableEvent e);
+
+       /**
+        * Returns the caption for the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - the caption for the table, or null if the table does not have a caption</li>
+        * </ul>
+        *
+        * @deprecated IAccessibleTable2::caption is deprecated, instead use the
+        * IA2_RELATION_LABELED_BY relation to create a relation between the table and its caption.
+        */
+       @Deprecated
+       public void getCaption(AccessibleTableEvent e);
+
+       /**
+        * Returns the accessible object at the specified row and column in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - the 0 based row index for which to retrieve the accessible cell</li>
+        * <li>[in] column - the 0 based column index for which to retrieve the accessible cell</li>
+        * <li>[out] accessible - the table cell at the specified row and column index,
+        *              or null if the row or column index are not valid</li>
+        * </ul>
+        */
+       public void getCell(AccessibleTableEvent e);
+
+       /**
+        * Returns the accessible object for the specified column in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - the 0 based column index for which to retrieve the accessible column</li>
+        * <li>[out] accessible - the table column at the specified column index,
+        *              or null if the column index is not valid</li>
+        * </ul>
+        */
+       public void getColumn(AccessibleTableEvent e);
+
+       /**
+        * Returns the total number of columns in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of columns in the table</li>
+        * </ul>
+        */
+       public void getColumnCount(AccessibleTableEvent e);
+
+       /**
+        * Returns the description text of the specified column in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - the 0 based index of the column for which to retrieve the description</li>
+        * <li>[out] result - the description text of the specified column in the table,
+        *              or null if the column does not have a description</li>
+        * </ul>
+        */
+       public void getColumnDescription(AccessibleTableEvent e);
+
+       /**
+        * Returns the accessible object for the column header.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - an accessible object representing the column header,
+        *              or null if there is no column header</li>
+        * </ul>
+        */
+       public void getColumnHeader(AccessibleTableEvent e);
+
+       /**
+        * Returns the column header cells as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing column header cells,
+        *              or null if there are no column header cells</li>
+        * </ul>
+        */
+       public void getColumnHeaderCells(AccessibleTableEvent e);
+
+       /**
+        * Returns the columns as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing columns,
+        *              or null if there are no columns</li>
+        * </ul>
+        */
+       public void getColumns(AccessibleTableEvent e);
+
+       /**
+        * Returns the accessible object for the specified row in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - the 0 based row index for which to retrieve the accessible row</li>
+        * <li>[out] accessible - the table row at the specified row index,
+        *              or null if the row index is not valid</li>
+        * </ul>
+        */
+       public void getRow(AccessibleTableEvent e);
+
+       /**
+        * Returns the total number of rows in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of rows in the table</li>
+        * </ul>
+        */
+       public void getRowCount(AccessibleTableEvent e);
+
+       /**
+        * Returns the description text of the specified row in the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - the 0 based index of the row for which to retrieve the description</li>
+        * <li>[out] result - the description text of the specified row in the table,
+        *              or null if the row does not have a description</li>
+        * </ul>
+        */
+       public void getRowDescription(AccessibleTableEvent e);
+
+       /**
+        * Returns the accessible object for the row header.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - an accessible object representing the row header,
+        *              or null if there is no row header</li>
+        * </ul>
+        */
+       public void getRowHeader(AccessibleTableEvent e);
+
+       /**
+        * Returns the row header cells as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing row header cells,
+        *              or null if there are no row header cells</li>
+        * </ul>
+        */
+       public void getRowHeaderCells(AccessibleTableEvent e);
+
+       /**
+        * Returns the rows as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing rows,
+        *              or null if there are no rows</li>
+        * </ul>
+        */
+       public void getRows(AccessibleTableEvent e);
+
+       /**
+        * Returns the number of selected cells.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count -  the number of cells currently selected</li>
+        * </ul>
+        */
+       public void getSelectedCellCount(AccessibleTableEvent e);
+
+       /**
+        * Returns the currently selected cells.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - array containing the selected accessible cells</li>
+        * </ul>
+        */
+       public void getSelectedCells(AccessibleTableEvent e);
+
+       /**
+        * Returns the number of selected columns.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of columns currently selected</li>
+        * </ul>
+        */
+       public void getSelectedColumnCount(AccessibleTableEvent e);
+
+       /**
+        * Returns the column indexes that are currently selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] selected - an array of 0 based column indexes of selected columns</li>
+        * </ul>
+        */
+       public void getSelectedColumns(AccessibleTableEvent e);
+
+       /**
+        * Returns the number of selected rows.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of rows currently selected</li>
+        * </ul>
+        */
+       public void getSelectedRowCount(AccessibleTableEvent e);
+
+       /**
+        * Returns the row indexes that are currently selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] selected - an array of 0 based row indexes of selected rows</li>
+        * </ul>
+        */
+       public void getSelectedRows(AccessibleTableEvent e);
+
+       /**
+        * Returns the summary description of the table.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessible - the summary for the table,
+        *              or null if the table does not have a summary</li>
+        * </ul>
+        *
+        * @deprecated IAccessibleTable2::summary is deprecated, instead use the
+        * IA2_RELATION_DESCRIBED_BY relation to create a relation between the table and its summary.
+        */
+       @Deprecated
+       public void getSummary(AccessibleTableEvent e);
+
+       /**
+        * Returns the visible columns as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing visible columns,
+        *              or null if there are no visible columns</li>
+        * </ul>
+        */
+       public void getVisibleColumns(AccessibleTableEvent e);
+
+       /**
+        * Returns the visible rows as an array of accessible objects.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] accessibles - an array of accessible objects representing visible rows,
+        *              or null if there are no visible rows</li>
+        * </ul>
+        */
+       public void getVisibleRows(AccessibleTableEvent e);
+
+       /**
+        * Returns a boolean value indicating whether the specified column is
+        * completely selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column for which to determine whether it is selected</li>
+        * <li>[out] isSelected - true if the specified column is selected completely, and false otherwise</li>
+        * </ul>
+        */
+       public void isColumnSelected(AccessibleTableEvent e);
+
+       /**
+        * Returns a boolean value indicating whether the specified row is
+        * completely selected.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row for which to determine whether it is selected</li>
+        * <li>[out] isSelected - true if the specified row is selected completely, and false otherwise</li>
+        * </ul>
+        */
+       public void isRowSelected(AccessibleTableEvent e);
+
+       /**
+        * Selects a column.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the column was selected.</li>
+        * </ul>
+        */
+       public void selectColumn(AccessibleTableEvent e);
+
+       /**
+        * Selects a row.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the row was selected.</li>
+        * </ul>
+        */
+       public void selectRow(AccessibleTableEvent e);
+
+       /**
+        * Selects a column and deselects all previously selected columns.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] column - 0 based index of the column to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the column was selected.</li>
+        * </ul>
+        */
+       public void setSelectedColumn(AccessibleTableEvent e);
+
+       /**
+        * Selects a row and deselects all previously selected rows.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] row - 0 based index of the row to be selected</li>
+        * <li>[out] result - set to {@link ACC#OK} if the row was selected.</li>
+        * </ul>
+        */
+       public void setSelectedRow(AccessibleTableEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextAdapter.java
new file mode 100644 (file)
index 0000000..550ee85
--- /dev/null
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+/**
+ * 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 implements 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>
+        */
+       @Override
+       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>
+        */
+       @Override
+       public void getSelectionRange (AccessibleTextEvent e) {
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextAttributeEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextAttributeEvent.java
new file mode 100644 (file)
index 0000000..45897eb
--- /dev/null
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleAttribute or AccessibleEditableText messages to an
+ * accessible object.
+ *
+ * @see AccessibleAttributeListener
+ * @see AccessibleAttributeAdapter
+ * @see AccessibleEditableTextListener
+ * @see AccessibleEditableTextAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleTextAttributeEvent extends EventObject {
+
+       /**
+        * [in] the 0-based text offset for which to return attribute information
+        *
+        * @see AccessibleAttributeListener#getTextAttributes
+        */
+       public int offset;
+
+       /**
+        * [in/out] the starting and ending offsets of the character range
+        *
+        * @see AccessibleAttributeListener#getTextAttributes
+        * @see AccessibleEditableTextListener#setTextAttributes
+        */
+       public int start, end;
+
+       /**
+        * [in/out] the TextStyle of the character range
+        *
+        * @see AccessibleAttributeListener#getTextAttributes
+        * @see AccessibleEditableTextListener#setTextAttributes
+        */
+       public TextStyle textStyle;
+
+       /**
+        * [in/out] an array of alternating key and value Strings
+        * that represent attributes that do not correspond to TextStyle fields
+        *
+        * @see AccessibleAttributeListener#getTextAttributes
+        * @see AccessibleEditableTextListener#setTextAttributes
+        */
+       public String [] attributes;
+
+       /**
+        * [out] Set this field to {@link ACC#OK} if the operation
+        * was completed successfully, and null otherwise.
+        *
+        * @see AccessibleEditableTextListener#setTextAttributes
+        *
+        * @since 3.7
+        */
+       public String result;
+
+       static final long serialVersionUID = 7131825608864332802L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleTextAttributeEvent(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 "AccessibleAttributeEvent {" //$NON-NLS-1$
+               + " offset=" + offset   //$NON-NLS-1$
+               + " start=" + start   //$NON-NLS-1$
+               + " end=" + end   //$NON-NLS-1$
+               + " textStyle=" + textStyle   //$NON-NLS-1$
+               + " attributes=" + toAttributeString(attributes)   //$NON-NLS-1$
+               + " result=" + result   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+
+String toAttributeString(String [] attributes) {
+       if (attributes == null || attributes.length == 0) return "" + attributes;   //$NON-NLS-1$
+       StringBuilder attributeString = new StringBuilder();
+       for (int i = 0; i < attributes.length; i++) {
+               attributeString.append(attributes[i]);
+               attributeString.append((i % 2 == 0) ? ":" : ";");   //$NON-NLS-1$   //$NON-NLS-2$
+       }
+       return attributeString.toString();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextEvent.java
new file mode 100644 (file)
index 0000000..945fd9d
--- /dev/null
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import java.util.*;
+
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 extends EventObject {
+       public int childID;                             // IN
+       public int offset, length;              // OUT
+       /** @since 3.6 */
+       public Accessible accessible;
+
+       /**
+        * The value of this field must be set in the accessible text extended listener method
+        * before returning. What to set it to depends on the listener method called.
+        * @since 3.6
+        */
+       public String result;
+
+       /** @since 3.6 */
+       public int count;
+       /** @since 3.6 */
+       public int index;
+       /** @since 3.6 */
+       public int start, end;
+       /** @since 3.6 */
+       public int type;
+       /** @since 3.6 */
+       public int x, y, width, height;
+       /** @since 3.6 */
+       public int [] ranges;
+       /** @since 3.6 */
+       public Rectangle [] rectangles;
+
+       static final long serialVersionUID = 3977019530868308275L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleTextEvent (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 "AccessibleTextEvent {childID=" + childID +  //$NON-NLS-1$
+               " offset=" + offset +  //$NON-NLS-1$
+               " length=" + length +  //$NON-NLS-1$
+               "}"; //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextExtendedAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextExtendedAdapter.java
new file mode 100644 (file)
index 0000000..94abb1c
--- /dev/null
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleTextExtendedListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleTextExtended</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleTextExtendedListener
+ * @see AccessibleTextEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleTextExtendedAdapter extends AccessibleTextAdapter implements AccessibleTextExtendedListener {
+       /**
+        * Adds a text selection.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the new selection</li>
+        * <li>[in] end - the 0 based offset after the last character of the new selection</li>
+        * <li>[out] result - set to {@link ACC#OK} if the text selection was added</li>
+        * </ul>
+        */
+       @Override
+       public void addSelection(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the total number of characters in the text.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the total number of characters</li>
+        * </ul>
+        */
+       @Override
+       public void getCharacterCount(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the number of links and link groups contained within this hypertext
+        * paragraph.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of links and link groups within this hypertext paragraph,
+        *              or 0 if there are none</li>
+        * </ul>
+        */
+       @Override
+       public void getHyperlinkCount(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the specified hyperlink.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of the hyperlink to return</li>
+        * <li>[out] accessible - the specified hyperlink object, or null if the index is invalid</li>
+        * </ul>
+        */
+       @Override
+       public void getHyperlink(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the index of the hyperlink that is associated with this character offset.
+        * <p>
+        * This is the case when a link spans the given character index.
+        * </p>
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] offset - the 0 based offset of the character for which to return the link index</li>
+        * <li>[out] index - the 0 based index of the hyperlink that is associated with this
+        *              character offset, or -1 if the offset is not in a link</li>
+        * </ul>
+        */
+       @Override
+       public void getHyperlinkIndex(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the offset of the character under the specified point.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] x - the X value in display coordinates for which to look up the offset of the character
+        *              that is rendered on the display at that point</li>
+        * <li>[in] y - the position's Y value for which to look up the offset of the character
+        *              that is rendered on the display at that point</li>
+        * <li>[out] offset - the 0 based offset of the character under the given point,
+        *              or -1 if the point is invalid or there is no character under the point</li>
+        * </ul>
+        */
+       @Override
+       public void getOffsetAtPoint(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the text range(s) contained within the given bounding box.
+        * <p>
+        * Partially visible characters are included in the returned ranges.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] x - the X coordinate of the top left corner of the bounding box, in display relative coordinates</li>
+        * <li>[in] y - the Y coordinate of the top left corner of the bounding box, in display relative coordinates</li>
+        * <li>[in] width - the width of the bounding box</li>
+        * <li>[in] height - the height of the bounding box</li>
+        * <li>[typical out] start - the 0 based offset of the first character of the substring in the bounding box</li>
+        * <li>[typical out] end - the 0 based offset after the last character of the substring in the bounding box</li>
+        * <li>[optional out] ranges - an array of pairs specifying the start and end offsets of each range,
+        *              if the text range is clipped by the bounding box</li>
+        * </ul>
+        */
+       @Override
+       public void getRanges(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the character offsets of the specified text selection.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of the selection</li>
+        * <li>[out] start - the 0 based offset of first selected character</li>
+        * <li>[out] end - the 0 based offset after the last selected character</li>
+        * </ul>
+        */
+       @Override
+       public void getSelection(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the number of active non-contiguous selections.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of active non-contiguous selections</li>
+        * </ul>
+        */
+       @Override
+       public void getSelectionCount(AccessibleTextEvent e) {}
+
+       /**
+        * Returns a substring and its range for the given range, count and boundary type.
+        * <p>
+        * Returns the substring of the specified boundary type that is located count
+        * positions from the given character range. Also returns the start and end
+        * offsets of the returned substring.
+        * </p><p>
+        * For example, if the boundary type is TEXT_BOUNDARY_WORD, then the complete
+        * word that is located count words from the specified range is returned.
+        * If count is negative, then return the word that is count words before start.
+        * If count is positive, then return the word that is count words after end.
+        * If count is zero, start and end are the same, so return the word at start.
+        * </p><p>
+        * The whole text can be requested by passing start == 0 and end == getCharacterCount,
+        * TEXT_BOUNDARY_ALL, and 0 for count. Alternatively the whole text can be requested
+        * by calling AccessibleControlListener.getValue().
+        * </p><p>
+        * If start and end are valid, but no suitable word (or other boundary type) is found,
+        * the returned string is null and the returned range is degenerate (start == end).
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] type - the boundary type of the substring to return. One of:<ul>
+        *              <li> {@link ACC#TEXT_BOUNDARY_CHAR}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_WORD}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_SENTENCE}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_PARAGRAPH}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_LINE}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_ALL}</li>
+        *              </ul></li>
+        * <li>[in,out] start - the 0 based offset of first character of the substring</li>
+        * <li>[in,out] end - the 0 based offset after the last character of the substring</li>
+        * <li>[in,out] count - the number of boundary type units to move to find the substring:<ul>
+        *              <li>in - look count units before start if count &lt; 0, or after end if count &gt; 0. Look at start if count == 0</li>
+        *              <li>out - the actual number of boundary type units that were moved. This may be fewer than the input count</li>
+        *              </ul></li>
+        * <li>[out] result - the requested substring.  This may be empty or null
+        *              when no appropriate substring is found, or if the type is invalid.</li>
+        * </ul>
+        */
+       @Override
+       public void getText(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the bounding box(es) of the specified text range in display coordinates.
+        * <p>
+        * Typically, the text range will represent a single character, i.e. end - start = 1,
+        * therefore providers should optimize for this case.
+        * </p><p>
+        * Note: The virtual character after the last character of the represented text,
+        * i.e. the one at offset getCharacterCount, is a special case. It represents the
+        * current input position and will therefore typically be queried by AT more
+        * often than other positions.  Because it does not represent an existing character
+        * its bounding box is defined in relation to preceding characters.  It should be
+        * roughly equivalent to the bounding box of some character when inserted at the
+        * end of the text; its height typically being the maximal height of all the
+        * characters in the text or the height of the preceding character, its width
+        * being at least one pixel so that the bounding box is not degenerate.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring in the bounding box</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring in the bounding box</li>
+        * <li>[typical out] x - the X coordinate of the top left corner of the bounding box of the specified substring</li>
+        * <li>[typical out] y - the Y coordinate of the top left corner of the bounding box of the specified substring</li>
+        * <li>[typical out] width - the width of the bounding box of the specified substring</li>
+        * <li>[typical out] height - the height of the bounding box of the specified substring</li>
+        * <li>[optional out] rectangles - a set of disjoint bounding rectangles, if the specified text range includes
+        *              partial lines</li>
+        * </ul>
+        */
+       @Override
+       public void getTextBounds(AccessibleTextEvent e) {}
+
+       /**
+        * Returns the visible text range(s).
+        * <p>
+        * Partially visible characters are included in the returned ranges.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[typical out] start - the 0 based offset of the first character of the visible substring</li>
+        * <li>[typical out] end - the 0 based offset after the last character of the visible substring</li>
+        * <li>[optional out] ranges - an array of pairs specifying the start and end offsets of each range,
+        *              if the visible text range is clipped</li>
+        * </ul>
+        */
+       @Override
+       public void getVisibleRanges(AccessibleTextEvent e) {}
+
+       /**
+        * Deselects a range of text.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of selection to remove</li>
+        * <li>[out] result - set to {@link ACC#OK} if the range of text was deselected</li>
+        * </ul>
+        */
+       @Override
+       public void removeSelection(AccessibleTextEvent e) {}
+
+       /**
+        * Scrolls a specific part of a substring according to the scroll type.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring</li>
+        * <li>[in] type - a scroll type indicating where the substring should be placed
+        *              on the screen. One of:<ul>
+        *              <li> {@link ACC#SCROLL_TYPE_TOP_LEFT}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_BOTTOM_RIGHT}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_TOP_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_BOTTOM_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_LEFT_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_RIGHT_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_ANYWHERE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_POINT}</li>
+        *              </ul></li>
+        * <li>[optional in] x - for SCROLL_TYPE_POINT, the X coordinate of the destination point in display coordinates</li>
+        * <li>[optional in] y - for SCROLL_TYPE_POINT, the Y coordinate of the destination point in display coordinates</li>
+        * <li>[out] result - set to {@link ACC#OK} if the text was scrolled</li>
+        * </ul>
+        */
+       @Override
+       public void scrollText(AccessibleTextEvent e) {}
+
+       /**
+        * Sets the position of the caret.
+        * <p>
+        * The caret position is that of the character logically following it,
+        * e.g. to the right of it in a left to right language.
+        * The caret is actually placed to the leading side of the character with
+        * that offset. An offset of 0 places the caret so that the next insertion
+        * goes before the first character. An offset of getCharacterCount places
+        * the caret so that the next insertion goes after the last character.
+        * </p><p>
+        * Setting the caret position may or may not alter the current selection.  A
+        * change of the selection is notified to the accessibility event listeners with
+        * an EVENT_TEXT_SELECTION_CHANGED event.
+        * </p><p>
+        * When the new caret position differs from the old one, this is notified to the
+        * accessibility event listeners with an EVENT_TEXT_CARET_MOVED event.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] offset - the new offset of the caret</li>
+        * <li>[out] result - set to {@link ACC#OK} if the caret position was set</li>
+        * </ul>
+        */
+       @Override
+       public void setCaretOffset(AccessibleTextEvent e) {}
+
+       /**
+        * Changes the bounds of an existing selection.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of the selection to change</li>
+        * <li>[in] start - the new 0 based offset of the first character of the selection</li>
+        * <li>[in] end - the new 0 based offset after the last character of the selection</li>
+        * <li>[out] result - set to {@link ACC#OK} if the selection was set</li>
+        * </ul>
+        */
+       @Override
+       public void setSelection(AccessibleTextEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextExtendedListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextExtendedListener.java
new file mode 100644 (file)
index 0000000..1464b6e
--- /dev/null
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleTextExtended events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleTextListener</code> method and removed using
+ * the <code>removeAccessibleTextListener</code> method.
+ * </p>
+ *
+ * @see AccessibleTextExtendedAdapter
+ * @see AccessibleTextEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleTextExtendedListener extends AccessibleTextListener {
+       /**
+        * Adds a text selection.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the new selection</li>
+        * <li>[in] end - the 0 based offset after the last character of the new selection</li>
+        * <li>[out] result - set to {@link ACC#OK} if the text selection was added</li>
+        * </ul>
+        */
+       public void addSelection(AccessibleTextEvent e);
+
+       /**
+        * Returns the total number of characters in the text.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the total number of characters</li>
+        * </ul>
+        */
+       public void getCharacterCount(AccessibleTextEvent e);
+
+       /**
+        * Returns the number of links and link groups contained within this hypertext
+        * paragraph.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of links and link groups within this hypertext paragraph,
+        *              or 0 if there are none</li>
+        * </ul>
+        */
+       public void getHyperlinkCount(AccessibleTextEvent e);
+
+       /**
+        * Returns the specified hyperlink.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of the hyperlink to return</li>
+        * <li>[out] accessible - the specified hyperlink object, or null if the index is invalid</li>
+        * </ul>
+        */
+       public void getHyperlink(AccessibleTextEvent e);
+
+       /**
+        * Returns the index of the hyperlink that is associated with this character offset.
+        * <p>
+        * This is the case when a link spans the given character index.
+        * </p>
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] offset - the 0 based offset of the character for which to return the link index</li>
+        * <li>[out] index - the 0 based index of the hyperlink that is associated with this
+        *              character offset, or -1 if the offset is not in a link</li>
+        * </ul>
+        */
+       public void getHyperlinkIndex(AccessibleTextEvent e);
+
+       /**
+        * Returns the offset of the character under the specified point.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] x - the X value in display coordinates for which to look up the offset of the character
+        *              that is rendered on the display at that point</li>
+        * <li>[in] y - the position's Y value for which to look up the offset of the character
+        *              that is rendered on the display at that point</li>
+        * <li>[out] offset - the 0 based offset of the character under the given point,
+        *              or -1 if the point is invalid or there is no character under the point</li>
+        * </ul>
+        */
+       public void getOffsetAtPoint(AccessibleTextEvent e);
+
+       /**
+        * Returns the text range(s) contained within the given bounding box.
+        * <p>
+        * Partially visible characters are included in the returned ranges.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] x - the X coordinate of the top left corner of the bounding box, in display relative coordinates</li>
+        * <li>[in] y - the Y coordinate of the top left corner of the bounding box, in display relative coordinates</li>
+        * <li>[in] width - the width of the bounding box</li>
+        * <li>[in] height - the height of the bounding box</li>
+        * <li>[typical out] start - the 0 based offset of the first character of the substring in the bounding box</li>
+        * <li>[typical out] end - the 0 based offset after the last character of the substring in the bounding box</li>
+        * <li>[optional out] ranges - an array of pairs specifying the start and end offsets of each range,
+        *              if the text range is clipped by the bounding box</li>
+        * </ul>
+        */
+       public void getRanges(AccessibleTextEvent e);
+
+       /**
+        * Returns the character offsets of the specified text selection.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of the selection</li>
+        * <li>[out] start - the 0 based offset of first selected character</li>
+        * <li>[out] end - the 0 based offset after the last selected character</li>
+        * </ul>
+        */
+       public void getSelection(AccessibleTextEvent e);
+
+       /**
+        * Returns the number of active non-contiguous selections.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] count - the number of active non-contiguous selections</li>
+        * </ul>
+        */
+       public void getSelectionCount(AccessibleTextEvent e);
+
+       /**
+        * Returns a substring and its range for the given range, count and boundary type.
+        * <p>
+        * Returns the substring of the specified boundary type that is located count
+        * positions from the given character range. Also returns the start and end
+        * offsets of the returned substring.
+        * </p><p>
+        * For example, if the boundary type is TEXT_BOUNDARY_WORD, then the complete
+        * word that is located count words from the specified range is returned.
+        * If count is negative, then return the word that is count words before start.
+        * If count is positive, then return the word that is count words after end.
+        * If count is zero, start and end are the same, so return the word at start.
+        * </p><p>
+        * The whole text can be requested by passing start == 0 and end == getCharacterCount,
+        * TEXT_BOUNDARY_ALL, and 0 for count. Alternatively the whole text can be requested
+        * by calling AccessibleControlListener.getValue().
+        * </p><p>
+        * If start and end are valid, but no suitable word (or other boundary type) is found,
+        * the returned string is null and the returned range is degenerate (start == end).
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] type - the boundary type of the substring to return. One of:<ul>
+        *              <li> {@link ACC#TEXT_BOUNDARY_CHAR}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_WORD}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_SENTENCE}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_PARAGRAPH}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_LINE}</li>
+        *              <li> {@link ACC#TEXT_BOUNDARY_ALL}</li>
+        *              </ul></li>
+        * <li>[in,out] start - the 0 based offset of first character of the substring</li>
+        * <li>[in,out] end - the 0 based offset after the last character of the substring</li>
+        * <li>[in,out] count - the number of boundary type units to move to find the substring:<ul>
+        *              <li>in - look count units before start if count &lt; 0, or after end if count &gt; 0. Look at start if count == 0</li>
+        *              <li>out - the actual number of boundary type units that were moved. This may be fewer than the input count</li>
+        *              </ul></li>
+        * <li>[out] result - the requested substring.  This may be empty or null
+        *              when no appropriate substring is found, or if the type is invalid.</li>
+        * </ul>
+        */
+       public void getText(AccessibleTextEvent e);
+
+       /**
+        * Returns the bounding box(es) of the specified text range in display coordinates.
+        * <p>
+        * Typically, the text range will represent a single character, i.e. end - start = 1,
+        * therefore providers should optimize for this case.
+        * </p><p>
+        * Note: The virtual character after the last character of the represented text,
+        * i.e. the one at offset getCharacterCount, is a special case. It represents the
+        * current input position and will therefore typically be queried by AT more
+        * often than other positions.  Because it does not represent an existing character
+        * its bounding box is defined in relation to preceding characters.  It should be
+        * roughly equivalent to the bounding box of some character when inserted at the
+        * end of the text; its height typically being the maximal height of all the
+        * characters in the text or the height of the preceding character, its width
+        * being at least one pixel so that the bounding box is not degenerate.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring in the bounding box</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring in the bounding box</li>
+        * <li>[typical out] x - the X coordinate of the top left corner of the bounding box of the specified substring</li>
+        * <li>[typical out] y - the Y coordinate of the top left corner of the bounding box of the specified substring</li>
+        * <li>[typical out] width - the width of the bounding box of the specified substring</li>
+        * <li>[typical out] height - the height of the bounding box of the specified substring</li>
+        * <li>[optional out] rectangles - a set of disjoint bounding rectangles, if the specified text range includes
+        *              partial lines</li>
+        * </ul>
+        */
+       public void getTextBounds(AccessibleTextEvent e);
+
+       /**
+        * Returns the visible text range(s).
+        * <p>
+        * Partially visible characters are included in the returned ranges.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[typical out] start - the 0 based offset of the first character of the visible substring</li>
+        * <li>[typical out] end - the 0 based offset after the last character of the visible substring</li>
+        * <li>[optional out] ranges - an array of pairs specifying the start and end offsets of each range,
+        *              if the visible text range is clipped</li>
+        * </ul>
+        */
+       public void getVisibleRanges(AccessibleTextEvent e);
+
+       /**
+        * Deselects a range of text.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of selection to remove</li>
+        * <li>[out] result - set to {@link ACC#OK} if the range of text was deselected</li>
+        * </ul>
+        */
+       public void removeSelection(AccessibleTextEvent e);
+
+       /**
+        * Scrolls a specific part of a substring according to the scroll type.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] start - the 0 based offset of the first character of the substring</li>
+        * <li>[in] end - the 0 based offset after the last character of the substring</li>
+        * <li>[in] type - a scroll type indicating where the substring should be placed
+        *              on the screen. One of:<ul>
+        *              <li> {@link ACC#SCROLL_TYPE_TOP_LEFT}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_BOTTOM_RIGHT}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_TOP_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_BOTTOM_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_LEFT_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_RIGHT_EDGE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_ANYWHERE}</li>
+        *              <li> {@link ACC#SCROLL_TYPE_POINT}</li>
+        *              </ul></li>
+        * <li>[optional in] x - for SCROLL_TYPE_POINT, the X coordinate of the destination point in display coordinates</li>
+        * <li>[optional in] y - for SCROLL_TYPE_POINT, the Y coordinate of the destination point in display coordinates</li>
+        * <li>[out] result - set to {@link ACC#OK} if the text was scrolled</li>
+        * </ul>
+        */
+       public void scrollText(AccessibleTextEvent e);
+
+       /**
+        * Sets the position of the caret.
+        * <p>
+        * The caret position is that of the character logically following it,
+        * e.g. to the right of it in a left to right language.
+        * The caret is actually placed to the leading side of the character with
+        * that offset. An offset of 0 places the caret so that the next insertion
+        * goes before the first character. An offset of getCharacterCount places
+        * the caret so that the next insertion goes after the last character.
+        * </p><p>
+        * Setting the caret position may or may not alter the current selection.  A
+        * change of the selection is notified to the accessibility event listeners with
+        * an EVENT_TEXT_SELECTION_CHANGED event.
+        * </p><p>
+        * When the new caret position differs from the old one, this is notified to the
+        * accessibility event listeners with an EVENT_TEXT_CARET_MOVED event.
+        * </p>
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] offset - the new offset of the caret</li>
+        * <li>[out] result - set to {@link ACC#OK} if the caret position was set</li>
+        * </ul>
+        */
+       public void setCaretOffset(AccessibleTextEvent e);
+
+       /**
+        * Changes the bounds of an existing selection.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in] index - the 0 based index of the selection to change</li>
+        * <li>[in] start - the new 0 based offset of the first character of the selection</li>
+        * <li>[in] end - the new 0 based offset after the last character of the selection</li>
+        * <li>[out] result - set to {@link ACC#OK} if the selection was set</li>
+        * </ul>
+        */
+       public void setSelection(AccessibleTextEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleTextListener.java
new file mode 100644 (file)
index 0000000..e029125
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 extends 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueAdapter.java
new file mode 100644 (file)
index 0000000..2789caf
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods in the <code>AccessibleValueListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleValue</code> events can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p>
+ *
+ * @see AccessibleValueListener
+ * @see AccessibleValueEvent
+ *
+ * @since 3.6
+ */
+public class AccessibleValueAdapter implements AccessibleValueListener {
+       /**
+        * Returns the value of this object as a number.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] value - the number that is the current value of this object</li>
+        * </ul>
+        */
+       @Override
+       public void getCurrentValue(AccessibleValueEvent e) {}
+
+       /**
+        * Sets the value of this object to the given number.
+        *
+        * The argument is clipped to the valid interval whose upper and lower
+        * bounds are returned by getMaximumValue and getMinimumValue,
+        * i.e. if it is lower than the minimum value the new value will be the minimum,
+        * and if it is greater than the maximum then the new value will be the maximum.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in/out] value - on input, the number that will be the new value of this object
+        *              <br>- on output, set to null if the value cannot be set</li>
+        * </ul>
+        */
+       @Override
+       public void setCurrentValue(AccessibleValueEvent e) {}
+
+       /**
+        * Returns the maximum value that can be represented by this object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] value - the number that is the maximum value that this object can represent.
+        *              If this object has no upper bound then null is returned.</li>
+        * </ul>
+        */
+       @Override
+       public void getMaximumValue(AccessibleValueEvent e) {}
+
+       /**
+        * Returns the minimum value that can be represented by this object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] value - the number that is the minimum value that this object can represent.
+        *              If this object has no lower bound then null is returned.</li>
+        * </ul>
+        */
+       @Override
+       public void getMinimumValue(AccessibleValueEvent e) {}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueEvent.java
new file mode 100644 (file)
index 0000000..bd381f2
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of accessibility clients
+ * sending AccessibleValue messages to an accessible object.
+ *
+ * @see AccessibleValueListener
+ * @see AccessibleValueAdapter
+ *
+ * @since 3.6
+ */
+public class AccessibleValueEvent extends EventObject {
+
+       public Number value;
+
+       static final long serialVersionUID = -465979079760740668L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public AccessibleValueEvent(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 "AccessibleValueEvent {" //$NON-NLS-1$
+               + "value=" + value   //$NON-NLS-1$
+               + "}";  //$NON-NLS-1$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/AccessibleValueListener.java
new file mode 100644 (file)
index 0000000..e012164
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that handle AccessibleValue events.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an accessible using the
+ * <code>addAccessibleValueListener</code> method and removed using
+ * the <code>removeAccessibleValueListener</code> method.
+ * </p>
+ *
+ * @see AccessibleValueAdapter
+ * @see AccessibleValueEvent
+ *
+ * @since 3.6
+ */
+public interface AccessibleValueListener extends SWTEventListener {
+       /**
+        * Returns the value of this object as a number.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] value - the number that is the current value of this object</li>
+        * </ul>
+        */
+       public void getCurrentValue(AccessibleValueEvent e);
+
+       /**
+        * Sets the value of this object to the given number.
+        *
+        * The argument is clipped to the valid interval whose upper and lower
+        * bounds are returned by getMaximumValue and getMinimumValue,
+        * i.e. if it is lower than the minimum value the new value will be the minimum,
+        * and if it is greater than the maximum then the new value will be the maximum.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[in/out] value - on input, the number that will be the new value of this object
+        *              <br>- on output, set to null if the value cannot be set</li>
+        * </ul>
+        */
+       public void setCurrentValue(AccessibleValueEvent e);
+
+       /**
+        * Returns the maximum value that can be represented by this object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] value - the number that is the maximum value that this object can represent.
+        *              If this object has no upper bound then null is returned.</li>
+        * </ul>
+        */
+       public void getMaximumValue(AccessibleValueEvent e);
+
+       /**
+        * Returns the minimum value that can be represented by this object.
+        *
+        * @param e an event object containing the following fields:<ul>
+        * <li>[out] value - the number that is the minimum value that this object can represent.
+        *              If this object has no lower bound then null is returned.</li>
+        * </ul>
+        */
+       public void getMinimumValue(AccessibleValueEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Relation.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Relation.java
new file mode 100644 (file)
index 0000000..760bd1b
--- /dev/null
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+class Relation {
+       Accessible accessible;
+       COMObject objIAccessibleRelation;
+       int refCount;
+       int type;
+       Accessible[] targets;
+       static final String[] relationTypeString = {
+               "controlledBy",         //$NON-NLS-1$
+               "controllerFor",        //$NON-NLS-1$
+               "describedBy",          //$NON-NLS-1$
+               "descriptionFor",       //$NON-NLS-1$
+               "embeddedBy",           //$NON-NLS-1$
+               "embeds",                       //$NON-NLS-1$
+               "flowsFrom",            //$NON-NLS-1$
+               "flowsTo",                      //$NON-NLS-1$
+               "labelFor",                     //$NON-NLS-1$
+               "labelledBy",           //$NON-NLS-1$
+               "memberOf",                     //$NON-NLS-1$
+               "nodeChildOf",          //$NON-NLS-1$
+               "parentWindowOf",       //$NON-NLS-1$
+               "popupFor",                     //$NON-NLS-1$
+               "subwindowOf",          //$NON-NLS-1$
+       };
+       static final String[] localizedRelationTypeString = {
+               SWT.getMessage("SWT_Controlled_By"),    //$NON-NLS-1$
+               SWT.getMessage("SWT_Controller_For"),   //$NON-NLS-1$
+               SWT.getMessage("SWT_Described_By"),             //$NON-NLS-1$
+               SWT.getMessage("SWT_Description_For"),  //$NON-NLS-1$
+               SWT.getMessage("SWT_Embedded_By"),              //$NON-NLS-1$
+               SWT.getMessage("SWT_Embeds"),                   //$NON-NLS-1$
+               SWT.getMessage("SWT_Flows_From"),               //$NON-NLS-1$
+               SWT.getMessage("SWT_Flows_To"),                 //$NON-NLS-1$
+               SWT.getMessage("SWT_Label_For"),                //$NON-NLS-1$
+               SWT.getMessage("SWT_Labelled_By"),              //$NON-NLS-1$
+               SWT.getMessage("SWT_Member_Of"),                //$NON-NLS-1$
+               SWT.getMessage("SWT_Node_Child_Of"),    //$NON-NLS-1$
+               SWT.getMessage("SWT_Parent_Window_Of"), //$NON-NLS-1$
+               SWT.getMessage("SWT_Popup_For"),                //$NON-NLS-1$
+               SWT.getMessage("SWT_Subwindow_Of"),             //$NON-NLS-1$
+       };
+
+       Relation(Accessible accessible, int type) {
+               this.accessible = accessible;
+               this.type = type;
+               this.targets = new Accessible[0];
+               AddRef();
+       }
+
+       long getAddress() {
+               /* The address of a Relation is the address of its IAccessibleRelation COMObject. */
+               if (objIAccessibleRelation == null) createIAccessibleRelation();
+               return objIAccessibleRelation.getAddress();
+       }
+
+       void createIAccessibleRelation() {
+               objIAccessibleRelation = new COMObject(new int[] {2,0,0,1,1,1,2,3}) {
+                       @Override
+                       public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+                       @Override
+                       public long method1(long[] args) {return AddRef();}
+                       @Override
+                       public long method2(long[] args) {return Release();}
+                       @Override
+                       public long method3(long[] args) {return get_relationType(args[0]);}
+                       @Override
+                       public long method4(long[] args) {return get_localizedRelationType(args[0]);}
+                       @Override
+                       public long method5(long[] args) {return get_nTargets(args[0]);}
+                       @Override
+                       public long method6(long[] args) {return get_target((int)args[0], args[1]);}
+                       @Override
+                       public long method7(long[] args) {return get_targets((int)args[0], args[1], args[2]);}
+               };
+       }
+
+       /* 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.
+        */
+       int QueryInterface(long iid, long ppvObject) {
+               GUID guid = new GUID();
+               COM.MoveMemory(guid, iid, GUID.sizeof);
+
+               if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) {
+                       OS.MoveMemory(ppvObject, new long[] { getAddress() }, C.PTR_SIZEOF);
+                       AddRef();
+                       return COM.S_OK;
+               }
+
+               return COM.E_NOINTERFACE;
+       }
+
+       int AddRef() {
+               refCount++;
+               return refCount;
+       }
+
+       int Release() {
+               refCount--;
+
+               if (refCount == 0) {
+                       if (objIAccessibleRelation != null)
+                               objIAccessibleRelation.dispose();
+                       objIAccessibleRelation = null;
+               }
+               return refCount;
+       }
+
+       /* IAccessibleRelation::get_relationType([out] pbstrRelationType) */
+       int get_relationType(long pbstrRelationType) {
+               setString(pbstrRelationType, relationTypeString[type]);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleRelation::get_localizedRelationType([out] pbstrLocalizedRelationType) */
+       int get_localizedRelationType(long pbstrLocalizedRelationType) {
+               setString(pbstrLocalizedRelationType, localizedRelationTypeString[type]);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleRelation::get_nTargets([out] pNTargets) */
+       int get_nTargets(long pNTargets) {
+               OS.MoveMemory(pNTargets, new int [] { targets.length }, 4);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleRelation::get_target([in] targetIndex, [out] ppTarget) */
+       int get_target(int targetIndex, long ppTarget) {
+               if (targetIndex < 0 || targetIndex >= targets.length) return COM.E_INVALIDARG;
+               Accessible target = targets[targetIndex];
+               target.AddRef();
+               OS.MoveMemory(ppTarget, new long[] { target.getAddress() }, C.PTR_SIZEOF);
+               return COM.S_OK;
+       }
+
+       /* IAccessibleRelation::get_targets([in] maxTargets, [out] ppTargets, [out] pNTargets) */
+       int get_targets(int maxTargets, long ppTargets, long pNTargets) {
+               int count = Math.min(targets.length, maxTargets);
+               for (int i = 0; i < count; i++) {
+                       Accessible target = targets[i];
+                       target.AddRef();
+                       OS.MoveMemory(ppTargets + i * C.PTR_SIZEOF, new long[] { target.getAddress() }, C.PTR_SIZEOF);
+               }
+               OS.MoveMemory(pNTargets, new int [] { count }, 4);
+               return COM.S_OK;
+       }
+
+       void addTarget(Accessible target) {
+               if (containsTarget(target)) return;
+               Accessible[] newTargets = new Accessible[targets.length + 1];
+               System.arraycopy(targets, 0, newTargets, 0, targets.length);
+               newTargets[targets.length] = target;
+               targets = newTargets;
+       }
+
+       boolean containsTarget(Accessible target) {
+               for (int i = 0; i < targets.length; i++) {
+                       if (targets[i] == target) return true;
+               }
+               return false;
+       }
+
+       void removeTarget(Accessible target) {
+               if (!containsTarget(target)) return;
+               Accessible[] newTargets = new Accessible[targets.length - 1];
+               int j = 0;
+               for (int i = 0; i < targets.length; i++) {
+                       if (targets[i] != target) {
+                               newTargets[j++] = targets[i];
+                       }
+               }
+               targets = newTargets;
+       }
+
+       boolean hasTargets() {
+               return targets.length > 0;
+       }
+
+       // setString copied from Accessible class
+       void setString(long psz, String string) {
+               char[] data = (string + "\0").toCharArray();
+               long ptr = COM.SysAllocString(data);
+               OS.MoveMemory(psz, new long [] { ptr }, C.PTR_SIZEOF);
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/package.html
new file mode 100644 (file)
index 0000000..ab6a590
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Accessibility.
+<h2>
+Package Specification</h2>
+This package contains the classes that support platform accessibility.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/awt/SWT_AWT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/awt/SWT_AWT.java
new file mode 100644 (file)
index 0000000..400800d
--- /dev/null
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.awt;
+
+/* AWT Imports */
+import java.awt.*;
+import java.awt.Canvas;
+import java.awt.event.*;
+import java.lang.reflect.*;
+
+/* SWT Imports */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * This class provides a bridge between SWT and AWT, so that it
+ * is possible to embed AWT components in SWT and vice versa.
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#awt">Swing/AWT snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class SWT_AWT {
+
+       /**
+        * The name of the embedded Frame class. The default class name
+        * for the platform will be used if <code>null</code>.
+        */
+       public static String embeddedFrameClass;
+
+       /**
+        * Key for looking up the embedded frame for a Composite using
+        * getData().
+        */
+       static String EMBEDDED_FRAME_KEY = "org.eclipse.swt.awt.SWT_AWT.embeddedFrame";
+
+static boolean loaded, swingInitialized;
+
+static native final long getAWTHandle (Canvas canvas);
+static native final Object initFrame (long handle, String className);
+static native final void synthesizeWindowActivation (Frame frame, boolean doActivate);
+
+static synchronized void loadLibrary () {
+       if (loaded) return;
+       loaded = true;
+       Toolkit.getDefaultToolkit();
+       /*
+       * Note that the jawt library is loaded explicitly
+       * because it cannot be found by the library loader.
+       * All exceptions are caught because the library may
+       * have been loaded already.
+       */
+       try {
+               System.loadLibrary("jawt");
+       } catch (Throwable e) {}
+       Library.loadLibrary("swt-awt");
+}
+
+static synchronized void initializeSwing() {
+       if (swingInitialized) return;
+       swingInitialized = true;
+       try {
+               /* Initialize the default focus traversal policy */
+               Class<?> clazz = Class.forName("javax.swing.UIManager");
+               Method method = clazz.getMethod("getDefaults");
+               if (method != null) method.invoke(clazz);
+       } catch (Throwable e) {}
+}
+
+/**
+ * Returns a <code>java.awt.Frame</code> which is the embedded frame
+ * associated with the specified composite.
+ *
+ * @param parent the parent <code>Composite</code> of the <code>java.awt.Frame</code>
+ * @return a <code>java.awt.Frame</code> the embedded frame or <code>null</code>.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public static Frame getFrame (Composite parent) {
+       if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if ((parent.getStyle () & SWT.EMBEDDED) == 0) return null;
+       return (Frame)parent.getData(EMBEDDED_FRAME_KEY);
+}
+
+/**
+ * Creates a new <code>java.awt.Frame</code>. This frame is the root for
+ * the AWT components that will be embedded within the composite. In order
+ * for the embedding to succeed, the composite must have been created
+ * with the SWT.EMBEDDED style.
+ * <p>
+ * IMPORTANT: As of JDK1.5, the embedded frame does not receive mouse events.
+ * When a lightweight component is added as a child of the embedded frame,
+ * the cursor does not change. In order to work around both these problems, it is
+ * strongly recommended that a heavyweight component such as <code>java.awt.Panel</code>
+ * be added to the frame as the root of all components.
+ * </p>
+ *
+ * @param parent the parent <code>Composite</code> of the new <code>java.awt.Frame</code>
+ * @return a <code>java.awt.Frame</code> to be the parent of the embedded AWT components
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent Composite does not have the SWT.EMBEDDED style</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public static Frame new_Frame (final Composite parent) {
+       if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if ((parent.getStyle () & SWT.EMBEDDED) == 0) {
+               SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       final long handle = parent.handle;
+       final Frame[] result = new Frame[1];
+       final Throwable[] exception = new Throwable[1];
+       Runnable runnable = () -> {
+               try {
+                       /*
+                        * Some JREs have implemented the embedded frame constructor to take an integer
+                        * and other JREs take a long.  To handle this binary incompatibility, use
+                        * reflection to create the embedded frame.
+                        */
+                       String className = embeddedFrameClass != null ? embeddedFrameClass : "sun.awt.windows.WEmbeddedFrame";
+                       try {
+                               if (embeddedFrameClass != null) {
+                                       Class.forName(className);
+                               }
+                               loadLibrary();
+                       } catch (ClassNotFoundException cne) {
+                               SWT.error (SWT.ERROR_NOT_IMPLEMENTED, cne);
+                       } catch (Throwable e) {
+                               exception[0] = e;
+                               return;
+                       }
+                       initializeSwing ();
+                       Object value = initFrame(handle, className);
+                       if (value == null || !(value instanceof Frame)) {
+                               exception [0] = new Throwable("[Error while creating AWT embedded frame]");
+                               SWT.error (SWT.ERROR_UNSPECIFIED, exception[0]);
+                               return;
+                       }
+                       result[0] = (Frame) value;
+               } finally {
+                       synchronized(result) {
+                               result.notify();
+                       }
+               }
+       };
+       if (EventQueue.isDispatchThread() || parent.getDisplay().getSyncThread() != null) {
+               runnable.run();
+       } else {
+               EventQueue.invokeLater(runnable);
+               OS.ReplyMessage(0);
+               boolean interrupted = false;
+               MSG msg = new MSG ();
+               int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
+               while (result[0] == null && exception[0] == null) {
+                       OS.PeekMessage (msg, 0, 0, 0, flags);
+                       try {
+                               synchronized (result) {
+                                       result.wait(50);
+                               }
+                       } catch (InterruptedException e) {
+                               interrupted = true;
+                       }
+               }
+               if (interrupted) {
+                       Thread.currentThread().interrupt();
+               }
+       }
+       if (exception[0] != null) {
+               SWT.error (SWT.ERROR_NOT_IMPLEMENTED, exception[0]);
+       }
+       final Frame frame = result[0];
+
+       parent.setData(EMBEDDED_FRAME_KEY, frame);
+
+       /* Forward the iconify and deiconify events */
+       final Listener shellListener = e -> {
+               switch (e.type) {
+                       case SWT.Deiconify:
+                               EventQueue.invokeLater(() -> frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEICONIFIED)));
+                               break;
+                       case SWT.Iconify:
+                               EventQueue.invokeLater(() -> frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ICONIFIED)));
+                               break;
+               }
+       };
+       Shell shell = parent.getShell ();
+       shell.addListener (SWT.Deiconify, shellListener);
+       shell.addListener (SWT.Iconify, shellListener);
+
+       /*
+       * Generate the appropriate events to activate and deactivate
+       * the embedded frame. This is needed in order to make keyboard
+       * focus work properly for lightweights.
+       */
+       Listener listener = e -> {
+               switch (e.type) {
+                       case SWT.Dispose:
+                               Shell shell1 = parent.getShell ();
+                               shell1.removeListener (SWT.Deiconify, shellListener);
+                               shell1.removeListener (SWT.Iconify, shellListener);
+                               parent.setVisible(false);
+                               EventQueue.invokeLater(() -> {
+                                       try {
+                                               frame.dispose ();
+                                       } catch (Throwable e1) {}
+                               });
+                               break;
+                       case SWT.FocusIn:
+                       case SWT.Activate:
+                               EventQueue.invokeLater(() -> {
+                                       if (frame.isActive()) return;
+                                       try {
+                                               Class<?> clazz = frame.getClass();
+                                               Method method = clazz.getMethod("synthesizeWindowActivation", boolean.class);
+                                               if (method != null) method.invoke(frame, Boolean.TRUE);
+                                       } catch (Throwable e1) {}
+                               });
+                               break;
+                       case SWT.Deactivate:
+                               EventQueue.invokeLater(() -> {
+                                       if (!frame.isActive()) return;
+                                       try {
+                                               Class<?> clazz = frame.getClass();
+                                               Method method = clazz.getMethod("synthesizeWindowActivation", boolean.class);
+                                               if (method != null) method.invoke(frame, Boolean.FALSE);
+                                       } catch (Throwable e1) {}
+                               });
+                               break;
+               }
+       };
+       parent.addListener (SWT.FocusIn, listener);
+       parent.addListener (SWT.Deactivate, listener);
+       parent.addListener (SWT.Dispose, listener);
+
+       parent.getDisplay().asyncExec(() -> {
+               if (parent.isDisposed()) return;
+               final Rectangle clientArea = DPIUtil.autoScaleUp(parent.getClientArea()); // To Pixels
+               EventQueue.invokeLater(() -> {
+                       frame.setSize (clientArea.width, clientArea.height);
+                       frame.validate ();
+               });
+       });
+       return frame;
+}
+
+/**
+ * Creates a new <code>Shell</code>. This Shell is the root for
+ * the SWT widgets that will be embedded within the AWT canvas.
+ *
+ * @param display the display for the new Shell
+ * @param parent the parent <code>java.awt.Canvas</code> of the new Shell
+ * @return a <code>Shell</code> to be the parent of the embedded SWT widgets
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the display is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent's peer is not created</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public static Shell new_Shell (final Display display, final Canvas parent) {
+       if (display == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       long handle = 0;
+       try {
+               loadLibrary ();
+               handle = getAWTHandle (parent);
+       } catch (Throwable e) {
+               SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e);
+       }
+       if (handle == 0) SWT.error (SWT.ERROR_INVALID_ARGUMENT, null, " [peer not created]");
+
+       final Shell shell = Shell.win32_new (display, handle);
+       final ComponentListener listener = new ComponentAdapter () {
+               @Override
+               public void componentResized (ComponentEvent e) {
+                       display.syncExec (() -> {
+                               if (shell.isDisposed()) return;
+                               Dimension dim = parent.getSize ();
+                               shell.setSize(DPIUtil.autoScaleDown(new Point(dim.width, dim.height))); // To Points
+                       });
+               }
+       };
+       parent.addComponentListener(listener);
+       shell.addListener(SWT.Dispose, event -> parent.removeComponentListener(listener));
+       shell.setVisible (true);
+       return shell;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/awt/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/awt/package.html
new file mode 100644 (file)
index 0000000..fb01e55
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT AWT embedding support.
+<h2>
+Package Specification</h2>
+This package contains a class named <code>SWT_AWT</code> which
+provides support for embedding AWT widgets within SWT composites.
+This package requires JDK 1.5 or higher.
+It works on Windows and GTK.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/AuthenticationEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/AuthenticationEvent.java
new file mode 100644 (file)
index 0000000..44d0046
--- /dev/null
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * An <code>AuthenticationEvent</code> is sent by a {@link Browser}
+ * to {@link AuthenticationListener}'s when the <code>Browser</code>
+ * navigates to a page that requires authentication. This event allows
+ * a client to either supply authentication credentials, cancel the
+ * authentication, or do nothing (which causes an authentication prompter
+ * to be shown to the user).
+ *
+ * @since 3.5
+ */
+public class AuthenticationEvent extends TypedEvent {
+       /** The location that triggered the authentication challenge */
+       public String location;
+
+       /** The user name to authenticate with */
+       public String user;
+
+       /** The password to authenticate with */
+       public String password;
+
+       /**
+        * A flag indicating whether the authentication should proceed.
+        * Setting this field to <code>false</code> will cancel the operation.
+        */
+       public boolean doit = true;
+
+       static final long serialVersionUID = -8322331206780057921L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param widget the widget that fired the event
+ *
+ * @since 3.5
+ */
+public AuthenticationEvent(Widget widget) {
+       super(widget);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " name=" + user
+               + " password=" + password
+               + " location=" + location
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/AuthenticationListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/AuthenticationListener.java
new file mode 100644 (file)
index 0000000..1e855de
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * an {@link AuthenticationEvent} notification when the {@link Browser}
+ * encounters a page that requires authentication.
+ *
+ * @see Browser#addAuthenticationListener(AuthenticationListener)
+ * @see Browser#removeAuthenticationListener(AuthenticationListener)
+ *
+ * @since 3.5
+ */
+@FunctionalInterface
+public interface AuthenticationListener extends SWTEventListener {
+
+/**
+ * This method is called when a page is navigated to that requires
+ * authentication.
+ * <p>
+ * Setting both the event's <code>user</code> and <code>password</code>
+ * fields causes these values to be used as credentials for authentication.
+ * Leaving one or both of these fields as <code>null</code> indicates
+ * that credentials are not known, so an authentication prompter should
+ * be shown to the user.  Otherwise, setting the event's <code>doit</code>
+ * field to <code>false</code> cancels the authentication challenge, and
+ * the page will not be loaded.
+ * </p>
+ *
+ * <p>The following fields in the <code>AuthenticationEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> that is attempting to show the
+ * page that requires authentication
+ * <li>(in) location the location issuing the authentication challenge
+ * <li>(in/out) doit can be set to <code>false</code> to cancel the
+ * authentication challenge
+ * <li>(out) user the user name to authenticate with
+ * <li>(out) password the password to authenticate with
+ * </ul>
+ *
+ * @param event the <code>AuthenticationEvent</code> that can be used to
+ * either supply authentication credentials, defer credential input to
+ * an authentication prompter, or cancel an authentication challenge.
+ */
+public void authenticate(AuthenticationEvent event);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/Browser.java
new file mode 100644 (file)
index 0000000..d344a70
--- /dev/null
@@ -0,0 +1,1223 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Instances of this class implement the browser user interface
+ * metaphor.  It allows the user to visualize and navigate through
+ * HTML documents.
+ * <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>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>NONE, WEBKIT</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>CloseWindowListener, LocationListener, OpenWindowListener, ProgressListener, StatusTextListener, TitleListener, VisibilityWindowListener</dd>
+ * </dl>
+ * <p>
+ * Note: MOZILLA is deprecated and is no longer supported.
+ * </p>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#browser">Browser snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: ControlExample, BrowserExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class Browser extends Composite {
+       WebBrowser webBrowser;
+       int userStyle;
+       boolean isClosing;
+
+       static int DefaultType = SWT.DEFAULT;
+
+       static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$
+       static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$
+       static final String PROPERTY_DEFAULTTYPE = "org.eclipse.swt.browser.DefaultType"; //$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>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for browser creation</li>
+ * </ul>
+ *
+ * @see Widget#getStyle
+ *
+ * @since 3.0
+ */
+public Browser (Composite parent, int style) {
+       super (checkParent (parent), checkStyle (style));
+       userStyle = style;
+
+       String platform = SWT.getPlatform ();
+       if ("gtk".equals (platform)) { //$NON-NLS-1$
+               parent.getDisplay ().setData (NO_INPUT_METHOD, null);
+       }
+
+       style = getStyle ();
+       webBrowser = new BrowserFactory ().createWebBrowser (style);
+       if (webBrowser != null) {
+               webBrowser.setBrowser (this);
+               webBrowser.create (parent, style);
+               return;
+       }
+       dispose ();
+
+       String errMsg = " because there is no underlying browser available.\n";
+       switch (SWT.getPlatform()) {
+       case "gtk":
+               errMsg = errMsg + "Please ensure that WebKit with its GTK 3.x bindings is installed (WebKit2 API level is preferred)."
+                               + " Additionally, please note that GTK4 does not currently have Browser support.\n";
+               break;
+       case "cocoa":
+               errMsg = errMsg + "SWT failed to load the WebKit library.\n";
+               break;
+       case "win32":
+               errMsg = errMsg + "SWT uses either IE or WebKit. Either the SWT.WEBKIT flag is passed and the WebKit library was not "
+                               + "loaded properly by SWT, or SWT failed to load IE.\n";
+               break;
+       default:
+               break;
+       }
+       SWT.error (SWT.ERROR_NO_HANDLES, null, errMsg);
+}
+
+static Composite checkParent (Composite parent) {
+       String platform = SWT.getPlatform ();
+       if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$
+
+       /*
+       * Note.  Mozilla provides all IM support needed for text input in web pages.
+       * If SWT creates another input method context for the widget it will cause
+       * indeterminate results to happen (hangs and crashes). The fix is to prevent
+       * SWT from creating an input method context for the  Browser widget.
+       */
+       if (parent != null && !parent.isDisposed ()) {
+               Display display = parent.getDisplay ();
+               if (display != null) {
+                       if (display.getThread () == Thread.currentThread ()) {
+                               display.setData (NO_INPUT_METHOD, "true"); //$NON-NLS-1$
+                       }
+               }
+       }
+       return parent;
+}
+
+@SuppressWarnings("deprecation")
+static int checkStyle(int style) {
+       String platform = SWT.getPlatform ();
+       if (DefaultType == SWT.DEFAULT) {
+               /*
+               * Some Browser clients that explicitly specify the native renderer to use (by
+               * creating a Browser with SWT.WEBKIT) may also need to specify that all
+               * "default" Browser instances (those created with style SWT.NONE) should use
+               * this renderer as well. This may be needed in order to avoid incompatibilities
+               * that can arise from having multiple native renderers loaded within the same
+               * process. A client can do this by setting the
+               * "org.eclipse.swt.browser.DefaultType" java system property to a value like
+               * "ie" or "webkit". Value "mozilla" is ignored now.
+               */
+
+               /*
+               * Plug-ins need an opportunity to set the org.eclipse.swt.browser.DefaultType
+               * system property before the first Browser is created.  To facilitate this,
+               * reflection is used to reference non-existent class
+               * org.eclipse.swt.browser.BrowserInitializer the first time a Browser is created.
+               * A client wishing to use this hook can do so by creating a fragment of
+               * org.eclipse.swt that implements this class and sets the system property in its
+               * static initializer.
+               */
+               try {
+                       Class.forName ("org.eclipse.swt.browser.BrowserInitializer"); //$NON-NLS-1$
+               } catch (ClassNotFoundException e) {
+                       /* no fragment is providing this class, which is the typical case */
+               }
+
+               String value = System.getProperty (PROPERTY_DEFAULTTYPE);
+               if (value != null) {
+                       int index = 0;
+                       int length = value.length();
+                       do {
+                               int newIndex = value.indexOf(',', index);
+                               if (newIndex == -1) {
+                                       newIndex = length;
+                               }
+                               String current = value.substring(index, newIndex).trim();
+                               if (current.equalsIgnoreCase ("webkit")) { //$NON-NLS-1$
+                                       DefaultType = SWT.WEBKIT;
+                                       break;
+                               } else if (current.equalsIgnoreCase ("ie") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$
+                                       DefaultType = SWT.NONE;
+                                       break;
+                               }
+                               index = newIndex + 1;
+                       } while (index < length);
+               }
+               if (DefaultType == SWT.DEFAULT) {
+                       DefaultType = SWT.NONE;
+               }
+       }
+
+       /* remove SWT.MOZILLA style if specified */
+       if ((style & SWT.MOZILLA) != 0) {
+               System.err.println ("Unsupported Browser Type: SWT.MOZILLA style is deprecated.\n" //$NON-NLS-1$
+                               + "It'll be removed from the user specified style. Browser will be created with the modified style " //$NON-NLS-1$
+                               + "and if no other style bit is specified, browser with SWT.NONE style will be created"); //$NON-NLS-1$
+               style &= ~SWT.MOZILLA;
+       }
+
+       if ((style & SWT.WEBKIT) == 0) {
+               style |= DefaultType;
+       }
+       if ((style & SWT.WEBKIT) != 0) {
+               return style;
+       }
+       if ("win32".equals (platform)) { //$NON-NLS-1$
+               /*
+               * For IE on win32 the border is supplied by the embedded browser, so remove
+               * the style so that the parent Composite will not draw a second border.
+               */
+               return style & ~SWT.BORDER;
+       }
+       return style;
+}
+
+@Override
+protected void checkWidget () {
+       super.checkWidget ();
+}
+
+/**
+ * Clears all session cookies from all current Browser instances.
+ *
+ * @since 3.2
+ */
+public static void clearSessions () {
+       WebBrowser.clearSessions ();
+}
+
+/**
+ * Returns the value of a cookie that is associated with a URL.
+ * Note that cookies are shared amongst all Browser instances.
+ *
+ * @param name the cookie name
+ * @param url the URL that the cookie is associated with
+ * @return the cookie value, or <code>null</code> if no such cookie exists
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the name is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the url is null</li>
+ * </ul>
+ *
+ * @since 3.5
+ */
+public static String getCookie (String name, String url) {
+       if (name == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return WebBrowser.GetCookie (name, url);
+}
+
+/**
+ * Sets a cookie on a URL.  Note that cookies are shared amongst all Browser instances.
+ *
+ * The <code>value</code> parameter must be a cookie header string that
+ * complies with <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a>.
+ * The value is passed through to the native browser unchanged.
+ * <p>
+ * Example value strings:
+ * <code>foo=bar</code> (basic session cookie)
+ * <code>foo=bar; path=/; domain=.eclipse.org</code> (session cookie)
+ * <code>foo=bar; expires=Thu, 01-Jan-2030 00:00:01 GMT</code> (persistent cookie)
+ * <code>foo=; expires=Thu, 01-Jan-1970 00:00:01 GMT</code> (deletes cookie <code>foo</code>)
+ *
+ * @param value the cookie value
+ * @param url the URL to associate the cookie with
+ * @return <code>true</code> if the cookie was successfully set and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the value is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the url is null</li>
+ * </ul>
+ *
+ * @since 3.5
+ */
+public static boolean setCookie (String value, String url) {
+       if (value == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return WebBrowser.SetCookie (value, url, true);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when authentication is required.
+ * <p>
+ * This notification occurs when a page requiring authentication is
+ * encountered.
+ * </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_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @since 3.5
+ */
+public void addAuthenticationListener (AuthenticationListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addAuthenticationListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the window hosting the receiver should be closed.
+ * <p>
+ * This notification occurs when a javascript command such as
+ * <code>window.close</code> gets executed by a <code>Browser</code>.
+ * </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_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 addCloseWindowListener (CloseWindowListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addCloseWindowListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the current location has changed or is about to change.
+ * <p>
+ * This notification typically occurs when the application navigates
+ * to a new location with {@link #setUrl(String)} or when the user
+ * activates a hyperlink.
+ * </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_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 addLocationListener (LocationListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addLocationListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when a new window needs to be created.
+ * <p>
+ * This notification occurs when a javascript command such as
+ * <code>window.open</code> gets executed by a <code>Browser</code>.
+ * </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_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 addOpenWindowListener (OpenWindowListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addOpenWindowListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when a progress is made during the loading of the current
+ * URL or when the loading of the current URL has been completed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void addProgressListener (ProgressListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addProgressListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the status text is changed.
+ * <p>
+ * The status text is typically displayed in the status bar of
+ * a browser application.
+ * </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_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 addStatusTextListener (StatusTextListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addStatusTextListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the title of the current document is available
+ * or has changed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void addTitleListener (TitleListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addTitleListener (listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when a window hosting the receiver needs to be displayed
+ * or hidden.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void addVisibilityWindowListener (VisibilityWindowListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.addVisibilityWindowListener (listener);
+}
+
+/**
+ * Navigate to the previous session history item.
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @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 #forward
+ *
+ * @since 3.0
+ */
+public boolean back () {
+       checkWidget();
+       return webBrowser.back ();
+}
+
+@Override
+protected void checkSubclass () {
+       String name = getClass ().getName ();
+       int index = name.lastIndexOf ('.');
+       if (!name.substring (0, index + 1).equals (PACKAGE_PREFIX)) {
+               SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+       }
+}
+
+/**
+ * Executes the specified script.
+ * <p>
+ * Executes a script containing javascript commands in the context of the current document.
+ * If document-defined functions or properties are accessed by the script then this method
+ * should not be invoked until the document has finished loading (<code>ProgressListener.completed()</code>
+ * gives notification of this).
+ *
+ * @param script the script with javascript commands
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the script 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 ProgressListener#completed(ProgressEvent)
+ *
+ * @since 3.1
+ */
+public boolean execute (String script) {
+       checkWidget();
+       if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return webBrowser.execute (script);
+}
+
+/**
+ * Attempts to dispose the receiver, but allows the dispose to be vetoed
+ * by the user in response to an <code>onbeforeunload</code> listener
+ * in the Browser's current page.
+ *
+ * @return <code>true</code> if the receiver was disposed, 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 #dispose()
+ *
+ * @since 3.6
+ */
+public boolean close () {
+       checkWidget();
+       if (webBrowser.close ()) {
+               isClosing = true;
+               dispose ();
+               isClosing = false;
+               return true;
+       }
+       return false;
+}
+
+/**
+ * Returns the result, if any, of executing the specified script.
+ * <p>
+ * Evaluates a script containing javascript commands in the context of
+ * the current document.  If document-defined functions or properties
+ * are accessed by the script then this method should not be invoked
+ * until the document has finished loading (<code>ProgressListener.completed()</code>
+ * gives notification of this).
+ * </p><p>
+ * If the script returns a value with a supported type then a java
+ * representation of the value is returned.  The supported
+ * javascript -&gt; java mappings are:
+ * <ul>
+ * <li>javascript null or undefined -&gt; <code>null</code></li>
+ * <li>javascript number -&gt; <code>java.lang.Double</code></li>
+ * <li>javascript string -&gt; <code>java.lang.String</code></li>
+ * <li>javascript boolean -&gt; <code>java.lang.Boolean</code></li>
+ * <li>javascript array whose elements are all of supported types -&gt; <code>java.lang.Object[]</code></li>
+ * </ul>
+ *
+ * An <code>SWTException</code> is thrown if the return value has an
+ * unsupported type, or if evaluating the script causes a javascript
+ * error to be thrown.
+ *
+ * @param script the script with javascript commands
+ *
+ * @return the return value, if any, of executing the script
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the script is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_FAILED_EVALUATE when the script evaluation causes a javascript error to be thrown</li>
+ *    <li>ERROR_INVALID_RETURN_VALUE when the script returns a value of unsupported type</li>
+ *    <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 Browser#evaluate(String,boolean)
+ * @see ProgressListener#completed(ProgressEvent)
+ *
+ * @since 3.5
+ */
+public Object evaluate (String script) throws SWTException {
+       checkWidget();
+       return evaluate (script, false);
+}
+
+/**
+ * Returns the result, if any, of executing the specified script.
+ * <p>
+ * Evaluates a script containing javascript commands.
+ * When <code>trusted</code> is <code>true</code> script is executed in the context of Chrome
+ * with Chrome security privileges.
+ * When <code>trusted</code> is <code>false</code> script is executed in the context of the
+ * current document with normal privileges.
+ * </p><p>
+ * If document-defined functions or properties are accessed by the script then
+ * this method should not be invoked until the document has finished loading
+ * (<code>ProgressListener.completed()</code> gives notification of this).
+ * </p><p>
+ * If the script returns a value with a supported type then a java
+ * representation of the value is returned.  The supported
+ * javascript -&gt; java mappings are:
+ * <ul>
+ * <li>javascript null or undefined -&gt; <code>null</code></li>
+ * <li>javascript number -&gt; <code>java.lang.Double</code></li>
+ * <li>javascript string -&gt; <code>java.lang.String</code></li>
+ * <li>javascript boolean -&gt; <code>java.lang.Boolean</code></li>
+ * <li>javascript array whose elements are all of supported types -&gt; <code>java.lang.Object[]</code></li>
+ * </ul>
+ * An <code>SWTException</code> is thrown if the return value has an
+ * unsupported type, or if evaluating the script causes a javascript
+ * error to be thrown.
+ * <p>
+ * Note: Chrome security context is applicable only to Browsers with style <code>SWT.Mozilla</code>.
+ * </p>
+ * @param script the script with javascript commands
+ * @param trusted <code>true</code> or <code>false</code> depending on the security context to be used
+ *
+ * @return the return value, if any, of executing the script
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the script is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_FAILED_EVALUATE when the script evaluation causes a javascript error to be thrown</li>
+ *    <li>ERROR_INVALID_RETURN_VALUE when the script returns a value of unsupported type</li>
+ *    <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 ProgressListener#completed(ProgressEvent)
+ */
+public Object evaluate (String script, boolean trusted) throws SWTException {
+       checkWidget();
+       if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return webBrowser.evaluate (script, trusted);
+}
+
+/**
+ * Navigate to the next session history item.
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @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 #back
+ *
+ * @since 3.0
+ */
+public boolean forward () {
+       checkWidget();
+       return webBrowser.forward ();
+}
+
+/**
+ * Returns the type of native browser being used by this instance.
+ * Examples: "ie", "mozilla", "voyager", "webkit"
+ *
+ * @return the type of the native browser
+ *
+ * @since 3.5
+ */
+public String getBrowserType () {
+       checkWidget();
+       return webBrowser.getBrowserType ();
+}
+
+/**
+ * Returns <code>true</code> if javascript will be allowed to run in pages
+ * subsequently viewed in the receiver, and <code>false</code> otherwise.
+ * Note that this may not reflect the javascript enablement on the currently-
+ * viewed page if <code>setJavascriptEnabled()</code> has been invoked during
+ * its lifetime.
+ *
+ * @return the receiver's javascript 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 #setJavascriptEnabled
+ *
+ * @since 3.5
+ */
+public boolean getJavascriptEnabled () {
+       checkWidget();
+       return webBrowser.jsEnabledOnNextPage;
+}
+
+@Override
+public int getStyle () {
+       /*
+       * If SWT.BORDER was specified at creation time then getStyle() should answer
+       * it even though it is removed for IE on win32 in checkStyle().
+       */
+       return super.getStyle () | (userStyle & SWT.BORDER);
+}
+
+/**
+ * Returns a string with HTML that represents the content of the current page.
+ *
+ * @return HTML representing the current page or an empty <code>String</code>
+ * if this is empty.<br>
+ * <p> Note, the exact return value is platform dependent.
+ * For example on Windows, the returned string is the proccessed webpage
+ * with javascript executed and missing html tags added.
+ * On Linux and OS X, this returns the original HTML before the browser has
+ * processed it.</p>
+ *
+ * @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.4
+ */
+public String getText () {
+       checkWidget();
+       return webBrowser.getText ();
+}
+
+/**
+ * Returns the current URL.
+ *
+ * @return the current URL or an empty <code>String</code> if there is no current URL
+ *
+ * @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 #setUrl
+ *
+ * @since 3.0
+ */
+public String getUrl () {
+       checkWidget();
+       return webBrowser.getUrl ();
+}
+
+/**
+ * Returns the JavaXPCOM <code>nsIWebBrowser</code> for the receiver, or <code>null</code>
+ * if it is not available.  In order for an <code>nsIWebBrowser</code> to be returned all
+ * of the following must be true: <ul>
+ *    <li>the receiver's style must be <code>SWT.MOZILLA</code></li>
+ *    <li>the classes from JavaXPCOM &gt;= 1.8.1.2 must be resolvable at runtime</li>
+ *    <li>the version of the underlying XULRunner must be &gt;= 1.8.1.2</li>
+ * </ul>
+ *
+ * @return the receiver's JavaXPCOM <code>nsIWebBrowser</code> or <code>null</code>
+ *
+ * @since 3.3
+ * @deprecated SWT.MOZILLA is deprecated and XULRunner as a browser renderer is no longer supported.
+ */
+@Deprecated
+public Object getWebBrowser () {
+       checkWidget();
+       return webBrowser.getWebBrowser ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver can navigate to the
+ * previous session history item, and <code>false</code> otherwise.
+ *
+ * @return the receiver's back command 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 #back
+ */
+public boolean isBackEnabled () {
+       checkWidget();
+       return webBrowser.isBackEnabled ();
+}
+
+@Override
+public boolean isFocusControl () {
+       checkWidget();
+       if (webBrowser.isFocusControl ()) return true;
+       return super.isFocusControl ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver can navigate to the
+ * next session history item, and <code>false</code> otherwise.
+ *
+ * @return the receiver's forward command 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 #forward
+ */
+public boolean isForwardEnabled () {
+       checkWidget();
+       return webBrowser.isForwardEnabled ();
+}
+
+/**
+ * Refresh the current page.
+ *
+ * @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 refresh () {
+       checkWidget();
+       webBrowser.refresh ();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when authentication is required.
+ *
+ * @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>
+ *
+ * @since 3.5
+ */
+public void removeAuthenticationListener (AuthenticationListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeAuthenticationListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the window hosting the receiver should be closed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeCloseWindowListener (CloseWindowListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeCloseWindowListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the current location is changed or about to be changed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeLocationListener (LocationListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeLocationListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a new window needs to be created.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeOpenWindowListener (OpenWindowListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeOpenWindowListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a progress is made during the loading of the current
+ * URL or when the loading of the current URL has been completed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeProgressListener (ProgressListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeProgressListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the status text is changed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeStatusTextListener (StatusTextListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeStatusTextListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the title of the current document is available
+ * or has changed.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeTitleListener (TitleListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeTitleListener (listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a window hosting the receiver needs to be displayed
+ * or hidden.
+ *
+ * @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>
+ *
+ * @since 3.0
+ */
+public void removeVisibilityWindowListener (VisibilityWindowListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       webBrowser.removeVisibilityWindowListener (listener);
+}
+
+/**
+ * Sets whether javascript will be allowed to run in pages subsequently
+ * viewed in the receiver.  Note that setting this value does not affect
+ * the running of javascript in the current page.
+ *
+ * @param enabled the receiver's new javascript 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>
+ *
+ * @since 3.5
+ */
+public void setJavascriptEnabled (boolean enabled) {
+       checkWidget();
+       webBrowser.jsEnabledOnNextPage = enabled;
+}
+
+/**
+ * Renders a string containing HTML.  The rendering of the content occurs asynchronously.
+ * The rendered page will be given trusted permissions; to render the page with untrusted
+ * permissions use <code>setText(String html, boolean trusted)</code> instead.
+ * <p>
+ * The html parameter is Unicode-encoded since it is a java <code>String</code>.
+ * As a result, the HTML meta tag charset should not be set. The charset is implied
+ * by the <code>String</code> itself.
+ *
+ * @param html the HTML content to be rendered
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the html 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 #setText(String,boolean)
+ * @see #setUrl
+ *
+ * @since 3.0
+ */
+public boolean setText (String html) {
+       checkWidget();
+       return setText (html, true);
+}
+
+/**
+ * Renders a string containing HTML.  The rendering of the content occurs asynchronously.
+ * The rendered page can be given either trusted or untrusted permissions.
+ * <p>
+ * The <code>html</code> parameter is Unicode-encoded since it is a java <code>String</code>.
+ * As a result, the HTML meta tag charset should not be set. The charset is implied
+ * by the <code>String</code> itself.
+ * <p>
+ * The <code>trusted</code> parameter affects the permissions that will be granted to the rendered
+ * page.  Specifying <code>true</code> for trusted gives the page permissions equivalent
+ * to a page on the local file system, while specifying <code>false</code> for trusted
+ * gives the page permissions equivalent to a page from the internet.  Page content should
+ * be specified as trusted if the invoker created it or trusts its source, since this would
+ * allow (for instance) style sheets on the local file system to be referenced.  Page
+ * content should be specified as untrusted if its source is not trusted or is not known.
+ *
+ * @param html the HTML content to be rendered
+ * @param trusted <code>false</code> if the rendered page should be granted restricted
+ * permissions and <code>true</code> otherwise
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the html 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 #setText(String)
+ * @see #setUrl
+ *
+ * @since 3.6
+ */
+public boolean setText (String html, boolean trusted) {
+       checkWidget();
+       if (html == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return webBrowser.setText (html, trusted);
+}
+
+/**
+ * Begins loading a URL.  The loading of its content occurs asynchronously.
+ *
+ * @param url the URL to be loaded
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the url 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 #getUrl
+ * @see #setUrl(String,String,String[])
+ *
+ * @since 3.0
+ */
+public boolean setUrl (String url) {
+       checkWidget();
+       return setUrl (url, null, null);
+}
+
+/**
+ * Begins loading a URL.  The loading of its content occurs asynchronously.
+ * <p>
+ * If the URL causes an HTTP request to be initiated then the provided
+ * <code>postData</code> and <code>header</code> arguments, if any, are
+ * sent with the request.  A value in the <code>headers</code> argument
+ * must be a name-value pair with a colon separator in order to be sent
+ * (for example: "<code>user-agent: custom</code>").
+ *
+ * @param url the URL to be loaded
+ * @param postData post data to be sent with the request, or <code>null</code>
+ * @param headers header lines to be sent with the request, or <code>null</code>
+ *
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the url 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>
+ *
+ * @since 3.6
+ */
+public boolean setUrl (String url, String postData, String[] headers) {
+       checkWidget();
+       if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return webBrowser.setUrl (url, postData, headers);
+}
+
+/**
+ * Stop any loading and rendering activity.
+ *
+ * @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 stop () {
+       checkWidget();
+       webBrowser.stop ();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/BrowserFactory.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/BrowserFactory.java
new file mode 100644 (file)
index 0000000..90d181c
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.*;
+
+class BrowserFactory {
+
+WebBrowser createWebBrowser (int style) {
+       if ((style & SWT.WEBKIT) != 0) {
+               return new WebKit ();
+       }
+       return new IE ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/BrowserFunction.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/BrowserFunction.java
new file mode 100644 (file)
index 0000000..2bf403b
--- /dev/null
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent java-side "functions" that
+ * are invokable from javascript.  Browser clients define these
+ * functions by subclassing <code>BrowserFunction</code> and
+ * overriding its <code>function(Object[])</code> method.  This
+ * method will be invoked whenever javascript running in the
+ * Browser makes a call with the function's name.
+ *
+ * <p>
+ * Application code must explicitly invoke the
+ * <code>BrowserFunction.dispose()</code> method to release the
+ * resources managed by each instance when those instances are no
+ * longer required.  Since there is usually a correlation between
+ * the registering of BrowserFunction(s) in a Browser and the
+ * loading of a page in the Browser that is aware of these
+ * functions, the <code>LocationListener.changed()</code> listener
+ * is often a good place to do this.
+ * </p><p>
+ * Note that disposing a Browser automatically disposes all
+ * BrowserFunctions associated with it.
+ * </p>
+ *
+ * @see #dispose()
+ * @see #function(Object[])
+ * @see org.eclipse.swt.browser.LocationListener#changed(LocationEvent)
+ *
+ * @since 3.5
+ */
+public class BrowserFunction {
+       Browser browser;
+       String name;
+       String functionString;
+       int index;
+       boolean isEvaluate, top;
+       String token;
+       String[] frameNames;
+
+/**
+ * Constructs a new instance of this class, which will be invokable
+ * by javascript running in the specified Browser.  The function will
+ * be accessible in the top-level window and all child frames.  To
+ * create a function with a reduced scope of accessibility use the
+ * <code>BrowserFunction</code> constructor that accepts frame names
+ * instead.
+ * <p>
+ * You must dispose the BrowserFunction when it is no longer required.
+ * A common place to do this is in a <code>LocationListener.changed()</code>
+ * listener.
+ * </p>
+ * @param browser the browser whose javascript can invoke this function
+ * @param name the name that javascript will use to invoke this function
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the browser is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the name is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the browser has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #dispose()
+ * @see #BrowserFunction(Browser, String, boolean, String[])
+ * @see org.eclipse.swt.browser.LocationListener#changed(LocationEvent)
+ */
+public BrowserFunction (Browser browser, String name) {
+       this (browser, name, true, null, true);
+}
+
+/**
+ * Constructs a new instance of this class, which will be invokable
+ * by javascript running in the specified Browser.  The accessibility
+ * of the function to the top-level window and its child frames is
+ * determined by the <code>top</code> and <code>frameNames</code>
+ * arguments.  To create a function that is globally accessible to
+ * the top-level window and all child frames use the
+ * <code>BrowserFunction</code> constructor that does not accept frame
+ * names instead.
+ * <p>
+ * You must dispose the BrowserFunction when it is no longer required.
+ * A common place to do this is in a <code>LocationListener.changed()</code>
+ * listener.
+ * </p>
+ * @param browser the browser whose javascript can invoke this function
+ * @param name the name that javascript will use to invoke this function
+ * @param top <code>true</code> if the function should be accessible to the
+ * top-level window and <code>false</code> otherwise
+ * @param frameNames the names of the child frames that the function should
+ * be accessible in
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the browser is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the name is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the browser has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #dispose()
+ * @see #BrowserFunction(Browser, String)
+ * @see org.eclipse.swt.browser.LocationListener#changed(LocationEvent)
+ *
+ * @since 3.8
+ */
+public BrowserFunction (Browser browser, String name, boolean top, String[] frameNames) {
+       this (browser, name, top, frameNames, true);
+}
+
+BrowserFunction (Browser browser, String name, boolean top, String[] frameNames, boolean create) {
+       super ();
+       if (browser == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (name == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (browser.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
+       browser.checkWidget ();
+       this.browser = browser;
+       this.name = name;
+       this.top = top;
+       this.frameNames = frameNames;
+
+       Random random = new Random ();
+       byte[] bytes = new byte[16];
+       random.nextBytes (bytes);
+       StringBuilder buffer = new StringBuilder ();
+       for (int i = 0; i < bytes.length; i++) {
+               buffer.append (Integer.toHexString (bytes[i] & 0xff));
+       }
+       token = buffer.toString ();
+       if (create) browser.webBrowser.createFunction (this);
+}
+
+/**
+ * Disposes of the resources associated with this BrowserFunction.
+ * Applications must dispose of all BrowserFunctions that they create.
+ * <p>
+ * Note that disposing a Browser automatically disposes all
+ * BrowserFunctions associated with it.
+ * </p>
+ */
+public void dispose () {
+       dispose (true);
+}
+
+void dispose (boolean remove) {
+       if (index < 0) return;
+       if (remove) browser.webBrowser.destroyFunction (this);
+       browser = null;
+       name = functionString = null;
+       index = -1;
+}
+
+/**
+ * Subclasses should override this method.  This method is invoked when
+ * the receiver's function is called from javascript.  If all of the
+ * arguments that are passed to the javascript function call are of
+ * supported types then this method is invoked with the argument values
+ * converted as follows:
+ *
+ * javascript null or undefined -&gt; <code>null</code>
+ * javascript number -&gt; <code>java.lang.Double</code>
+ * javascript string -&gt; <code>java.lang.String</code>
+ * javascript boolean -&gt; <code>java.lang.Boolean</code>
+ * javascript array whose elements are all of supported types -&gt; <code>java.lang.Object[]</code>
+ *
+ * If any of the javascript arguments are of unsupported types then the
+ * function invocation will fail and this method will not be called.
+ *
+ * This method must return a value with one of these supported java types to
+ * the javascript caller.  Note that <code>null</code> values are converted
+ * to javascript's <code>null</code> value (not <code>undefined</code>), and
+ * instances of any <code>java.lang.Number</code> subclass will be converted
+ * to a javascript number.
+ *
+ * @param arguments the javascript arguments converted to java equivalents
+ * @return the value to return to the javascript caller
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_FUNCTION_DISPOSED when the BrowserFunction has been disposed</li>
+ * </ul>
+ */
+public Object function (Object[] arguments) {
+       if (index < 0) SWT.error (SWT.ERROR_FUNCTION_DISPOSED);
+       browser.checkWidget ();
+       return null;
+}
+
+/**
+ * Returns the Browser whose pages can invoke this BrowserFunction.
+ *
+ * @return the Browser associated with this BrowserFunction
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_FUNCTION_DISPOSED when the BrowserFunction has been disposed</li>
+ * </ul>
+ */
+public Browser getBrowser () {
+       if (index < 0) SWT.error (SWT.ERROR_FUNCTION_DISPOSED);
+       browser.checkWidget ();
+       return browser;
+}
+
+/**
+ * Returns the name that javascript can use to invoke this BrowserFunction.
+ *
+ * @return the BrowserFunction's name
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_FUNCTION_DISPOSED when the BrowserFunction has been disposed</li>
+ * </ul>
+ */
+public String getName () {
+       if (index < 0) SWT.error (SWT.ERROR_FUNCTION_DISPOSED);
+       browser.checkWidget ();
+       return name;
+}
+
+/**
+ * Returns <code>true</code> if this BrowserFunction has been disposed
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the BrowserFunction.
+ * When a BrowserFunction has been disposed it is an error to
+ * invoke any of its methods.
+ * </p><p>
+ * Note that disposing a Browser automatically disposes all
+ * BrowserFunctions associated with it.
+ * </p>
+ * @return <code>true</code> if this BrowserFunction has been disposed
+ * and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+       return index < 0;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/CloseWindowListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/CloseWindowListener.java
new file mode 100644 (file)
index 0000000..a35b08c
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link WindowEvent} notification when a {@link Browser} is
+ * about to be closed and when its host window should be closed
+ * by the application.
+ *
+ * @see Browser#addCloseWindowListener(CloseWindowListener)
+ * @see Browser#removeCloseWindowListener(CloseWindowListener)
+ * @see OpenWindowListener
+ * @see VisibilityWindowListener
+ *
+ * @since 3.0
+ */
+@FunctionalInterface
+public interface CloseWindowListener extends SWTEventListener {
+
+/**
+ * This method is called when the window hosting a {@link Browser} should be closed.
+ * Application would typically close the {@link org.eclipse.swt.widgets.Shell} that
+ * hosts the <code>Browser</code>. The <code>Browser</code> is disposed after this
+ * notification.
+ *
+ * <p>The following fields in the <code>WindowEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> that is going to be disposed
+ * </ul>
+ *
+ * @param event the <code>WindowEvent</code> that specifies the <code>Browser</code>
+ * that is going to be disposed
+ *
+ * @see org.eclipse.swt.widgets.Shell#close()
+ *
+ * @since 3.0
+ */
+public void close(WindowEvent event);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/IE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/IE.java
new file mode 100644 (file)
index 0000000..4927206
--- /dev/null
@@ -0,0 +1,2042 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.ole.win32.*;
+import org.eclipse.swt.widgets.*;
+
+class IE extends WebBrowser {
+
+       OleFrame frame;
+       WebSite site;
+       OleAutomation auto;
+       OleListener domListener;
+       OleAutomation[] documents = new OleAutomation[0];
+
+       boolean back, forward, delaySetText, ignoreDispose, ignoreTraverse, performingInitialNavigate;
+       boolean installFunctionsOnDocumentComplete, untrustedText, isRefresh, isAboutBlank;
+       Point location;
+       Point size;
+       boolean addressBar = true, menuBar = true, statusBar = true, toolBar = true;
+       long globalDispatch;
+       String html, lastNavigateURL, uncRedirect;
+       Object[] pendingText, pendingUrl;
+       int style, lastKeyCode, lastCharCode;
+       int lastMouseMoveX, lastMouseMoveY;
+
+       static boolean Initialized;
+       static int IEVersion, PDFCount;
+       static String ProgId = "Shell.Explorer";        //$NON-NLS-1$
+
+       static final int BeforeNavigate2 = 0xfa;
+       static final int CommandStateChange = 0x69;
+       static final int DocumentComplete = 0x103;
+       static final int DownloadComplete = 0x68;
+       static final int NavigateComplete2 = 0xfc;
+       static final int NewWindow2 = 0xfb;
+       static final int OnMenuBar = 0x100;
+       static final int OnStatusBar = 0x101;
+       static final int OnToolBar = 0xff;
+       static final int OnVisible = 0xfe;
+       static final int ProgressChange = 0x6c;
+       static final int RegisterAsBrowser = 0x228;
+       static final int StatusTextChange = 0x66;
+       static final int TitleChange = 0x71;
+       static final int WindowClosing = 0x107;
+       static final int WindowSetHeight = 0x10b;
+       static final int WindowSetLeft = 0x108;
+       static final int WindowSetResizable = 0x106;
+       static final int WindowSetTop = 0x109;
+       static final int WindowSetWidth = 0x10a;
+       static final int NavigateError = 0x10f;
+
+       static final short CSC_NAVIGATEFORWARD = 1;
+       static final short CSC_NAVIGATEBACK = 2;
+       static final int INET_E_DEFAULT_ACTION = 0x800C0011;
+       static final int INET_E_RESOURCE_NOT_FOUND = 0x800C0005;
+       static final int READYSTATE_COMPLETE = 4;
+       static final int URLPOLICY_ALLOW = 0x00;
+       static final int URLPOLICY_DISALLOW = 0x03;
+       static final int URLPOLICY_JAVA_PROHIBIT = 0x0;
+       static final int URLPOLICY_JAVA_LOW = 0x00030000;
+       static final int URLZONE_LOCAL_MACHINE = 0;
+       static final int URLZONE_INTRANET = 1;
+       static final int URLACTION_ACTIVEX_MIN = 0x00001200;
+       static final int URLACTION_ACTIVEX_MAX = 0x000013ff;
+       static final int URLACTION_ACTIVEX_RUN = 0x00001200;
+       static final int URLACTION_FEATURE_ZONE_ELEVATION = 0x00002101;
+       static final int URLACTION_JAVA_MIN = 0x00001C00;
+       static final int URLACTION_JAVA_MAX = 0x00001Cff;
+       static final int URLACTION_SCRIPT_RUN = 0x00001400;
+
+       static final int DISPID_AMBIENT_DLCONTROL = -5512;
+       static final int DLCTL_DLIMAGES = 0x00000010;
+       static final int DLCTL_VIDEOS = 0x00000020;
+       static final int DLCTL_BGSOUNDS = 0x00000040;
+       static final int DLCTL_NO_SCRIPTS = 0x00000080;
+       static final int DLCTL_NO_JAVA = 0x00000100;
+       static final int DLCTL_NO_RUNACTIVEXCTLS = 0x00000200;
+       static final int DLCTL_NO_DLACTIVEXCTLS = 0x00000400;
+       static final int DLCTL_DOWNLOADONLY = 0x00000800;
+       static final int DLCTL_NO_FRAMEDOWNLOAD = 0x00001000;
+       static final int DLCTL_RESYNCHRONIZE = 0x00002000;
+       static final int DLCTL_PRAGMA_NO_CACHE = 0x00004000;
+       static final int DLCTL_FORCEOFFLINE = 0x10000000;
+       static final int DLCTL_NO_CLIENTPULL = 0x20000000;
+       static final int DLCTL_SILENT = 0x40000000;
+       static final int DOCHOSTUIFLAG_THEME = 0x00040000;
+       static final int DOCHOSTUIFLAG_NO3DBORDER  = 0x0000004;
+       static final int DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000;
+       static final int DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION = 0x04000000;
+       static final int DOCHOSTUIFLAG_DPI_AWARE = 0x40000000;
+
+       static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
+       static final String CLSID_SHELLEXPLORER1 = "{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}"; //$NON-NLS-1$
+       static final int DEFAULT_IE_VERSION = 9999;
+       static final String EXTENSION_PDF = ".pdf";     //$NON-NLS-1$
+       static final String HTML_DOCUMENT = "HTML Document";    //$NON-NLS-1$
+       static final int MAX_PDF = 20;
+       static final char SEPARATOR_OS = File.separatorChar;
+       static final String PROPERTY_IEVERSION = "org.eclipse.swt.browser.IEVersion"; //$NON-NLS-1$
+       static final String VALUE_DEFAULT = "default"; //$NON-NLS-1$
+
+       static final String EVENT_DOUBLECLICK = "dblclick"; //$NON-NLS-1$
+       static final String EVENT_DRAGEND = "dragend";  //$NON-NLS-1$
+       static final String EVENT_DRAGSTART = "dragstart";      //$NON-NLS-1$
+       static final String EVENT_KEYDOWN = "keydown";  //$NON-NLS-1$
+       static final String EVENT_KEYPRESS = "keypress";        //$NON-NLS-1$
+       static final String EVENT_KEYUP = "keyup";      //$NON-NLS-1$
+       static final String EVENT_MOUSEMOVE = "mousemove";      //$NON-NLS-1$
+       static final String EVENT_MOUSEWHEEL = "mousewheel";    //$NON-NLS-1$
+       static final String EVENT_MOUSEUP = "mouseup";  //$NON-NLS-1$
+       static final String EVENT_MOUSEDOWN = "mousedown";      //$NON-NLS-1$
+       static final String EVENT_MOUSEOUT = "mouseout";        //$NON-NLS-1$
+       static final String EVENT_MOUSEOVER = "mouseover";      //$NON-NLS-1$
+       static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$
+       static final String PROPERTY_ALTKEY = "altKey"; //$NON-NLS-1$
+       static final String PROPERTY_BUTTON = "button"; //$NON-NLS-1$
+       static final String PROPERTY_CTRLKEY = "ctrlKey"; //$NON-NLS-1$
+       static final String PROPERTY_DOCUMENT = "Document"; //$NON-NLS-1$
+       static final String PROPERTY_FROMELEMENT = "fromElement"; //$NON-NLS-1$
+       static final String PROPERTY_KEYCODE = "keyCode"; //$NON-NLS-1$
+       static final String PROPERTY_REPEAT = "repeat"; //$NON-NLS-1$
+       static final String PROPERTY_RETURNVALUE = "returnValue"; //$NON-NLS-1$
+       static final String PROPERTY_SCREENX = "screenX"; //$NON-NLS-1$
+       static final String PROPERTY_SCREENY = "screenY"; //$NON-NLS-1$
+       static final String PROPERTY_SHIFTKEY = "shiftKey"; //$NON-NLS-1$
+       static final String PROPERTY_TOELEMENT = "toElement"; //$NON-NLS-1$
+       static final String PROPERTY_TYPE = "type"; //$NON-NLS-1$
+       static final String PROPERTY_WHEELDELTA = "wheelDelta"; //$NON-NLS-1$
+
+       static {
+               NativeClearSessions = () -> {
+                       OS.InternetSetOption (0, OS.INTERNET_OPTION_END_BROWSER_SESSION, 0, 0);
+               };
+
+               NativeGetCookie = () -> {
+                       TCHAR url = new TCHAR (0, CookieUrl, true);
+                       TCHAR cookieData = new TCHAR (0, 8192);
+                       int[] size = new int[] {cookieData.length ()};
+                       if (!OS.InternetGetCookie (url, null, cookieData, size)) {
+                               /* original cookieData size was not large enough */
+                               size[0] /= TCHAR.sizeof;
+                               cookieData = new TCHAR (0, size[0]);
+                               if (!OS.InternetGetCookie (url, null, cookieData, size)) return;
+                       }
+                       String allCookies = cookieData.toString (0, size[0]);
+                       StringTokenizer tokenizer = new StringTokenizer (allCookies, ";"); //$NON-NLS-1$
+                       while (tokenizer.hasMoreTokens ()) {
+                               String cookie = tokenizer.nextToken ();
+                               int index = cookie.indexOf ('=');
+                               if (index != -1) {
+                                       String name = cookie.substring (0, index).trim ();
+                                       if (name.equals (CookieName)) {
+                                               CookieValue = cookie.substring (index + 1).trim ();
+                                               return;
+                                       }
+                               }
+                       }
+               };
+
+               NativeSetCookie = () -> {
+                       TCHAR url = new TCHAR (0, CookieUrl, true);
+                       TCHAR value = new TCHAR (0, CookieValue, true);
+                       CookieResult = OS.InternetSetCookie (url, null, value);
+               };
+
+               /*
+               * The installed version of IE can be determined by looking at registry entry
+               * HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\svcVersion, or
+               * HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Version (for
+               * IE releases prior to IE10).  Check this value in order to determine
+               * version-specific features that can be enabled.
+               */
+               TCHAR key = new TCHAR (0, "Software\\Microsoft\\Internet Explorer", true);      //$NON-NLS-1$
+               long [] phkResult = new long [1];
+               if (OS.RegOpenKeyEx (OS.HKEY_LOCAL_MACHINE, key, 0, OS.KEY_READ, phkResult) == 0) {
+                       int [] lpcbData = new int [1];
+                       TCHAR buffer = new TCHAR (0, "svcVersion", true); //$NON-NLS-1$
+                       int result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, (TCHAR) null, lpcbData);
+                       if (result != 0) {
+                               buffer = new TCHAR (0, "Version", true); //$NON-NLS-1$
+                               result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, (TCHAR) null, lpcbData);
+                       }
+                       if (result == 0) {
+                               TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
+                               result = OS.RegQueryValueEx (phkResult [0], buffer, 0, null, lpData, lpcbData);
+                               if (result == 0) {
+                                       String versionString = lpData.toString (0, lpData.strlen ());
+                                       int index = versionString.indexOf ("."); //$NON-NLS-1$
+                                       if (index != -1) {
+                                               String majorString = versionString.substring (0, index);
+                                               try {
+                                                       IEVersion = Integer.valueOf (majorString).intValue ();
+                                               } catch (NumberFormatException e) {
+                                                       /* just continue, version-specific features will not be enabled */
+                                               }
+                                       }
+                               }
+                       }
+                       OS.RegCloseKey (phkResult [0]);
+               }
+
+               /*
+               * Registry entry HKEY_CLASSES_ROOT\Shell.Explorer\CLSID indicates which version of
+               * Shell.Explorer to use by default.  We usually want to use this value because it
+               * typically points at the newest one that is available.  However it is possible for
+               * this registry entry to be changed by another application to point at some other
+               * Shell.Explorer version.
+               *
+               * The Browser depends on the Shell.Explorer version being at least Shell.Explorer.2.
+               * If it is detected in the registry to be Shell.Explorer.1 then change the progId that
+               * will be embedded to explicitly specify Shell.Explorer.2.
+               */
+               key = new TCHAR (0, "Shell.Explorer\\CLSID", true);     //$NON-NLS-1$
+               phkResult = new long [1];
+               if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) == 0) {
+                       int [] lpcbData = new int [1];
+                       int result = OS.RegQueryValueEx (phkResult [0], null, 0, null, (TCHAR) null, lpcbData);
+                       if (result == 0) {
+                               TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
+                               result = OS.RegQueryValueEx (phkResult [0], null, 0, null, lpData, lpcbData);
+                               if (result == 0) {
+                                       String clsid = lpData.toString (0, lpData.strlen ());
+                                       if (clsid.equals (CLSID_SHELLEXPLORER1)) {
+                                               /* Shell.Explorer.1 is the default, ensure that Shell.Explorer.2 is available */
+                                               key = new TCHAR (0, "Shell.Explorer.2", true);  //$NON-NLS-1$
+                                               long [] phkResult2 = new long [1];
+                                               if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult2) == 0) {
+                                                       /* specify that Shell.Explorer.2 is to be used */
+                                                       OS.RegCloseKey (phkResult2 [0]);
+                                                       ProgId = "Shell.Explorer.2";    //$NON-NLS-1$
+                                               }
+                                       }
+                               }
+                       }
+                       OS.RegCloseKey (phkResult [0]);
+               }
+
+               if (NativePendingCookies != null) {
+                       SetPendingCookies (NativePendingCookies);
+               }
+               NativePendingCookies = null;
+       }
+
+@Override
+public void create(Composite parent, int style) {
+       this.style = style;
+       frame = new OleFrame(browser, SWT.NONE);
+
+       try {
+               site = new WebSite(frame, SWT.NONE, ProgId);
+       } catch (SWTException e) {
+               browser.dispose();
+               SWT.error(SWT.ERROR_NO_HANDLES);
+       }
+
+       if (!Initialized) {
+               Initialized = true;
+               int version = 0;
+               String versionProperty = System.getProperty(PROPERTY_IEVERSION);
+               if (versionProperty != null) {
+                       if (versionProperty.equalsIgnoreCase(VALUE_DEFAULT)) {
+                               version = -1;
+                       } else {
+                               try {
+                                       version = Integer.valueOf(versionProperty).intValue();
+                               } catch (NumberFormatException e) {
+                                       /*
+                                        * An invalid value was specified for the IEVersion java property.  Ignore it
+                                        * and continue with the usual steps for determining the version to specify.
+                                        */
+                               }
+                       }
+               }
+               if (version == 0) {
+                       if (IEVersion != 0) {
+                               /*
+                                * By default in Embedded IE the docuemntMode is Quirks(5)
+                                * mode unless !DOCTYPE directives is defined in the HTML.
+                                * As per MSDN IE8 and onwards, there is a way we could hint
+                                * embedded IE to use current documentMode via appropriate
+                                * version value in the registry. Refer bug 342145.
+                                *
+                                * Complete list of IE emulation modes is listed on MSDN:
+                                * http://msdn.microsoft
+                                * .com/en-us/library/ie/ee330730%28v=vs
+                                * .85%29.aspx#browser_emulation
+                                */
+                               if (IEVersion >= 10) {
+                                       version = IEVersion * 1000 + 1;
+                               }
+                               else if (IEVersion >= 8) {
+                                       version = IEVersion * 1111;
+                               }
+                               else {
+                                       version = IEVersion * 1000;
+                               }
+                       } else {
+                               version = DEFAULT_IE_VERSION;
+                       }
+               }
+
+               if (version != -1) {
+                       long[] key = new long[1];
+                       final TCHAR subkey = new TCHAR(0, "Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);     //$NON-NLS-1$
+                       if (OS.RegCreateKeyEx(OS.HKEY_CURRENT_USER, subkey, 0, null, OS.REG_OPTION_VOLATILE, OS.KEY_WRITE | OS.KEY_QUERY_VALUE, 0, key, null) == 0) {
+                               TCHAR lpszFile = new TCHAR(0, OS.MAX_PATH);
+                               OS.GetModuleFileName(0, lpszFile, lpszFile.length());
+                               String path = lpszFile.toString(0, lpszFile.strlen());
+                               int index = path.lastIndexOf(SEPARATOR_OS);
+                               String executable = index != -1 ? path.substring(index + 1) : path;
+                               final TCHAR lpValueName = new TCHAR(0, executable, true);
+                               /*
+                                * Program name & IE version entry is added to the Windows
+                                * registry and same gets deleted during the dispose cycle.
+                                * There is a possibility if the SWT application crashes or
+                                * is exited forcefully, which leaves the registry entry
+                                * as-is and hence if entry exists, updating it next time
+                                * the SWT application creates embedded IE, refer bug 440300
+                                */
+                               int result = OS.RegQueryValueEx(key[0], lpValueName, 0, null, (int[])null, null);
+                               if (result == 0 || result == OS.ERROR_FILE_NOT_FOUND) {
+                                       if (OS.RegSetValueEx(key[0], lpValueName, 0, OS.REG_DWORD, new int[] {version}, 4) == 0) {
+                                               parent.getDisplay().addListener(SWT.Dispose, event -> {
+                                                       long[] key1 = new long[1];
+                                                       if (OS.RegOpenKeyEx(OS.HKEY_CURRENT_USER, subkey, 0, OS.KEY_WRITE, key1) == 0) {
+                                                               OS.RegDeleteValue(key1[0], lpValueName);
+                                                       }
+                                               });
+                                       }
+                               }
+                               OS.RegCloseKey(key[0]);
+                       }
+               }
+       }
+
+       site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
+       auto = new OleAutomation(site);
+
+       domListener = e -> handleDOMEvent(e);
+
+       Listener listener = e -> {
+               switch (e.type) {
+                       case SWT.Dispose: {
+                               /* make this handler run after other dispose listeners */
+                               if (ignoreDispose) {
+                                       ignoreDispose = false;
+                                       break;
+                               }
+                               ignoreDispose = true;
+                               browser.notifyListeners (e.type, e);
+                               e.type = SWT.NONE;
+
+                               /* invoke onbeforeunload handlers */
+                               if (!browser.isClosing) {
+                                       LocationListener[] oldLocationListeners = locationListeners;
+                                       locationListeners = new LocationListener[0];
+                                       site.ignoreAllMessages = true;
+                                       execute ("window.location.href='about:blank'"); //$NON-NLS-1$
+                                       site.ignoreAllMessages = false;
+                                       locationListeners = oldLocationListeners;
+                               }
+
+                               /*
+                               * It is possible for the Browser's OLE frame to have been disposed
+                               * by a Dispose listener that was invoked by notifyListeners above,
+                               * so check for this before unhooking its DOM listeners.
+                               */
+                               if (!frame.isDisposed ()) unhookDOMListeners(documents);
+
+                               for (int i = 0; i < documents.length; i++) {
+                                       documents[i].dispose();
+                               }
+                               documents = null;
+
+                               Iterator<BrowserFunction> elements = functions.values().iterator ();
+                               while (elements.hasNext ()) {
+                                       elements.next ().dispose (false);
+                               }
+                               functions = null;
+
+                               lastNavigateURL = uncRedirect = null;
+                               domListener = null;
+                               if (auto != null) auto.dispose();
+                               auto = null;
+                               break;
+                       }
+                       case SWT.Resize: {
+                               frame.setBounds(browser.getClientArea());
+                               break;
+                       }
+                       case SWT.MouseWheel: {
+                               /* MouseWheel events come from the DOM */
+                               e.doit = false;
+                               break;
+                       }
+                       case SWT.FocusIn: {
+                               site.setFocus();
+                               break;
+                       }
+                       case SWT.Traverse: {
+                               /*
+                                * Tabbing out of the browser can fail as a result of the WebSite
+                                * control embedded within the Browser.  The workaround is to
+                                * listen for traversals and re-perform the traversal on the
+                                * appropriate control.
+                                */
+                               if (e.detail == SWT.TRAVERSE_TAB_PREVIOUS && e.widget instanceof WebSite) {
+                                       /* otherwise will traverse to the Browser control */
+                                       browser.traverse(SWT.TRAVERSE_TAB_PREVIOUS, e);
+                                       e.doit = false;
+                               }
+                               /*
+                                * Return traversals can sometimes come through TranslateAccelerator,
+                                * depending on where focus is within the Browser.  Traversal
+                                * events should always be triggered by a key event from the DOM,
+                                * so if a Traversal from TranslateAccelerator is detected
+                                * (e.doit == true) then stop its propagation.
+                                */
+                               if (e.detail == SWT.TRAVERSE_RETURN && e.doit && e.widget instanceof Browser) {
+                                       e.type = SWT.None;
+                                       e.doit = false;
+                               }
+                               break;
+                       }
+               }
+       };
+       browser.addListener(SWT.Dispose, listener);
+       browser.addListener(SWT.FocusIn, listener);
+       browser.addListener(SWT.Resize, listener);
+       browser.addListener(SWT.Traverse, listener);
+       site.addListener(SWT.MouseWheel, listener);
+       site.addListener(SWT.Traverse, listener);
+
+       OleListener oleListener = event -> {
+               /* callbacks are asynchronous, auto could be disposed */
+               if (auto != null) {
+                       switch (event.type) {
+                               case BeforeNavigate2: {
+
+                                       /* don't send client events if the initial navigate to about:blank has not completed */
+                                       if (performingInitialNavigate) break;
+
+                                       Variant varResult1 = event.arguments[1];
+                                       String url1 = varResult1.getString();
+
+                                       if (uncRedirect != null) {
+                                               /*
+                                               * Silently allow the navigate to proceed if the url is the first segment of a
+                                               * UNC path being navigated to (initiated by the NavigateError listener to show
+                                               * a name/password prompter), or if the url is the full UNC path (initiated by
+                                               * the NavigateComplete listener to redirect from the UNC's first segment to its
+                                               * full path).
+                                               */
+                                               if (uncRedirect.equals(url1) || (uncRedirect.startsWith(url1) && uncRedirect.indexOf('\\', 2) == url1.length())) {
+                                                       Variant cancel1 = event.arguments[6];
+                                                       if (cancel1 != null) {
+                                                               long pCancel1 = cancel1.getByRef();
+                                                               OS.MoveMemory(pCancel1, new short[] {OS.VARIANT_FALSE}, 2);
+                                                       }
+                                                       setAboutBlank(false);
+                                                       break;
+                                               } else {
+                                                       /*
+                                                       * This navigate does not correspond to the previously-initiated
+                                                       * UNC navigation so clear this state since it's no longer valid.
+                                                       */
+                                                       uncRedirect = null;
+                                               }
+                                       }
+
+                                       /*
+                                       * Feature in IE.  For navigations on the local machine, BeforeNavigate2's url
+                                       * field contains a string representation of the file path in a non-URL format.
+                                       * In order to be consistent with the other Browser implementations, this
+                                       * case is detected and the string is changed to be a proper url string.
+                                       */
+                                       if (url1.indexOf(":/") == -1 && url1.indexOf(":\\") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
+                                               TCHAR filePath1 = new TCHAR(0, url1, true);
+                                               TCHAR urlResult1 = new TCHAR(0, OS.INTERNET_MAX_URL_LENGTH);
+                                               int[] size1 = new int[] {urlResult1.length()};
+                                               if (OS.UrlCreateFromPath(filePath1, urlResult1, size1, 0) == COM.S_OK) {
+                                                       url1 = urlResult1.toString(0, size1[0]);
+                                               } else {
+                                                       url1 = PROTOCOL_FILE + url1.replace('\\', '/');
+                                               }
+                                       }
+
+                                       /* Disallow local file system accesses if the browser content is untrusted */
+                                       if (url1.startsWith(PROTOCOL_FILE) && _getUrl().startsWith(ABOUT_BLANK) && untrustedText) {
+                                               Variant cancel2 = event.arguments[6];
+                                               if (cancel2 != null) {
+                                                       long pCancel2 = cancel2.getByRef();
+                                                       OS.MoveMemory(pCancel2, new short[] {OS.VARIANT_TRUE}, 2);
+                                               }
+                                               break;
+                                       }
+
+                                       LocationEvent newEvent1 = new LocationEvent(browser);
+                                       newEvent1.display = browser.getDisplay();
+                                       newEvent1.widget = browser;
+                                       newEvent1.location = url1;
+                                       newEvent1.doit = true;
+                                       for (int i1 = 0; i1 < locationListeners.length; i1++) {
+                                               locationListeners[i1].changing(newEvent1);
+                                       }
+                                       boolean doit1 = newEvent1.doit && !browser.isDisposed();
+                                       Variant cancel3 = event.arguments[6];
+                                       if (cancel3 != null) {
+                                               long pCancel3 = cancel3.getByRef();
+                                               OS.MoveMemory(pCancel3, new short[] {doit1 ? OS.VARIANT_FALSE : OS.VARIANT_TRUE}, 2);
+                                       }
+                                       if (doit1) {
+                                               varResult1 = event.arguments[0];
+                                               IDispatch dispatch1 = varResult1.getDispatch();
+                                               Variant variant1 = new Variant(auto); /* does not need to be disposed */
+                                               IDispatch top1 = variant1.getDispatch();
+                                               if (top1.getAddress() == dispatch1.getAddress()) {
+                                                       setAboutBlank(url1.startsWith(ABOUT_BLANK));
+                                               }
+                                       }
+                                       break;
+                               }
+                               case CommandStateChange: {
+                                       boolean enabled = false;
+                                       Variant varResult2 = event.arguments[0];
+                                       int command = varResult2.getInt();
+                                       varResult2 = event.arguments[1];
+                                       enabled = varResult2.getBoolean();
+                                       switch (command) {
+                                               case CSC_NAVIGATEBACK : back = enabled; break;
+                                               case CSC_NAVIGATEFORWARD : forward = enabled; break;
+                                       }
+                                       break;
+                               }
+                               case DocumentComplete: {
+                                       if (performingInitialNavigate) {
+                                               /* this event marks the completion of the initial navigate to about:blank */
+                                               performingInitialNavigate = false;
+
+                                               /* if browser content has been provided by the client then set it now */
+                                               if (pendingText != null) {
+                                                       setText((String)pendingText[0], ((Boolean)pendingText[1]).booleanValue());
+                                               } else if (pendingUrl != null) {
+                                                       setUrl((String)pendingUrl[0], (String)pendingUrl[1], (String[])pendingUrl[2]);
+                                               }
+                                               pendingText = pendingUrl = null;
+                                               break;
+                                       }
+
+                                       Variant varResult3 = event.arguments[0];
+                                       IDispatch dispatch2 = varResult3.getDispatch();
+
+                                       varResult3 = event.arguments[1];
+                                       String url2 = varResult3.getString();
+                                       /*
+                                       * Feature in IE.  For navigations on the local machine, DocumentComplete's url
+                                       * field contains a string representation of the file path in a non-URL format.
+                                       * In order to be consistent with the other Browser implementations, this
+                                       * case is detected and the string is changed to be a proper url string.
+                                       */
+                                       if (url2.indexOf(":/") == -1 && url2.indexOf(":\\") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
+                                               TCHAR filePath2 = new TCHAR(0, url2, true);
+                                               TCHAR urlResult2 = new TCHAR(0, OS.INTERNET_MAX_URL_LENGTH);
+                                               int[] size2 = new int[] {urlResult2.length()};
+                                               if (OS.UrlCreateFromPath(filePath2, urlResult2, size2, 0) == COM.S_OK) {
+                                                       url2 = urlResult2.toString(0, size2[0]);
+                                               } else {
+                                                       url2 = PROTOCOL_FILE + url2.replace('\\', '/');
+                                               }
+                                       }
+                                       if (html != null && url2.equals(ABOUT_BLANK)) {
+                                               if (delaySetText) {
+                                                       delaySetText = false;
+                                                       browser.getDisplay().asyncExec(() -> {
+                                                               if (browser.isDisposed() || html == null) return;
+                                                               setHTML(html);
+                                                               html = null;
+                                                       });
+                                               } else {
+                                                       setHTML(html);
+                                                       html = null;
+                                               }
+                                       } else {
+                                               Variant variant2 = new Variant(auto); /* does not need to be disposed */
+                                               IDispatch top2 = variant2.getDispatch();
+                                               LocationEvent locationEvent = new LocationEvent(browser);
+                                               locationEvent.display = browser.getDisplay();
+                                               locationEvent.widget = browser;
+                                               locationEvent.location = url2;
+                                               locationEvent.top = top2.getAddress() == dispatch2.getAddress();
+                                               for (int i2 = 0; i2 < locationListeners.length; i2++) {
+                                                       locationListeners[i2].changed(locationEvent);
+                                               }
+                                               if (browser.isDisposed()) return;
+
+                                               /*
+                                               * With the IBM 64-bit JVM an unexpected document complete event occurs before
+                                               * the native browser's DOM has been built. Filter this premature event based
+                                               * on the browser's ready state.
+                                               */
+                                               int[] rgdispid1 = auto.getIDsOfNames(new String[] { "ReadyState" }); //$NON-NLS-1$
+                                               Variant pVarResult1 = auto.getProperty(rgdispid1[0]);
+                                               if (pVarResult1 != null) {
+                                                       int readyState = pVarResult1.getInt();
+                                                       pVarResult1.dispose ();
+                                                       if (readyState != READYSTATE_COMPLETE) {
+                                                               break;
+                                                       }
+                                               }
+
+                                               /*
+                                                * Note.  The completion of the page loading is detected as
+                                                * described in the MSDN article "Determine when a page is
+                                                * done loading in WebBrowser Control".
+                                                */
+                                               if (globalDispatch != 0 && dispatch2.getAddress() == globalDispatch) {
+                                                       /* final document complete */
+                                                       globalDispatch = 0;
+
+                                                       /* re-install registered functions iff needed */
+                                                       IE ie = (IE)browser.webBrowser;
+                                                       if (ie.installFunctionsOnDocumentComplete) {
+                                                               ie.installFunctionsOnDocumentComplete = false;
+                                                               Iterator<BrowserFunction> elements1 = functions.values().iterator ();
+                                                               while (elements1.hasNext ()) {
+                                                                       BrowserFunction function1 = elements1.next ();
+                                                                       execute (function1.functionString);
+                                                               }
+                                                       }
+
+                                                       ProgressEvent progressEvent1 = new ProgressEvent(browser);
+                                                       progressEvent1.display = browser.getDisplay();
+                                                       progressEvent1.widget = browser;
+                                                       for (int i3 = 0; i3 < progressListeners.length; i3++) {
+                                                               progressListeners[i3].completed(progressEvent1);
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               }
+                               case DownloadComplete: {
+                                       /*
+                                       * IE feature.  Some events that swt relies on are not sent when
+                                       * a page is refreshed (as opposed to being navigated to).  The
+                                       * workaround is to use DownloadComplete as an opportunity to
+                                       * do this work.
+                                       */
+
+                                       Iterator<BrowserFunction> elements2 = functions.values().iterator ();
+                                       while (elements2.hasNext ()) {
+                                               BrowserFunction function2 = elements2.next ();
+                                               execute (function2.functionString);
+                                       }
+
+                                       if (!isRefresh) break;
+                                       isRefresh = false;
+
+                                       /*
+                                       * DocumentComplete is not received for refreshes, but clients may rely
+                                       * on this event for tasks like hooking javascript listeners, so send the
+                                       * event here.
+                                       */
+                                       ProgressEvent progressEvent2 = new ProgressEvent(browser);
+                                       progressEvent2.display = browser.getDisplay();
+                                       progressEvent2.widget = browser;
+                                       for (int i4 = 0; i4 < progressListeners.length; i4++) {
+                                               progressListeners[i4].completed(progressEvent2);
+                                       }
+
+                                       break;
+                               }
+                               case NavigateComplete2: {
+                                       jsEnabled = jsEnabledOnNextPage;
+
+                                       Variant varResult4 = event.arguments[1];
+                                       String url3 = varResult4.getString();
+                                       if (!performingInitialNavigate) {
+                                               varResult4 = event.arguments[0];
+                                               IDispatch dispatch3 = varResult4.getDispatch();
+                                               Variant variant3 = new Variant(auto); /* does not need to be disposed */
+                                               IDispatch top3 = variant3.getDispatch();
+                                               if (top3.getAddress() == dispatch3.getAddress()) {
+                                                       setAboutBlank(url3.startsWith(ABOUT_BLANK));
+                                                       lastNavigateURL = url3;
+                                               }
+                                       }
+
+                                       /*
+                                       * Bug in Acrobat Reader.  Opening > MAX_PDF PDF files causes Acrobat to not
+                                       * clean up its shells properly when the container Browser is disposed.
+                                       * This results in Eclipse crashing at shutdown time because the leftover
+                                       * shells have invalid references to unloaded Acrobat libraries.  The
+                                       * workaround is to not unload the Acrobat libraries if > MAX_PDF PDF
+                                       * files have been opened.
+                                       */
+                                       boolean isPDF = false;
+                                       String path = null;
+                                       try {
+                                               path = new URL(url3).getPath();
+                                       } catch (MalformedURLException e) {
+                                       }
+                                       if (path != null) {
+                                               int extensionIndex = path.lastIndexOf('.');
+                                               if (extensionIndex != -1) {
+                                                       String extension = path.substring(extensionIndex);
+                                                       if (extension.equalsIgnoreCase(EXTENSION_PDF)) {
+                                                               isPDF = true;
+                                                               PDFCount++;
+                                                               if (PDFCount > MAX_PDF) {
+                                                                       COM.FreeUnusedLibraries = false;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if (uncRedirect != null) {
+                                               if (uncRedirect.equals(url3)) {
+                                                       /* full UNC path has been successfully navigated */
+                                                       uncRedirect = null;
+                                                       break;
+                                               }
+                                               if (uncRedirect.startsWith(url3)) {
+                                                       /*
+                                                       * UNC first segment has been successfully navigated,
+                                                       * now redirect to the full UNC path.
+                                                       */
+                                                       navigate(uncRedirect, null, null, true);
+                                                       break;
+                                               }
+                                               uncRedirect = null;
+                                       }
+
+                                       varResult4 = event.arguments[0];
+                                       IDispatch dispatch4 = varResult4.getDispatch();
+                                       if (globalDispatch == 0) globalDispatch = dispatch4.getAddress();
+
+                                       OleAutomation webBrowser = varResult4.getAutomation();
+                                       Variant variant4 = new Variant(auto); /* does not need to be disposed */
+                                       IDispatch top4 = variant4.getDispatch();
+                                       boolean isTop = top4.getAddress() == dispatch4.getAddress();
+                                       if (isTop) {
+                                               /* unhook DOM listeners and unref the last document(s) */
+                                               unhookDOMListeners(documents);
+                                               for (int i5 = 0; i5 < documents.length; i5++) {
+                                                       documents[i5].dispose();
+                                               }
+                                               documents = new OleAutomation[0];
+
+                                               /* re-install registered functions */
+                                               Iterator<BrowserFunction> elements3 = functions.values().iterator ();
+                                               while (elements3.hasNext ()) {
+                                                       BrowserFunction function3 = elements3.next ();
+                                                       execute (function3.functionString);
+                                               }
+                                       }
+                                       if (!isPDF) {
+                                               hookDOMListeners(webBrowser, isTop);
+                                       }
+                                       webBrowser.dispose();
+                                       break;
+                               }
+                               case NavigateError: {
+                                       if (uncRedirect != null) {
+                                               /*
+                                               * This is the second error attempting to reach this UNC path, so
+                                               * it does not exist.  Don't override the default error handling.
+                                               */
+                                               uncRedirect = null;
+                                               break;
+                                       }
+                                       Variant varResult5 = event.arguments[1];
+                                       final String url4 = varResult5.getString();
+                                       if (url4.startsWith("\\\\")) { //$NON-NLS-1$
+                                               varResult5 = event.arguments[3];
+                                               int statusCode = varResult5.getInt();
+                                               if (statusCode == INET_E_RESOURCE_NOT_FOUND) {
+                                                       int index = url4.indexOf('\\', 2);
+                                                       if (index != -1) {
+                                                               final String host = url4.substring(0, index);
+                                                               Variant cancel4 = event.arguments[4];
+                                                               if (cancel4 != null) {
+                                                                       long pCancel4 = cancel4.getByRef();
+                                                                       OS.MoveMemory(pCancel4, new short[] {OS.VARIANT_TRUE}, 2);
+                                                               }
+                                                               browser.getDisplay().asyncExec(() -> {
+                                                                       if (browser.isDisposed()) return;
+                                                                       /*
+                                                                       * Feature of IE.  When a UNC path ends with a '\' character IE
+                                                                       * drops this character when providing the path as an argument
+                                                                       * to some IE listeners.  Remove this character here too in
+                                                                       * order to match these other listener argument values.
+                                                                       */
+                                                                       if (url4.endsWith("\\")) { //$NON-NLS-1$
+                                                                               uncRedirect = url4.substring(0, url4.length() - 1);
+                                                                       } else {
+                                                                               uncRedirect = url4;
+                                                                       }
+                                                                       navigate(host, null, null, true);
+                                                               });
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               }
+                               case NewWindow2: {
+                                       Variant cancel5 = event.arguments[1];
+                                       long pCancel5 = cancel5.getByRef();
+                                       WindowEvent newEvent2 = new WindowEvent(browser);
+                                       newEvent2.display = browser.getDisplay();
+                                       newEvent2.widget = browser;
+                                       newEvent2.required = false;
+                                       for (int i6 = 0; i6 < openWindowListeners.length; i6++) {
+                                               openWindowListeners[i6].open(newEvent2);
+                                       }
+                                       IE browser = null;
+                                       if (newEvent2.browser != null && newEvent2.browser.webBrowser instanceof IE) {
+                                               browser = (IE)newEvent2.browser.webBrowser;
+                                       }
+                                       boolean doit2 = browser != null && !browser.browser.isDisposed();
+                                       if (doit2) {
+                                               /*
+                                               * When a Browser is opened in a new window, BrowserFunctions that are
+                                               * installed in it in the NavigateComplete2 callback are not retained
+                                               * through the loading of the page.  The workaround is to re-install
+                                               * the functions when DocumentComplete is received.
+                                               */
+                                               browser.installFunctionsOnDocumentComplete = true;
+
+                                               Variant variant5 = new Variant(browser.auto); /* does not need to be disposed */
+                                               IDispatch iDispatch = variant5.getDispatch();
+                                               Variant ppDisp = event.arguments[0];
+                                               long byref = ppDisp.getByRef();
+                                               if (byref != 0) OS.MoveMemory(byref, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
+                                       }
+                                       if (newEvent2.required) {
+                                               OS.MoveMemory(pCancel5, new short[]{doit2 ? OS.VARIANT_FALSE : OS.VARIANT_TRUE}, 2);
+                                       }
+                                       break;
+                               }
+                               case OnMenuBar: {
+                                       Variant arg01 = event.arguments[0];
+                                       menuBar = arg01.getBoolean();
+                                       break;
+                               }
+                               case OnStatusBar: {
+                                       Variant arg02 = event.arguments[0];
+                                       statusBar = arg02.getBoolean();
+                                       break;
+                               }
+                               case OnToolBar: {
+                                       Variant arg03 = event.arguments[0];
+                                       toolBar = arg03.getBoolean();
+                                       /*
+                                       * Feature in Internet Explorer.  OnToolBar FALSE is emitted
+                                       * when both tool bar, address bar and menu bar must not be visible.
+                                       * OnToolBar TRUE is emitted when either of tool bar, address bar
+                                       * or menu bar is visible.
+                                       */
+                                       if (!toolBar) {
+                                               addressBar = false;
+                                               menuBar = false;
+                                       }
+                                       break;
+                               }
+                               case OnVisible: {
+                                       Variant arg11 = event.arguments[0];
+                                       boolean visible = arg11.getBoolean();
+                                       WindowEvent newEvent3 = new WindowEvent(browser);
+                                       newEvent3.display = browser.getDisplay();
+                                       newEvent3.widget = browser;
+                                       if (visible) {
+                                               if (addressBar) {
+                                                       /*
+                                                       * Bug in Internet Explorer.  There is no distinct notification for
+                                                       * the address bar.  If neither address, menu or tool bars are visible,
+                                                       * OnToolBar FALSE is emitted. For some reason, querying the value of
+                                                       * AddressBar in this case returns true even though it should not be
+                                                       * set visible.  The workaround is to only query the value of AddressBar
+                                                       * when OnToolBar FALSE has not been emitted.
+                                                       */
+                                                       int[] rgdispid2 = auto.getIDsOfNames(new String[] { "AddressBar" }); //$NON-NLS-1$
+                                                       Variant pVarResult2 = auto.getProperty(rgdispid2[0]);
+                                                       if (pVarResult2 != null) {
+                                                               if (pVarResult2.getType () == OLE.VT_BOOL) {
+                                                                       addressBar = pVarResult2.getBoolean ();
+                                                               }
+                                                               pVarResult2.dispose ();
+                                                       }
+                                               }
+                                               newEvent3.addressBar = addressBar;
+                                               newEvent3.menuBar = menuBar;
+                                               newEvent3.statusBar = statusBar;
+                                               newEvent3.toolBar = toolBar;
+                                               newEvent3.location = location;
+                                               newEvent3.size = size;
+                                               for (int i7 = 0; i7 < visibilityWindowListeners.length; i7++) {
+                                                       visibilityWindowListeners[i7].show(newEvent3);
+                                               }
+                                               location = null;
+                                               size = null;
+                                       } else {
+                                               for (int i8 = 0; i8 < visibilityWindowListeners.length; i8++) {
+                                                       visibilityWindowListeners[i8].hide(newEvent3);
+                                               }
+                                       }
+                                       break;
+                               }
+                               case ProgressChange: {
+                                       /* don't send client events if the initial navigate to about:blank has not completed */
+                                       if (performingInitialNavigate) break;
+
+                                       Variant arg12 = event.arguments[0];
+                                       int nProgress = arg12.getType() != OLE.VT_I4 ? 0 : arg12.getInt(); // may be -1
+                                       Variant arg2 = event.arguments[1];
+                                       int nProgressMax = arg2.getType() != OLE.VT_I4 ? 0 : arg2.getInt();
+                                       ProgressEvent newEvent4 = new ProgressEvent(browser);
+                                       newEvent4.display = browser.getDisplay();
+                                       newEvent4.widget = browser;
+                                       newEvent4.current = nProgress;
+                                       newEvent4.total = nProgressMax;
+                                       if (nProgress != -1) {
+                                               for (int i9 = 0; i9 < progressListeners.length; i9++) {
+                                                       progressListeners[i9].changed(newEvent4);
+                                               }
+                                       }
+                                       break;
+                               }
+                               case StatusTextChange: {
+                                       /* don't send client events if the initial navigate to about:blank has not completed */
+                                       if (performingInitialNavigate) break;
+
+                                       Variant arg13 = event.arguments[0];
+                                       if (arg13.getType() == OLE.VT_BSTR) {
+                                               String text = arg13.getString();
+                                               StatusTextEvent newEvent5 = new StatusTextEvent(browser);
+                                               newEvent5.display = browser.getDisplay();
+                                               newEvent5.widget = browser;
+                                               newEvent5.text = text;
+                                               for (int i10 = 0; i10 < statusTextListeners.length; i10++) {
+                                                       statusTextListeners[i10].changed(newEvent5);
+                                               }
+                                       }
+                                       break;
+                               }
+                               case TitleChange: {
+                                       /* don't send client events if the initial navigate to about:blank has not completed */
+                                       if (performingInitialNavigate) break;
+
+                                       Variant arg14 = event.arguments[0];
+                                       if (arg14.getType() == OLE.VT_BSTR) {
+                                               String title = arg14.getString();
+                                               TitleEvent newEvent6 = new TitleEvent(browser);
+                                               newEvent6.display = browser.getDisplay();
+                                               newEvent6.widget = browser;
+                                               newEvent6.title = title;
+                                               for (int i11 = 0; i11 < titleListeners.length; i11++) {
+                                                       titleListeners[i11].changed(newEvent6);
+                                               }
+                                       }
+                                       break;
+                               }
+                               case WindowClosing: {
+                                       /*
+                                       * Disposing the Browser directly from this callback will crash if the
+                                       * Browser has a text field with an active caret.  As a workaround fire
+                                       * the Close event and dispose the Browser in an async block.
+                                       */
+                                       browser.getDisplay().asyncExec(() -> {
+                                               if (browser.isDisposed()) return;
+                                               WindowEvent newEvent = new WindowEvent(browser);
+                                               newEvent.display = browser.getDisplay();
+                                               newEvent.widget = browser;
+                                               for (int i = 0; i < closeWindowListeners.length; i++) {
+                                                       closeWindowListeners[i].close(newEvent);
+                                               }
+                                               browser.dispose();
+                                       });
+                                       Variant cancel6 = event.arguments[1];
+                                       long pCancel6 = cancel6.getByRef();
+                                       Variant arg15 = event.arguments[0];
+                                       boolean isChildWindow = arg15.getBoolean();
+                                       OS.MoveMemory(pCancel6, new short[]{isChildWindow ? OS.VARIANT_FALSE : OS.VARIANT_TRUE}, 2);
+                                       break;
+                               }
+                               case WindowSetHeight: {
+                                       if (size == null) size = new Point(0, 0);
+                                       Variant arg16 = event.arguments[0];
+                                       size.y = arg16.getInt();
+                                       break;
+                               }
+                               case WindowSetLeft: {
+                                       if (location == null) location = new Point(0, 0);
+                                       Variant arg17 = event.arguments[0];
+                                       location.x = arg17.getInt();
+                                       break;
+                               }
+                               case WindowSetTop: {
+                                       if (location == null) location = new Point(0, 0);
+                                       Variant arg18 = event.arguments[0];
+                                       location.y = arg18.getInt();
+                                       break;
+                               }
+                               case WindowSetWidth: {
+                                       if (size == null) size = new Point(0, 0);
+                                       Variant arg19 = event.arguments[0];
+                                       size.x = arg19.getInt();
+                                       break;
+                               }
+                       }
+               }
+       };
+       site.addEventListener(BeforeNavigate2, oleListener);
+       site.addEventListener(CommandStateChange, oleListener);
+       site.addEventListener(DocumentComplete, oleListener);
+       site.addEventListener(DownloadComplete, oleListener);
+       site.addEventListener(NavigateComplete2, oleListener);
+       site.addEventListener(NavigateError, oleListener);
+       site.addEventListener(NewWindow2, oleListener);
+       site.addEventListener(OnMenuBar, oleListener);
+       site.addEventListener(OnStatusBar, oleListener);
+       site.addEventListener(OnToolBar, oleListener);
+       site.addEventListener(OnVisible, oleListener);
+       site.addEventListener(ProgressChange, oleListener);
+       site.addEventListener(StatusTextChange, oleListener);
+       site.addEventListener(TitleChange, oleListener);
+       site.addEventListener(WindowClosing, oleListener);
+       site.addEventListener(WindowSetHeight, oleListener);
+       site.addEventListener(WindowSetLeft, oleListener);
+       site.addEventListener(WindowSetTop, oleListener);
+       site.addEventListener(WindowSetWidth, oleListener);
+
+       Variant variant = new Variant(true);
+       auto.setProperty(RegisterAsBrowser, variant);
+       variant.dispose();
+
+       variant = new Variant(false);
+       int[] rgdispid = auto.getIDsOfNames(new String[] {"RegisterAsDropTarget"}); //$NON-NLS-1$
+       if (rgdispid != null) auto.setProperty(rgdispid[0], variant);
+       variant.dispose();
+}
+
+@Override
+public boolean back() {
+       if (!back) return false;
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "GoBack" }); //$NON-NLS-1$
+       Variant pVarResult = auto.invoke(rgdispid[0]);
+       return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
+}
+
+@Override
+public boolean close() {
+       boolean result = true;
+       int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
+       int dispIdMember = rgdispid[0];
+       Variant pVarResult = auto.getProperty(dispIdMember);
+       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+               if (pVarResult != null) pVarResult.dispose();
+       } else {
+               OleAutomation document = pVarResult.getAutomation();
+               pVarResult.dispose();
+               rgdispid = document.getIDsOfNames(new String[]{"parentWindow"}); //$NON-NLS-1$
+               /* rgdispid != null implies HTML content */
+               if (rgdispid != null) {
+                       dispIdMember = rgdispid[0];
+                       pVarResult = document.getProperty(dispIdMember);
+                       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+                               if (pVarResult != null) pVarResult.dispose();
+                       } else {
+                               OleAutomation window = pVarResult.getAutomation();
+                               pVarResult.dispose();
+                               rgdispid = window.getIDsOfNames(new String[]{"location"}); //$NON-NLS-1$
+                               dispIdMember = rgdispid[0];
+                               pVarResult = window.getProperty(dispIdMember);
+                               if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+                                       if (pVarResult != null) pVarResult.dispose();
+                               } else {
+                                       OleAutomation location = pVarResult.getAutomation();
+                                       pVarResult.dispose();
+                                       LocationListener[] oldListeners = locationListeners;
+                                       locationListeners = new LocationListener[0];
+                                       rgdispid = location.getIDsOfNames(new String[]{"replace"}); //$NON-NLS-1$
+                                       dispIdMember = rgdispid[0];
+                                       Variant[] args = new Variant[] {new Variant("about:blank")}; //$NON-NLS-1$
+                                       pVarResult = location.invoke(dispIdMember, args);
+                                       if (pVarResult == null) {
+                                               /* cancelled by user */
+                                               result = false;
+                                       } else {
+                                               pVarResult.dispose();
+                                       }
+                                       args[0].dispose();
+                                       locationListeners = oldListeners;
+                                       location.dispose();
+                               }
+                               window.dispose();
+                       }
+               }
+               document.dispose();
+       }
+       return result;
+}
+
+static Variant createSafeArray(String string) {
+       /* Create a pointer and copy the data into it */
+       byte[] bytes = string.getBytes();
+       int length = bytes.length;
+       long pvData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, length);
+       C.memmove(pvData, bytes, length);
+       int cElements1 = length;
+
+       /* Create a SAFEARRAY in memory */
+       long pSafeArray = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, SAFEARRAY.sizeof);
+       SAFEARRAY safeArray = new SAFEARRAY();
+       safeArray.cDims = 1;
+       safeArray.fFeatures = OS.FADF_FIXEDSIZE;
+       safeArray.cbElements = 1;
+       safeArray.pvData = pvData;
+       SAFEARRAYBOUND safeArrayBound = new SAFEARRAYBOUND();
+       safeArray.rgsabound = safeArrayBound;
+       safeArrayBound.cElements = cElements1;
+       OS.MoveMemory (pSafeArray, safeArray, SAFEARRAY.sizeof);
+
+       /* Return a Variant that holds the SAFEARRAY */
+       long pVariant = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof);
+       short vt = (short)(OLE.VT_ARRAY | OLE.VT_UI1);
+       OS.MoveMemory(pVariant, new short[] {vt}, 2);
+       OS.MoveMemory(pVariant + 8, new long[] {pSafeArray}, C.PTR_SIZEOF);
+       return new Variant(pVariant, (short)(OLE.VT_BYREF | OLE.VT_VARIANT));
+}
+
+@Override
+public boolean execute(String script) {
+       /*
+        * Issue with IE: If the browser has not shown any content yet then
+        * first navigate to about:blank to work around bug 465822, then execute
+        * the requested script.
+        */
+       if (!performingInitialNavigate && _getUrl().length() == 0) {
+               performingInitialNavigate = true;
+               navigate (ABOUT_BLANK, null, null, true);
+       }
+
+       /* get IHTMLDocument2 */
+       int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
+       int dispIdMember = rgdispid[0];
+       Variant pVarResult = auto.getProperty(dispIdMember);
+       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+               if (pVarResult != null) pVarResult.dispose ();
+               return false;
+       }
+       OleAutomation document = pVarResult.getAutomation();
+       pVarResult.dispose();
+
+       /* get IHTMLWindow2 */
+       rgdispid = document.getIDsOfNames(new String[]{"parentWindow"}); //$NON-NLS-1$
+       if (rgdispid == null) {
+               /* implies that browser's content is not a IHTMLDocument2 (eg.- acrobat reader) */
+               document.dispose();
+               return false;
+       }
+       dispIdMember = rgdispid[0];
+       pVarResult = document.getProperty(dispIdMember);
+       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+               if (pVarResult != null) pVarResult.dispose ();
+               document.dispose();
+               return false;
+       }
+       OleAutomation ihtmlWindow2 = pVarResult.getAutomation();
+       pVarResult.dispose();
+       document.dispose();
+
+       rgdispid = ihtmlWindow2.getIDsOfNames(new String[] { "execScript", "code" }); //$NON-NLS-1$  //$NON-NLS-2$
+       if (rgdispid == null) {
+               ihtmlWindow2.dispose();
+               return false;
+       }
+       Variant[] rgvarg = new Variant[1];
+       rgvarg[0] = new Variant(script);
+       int[] rgdispidNamedArgs = new int[1];
+       rgdispidNamedArgs[0] = rgdispid[1];
+       pVarResult = ihtmlWindow2.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
+       rgvarg[0].dispose();
+       ihtmlWindow2.dispose();
+       if (pVarResult == null) return false;
+       pVarResult.dispose();
+       return true;
+}
+
+@Override
+public boolean forward() {
+       if (!forward) return false;
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "GoForward" }); //$NON-NLS-1$
+       Variant pVarResult = auto.invoke(rgdispid[0]);
+       return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
+}
+
+@Override
+public String getBrowserType () {
+       return "ie"; //$NON-NLS-1$
+}
+
+@Override
+String getDeleteFunctionString (String functionName) {
+       return "window." + functionName + "=undefined"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+@Override
+public String getText() {
+       /* get the document object */
+       int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
+       Variant pVarResult = auto.getProperty(rgdispid[0]);
+       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+               if (pVarResult != null) pVarResult.dispose ();
+               return ""; //$NON-NLS-1$
+       }
+       OleAutomation document = pVarResult.getAutomation();
+       pVarResult.dispose();
+
+       /* get the html object */
+       rgdispid = document.getIDsOfNames(new String[] {"documentElement"}); //$NON-NLS-1$
+       if (rgdispid == null) {
+               /* implies that the browser is displaying non-HTML content */
+               document.dispose();
+               return ""; //$NON-NLS-1$
+       }
+       pVarResult = document.getProperty(rgdispid[0]);
+       document.dispose();
+       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY || pVarResult.getType() == COM.VT_NULL) {
+               if (pVarResult != null) pVarResult.dispose ();
+               return ""; //$NON-NLS-1$
+       }
+       OleAutomation element = pVarResult.getAutomation();
+       pVarResult.dispose();
+
+       /* get its outerHTML property */
+       rgdispid = element.getIDsOfNames(new String[] {"outerHTML"}); //$NON-NLS-1$
+       pVarResult = element.getProperty(rgdispid[0]);
+       element.dispose();
+       if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY) {
+               if (pVarResult != null) pVarResult.dispose ();
+               return ""; //$NON-NLS-1$
+       }
+       String result = pVarResult.getString();
+       pVarResult.dispose();
+
+       return result;
+}
+
+@Override
+public String getUrl() {
+       /*
+        * If the url is "" then return ABOUT_BLANK in order to be consistent
+        * with the other Browser implementations which auto-navigate to ABOUT_BLANK
+        * when opened.
+        */
+       String result = _getUrl();
+       return result.length() != 0 ? result : ABOUT_BLANK;
+}
+
+String _getUrl() {
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
+       Variant pVarResult = auto.getProperty(rgdispid[0]);
+       if (pVarResult == null || pVarResult.getType() != OLE.VT_BSTR) return ""; //$NON-NLS-1$
+       String result = pVarResult.getString();
+       pVarResult.dispose();
+       return result;
+}
+
+@Override
+public boolean isBackEnabled() {
+       return back;
+}
+
+@Override
+public boolean isForwardEnabled() {
+       return forward;
+}
+
+@Override
+public boolean isFocusControl () {
+       return site.isFocusControl() || frame.isFocusControl();
+}
+
+boolean navigate(String url, String postData, String headers[], boolean silent) {
+       int count = 1;
+       if (postData != null) count++;
+       if (headers != null) count++;
+       Variant[] rgvarg = new Variant[count];
+       int[] rgdispidNamedArgs = new int[count];
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL", "PostData", "Headers" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+       int index = 0;
+       rgvarg[index] = new Variant(url);
+       rgdispidNamedArgs[index++] = rgdispid[1];
+       if (postData != null) {
+               rgvarg[index] = createSafeArray(postData);
+               rgdispidNamedArgs[index++] = rgdispid[2];
+       }
+       if (headers != null) {
+               StringBuilder buffer = new StringBuilder();
+               for (int i = 0; i < headers.length; i++) {
+                       String current = headers[i];
+                       if (current != null) {
+                               int sep = current.indexOf(':');
+                               if (sep != -1) {
+                                       String key = current.substring(0, sep).trim();
+                                       String value = current.substring(sep + 1).trim();
+                                       if (key.length() > 0 && value.length() > 0) {
+                                               buffer.append(key);
+                                               buffer.append(':');
+                                               buffer.append(value);
+                                               buffer.append("\r\n");
+                                       }
+                               }
+                       }
+               }
+               rgvarg[index] = new Variant(buffer.toString());
+               rgdispidNamedArgs[index++] = rgdispid[3];
+       }
+       boolean oldValue = false;
+       if (silent && IEVersion >= 7) {
+               int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
+               oldValue = hResult == COM.S_OK;
+               OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
+       }
+       Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
+       if (silent && IEVersion >= 7) {
+               OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
+       }
+       for (int i = 0; i < count; i++) {
+               rgvarg[i].dispose();
+       }
+       if (pVarResult == null) return false;
+       boolean result = pVarResult.getType() == OLE.VT_EMPTY;
+       pVarResult.dispose();
+       return result;
+}
+
+@Override
+public void refresh() {
+       uncRedirect = null;
+
+       /*
+       * Bug in Acrobat Reader.  Opening > MAX_PDF PDF files causes Acrobat to not
+       * clean up its shells properly when the container Browser is disposed.
+       * This results in Eclipse crashing at shutdown time because the leftover
+       * shells have invalid references to unloaded Acrobat libraries.  The
+       * workaround is to not unload the Acrobat libraries if > MAX_PDF PDF
+       * files have been opened.
+       */
+       String url = _getUrl();
+       int extensionIndex = url.lastIndexOf('.');
+       if (extensionIndex != -1) {
+               String extension = url.substring(extensionIndex);
+               if (extension.equalsIgnoreCase (EXTENSION_PDF)) {
+                       PDFCount++;
+                       if (PDFCount > MAX_PDF) {
+                               COM.FreeUnusedLibraries = false;
+                       }
+               }
+       }
+
+       isRefresh = true;
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "Refresh" }); //$NON-NLS-1$
+       auto.invoke(rgdispid[0]);
+}
+
+void setHTML (String string) {
+       int charCount = string.length();
+       char[] chars = new char[charCount];
+       string.getChars(0, charCount, chars, 0);
+       int byteCount = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, null, 0, null, null);
+       /*
+       * Internet Explorer appears to treat the data loaded with
+       * nsIPersistStreamInit.Load as if it were encoded using the default
+       * local charset.  There does not seem to be an API to set the
+       * desired charset explicitly in this case.  The fix is to
+       * prepend the UTF-8 Byte Order Mark signature to the data.
+       */
+       byte[] UTF8BOM = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
+       long hGlobal = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, UTF8BOM.length + byteCount);
+       if (hGlobal != 0) {
+               OS.MoveMemory(hGlobal, UTF8BOM, UTF8BOM.length);
+               OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, hGlobal + UTF8BOM.length, byteCount, null, null);
+               long [] ppstm = new long [1];
+               /*
+               * CreateStreamOnHGlobal is called with the flag fDeleteOnRelease.
+               * If the call succeeds the buffer hGlobal is freed automatically
+               * when the IStream object is released. If the call fails, free the
+               * buffer hGlobal.
+               */
+               if (OS.CreateStreamOnHGlobal(hGlobal, true, ppstm) == OS.S_OK) {
+                       int[] rgdispid = auto.getIDsOfNames(new String[] {PROPERTY_DOCUMENT});
+                       Variant pVarResult = auto.getProperty(rgdispid[0]);
+                       IDispatch dispatchDocument = pVarResult.getDispatch();
+                       long [] ppvObject = new long [1];
+                       int result = dispatchDocument.QueryInterface(COM.IIDIPersistStreamInit, ppvObject);
+                       if (result == OS.S_OK) {
+                               IPersistStreamInit persistStreamInit = new IPersistStreamInit(ppvObject[0]);
+                               if (persistStreamInit.InitNew() == OS.S_OK) {
+                                       persistStreamInit.Load(ppstm[0]);
+                               }
+                               persistStreamInit.Release();
+                       }
+                       pVarResult.dispose();
+                       IUnknown stream = new IUnknown(ppstm[0]);
+                       stream.Release();
+               } else {
+                       OS.GlobalFree(hGlobal);
+               }
+       }
+}
+
+private void setAboutBlank(boolean value) {
+       isAboutBlank = value;
+       updateForceTrusted();
+}
+
+private void setUntrustedText(boolean value) {
+       untrustedText = value;
+       updateForceTrusted();
+}
+
+private void updateForceTrusted() {
+       site.isForceTrusted = isAboutBlank && !untrustedText;
+}
+
+@Override
+public boolean setText(final String html, boolean trusted) {
+       /*
+       * If the browser is navigating to about:blank in response to its first
+       * setUrl() invocation then delay setting this text content until the
+       * navigate has completed.  about:blank will be re-navigated to in order
+       * to ensure that all expected client events are sent.
+       */
+       if (performingInitialNavigate) {
+               pendingText = new Object[] {html, trusted};
+               pendingUrl = null;
+               return true;
+       }
+
+       /*
+       * If the html field is non-null then the about:blank page is already being
+       * loaded from a previous setText() invocation, so no Stop or Navigate is
+       * required.  Just set the html that is to be shown.
+       */
+       boolean blankLoading = this.html != null;
+       this.html = html;
+       setUntrustedText(!trusted);
+       if (blankLoading) return true;
+
+       /*
+       * Navigate to the blank page and insert the given html when
+       * receiving the next DocumentComplete notification.  See the
+       * MSDN article "Loading HTML content from a Stream".
+       *
+       * Note.  Stop any pending request.  This is required to avoid displaying a
+       * blank page as a result of consecutive calls to setUrl and/or setText.
+       * The previous request would otherwise render the new html content and
+       * reset the html field before the browser actually navigates to the blank
+       * page as requested below.
+       *
+       * Feature in Internet Explorer.  Stopping pending requests when no request
+       * is pending causes a default page 'Action cancelled' to be displayed.  The
+       * workaround is to not invoke 'stop' when no request has been set since
+       * that instance was created.
+       */
+
+       /*
+       * Stopping the loading of a page causes DocumentComplete events from previous
+       * requests to be received before the DocumentComplete for this page.  In such
+       * cases we must be sure to not set the html into the browser too soon, since
+       * doing so could result in its page being cleared out by a subsequent
+       * DocumentComplete.  The Browser's ReadyState can be used to determine whether
+       * these extra events will be received or not.
+       */
+       if (_getUrl().length() != 0) {
+               int[] rgdispid = auto.getIDsOfNames(new String[] { "ReadyState" }); //$NON-NLS-1$
+               Variant pVarResult = auto.getProperty(rgdispid[0]);
+               if (pVarResult == null) return false;
+               delaySetText = pVarResult.getInt() != READYSTATE_COMPLETE;
+               pVarResult.dispose();
+               rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
+               auto.invoke(rgdispid[0]);
+       }
+
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
+       Variant[] rgvarg = new Variant[1];
+       rgvarg[0] = new Variant(ABOUT_BLANK);
+       int[] rgdispidNamedArgs = new int[1];
+       rgdispidNamedArgs[0] = rgdispid[1];
+       boolean oldValue = false;
+       if (IEVersion >= 7) {
+               int hResult = OS.CoInternetIsFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.GET_FEATURE_FROM_PROCESS);
+               oldValue = hResult == COM.S_OK;
+               OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
+       }
+       Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
+       if (IEVersion >= 7) {
+               OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, oldValue);
+       }
+       rgvarg[0].dispose();
+       if (pVarResult == null) return false;
+       boolean result = pVarResult.getType() == OLE.VT_EMPTY;
+       pVarResult.dispose();
+       return result;
+}
+
+@Override
+public boolean setUrl(String url, String postData, String headers[]) {
+       html = uncRedirect = null;
+
+       /*
+       * If the browser has not shown any content yet then first navigate to
+       * about:blank to work around IE bug http://support.microsoft.com/kb/320153,
+       * then navigate to the requested url once about:blank has loaded.
+       */
+       if (_getUrl().length() == 0 && !ABOUT_BLANK.equalsIgnoreCase(url)) {
+               pendingText = null;
+               pendingUrl = new Object[] {url, postData, headers};
+               performingInitialNavigate = true;
+               navigate (ABOUT_BLANK, null, null, true);
+               return true;
+       }
+
+       /*
+       * Bug in Internet Explorer.  For some reason, Navigating to an xml document before
+       * a previous Navigate has completed will leave the Browser in a bad state if the
+       * Navigate to the xml document does not complete.  This bad state causes a GP when
+       * the parent window is eventually disposed.  The workaround is to issue a Stop before
+       * navigating to any xml document.
+       */
+       if (url.endsWith(".xml")) {     //$NON-NLS-1$
+               int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
+               auto.invoke(rgdispid[0]);
+       }
+       return navigate(url, postData, headers, false);
+}
+
+@Override
+public void stop() {
+       /*
+       * If the browser has not completed its initial navigate to about:blank
+       * then do not issue Stop here, as this will display the IE error page.
+       * Just clear the pending url and text fields so that any pending content
+       * will not be set into the browser when the about:blank navigate completes.
+       */
+       if (performingInitialNavigate) {
+               pendingText = pendingUrl = null;
+               return;
+       }
+
+       /*
+       * Feature of IE.  Invoking Stop in IE before any content has been shown
+       * displays a Navigation Cancelled error page.  The workaround is to not
+       * invoke Stop if no content has been shown yet.
+       */
+       if (_getUrl().length() == 0) return;
+
+       /*
+       * Ensure that isAboutBlank is set accurately since Stop can be issued at
+       * any stage in the page load cycle.
+       */
+       setAboutBlank(getUrl().startsWith(ABOUT_BLANK));
+
+       uncRedirect = null;
+       int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
+       auto.invoke(rgdispid[0]);
+}
+
+@Override
+boolean translateMnemonics () {
+       return false;
+}
+
+void handleDOMEvent (OleEvent e) {
+       if (e.arguments == null || e.arguments.length == 0) return; /* for IE5 */
+
+       Variant arg = e.arguments[0];
+       OleAutomation event = arg.getAutomation();
+       int[] rgdispid = event.getIDsOfNames(new String[]{ PROPERTY_TYPE });
+       int dispIdMember = rgdispid[0];
+       Variant pVarResult = event.getProperty(dispIdMember);
+       String eventType = pVarResult.getString();
+       pVarResult.dispose();
+
+       if (eventType.equals(EVENT_KEYDOWN)) {
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               lastKeyCode = translateKey (pVarResult.getInt());
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames (new String[] {PROPERTY_RETURNVALUE});
+               pVarResult = event.getProperty (rgdispid[0]);
+               boolean consume = pVarResult != null && pVarResult.getType () == OLE.VT_BOOL && !pVarResult.getBoolean ();
+               pVarResult.dispose ();
+
+               MSG msg = new MSG ();
+               int flags = OS.PM_NOYIELD | (consume ? OS.PM_REMOVE : OS.PM_NOREMOVE);
+               if (OS.PeekMessage (msg, frame.handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
+                       /* a keypress will be received for this key so don't send KeyDown here */
+                       event.dispose();
+                       return;
+               }
+
+               if (consume) {
+                       /*
+                        * an event should not be sent if another listener has vetoed the
+                        * KeyDown (this is for non-character cases like arrow keys, etc.)
+                        */
+                       event.dispose();
+                       return;
+               }
+
+               /* if this is a repeating key then an event should not be fired for it */
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_REPEAT });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               boolean repeating = pVarResult.getBoolean();
+               pVarResult.dispose();
+               if (repeating) {
+                       event.dispose();
+                       return;
+               }
+
+               int mask = 0;
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.ALT;
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.CTRL;
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
+               pVarResult.dispose();
+
+               Event keyEvent = new Event ();
+               keyEvent.widget = browser;
+               keyEvent.type = SWT.KeyDown;
+               keyEvent.keyCode = lastKeyCode;
+               keyEvent.stateMask = mask;
+               keyEvent.stateMask &= ~lastKeyCode;             /* remove current keydown if it's a state key */
+               /*
+               * keypress events are not received for Backspace, Enter, Delete and
+               * Tab, so KeyDown events are sent for them here.  Set the KeyDown
+               * event's character field and IE's lastCharCode field for these keys
+               * so that the Browser's key events are consistent with other controls.
+               */
+               switch (lastKeyCode) {
+                       case SWT.BS: lastCharCode = keyEvent.character = SWT.BS; break;
+                       case SWT.CR: lastCharCode = keyEvent.character = SWT.CR; break;
+                       case SWT.DEL: lastCharCode = keyEvent.character = SWT.DEL; break;
+                       case SWT.TAB: lastCharCode = keyEvent.character = SWT.TAB; break;
+               }
+
+               if (!sendKeyEvent(keyEvent)) {
+                       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
+                       dispIdMember = rgdispid[0];
+                       Variant pVarFalse = new Variant(false);
+                       event.setProperty(dispIdMember, pVarFalse);
+                       pVarFalse.dispose();
+               }
+
+               /*
+               * Pressing F5 refreshes the current page.  If this is about to happen
+               * then set isRefresh to true so that received IE events will be treated
+               * accordingly.
+               */
+               if (lastKeyCode == SWT.F5) isRefresh = true;
+
+               event.dispose();
+               return;
+       }
+
+       if (eventType.equals(EVENT_KEYPRESS)) {
+               int mask = 0;
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.CTRL;
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.ALT;
+               pVarResult.dispose();
+
+               /* in the keypress event the keyCode actually corresponds to the character code */
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               lastCharCode = pVarResult.getInt();
+               pVarResult.dispose();
+
+               /*
+               * WebSite.TranslateAccelerator() explicitly does not translate OS.VK_RETURN
+               * keys, so the PeekMessage check in the keydown handler always allows a
+               * KeyDown to be sent for this key.  However, keydown and keypress events are
+               * both sometimes received for OS.VK_RETURN, depending on the page's focus
+               * control.  To handle this, do not send a KeyDown for CR or LF here since
+               * one is always sent for it from the keydown handler.
+               */
+               if (lastCharCode == SWT.CR || lastCharCode == SWT.LF) {
+                       event.dispose();
+                       return;
+               }
+
+               Event keyEvent = new Event ();
+               keyEvent.widget = browser;
+               keyEvent.type = SWT.KeyDown;
+               keyEvent.keyCode = lastKeyCode;
+               keyEvent.character = (char)lastCharCode;
+               keyEvent.stateMask = mask;
+               if (!sendKeyEvent(keyEvent)) {
+                       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
+                       dispIdMember = rgdispid[0];
+                       Variant pVarFalse = new Variant(false);
+                       event.setProperty(dispIdMember, pVarFalse);
+                       pVarFalse.dispose();
+               }
+
+               event.dispose();
+               return;
+       }
+
+       if (eventType.equals(EVENT_KEYUP)) {
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_KEYCODE });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               int keyCode = translateKey (pVarResult.getInt());
+               pVarResult.dispose();
+
+               /*
+               * if a key code could not be determined for this key then it's a
+               * key for which key events are not sent (eg.- the Windows key)
+               */
+               if (keyCode == 0) {
+                       lastKeyCode = lastCharCode = 0;
+                       event.dispose();
+                       return;
+               }
+
+               if (keyCode != lastKeyCode) {
+                       /* keyup does not correspond to the last keydown */
+                       lastKeyCode = keyCode;
+                       lastCharCode = 0;
+               }
+
+               int mask = 0;
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.CTRL;
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.ALT;
+               pVarResult.dispose();
+
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
+               pVarResult.dispose();
+
+               Event keyEvent = new Event ();
+               keyEvent.widget = browser;
+               keyEvent.type = SWT.KeyUp;
+               keyEvent.keyCode = lastKeyCode;
+               keyEvent.character = (char)lastCharCode;
+               keyEvent.stateMask = mask;
+               switch (lastKeyCode) {
+                       case SWT.SHIFT:
+                       case SWT.CONTROL:
+                       case SWT.ALT:
+                       case SWT.COMMAND: {
+                               keyEvent.stateMask |= lastKeyCode;
+                       }
+               }
+               browser.notifyListeners (keyEvent.type, keyEvent);
+               if (!keyEvent.doit) {
+                       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_RETURNVALUE });
+                       dispIdMember = rgdispid[0];
+                       Variant pVarFalse = new Variant(false);
+                       event.setProperty(dispIdMember, pVarFalse);
+                       pVarFalse.dispose();
+               }
+
+               lastKeyCode = lastCharCode = 0;
+               event.dispose();
+               return;
+       }
+
+       /*
+        * Feature in IE. MouseOver/MouseOut events are fired any time the mouse enters
+        * or exits any element within the Browser.  To ensure that SWT events are only
+        * fired for mouse movements into or out of the Browser, do not fire an event if
+        * the element being exited (on MouseOver) or entered (on MouseExit) is within
+        * the Browser.
+        */
+       if (eventType.equals(EVENT_MOUSEOVER)) {
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_FROMELEMENT });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
+               pVarResult.dispose();
+               if (isInternal) {
+                       event.dispose();
+                       return;
+               }
+       }
+       if (eventType.equals(EVENT_MOUSEOUT)) {
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_TOELEMENT });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               boolean isInternal = pVarResult.getType() != COM.VT_EMPTY;
+               pVarResult.dispose();
+               if (isInternal) {
+                       event.dispose();
+                       return;
+               }
+       }
+
+       int mask = 0;
+       Event newEvent = new Event();
+       newEvent.widget = browser;
+
+       /*
+        * The position of mouse events is received in screen-relative coordinates
+        * in order to handle pages with frames, since frames express their event
+        * coordinates relative to themselves rather than relative to their top-
+        * level page.  Convert screen-relative coordinates to be browser-relative.
+        */
+       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SCREENX });
+       dispIdMember = rgdispid[0];
+       pVarResult = event.getProperty(dispIdMember);
+       int screenX = pVarResult.getInt();
+       pVarResult.dispose();
+
+       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SCREENY });
+       dispIdMember = rgdispid[0];
+       pVarResult = event.getProperty(dispIdMember);
+       int screenY = pVarResult.getInt();
+       pVarResult.dispose();
+
+       Point position = DPIUtil.autoScaleDown(new Point(screenX, screenY)); // To Points
+       position = browser.getDisplay().map(null, browser, position);
+       newEvent.x = position.x; newEvent.y = position.y;
+
+       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_CTRLKEY });
+       dispIdMember = rgdispid[0];
+       pVarResult = event.getProperty(dispIdMember);
+       if (pVarResult.getBoolean()) mask |= SWT.CTRL;
+       pVarResult.dispose();
+
+       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_ALTKEY });
+       dispIdMember = rgdispid[0];
+       pVarResult = event.getProperty(dispIdMember);
+       if (pVarResult.getBoolean()) mask |= SWT.ALT;
+       pVarResult.dispose();
+
+       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_SHIFTKEY });
+       dispIdMember = rgdispid[0];
+       pVarResult = event.getProperty(dispIdMember);
+       if (pVarResult.getBoolean()) mask |= SWT.SHIFT;
+       pVarResult.dispose();
+
+       newEvent.stateMask = mask;
+
+       rgdispid = event.getIDsOfNames(new String[] { PROPERTY_BUTTON });
+       dispIdMember = rgdispid[0];
+       pVarResult = event.getProperty(dispIdMember);
+       int button = pVarResult.getInt();
+       pVarResult.dispose();
+       switch (button) {
+               case 1: button = 1; break;
+               case 2: button = 3; break;
+               case 4: button = 2; break;
+       }
+
+       if (eventType.equals(EVENT_MOUSEDOWN)) {
+               newEvent.type = SWT.MouseDown;
+               newEvent.button = button;
+               newEvent.count = 1;
+       } else if (eventType.equals(EVENT_MOUSEUP) || eventType.equals(EVENT_DRAGEND)) {
+               newEvent.type = SWT.MouseUp;
+               newEvent.button = button != 0 ? button : 1;     /* button assumed to be 1 for dragends */
+               newEvent.count = 1;
+               switch (newEvent.button) {
+                       case 1: newEvent.stateMask |= SWT.BUTTON1; break;
+                       case 2: newEvent.stateMask |= SWT.BUTTON2; break;
+                       case 3: newEvent.stateMask |= SWT.BUTTON3; break;
+                       case 4: newEvent.stateMask |= SWT.BUTTON4; break;
+                       case 5: newEvent.stateMask |= SWT.BUTTON5; break;
+               }
+       } else if (eventType.equals(EVENT_MOUSEWHEEL)) {
+               newEvent.type = SWT.MouseWheel;
+               rgdispid = event.getIDsOfNames(new String[] { PROPERTY_WHEELDELTA });
+               dispIdMember = rgdispid[0];
+               pVarResult = event.getProperty(dispIdMember);
+               newEvent.count = pVarResult.getInt () / 120 * 3;
+               pVarResult.dispose();
+       } else if (eventType.equals(EVENT_MOUSEMOVE)) {
+               /*
+               * Feature in IE.  Spurious and redundant mousemove events are often received.  The workaround
+               * is to not fire MouseMove events whose x and y values match the last MouseMove.
+               */
+               if (newEvent.x == lastMouseMoveX && newEvent.y == lastMouseMoveY) {
+                       event.dispose();
+                       return;
+               }
+               newEvent.type = SWT.MouseMove;
+               lastMouseMoveX = newEvent.x; lastMouseMoveY = newEvent.y;
+       } else if (eventType.equals(EVENT_MOUSEOVER)) {
+               newEvent.type = SWT.MouseEnter;
+       } else if (eventType.equals(EVENT_MOUSEOUT)) {
+               newEvent.type = SWT.MouseExit;
+       } else if (eventType.equals(EVENT_DRAGSTART)) {
+               newEvent.type = SWT.DragDetect;
+               newEvent.button = 1;    /* button assumed to be 1 for dragstarts */
+               newEvent.stateMask |= SWT.BUTTON1;
+       }
+
+       event.dispose();
+       browser.notifyListeners(newEvent.type, newEvent);
+
+       if (eventType.equals(EVENT_DOUBLECLICK)) {
+               newEvent = new Event ();
+               newEvent.widget = browser;
+               newEvent.type = SWT.MouseDoubleClick;
+               newEvent.x = position.x; newEvent.y = position.y;
+               newEvent.stateMask = mask;
+               newEvent.type = SWT.MouseDoubleClick;
+               newEvent.button = 1; /* dblclick only comes for button 1 and does not set the button property */
+               newEvent.count = 2;
+               browser.notifyListeners (newEvent.type, newEvent);
+       }
+}
+
+void hookDOMListeners(OleAutomation webBrowser, final boolean isTop) {
+       int[] rgdispid = webBrowser.getIDsOfNames(new String[] { PROPERTY_DOCUMENT });
+       int dispIdMember = rgdispid[0];
+       Variant pVarResult = webBrowser.getProperty(dispIdMember);
+       if (pVarResult == null) return;
+       if (pVarResult.getType() == COM.VT_EMPTY) {
+               pVarResult.dispose();
+               return;
+       }
+       final OleAutomation document = pVarResult.getAutomation();
+       pVarResult.dispose();
+
+       /*
+        * In some cases, such as setting the Browser's content from a string,
+        * NavigateComplete2 is received multiple times for a top-level document.
+        * For cases like this, any previously-hooked DOM listeners must be
+        * removed from the document before hooking the new set of listeners,
+        * otherwise multiple sets of events will be received.
+        */
+       unhookDOMListeners (new OleAutomation[] {document});
+
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYUP, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, domListener);
+       site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND, domListener);
+       /* ensure that enter/exit are only fired once, by the top-level document */
+       if (isTop) {
+               site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, domListener);
+               site.addEventListener(document, COM.IIDIHTMLDocumentEvents2, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, domListener);
+       }
+
+       OleAutomation[] newDocuments = new OleAutomation[documents.length + 1];
+       System.arraycopy(documents, 0, newDocuments, 0, documents.length);
+       newDocuments[documents.length] = document;
+       documents = newDocuments;
+}
+
+void unhookDOMListeners(OleAutomation[] documents) {
+       char[] buffer = (COM.IIDIHTMLDocumentEvents2 + '\0').toCharArray();
+       GUID guid = new GUID();
+       if (COM.IIDFromString(buffer, guid) == COM.S_OK) {
+               for (int i = 0; i < documents.length; i++) {
+                       OleAutomation document = documents[i];
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONKEYUP, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER, domListener);
+                       site.removeEventListener(document, guid, COM.DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT, domListener);
+               }
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationAdapter.java
new file mode 100644 (file)
index 0000000..1962291
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the {@link LocationListener} interface.
+ * <p>
+ * Classes that wish to deal with {@link LocationEvent}'s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ * <p>
+ * An alternative to this class are the static helper methods in
+ * {@link LocationListener},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public abstract class LocationAdapter implements LocationListener {
+
+@Override
+public void changing(LocationEvent event) {
+}
+
+@Override
+public void changed(LocationEvent event) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationEvent.java
new file mode 100644 (file)
index 0000000..068f139
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A <code>LocationEvent</code> is sent by a {@link Browser} to
+ * {@link LocationListener}'s when the <code>Browser</code>
+ * navigates to a different URL. This notification typically
+ * occurs when the application navigates to a new location with
+ * {@link Browser#setUrl(String)} or when the user activates a
+ * hyperlink.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class LocationEvent extends TypedEvent {
+       /**
+        * The URL of this event, escaped and encoded for consumption by
+        * {@link java.net.URI#URI(String)}.
+        */
+       public String location;
+
+       /**
+        * A flag indicating whether the location opens in the top frame
+        * or not.
+        */
+       public boolean top;
+
+       /**
+        * A flag indicating whether the location loading should be allowed.
+        * Setting this field to <code>false</code> will cancel the operation.
+        */
+       public boolean doit;
+
+       static final long serialVersionUID = 3906644198244299574L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param widget the widget that fired the event
+ *
+ * @since 3.5
+ */
+public LocationEvent(Widget widget) {
+       super(widget);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " location=" + location
+               + " top=" + top
+               + " doit=" + doit
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/LocationListener.java
new file mode 100644 (file)
index 0000000..5a37109
--- /dev/null
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link LocationEvent} notification when a {@link Browser}
+ * navigates to a different URL.
+ *
+ * @see Browser#addLocationListener(LocationListener)
+ * @see Browser#removeLocationListener(LocationListener)
+ * @see LocationAdapter
+ *
+ * @since 3.0
+ */
+public interface LocationListener extends SWTEventListener {
+
+/**
+ * This method is called when the current location is about to be changed.
+ *
+ * <p>The following fields in the <code>LocationEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) location the location to be loaded
+ * <li>(in) widget the <code>Browser</code> whose location is changing
+ * <li>(in/out) doit can be set to <code>false</code> to prevent the location
+ * from being loaded
+ * </ul>
+ *
+ * @param event the <code>LocationEvent</code> that specifies the location
+ * to be loaded by a <code>Browser</code>
+ *
+ * @since 3.0
+ */
+public void changing(LocationEvent event);
+
+/**
+ * This method is called when the current location is changed.
+ *
+ * <p>The following fields in the <code>LocationEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) location the current location
+ * <li>(in) top <code>true</code> if the location opens in the top frame or
+ * <code>false</code> otherwise
+ * <li>(in) widget the <code>Browser</code> whose location has changed
+ * </ul>
+ *
+ * @param event the <code>LocationEvent</code> that specifies  the new
+ * location of a <code>Browser</code>
+ *
+ * @since 3.0
+ */
+public void changed(LocationEvent event);
+
+/**
+ * Static helper method to create a <code>LocationListener</code> for the
+ * {@link #changing(LocationEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return LocationListener
+ * @since 3.107
+ */
+public static LocationListener changingAdapter(Consumer<LocationEvent> c) {
+       return new LocationAdapter() {
+               @Override
+               public void changing(LocationEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>LocationListener</code> for the
+ * {@link #changed(LocationEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return LocationListener
+ * @since 3.107
+ */
+public static LocationListener changedAdapter(Consumer<LocationEvent> c) {
+       return new LocationAdapter() {
+               @Override
+               public void changed(LocationEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/OpenWindowListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/OpenWindowListener.java
new file mode 100644 (file)
index 0000000..8dc165f
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link WindowEvent} notification when a new {@link Browser}
+ * needs to be provided by the application.
+ *
+ * @see Browser#addOpenWindowListener(OpenWindowListener)
+ * @see Browser#removeOpenWindowListener(OpenWindowListener)
+ * @see CloseWindowListener
+ * @see VisibilityWindowListener
+ *
+ * @since 3.0
+ */
+@FunctionalInterface
+public interface OpenWindowListener extends SWTEventListener {
+
+/**
+ * This method is called when a new window needs to be created.
+ * <p>
+ * A particular <code>Browser</code> can be passed to the event.browser
+ * field to host the content of a new window.
+ * <p>
+ * A standalone system browser is used to host the new window
+ * if the event.required field value is <code>false</code> and if the event.browser
+ * field is left <code>null</code>. The event.required field
+ * is <code>true</code> on platforms that don't support a standalone system browser for
+ * new window requests.
+ * <p>
+ * The navigation is cancelled if the event.required field is set to
+ * <code>true</code> and the event.browser field is left <code>null</code>.</p>
+ * <p>The following fields in the <code>WindowEvent</code> apply:</p>
+ * <ul>
+ * <li>(in/out) {@link WindowEvent#required}: true if the platform requires the user to provide a
+ * <code>Browser</code> to handle the new window or false otherwise.
+ * <li>(out) {@link WindowEvent#browser}: the new (unique) <code>Browser</code> that will host the
+ * content of the new window.
+ * <li>(in) widget the <code>Browser</code> that is requesting to open a
+ * new window
+ * </ul>
+ *
+ * @param event the <code>WindowEvent</code> that needs to be passed a new
+ * <code>Browser</code> to handle the new window request
+ *
+ * @since 3.0
+ */
+public void open(WindowEvent event);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressAdapter.java
new file mode 100644 (file)
index 0000000..9a31a08
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the {@link ProgressListener} interface.
+ * <p>
+ * Classes that wish to deal with {@link ProgressEvent}'s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ * <p>
+ * An alternative to this class are the static helper methods in
+ * {@link ProgressListener},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public abstract class ProgressAdapter implements ProgressListener {
+
+@Override
+public void changed(ProgressEvent event) {
+}
+
+@Override
+public void completed(ProgressEvent event) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressEvent.java
new file mode 100644 (file)
index 0000000..a07f9e0
--- /dev/null
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * A <code>ProgressEvent</code> is sent by a {@link Browser} to
+ * {@link ProgressListener}'s when a progress is made during the
+ * loading of the current URL or when the loading of the current
+ * URL has been completed.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class ProgressEvent extends TypedEvent {
+       /** current value */
+       public int current;
+       /** total value */
+       public int total;
+
+       static final long serialVersionUID = 3977018427045393972L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param widget the widget that fired the event
+ *
+ * @since 3.5
+ */
+public ProgressEvent(Widget widget) {
+       super(widget);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " current=" + current
+               + " total=" + total
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/ProgressListener.java
new file mode 100644 (file)
index 0000000..c24333f
--- /dev/null
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link ProgressEvent} notification when a {@link Browser}
+ * makes a progress in loading the current URL or when the
+ * current URL has been loaded.
+ *
+ * @see Browser#addProgressListener(ProgressListener)
+ * @see Browser#removeProgressListener(ProgressListener)
+ * @see Browser#getUrl()
+ *
+ * @since 3.0
+ */
+public interface ProgressListener extends SWTEventListener {
+
+/**
+ * This method is called when a progress is made during the loading of the
+ * current location.
+ *
+ *
+ * <p>The following fields in the <code>ProgressEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) current the progress for the location currently being loaded
+ * <li>(in) total the maximum progress for the location currently being loaded
+ * <li>(in) widget the <code>Browser</code> whose current URL is being loaded
+ * </ul>
+ *
+ * @param event the <code>ProgressEvent</code> related to the loading of the
+ * current location of a <code>Browser</code>
+ *
+ * @since 3.0
+ */
+public void changed(ProgressEvent event);
+
+/**
+ * This method is called when the current location has been completely loaded.
+ *
+ *
+ * <p>The following fields in the <code>ProgressEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> whose current URL has been loaded
+ * </ul>
+ *
+ * @param event the <code>ProgressEvent</code> related to the <code>Browser</code>
+ * that has loaded its current URL.
+ *
+ * @since 3.0
+ */
+public void completed(ProgressEvent event);
+
+/**
+ * Static helper method to create a <code>ProgressListener</code> for the
+ * {@link #changed(ProgressEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return LocationListener
+ * @since 3.107
+ */
+public static ProgressListener changedAdapter(Consumer<ProgressEvent> c) {
+       return new ProgressAdapter() {
+               @Override
+               public void changed(ProgressEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ProgressListener</code> for the
+ * {@link #completed(ProgressEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return LocationListener
+ * @since 3.107
+ */
+public static ProgressListener completedAdapter(Consumer<ProgressEvent> c) {
+       return new ProgressAdapter() {
+               @Override
+               public void completed(ProgressEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/StatusTextEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/StatusTextEvent.java
new file mode 100644 (file)
index 0000000..7462b36
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * A <code>StatusTextEvent</code> is sent by a {@link Browser} to
+ * {@link StatusTextListener}'s when the status text is changed.
+ * The status text is typically displayed in the status bar of
+ * a browser application.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class StatusTextEvent extends TypedEvent {
+       /** status text */
+       public String text;
+
+       static final long serialVersionUID = 3258407348371600439L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param widget the widget that fired the event
+ *
+ * @since 3.5
+ */
+public StatusTextEvent(Widget widget) {
+       super(widget);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " text=" + text
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/StatusTextListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/StatusTextListener.java
new file mode 100644 (file)
index 0000000..93786c4
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link StatusTextEvent} notification when the status text for
+ * a {@link Browser} is changed.
+ *
+ * @see Browser#addStatusTextListener(StatusTextListener)
+ * @see Browser#removeStatusTextListener(StatusTextListener)
+ *
+ * @since 3.0
+ */
+@FunctionalInterface
+public interface StatusTextListener extends SWTEventListener {
+
+/**
+ * This method is called when the status text is changed. The
+ * status text is typically displayed in the status bar of a browser
+ * application.
+ *
+ * <p>The following fields in the <code>StatusTextEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) text the modified status text
+ * <li>(in) widget the <code>Browser</code> whose status text is changed
+ * </ul>
+ *
+ * @param event the <code>StatusTextEvent</code> that contains the updated
+ * status description of a <code>Browser</code>
+ *
+ * @since 3.0
+ */
+public void changed(StatusTextEvent event);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/TitleEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/TitleEvent.java
new file mode 100644 (file)
index 0000000..13ff512
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * A <code>TitleEvent</code> is sent by a {@link Browser} to
+ * {@link TitleListener}'s when the title of the current document
+ * is available or when it is modified.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class TitleEvent extends TypedEvent {
+       /** the title of the current document */
+       public String title;
+
+       static final long serialVersionUID = 4121132532906340919L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param widget the widget that fired the event
+ *
+ * @since 3.5
+ */
+public TitleEvent(Widget widget) {
+       super(widget);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " title=" + title
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/TitleListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/TitleListener.java
new file mode 100644 (file)
index 0000000..3fa84cf
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link TitleEvent} notification when the title of the document
+ * displayed in a {@link Browser} is known or has been changed.
+ *
+ * @see Browser#addTitleListener(TitleListener)
+ * @see Browser#removeTitleListener(TitleListener)
+ *
+ * @since 3.0
+ */
+@FunctionalInterface
+public interface TitleListener extends SWTEventListener {
+
+/**
+ * This method is called when the title of the current document
+ * is available or has changed.
+ *
+ * <p>The following fields in the <code>TitleEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) title the title of the current document
+ * <li>(in) widget the <code>Browser</code> whose current document's
+ * title is known or modified
+ * </ul>
+ *
+ * @param event the <code>TitleEvent</code> that contains the title
+ * of the document currently displayed in a <code>Browser</code>
+ *
+ * @since 3.0
+ */
+public void changed(TitleEvent event);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/VisibilityWindowAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/VisibilityWindowAdapter.java
new file mode 100644 (file)
index 0000000..57e2d8c
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the {@link VisibilityWindowListener} interface.
+ * <p>
+ * Classes that wish to deal with {@link WindowEvent}'s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ * <p>
+ * An alternative to this class are the static helper methods in
+ * {@link VisibilityWindowListener},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public abstract class VisibilityWindowAdapter implements VisibilityWindowListener {
+
+@Override
+public void hide(WindowEvent event) {
+}
+
+@Override
+public void show(WindowEvent event) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/VisibilityWindowListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/VisibilityWindowListener.java
new file mode 100644 (file)
index 0000000..cbb88c7
--- /dev/null
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * a {@link WindowEvent} notification when a window hosting a
+ * {@link Browser} needs to be displayed or hidden.
+ *
+ * @see Browser#addVisibilityWindowListener(VisibilityWindowListener)
+ * @see Browser#removeVisibilityWindowListener(VisibilityWindowListener)
+ * @see OpenWindowListener
+ * @see CloseWindowListener
+ *
+ * @since 3.0
+ */
+public interface VisibilityWindowListener extends SWTEventListener {
+
+/**
+ * This method is called when the window hosting a <code>Browser</code>
+ * is requested to be hidden. Application would typically hide the
+ * {@link org.eclipse.swt.widgets.Shell} that hosts the <code>Browser</code>.
+ *
+ * <p>The following fields in the <code>WindowEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> that needs to be hidden
+ * </ul>
+ *
+ * @param event the <code>WindowEvent</code> that specifies the
+ * <code>Browser</code> that needs to be hidden
+ *
+ * @see org.eclipse.swt.widgets.Shell#setVisible(boolean)
+ *
+ * @since 3.0
+ */
+public void hide(WindowEvent event);
+
+/**
+ * This method is called when the window hosting a <code>Browser</code>
+ * is requested to be displayed. Application would typically set the
+ * location and the size of the {@link org.eclipse.swt.widgets.Shell}
+ * that hosts the <code>Browser</code>, if a particular location and size
+ * are specified. The application would then open that <code>Shell</code>.
+ *
+ * <p>The following fields in the <code>WindowEvent</code> apply:</p>
+ * <ul>
+ * <li>(in) widget the <code>Browser</code> to display
+ * <li>(in) location the requested location for the <code>Shell</code>
+ * hosting the browser. It is <code>null</code> if no location is set.
+ * <li>(in) size the requested size for the <code>Browser</code>.
+ * The client area of the <code>Shell</code> hosting the
+ * <code>Browser</code> should be large enough to accommodate that size.
+ * It is <code>null</code> if no size is set.
+ * <li>(in) addressBar <code>true</code> if the <code>Shell</code>
+ * hosting the <code>Browser</code> should display an address bar or
+ * <code>false</code> otherwise
+ * <li>(in) menuBar <code>true</code> if the <code>Shell</code>
+ * hosting the <code>Browser</code> should display a menu bar or
+ * <code>false</code> otherwise
+ * <li>(in) statusBar <code>true</code> if the <code>Shell</code>
+ * hosting the <code>Browser</code> should display a status bar or
+ * <code>false</code> otherwise
+ * <li>(in) toolBar <code>true</code> if the <code>Shell</code>
+ * hosting the <code>Browser</code> should display a tool bar or
+ * <code>false</code> otherwise
+ * </ul>
+ *
+ * @param event the <code>WindowEvent</code> that specifies the
+ * <code>Browser</code> that needs to be displayed
+ *
+ * @see org.eclipse.swt.widgets.Control#setLocation(org.eclipse.swt.graphics.Point)
+ * @see org.eclipse.swt.widgets.Control#setSize(org.eclipse.swt.graphics.Point)
+ * @see org.eclipse.swt.widgets.Shell#open()
+ *
+ * @since 3.0
+ */
+public void show(WindowEvent event);
+
+/**
+ * Static helper method to create a <code>VisibilityWindowListener</code> for thehide
+ * {@link #hide(WindowEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return LocationListener
+ * @since 3.107
+ */
+public static VisibilityWindowListener hideAdapter(Consumer<WindowEvent> c) {
+       return new VisibilityWindowAdapter() {
+               @Override
+               public void hide(WindowEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>VisibilityWindowListener</code> for the
+ * {@link #show(WindowEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return LocationListener
+ * @since 3.107
+ */
+public static VisibilityWindowListener showAdapter(Consumer<WindowEvent> c) {
+       return new VisibilityWindowAdapter() {
+               @Override
+               public void show(WindowEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebBrowser.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebBrowser.java
new file mode 100644 (file)
index 0000000..27dd9f5
--- /dev/null
@@ -0,0 +1,745 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+
+abstract class WebBrowser {
+       Browser browser;
+       Map<Integer, BrowserFunction> functions = new HashMap<> ();
+       AuthenticationListener[] authenticationListeners = new AuthenticationListener[0];
+       CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0];
+       LocationListener[] locationListeners = new LocationListener[0];
+       OpenWindowListener[] openWindowListeners = new OpenWindowListener[0];
+       ProgressListener[] progressListeners = new ProgressListener[0];
+       StatusTextListener[] statusTextListeners = new StatusTextListener[0];
+       TitleListener[] titleListeners = new TitleListener[0];
+       VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0];
+       boolean jsEnabledOnNextPage = true, jsEnabled = true;
+       int nextFunctionIndex = 1;
+       Object evaluateResult;
+
+       static final String ERROR_ID = "org.eclipse.swt.browser.error"; // $NON-NLS-1$
+       static final String EXECUTE_ID = "SWTExecuteTemporaryFunction"; // $NON-NLS-1$
+
+       static List<String[]> NativePendingCookies = new ArrayList<> ();
+       static String CookieName, CookieValue, CookieUrl;
+       static boolean CookieResult;
+       static Runnable NativeClearSessions;
+       static Runnable NativeGetCookie;
+       static Runnable NativeSetCookie;
+
+       /* Key Mappings */
+       static final int [][] KeyTable = {
+               /* Keyboard and Mouse Masks */
+               {18,    SWT.ALT},
+               {16,    SWT.SHIFT},
+               {17,    SWT.CONTROL},
+               {224,   SWT.COMMAND},
+
+               /* Literal Keys */
+               {65,    'a'},
+               {66,    'b'},
+               {67,    'c'},
+               {68,    'd'},
+               {69,    'e'},
+               {70,    'f'},
+               {71,    'g'},
+               {72,    'h'},
+               {73,    'i'},
+               {74,    'j'},
+               {75,    'k'},
+               {76,    'l'},
+               {77,    'm'},
+               {78,    'n'},
+               {79,    'o'},
+               {80,    'p'},
+               {81,    'q'},
+               {82,    'r'},
+               {83,    's'},
+               {84,    't'},
+               {85,    'u'},
+               {86,    'v'},
+               {87,    'w'},
+               {88,    'x'},
+               {89,    'y'},
+               {90,    'z'},
+               {48,    '0'},
+               {49,    '1'},
+               {50,    '2'},
+               {51,    '3'},
+               {52,    '4'},
+               {53,    '5'},
+               {54,    '6'},
+               {55,    '7'},
+               {56,    '8'},
+               {57,    '9'},
+               {32,    ' '},
+               {59,    ';'},
+               {61,    '='},
+               {188,   ','},
+               {190,   '.'},
+               {191,   '/'},
+               {219,   '['},
+               {221,   ']'},
+               {222,   '\''},
+               {192,   '`'},
+               {220,   '\\'},
+               {108,   '|'},
+               {226,   '<'},
+
+               /* Non-Numeric Keypad Keys */
+               {37,    SWT.ARROW_LEFT},
+               {39,    SWT.ARROW_RIGHT},
+               {38,    SWT.ARROW_UP},
+               {40,    SWT.ARROW_DOWN},
+               {45,    SWT.INSERT},
+               {36,    SWT.HOME},
+               {35,    SWT.END},
+               {46,    SWT.DEL},
+               {33,    SWT.PAGE_UP},
+               {34,    SWT.PAGE_DOWN},
+
+               /* Virtual and Ascii Keys */
+               {8,             SWT.BS},
+               {13,    SWT.CR},
+               {9,             SWT.TAB},
+               {27,    SWT.ESC},
+               {12,    SWT.DEL},
+
+               /* Functions Keys */
+               {112,   SWT.F1},
+               {113,   SWT.F2},
+               {114,   SWT.F3},
+               {115,   SWT.F4},
+               {116,   SWT.F5},
+               {117,   SWT.F6},
+               {118,   SWT.F7},
+               {119,   SWT.F8},
+               {120,   SWT.F9},
+               {121,   SWT.F10},
+               {122,   SWT.F11},
+               {123,   SWT.F12},
+               {124,   SWT.F13},
+               {125,   SWT.F14},
+               {126,   SWT.F15},
+               {127,   0},
+               {128,   0},
+               {129,   0},
+               {130,   0},
+               {131,   0},
+               {132,   0},
+               {133,   0},
+               {134,   0},
+               {135,   0},
+
+               /* Numeric Keypad Keys */
+               {96,    SWT.KEYPAD_0},
+               {97,    SWT.KEYPAD_1},
+               {98,    SWT.KEYPAD_2},
+               {99,    SWT.KEYPAD_3},
+               {100,   SWT.KEYPAD_4},
+               {101,   SWT.KEYPAD_5},
+               {102,   SWT.KEYPAD_6},
+               {103,   SWT.KEYPAD_7},
+               {104,   SWT.KEYPAD_8},
+               {105,   SWT.KEYPAD_9},
+               {14,    SWT.KEYPAD_CR},
+               {107,   SWT.KEYPAD_ADD},
+               {109,   SWT.KEYPAD_SUBTRACT},
+               {106,   SWT.KEYPAD_MULTIPLY},
+               {111,   SWT.KEYPAD_DIVIDE},
+               {110,   SWT.KEYPAD_DECIMAL},
+
+               /* Other keys */
+               {20,    SWT.CAPS_LOCK},
+               {144,   SWT.NUM_LOCK},
+               {145,   SWT.SCROLL_LOCK},
+               {44,    SWT.PRINT_SCREEN},
+               {6,             SWT.HELP},
+               {19,    SWT.PAUSE},
+               {3,             SWT.BREAK},
+
+               /* WebKit-specific */
+               {186,   ';'},
+               {187,   '='},
+               {189,   '-'},
+       };
+
+public class EvaluateFunction extends BrowserFunction {
+       public EvaluateFunction (Browser browser, String name) {
+               super (browser, name, true, new String[0], false);
+       }
+       @Override
+       public Object function (Object[] arguments) {
+               if (arguments[0] instanceof String) {
+                       String string = (String)arguments[0];
+                       if (string.startsWith (ERROR_ID)) {
+                               String errorString = ExtractError (string);
+                               if (errorString.length () > 0) {
+                                       evaluateResult = new SWTException (SWT.ERROR_FAILED_EVALUATE, errorString);
+                               } else {
+                                       evaluateResult = new SWTException (SWT.ERROR_FAILED_EVALUATE);
+                               }
+                               return null;
+                       }
+               }
+               evaluateResult = arguments[0];
+               return null;
+       }
+}
+
+public void addAuthenticationListener (AuthenticationListener listener) {
+       AuthenticationListener[] newAuthenticationListeners = new AuthenticationListener[authenticationListeners.length + 1];
+       System.arraycopy(authenticationListeners, 0, newAuthenticationListeners, 0, authenticationListeners.length);
+       authenticationListeners = newAuthenticationListeners;
+       authenticationListeners[authenticationListeners.length - 1] = listener;
+}
+
+public void addCloseWindowListener (CloseWindowListener listener) {
+       CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1];
+       System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, closeWindowListeners.length);
+       closeWindowListeners = newCloseWindowListeners;
+       closeWindowListeners[closeWindowListeners.length - 1] = listener;
+}
+
+public void addLocationListener (LocationListener listener) {
+       LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1];
+       System.arraycopy(locationListeners, 0, newLocationListeners, 0, locationListeners.length);
+       locationListeners = newLocationListeners;
+       locationListeners[locationListeners.length - 1] = listener;
+}
+
+public void addOpenWindowListener (OpenWindowListener listener) {
+       OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1];
+       System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, openWindowListeners.length);
+       openWindowListeners = newOpenWindowListeners;
+       openWindowListeners[openWindowListeners.length - 1] = listener;
+}
+
+public void addProgressListener (ProgressListener listener) {
+       ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1];
+       System.arraycopy(progressListeners, 0, newProgressListeners, 0, progressListeners.length);
+       progressListeners = newProgressListeners;
+       progressListeners[progressListeners.length - 1] = listener;
+}
+
+public void addStatusTextListener (StatusTextListener listener) {
+       StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1];
+       System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, statusTextListeners.length);
+       statusTextListeners = newStatusTextListeners;
+       statusTextListeners[statusTextListeners.length - 1] = listener;
+}
+
+public void addTitleListener (TitleListener listener) {
+       TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1];
+       System.arraycopy(titleListeners, 0, newTitleListeners, 0, titleListeners.length);
+       titleListeners = newTitleListeners;
+       titleListeners[titleListeners.length - 1] = listener;
+}
+
+public void addVisibilityWindowListener (VisibilityWindowListener listener) {
+       VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1];
+       System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, visibilityWindowListeners.length);
+       visibilityWindowListeners = newVisibilityWindowListeners;
+       visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener;
+}
+
+public abstract boolean back ();
+
+public static void clearSessions () {
+       if (NativeClearSessions != null) NativeClearSessions.run ();
+}
+
+public static String GetCookie (String name, String url) {
+       CookieName = name; CookieUrl = url; CookieValue = null;
+       if (NativeGetCookie != null) NativeGetCookie.run ();
+       String result = CookieValue;
+       CookieName = CookieValue = CookieUrl = null;
+       return result;
+}
+
+public static boolean SetCookie (String value, String url, boolean addToPending) {
+       CookieValue = value; CookieUrl = url;
+       CookieResult = false;
+       if (NativeSetCookie != null) {
+               NativeSetCookie.run ();
+       } else {
+               if (addToPending && NativePendingCookies != null) {
+                       NativePendingCookies.add (new String[] {value, url});
+               }
+       }
+       CookieValue = CookieUrl = null;
+       return CookieResult;
+}
+
+static void SetPendingCookies (List<String[]> pendingCookies) {
+       for (String[] current : pendingCookies) {
+               SetCookie (current[0], current[1], false);
+       }
+}
+
+public abstract void create (Composite parent, int style);
+
+static String CreateErrorString (String error) {
+       return ERROR_ID + error;
+}
+
+static String ExtractError (String error) {
+       return error.substring (ERROR_ID.length ());
+}
+
+public boolean close () {
+       return true;
+}
+
+public void createFunction (BrowserFunction function) {
+       /*
+        * If an existing function with the same name is found then
+        * remove it so that it is not recreated on subsequent pages
+        * (the new function overwrites the old one).
+        */
+       for (BrowserFunction current : functions.values()) {
+               if (current.name.equals (function.name)) {
+                       deregisterFunction (current);
+                       break;
+               }
+       }
+
+       function.index = getNextFunctionIndex ();
+       registerFunction (function);
+
+       StringBuilder functionBuffer = new StringBuilder (function.name);
+       functionBuffer.append (" = function "); //$NON-NLS-1$
+       functionBuffer.append (function.name);
+       functionBuffer.append ("() {var result = callJava("); //$NON-NLS-1$
+       functionBuffer.append (function.index);
+       functionBuffer.append (",'"); //$NON-NLS-1$
+       functionBuffer.append (function.token);
+       functionBuffer.append ("',Array.prototype.slice.call(arguments)); if (typeof result == 'string' && result.indexOf('"); //$NON-NLS-1$
+       functionBuffer.append (ERROR_ID);
+       functionBuffer.append ("') == 0) {var error = new Error(result.substring("); //$NON-NLS-1$
+       functionBuffer.append (ERROR_ID.length ());
+       functionBuffer.append (")); throw error;} return result;};"); //$NON-NLS-1$
+
+       String javaCallDeclaration = getJavaCallDeclaration();
+
+       StringBuilder buffer = new StringBuilder (); //$NON-NLS-1$
+       buffer.append (javaCallDeclaration); //$NON-NLS-1$
+       if (function.top) {
+               buffer.append (functionBuffer.toString ());
+       }
+
+       buffer.append ("var frameIds = null;"); //$NON-NLS-1$
+       if (function.frameNames != null) {
+               buffer.append ("frameIds = {"); //$NON-NLS-1$
+               for (int i = 0; i < function.frameNames.length; i++) {
+                       buffer.append ('\'');
+                       buffer.append (function.frameNames[i]);
+                       buffer.append ("':1,"); //$NON-NLS-1$
+               }
+               if (function.frameNames.length > 0) {
+                       buffer.deleteCharAt(buffer.length () - 1);
+               }
+               buffer.append ("};"); //$NON-NLS-1$
+       }
+
+       buffer.append ("for (var i = 0; i < frames.length; i++) {try {if (!frameIds || (frames[i].name && frameIds[frames[i].name])) {"); //$NON-NLS-1$
+       buffer.append ("if (!frames[i].callJava) {frames[i].callJava = window.callJava;} frames[i]."); //$NON-NLS-1$
+       buffer.append (functionBuffer.toString ());
+       buffer.append ("}} catch(e) {}};"); //$NON-NLS-1$
+
+       function.functionString = buffer.toString ();
+       nonBlockingExecute (function.functionString);
+}
+
+/**
+ * Designed to be overriden.
+ * @return javaScrit code that defines the 'callJava' syntax for javascript.
+ */
+String getJavaCallDeclaration() {
+       return    "if (!window.callJava) {\n"
+                       + "             window.callJava = function callJava(index, token, args) {\n"
+                       + "                     return external.callJava(index,token,args);\n"
+                       + "             }\n"
+                       + "};\n";
+}
+
+void deregisterFunction (BrowserFunction function) {
+       functions.remove (function.index);
+}
+
+public void destroyFunction (BrowserFunction function) {
+       String deleteString = getDeleteFunctionString (function.name);
+       StringBuilder buffer = new StringBuilder ("for (var i = 0; i < frames.length; i++) {try {frames[i].eval(\""); //$NON-NLS-1$
+       buffer.append (deleteString);
+       buffer.append ("\");} catch (e) {}}"); //$NON-NLS-1$
+       nonBlockingExecute (buffer.toString ());
+       nonBlockingExecute (deleteString);
+       deregisterFunction (function);
+}
+
+// Designed to be overriden by platform implementations, used for optimization and avoiding deadlocks.
+// Webkit2 is async, we often don't need to bother waiting for a return type if we never use it.
+void nonBlockingExecute(String script) {
+       execute(script);
+}
+
+public abstract boolean execute (String script);
+
+public Object evaluate (String script, boolean trusted) throws SWTException {
+       return evaluate(script);
+}
+
+public Object evaluate (String script) throws SWTException {
+       // Gtk Developer note:
+       // Webkit1 uses this mechanism.
+       // Webkit2 uses a different mechanism. See WebKit:evaluate();
+       BrowserFunction function = new EvaluateFunction (browser, ""); // $NON-NLS-1$
+       int index = getNextFunctionIndex ();
+       function.index = index;
+       function.isEvaluate = true;  // Note, Webkit2 doesn't use 'isEvaluate' machinery because it doesn't use a function for evaluation.
+       registerFunction (function);
+       String functionName = EXECUTE_ID + index;
+
+       StringBuilder buffer = new StringBuilder ("window."); // $NON-NLS-1$
+       buffer.append (functionName);
+       buffer.append (" = function "); // $NON-NLS-1$
+       buffer.append (functionName);
+       buffer.append ("() {\n"); // $NON-NLS-1$
+       buffer.append (script);
+       buffer.append ("\n};"); // $NON-NLS-1$
+       nonBlockingExecute (buffer.toString ());
+
+       buffer = new StringBuilder ("if (window."); // $NON-NLS-1$
+       buffer.append (functionName);
+       buffer.append (" == undefined) {window.external.callJava("); // $NON-NLS-1$
+       buffer.append (index);
+       buffer.append (",'"); //$NON-NLS-1$
+       buffer.append (function.token);
+       buffer.append ("', ['"); // $NON-NLS-1$
+       buffer.append (ERROR_ID);
+       buffer.append ("']);} else {try {var result = "); // $NON-NLS-1$
+       buffer.append (functionName);
+       buffer.append ("(); window.external.callJava("); // $NON-NLS-1$
+       buffer.append (index);
+       buffer.append (",'"); //$NON-NLS-1$
+       buffer.append (function.token);
+       buffer.append ("', [result]);} catch (e) {window.external.callJava("); // $NON-NLS-1$
+       buffer.append (index);
+       buffer.append (",'"); //$NON-NLS-1$
+       buffer.append (function.token);
+       buffer.append ("', ['"); // $NON-NLS-1$
+       buffer.append (ERROR_ID);
+       buffer.append ("' + e.message]);}}"); // $NON-NLS-1$
+       nonBlockingExecute (buffer.toString ());
+       nonBlockingExecute (getDeleteFunctionString (functionName));
+       deregisterFunction (function);
+
+       Object result = evaluateResult;
+       evaluateResult = null;
+       if (result instanceof SWTException) throw (SWTException)result;
+       return result;
+}
+
+public abstract boolean forward ();
+
+public abstract String getBrowserType ();
+
+String getDeleteFunctionString (String functionName) {
+       return "delete window." + functionName; //$NON-NLS-1$
+}
+
+int getNextFunctionIndex () {
+       return nextFunctionIndex++;
+}
+
+public abstract String getText ();
+
+public abstract String getUrl ();
+
+public Object getWebBrowser () {
+       return null;
+}
+
+public abstract boolean isBackEnabled ();
+
+public boolean isFocusControl () {
+       return false;
+}
+
+public abstract boolean isForwardEnabled ();
+
+public abstract void refresh ();
+
+void registerFunction (BrowserFunction function) {
+       functions.put (function.index, function);
+}
+
+public void removeAuthenticationListener (AuthenticationListener listener) {
+       if (authenticationListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < authenticationListeners.length; i++) {
+               if (listener == authenticationListeners[i]) {
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (authenticationListeners.length == 1) {
+               authenticationListeners = new AuthenticationListener[0];
+               return;
+       }
+       AuthenticationListener[] newAuthenticationListeners = new AuthenticationListener[authenticationListeners.length - 1];
+       System.arraycopy (authenticationListeners, 0, newAuthenticationListeners, 0, index);
+       System.arraycopy (authenticationListeners, index + 1, newAuthenticationListeners, index, authenticationListeners.length - index - 1);
+       authenticationListeners = newAuthenticationListeners;
+}
+
+public void removeCloseWindowListener (CloseWindowListener listener) {
+       if (closeWindowListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < closeWindowListeners.length; i++) {
+               if (listener == closeWindowListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (closeWindowListeners.length == 1) {
+               closeWindowListeners = new CloseWindowListener[0];
+               return;
+       }
+       CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1];
+       System.arraycopy (closeWindowListeners, 0, newCloseWindowListeners, 0, index);
+       System.arraycopy (closeWindowListeners, index + 1, newCloseWindowListeners, index, closeWindowListeners.length - index - 1);
+       closeWindowListeners = newCloseWindowListeners;
+}
+
+public void removeLocationListener (LocationListener listener) {
+       if (locationListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < locationListeners.length; i++) {
+               if (listener == locationListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (locationListeners.length == 1) {
+               locationListeners = new LocationListener[0];
+               return;
+       }
+       LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1];
+       System.arraycopy (locationListeners, 0, newLocationListeners, 0, index);
+       System.arraycopy (locationListeners, index + 1, newLocationListeners, index, locationListeners.length - index - 1);
+       locationListeners = newLocationListeners;
+}
+
+public void removeOpenWindowListener (OpenWindowListener listener) {
+       if (openWindowListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < openWindowListeners.length; i++) {
+               if (listener == openWindowListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (openWindowListeners.length == 1) {
+               openWindowListeners = new OpenWindowListener[0];
+               return;
+       }
+       OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1];
+       System.arraycopy (openWindowListeners, 0, newOpenWindowListeners, 0, index);
+       System.arraycopy (openWindowListeners, index + 1, newOpenWindowListeners, index, openWindowListeners.length - index - 1);
+       openWindowListeners = newOpenWindowListeners;
+}
+
+public void removeProgressListener (ProgressListener listener) {
+       if (progressListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < progressListeners.length; i++) {
+               if (listener == progressListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (progressListeners.length == 1) {
+               progressListeners = new ProgressListener[0];
+               return;
+       }
+       ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1];
+       System.arraycopy (progressListeners, 0, newProgressListeners, 0, index);
+       System.arraycopy (progressListeners, index + 1, newProgressListeners, index, progressListeners.length - index - 1);
+       progressListeners = newProgressListeners;
+}
+
+public void removeStatusTextListener (StatusTextListener listener) {
+       if (statusTextListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < statusTextListeners.length; i++) {
+               if (listener == statusTextListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (statusTextListeners.length == 1) {
+               statusTextListeners = new StatusTextListener[0];
+               return;
+       }
+       StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1];
+       System.arraycopy (statusTextListeners, 0, newStatusTextListeners, 0, index);
+       System.arraycopy (statusTextListeners, index + 1, newStatusTextListeners, index, statusTextListeners.length - index - 1);
+       statusTextListeners = newStatusTextListeners;
+}
+
+public void removeTitleListener (TitleListener listener) {
+       if (titleListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < titleListeners.length; i++) {
+               if (listener == titleListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (titleListeners.length == 1) {
+               titleListeners = new TitleListener[0];
+               return;
+       }
+       TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1];
+       System.arraycopy (titleListeners, 0, newTitleListeners, 0, index);
+       System.arraycopy (titleListeners, index + 1, newTitleListeners, index, titleListeners.length - index - 1);
+       titleListeners = newTitleListeners;
+}
+
+public void removeVisibilityWindowListener (VisibilityWindowListener listener) {
+       if (visibilityWindowListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < visibilityWindowListeners.length; i++) {
+               if (listener == visibilityWindowListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (visibilityWindowListeners.length == 1) {
+               visibilityWindowListeners = new VisibilityWindowListener[0];
+               return;
+       }
+       VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1];
+       System.arraycopy (visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, index);
+       System.arraycopy (visibilityWindowListeners, index + 1, newVisibilityWindowListeners, index, visibilityWindowListeners.length - index - 1);
+       visibilityWindowListeners = newVisibilityWindowListeners;
+}
+
+boolean sendKeyEvent (Event event) {
+       int traversal = SWT.TRAVERSE_NONE;
+       boolean traverseDoit = true;
+       switch (event.keyCode) {
+               case SWT.ESC: {
+                       traversal = SWT.TRAVERSE_ESCAPE;
+                       traverseDoit = true;
+                       break;
+               }
+               case SWT.CR: {
+                       traversal = SWT.TRAVERSE_RETURN;
+                       traverseDoit = false;
+                       break;
+               }
+               case SWT.ARROW_DOWN:
+               case SWT.ARROW_RIGHT: {
+                       traversal = SWT.TRAVERSE_ARROW_NEXT;
+                       traverseDoit = false;
+                       break;
+               }
+               case SWT.ARROW_UP:
+               case SWT.ARROW_LEFT: {
+                       traversal = SWT.TRAVERSE_ARROW_PREVIOUS;
+                       traverseDoit = false;
+                       break;
+               }
+               case SWT.TAB: {
+                       traversal = (event.stateMask & SWT.SHIFT) != 0 ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT;
+                       traverseDoit = (event.stateMask & SWT.CTRL) != 0;
+                       break;
+               }
+               case SWT.PAGE_DOWN: {
+                       if ((event.stateMask & SWT.CTRL) != 0) {
+                               traversal = SWT.TRAVERSE_PAGE_NEXT;
+                               traverseDoit = true;
+                       }
+                       break;
+               }
+               case SWT.PAGE_UP: {
+                       if ((event.stateMask & SWT.CTRL) != 0) {
+                               traversal = SWT.TRAVERSE_PAGE_PREVIOUS;
+                               traverseDoit = true;
+                       }
+                       break;
+               }
+               default: {
+                       if (translateMnemonics ()) {
+                               if (event.character != 0 && (event.stateMask & (SWT.ALT | SWT.CTRL)) == SWT.ALT) {
+                                       traversal = SWT.TRAVERSE_MNEMONIC;
+                                       traverseDoit = true;
+                               }
+                       }
+                       break;
+               }
+       }
+
+       boolean doit = true;
+       if (traversal != SWT.TRAVERSE_NONE) {
+               boolean oldEventDoit = event.doit;
+               event.doit = traverseDoit;
+               doit = !browser.traverse (traversal, event);
+               event.doit = oldEventDoit;
+       }
+       if (doit) {
+               browser.notifyListeners (event.type, event);
+               doit = event.doit;
+       }
+       return doit;
+}
+
+public void setBrowser (Browser browser) {
+       this.browser = browser;
+}
+
+public abstract boolean setText (String html, boolean trusted);
+
+public abstract boolean setUrl (String url, String postData, String[] headers);
+
+public abstract void stop ();
+
+int translateKey (int key) {
+       for (int i = 0; i < KeyTable.length; i++) {
+               if (KeyTable[i][0] == key) return KeyTable[i][1];
+       }
+       return 0;
+}
+
+boolean translateMnemonics () {
+       return true;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebDownloadDelegate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebDownloadDelegate.java
new file mode 100644 (file)
index 0000000..eaf177a
--- /dev/null
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.webkit.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+class WebDownloadDelegate {
+       COMObject iWebDownloadDelegate;
+
+       Browser browser;
+       int refCount = 0;
+       int status = -1;
+       long size, totalSize;
+       String url;
+
+       static final int DOWNLOAD_FINISHED = 0;
+       static final int DOWNLOAD_CANCELLED = 1;
+       static final int DOWNLOAD_ERROR = 3;
+
+WebDownloadDelegate (Browser browser) {
+       createCOMInterfaces ();
+       this.browser = browser;
+}
+
+int AddRef () {
+       refCount++;
+       return refCount;
+}
+
+void createCOMInterfaces () {
+       iWebDownloadDelegate = new COMObject (new int[] {2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 1, 1}) {
+               @Override
+               public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
+               @Override
+               public long method1 (long[] args) {return AddRef ();}
+               @Override
+               public long method2 (long[] args) {return Release ();}
+               @Override
+               public long method3 (long[] args) {return decideDestinationWithSuggestedFilename (args[0], args[1]);}
+               @Override
+               public long method4 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method5 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method6 (long[] args) {return didFailWithError (args[0], args[1]);}
+               @Override
+               public long method7 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method8 (long[] args) {return didReceiveDataOfLength (args[0], (int)args[1]);}
+               @Override
+               public long method9 (long[] args) {return didReceiveResponse (args[0], args[1]);}
+               @Override
+               public long method10 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method11 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method12 (long[] args) {return willSendRequest (args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method13 (long[] args) {return didBegin (args[0]);}
+               @Override
+               public long method14 (long[] args) {return didFinish (args[0]);}
+       };
+}
+
+int decideDestinationWithSuggestedFilename (long download, long filename) {
+       String name = WebKit.extractBSTR (filename);
+       FileDialog dialog = new FileDialog (browser.getShell(), SWT.SAVE);
+       dialog.setText (SWT.getMessage ("SWT_FileDownload")); //$NON-NLS-1$
+       dialog.setFileName (name);
+       dialog.setOverwrite (true);
+       String path = dialog.open ();
+       IWebDownload iwebdownload = new IWebDownload (download);
+       iwebdownload.setDeletesFileUponFailure (0);
+       if (path == null) {
+               /*
+               * Bug in WebKit.  Failure to set a non-null destination on the IWebDownload results in
+               * a crash, even when the download is being cancelled.
+               */
+               iwebdownload.setDestination (WebKit.createBSTR (""), 1); //$NON-NLS-1$
+               iwebdownload.cancel();
+               iwebdownload.Release();
+       } else {
+               File file = new File (path);
+               if (file.exists ()) file.delete ();
+               iwebdownload.setDestination (WebKit.createBSTR (path), 1);
+               openDownloadWindow (iwebdownload, path);
+       }
+       return COM.S_OK;
+}
+
+int didBegin (long download) {
+       new IWebDownload (download).AddRef ();
+       status = -1;
+       size = 0;
+       totalSize = 0;
+       url = null;
+       return COM.S_OK;
+}
+
+int didFailWithError (long download, long error) {
+       new IWebDownload (download).Release ();
+       status = DOWNLOAD_ERROR;
+       return COM.S_OK;
+}
+
+int didFinish (long download) {
+       new IWebDownload (download).Release ();
+       status = DOWNLOAD_FINISHED;
+       return COM.S_OK;
+}
+
+int didReceiveDataOfLength (long download, int length) {
+       size += length;
+       return COM.S_OK;
+}
+
+int didReceiveResponse (long download, long response) {
+       if (response != 0) {
+               IWebURLResponse urlResponse = new IWebURLResponse (response);
+               long[] size = new long[1];
+               int hr = urlResponse.expectedContentLength (size);
+               if (hr == COM.S_OK) totalSize = size[0];
+               long[] result = new long[1];
+               hr = urlResponse.URL (result);
+               if (hr == COM.S_OK && result[0] != 0) {
+                       url = WebKit.extractBSTR (result[0]);
+                       COM.SysFreeString (result[0]);
+               }
+       }
+       return COM.S_OK;
+}
+
+void disposeCOMInterfaces () {
+       if (iWebDownloadDelegate != null) {
+               iWebDownloadDelegate.dispose ();
+               iWebDownloadDelegate = null;
+       }
+}
+
+long getAddress () {
+       return iWebDownloadDelegate.getAddress ();
+}
+
+void openDownloadWindow (final IWebDownload download, String name) {
+       final Shell shell = new Shell ();
+       shell.setText (Compatibility.getMessage ("SWT_FileDownload"));  //$NON-NLS-1$
+       GridLayout gridLayout = new GridLayout ();
+       gridLayout.marginHeight = 15;
+       gridLayout.marginWidth = 15;
+       gridLayout.verticalSpacing = 20;
+       shell.setLayout (gridLayout);
+
+       Label nameLabel = new Label (shell, SWT.WRAP);
+       nameLabel.setText (Compatibility.getMessage ("SWT_Download_Location", new Object[] {name, url})); //$NON-NLS-1$
+       GridData data = new GridData ();
+       Monitor monitor = browser.getMonitor ();
+       int maxWidth = monitor.getBounds ().width / 2;
+       int width = nameLabel.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       data.widthHint = Math.min (width, maxWidth);
+       data.horizontalAlignment = GridData.FILL;
+       data.grabExcessHorizontalSpace = true;
+       nameLabel.setLayoutData (data);
+
+       final Label statusLabel = new Label (shell, SWT.NONE);
+       statusLabel.setText (Compatibility.getMessage ("SWT_Download_Started")); //$NON-NLS-1$
+       data = new GridData (GridData.FILL_BOTH);
+       statusLabel.setLayoutData (data);
+
+       final Button cancel = new Button (shell, SWT.PUSH);
+       cancel.setText (Compatibility.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+       data = new GridData ();
+       data.horizontalAlignment = GridData.CENTER;
+       cancel.setLayoutData (data);
+       final Listener cancelListener = event -> {
+               download.cancel ();
+               status = DOWNLOAD_CANCELLED;
+               download.Release ();
+       };
+       cancel.addListener (SWT.Selection, cancelListener);
+
+       final Display display = browser.getDisplay ();
+       final int INTERVAL = 500;
+       display.timerExec (INTERVAL, new Runnable () {
+               @Override
+               public void run () {
+                       if (shell.isDisposed () || status == DOWNLOAD_FINISHED || status == DOWNLOAD_CANCELLED) {
+                               shell.dispose ();
+                               return;
+                       }
+                       if (status == DOWNLOAD_ERROR) {
+                               statusLabel.setText (Compatibility.getMessage ("SWT_Download_Error")); //$NON-NLS-1$
+                               cancel.removeListener (SWT.Selection, cancelListener);
+                               cancel.addListener (SWT.Selection, event -> shell.dispose ());
+                               return;
+                       }
+                       long current = size / 1024L;
+                       long total = totalSize / 1024L;
+                       String message = Compatibility.getMessage ("SWT_Download_Status", new Object[] {current, total}); //$NON-NLS-1$
+                       statusLabel.setText (message);
+                       display.timerExec (INTERVAL, this);
+               }
+       });
+       shell.pack ();
+       shell.open ();
+}
+
+int QueryInterface (long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID ();
+       COM.MoveMemory (guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebDownloadDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebDownloadDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebDownloadDelegate)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebDownloadDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebDownloadDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+int Release () {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces ();
+       }
+       return refCount;
+}
+
+int willSendRequest (long download, long request, long redirectResponse, long finalRequest) {
+       IWebMutableURLRequest req = new IWebMutableURLRequest (request);
+       req.AddRef ();
+       OS.MoveMemory (finalRequest, new long[] {request}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebFrameLoadDelegate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebFrameLoadDelegate.java
new file mode 100644 (file)
index 0000000..8fb1426
--- /dev/null
@@ -0,0 +1,760 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+
+import java.net.*;
+import java.nio.charset.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.webkit.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+class WebFrameLoadDelegate {
+       COMObject iWebFrameLoadDelegate;
+       int refCount = 0;
+
+       Browser browser;
+       String html;
+       String url;
+
+       static final String OBJECTNAME_EXTERNAL = "external"; //$NON-NLS-1$
+
+WebFrameLoadDelegate (Browser browser) {
+       createCOMInterfaces ();
+       this.browser = browser;
+}
+
+void addEventHandlers (boolean top) {
+       if (top) {
+               StringBuilder buffer = new StringBuilder ("window.SWTkeyhandler = function SWTkeyhandler(e) {"); //$NON-NLS-1$
+               buffer.append ("try {e.returnValue = HandleWebKitEvent(e.type, e.keyCode, e.charCode, e.altKey, e.ctrlKey, e.shiftKey, e.metaKey);} catch (e) {}};"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('keydown', SWTkeyhandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('keypress', SWTkeyhandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('keyup', SWTkeyhandler, true);"); //$NON-NLS-1$
+               browser.execute (buffer.toString ());
+
+               buffer = new StringBuilder ("window.SWTmousehandler = function SWTmousehandler(e) {"); //$NON-NLS-1$
+               buffer.append ("try {e.returnValue = HandleWebKitEvent(e.type, e.screenX, e.screenY, e.detail, e.button + 1, e.altKey, e.ctrlKey, e.shiftKey, e.metaKey, e.relatedTarget != null);} catch (e) {}};"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('mousedown', SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('mouseup', SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('mousemove', SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('mousewheel', SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('dragstart', SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('mouseover', SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("document.addEventListener('mouseout', SWTmousehandler, true);"); //$NON-NLS-1$
+
+               browser.execute (buffer.toString ());
+       } else {
+               StringBuilder buffer = new StringBuilder ("for (var i = 0; i < frames.length; i++) {"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('keydown', window.SWTkeyhandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('keypress', window.SWTkeyhandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('keyup', window.SWTkeyhandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('mousedown', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('mouseup', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('mousemove', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('mouseover', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('mouseout', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('mousewheel', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ("frames[i].document.addEventListener('dragstart', window.SWTmousehandler, true);"); //$NON-NLS-1$
+               buffer.append ('}');
+               browser.execute (buffer.toString ());
+       }
+}
+
+int AddRef () {
+       refCount++;
+       return refCount;
+}
+
+void createCOMInterfaces () {
+       iWebFrameLoadDelegate = new COMObject (new int[] {2, 0, 0, 2, 2, 3, 2, 3, 3, 2, 3, 2, 5, 2, 2, 3, 4}) {
+               @Override
+               public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
+               @Override
+               public long method1 (long[] args) {return AddRef ();}
+               @Override
+               public long method2 (long[] args) {return Release ();}
+               @Override
+               public long method3 (long[] args) {return didStartProvisionalLoadForFrame (args[0], args[1]);}
+               @Override
+               public long method4 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method5 (long[] args) {return didFailProvisionalLoadWithError (args[0], args[1], args[2]);}
+               @Override
+               public long method6 (long[] args) {return didCommitLoadForFrame (args[0], args[1]);}
+               @Override
+               public long method7 (long[] args) {return didReceiveTitle (args[0], args[1], args[2]);}
+               @Override
+               public long method8 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method9 (long[] args) {return didFinishLoadForFrame (args[0], args[1]);}
+               @Override
+               public long method10 (long[] args){return COM.E_NOTIMPL;}
+               @Override
+               public long method11 (long[] args){return didChangeLocationWithinPageForFrame (args[0], args[1]);}
+               @Override
+               public long method12 (long[] args){return COM.S_OK;}
+               @Override
+               public long method13 (long[] args){return COM.E_NOTIMPL;}
+               @Override
+               public long method14 (long[] args){return COM.S_OK;}
+               @Override
+               public long method15 (long[] args){return COM.S_OK;}
+               @Override
+               public long method16 (long[] args){return didClearWindowObject (args[0], args[1], args[2], args[3]);}
+       };
+
+       /* Callbacks that take double parameters require custom callbacks that instead pass pointers to the doubles. */
+       long ppVtable = iWebFrameLoadDelegate.ppVtable;
+       long[] pVtable = new long[1];
+       OS.MoveMemory (pVtable, ppVtable, C.PTR_SIZEOF);
+       long[] funcs = new long[17];
+       OS.MoveMemory (funcs, pVtable[0], C.PTR_SIZEOF * funcs.length);
+       funcs[12] = WebKit_win32.willPerformClientRedirectToURL_CALLBACK (funcs[12]);
+       OS.MoveMemory (pVtable[0], funcs, C.PTR_SIZEOF * funcs.length);
+}
+
+int didChangeLocationWithinPageForFrame (long webView, long frame) {
+       IWebFrame iwebframe = new IWebFrame (frame);
+       long[] result = new long[1];
+       int hr = iwebframe.dataSource (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebDataSource dataSource = new IWebDataSource (result[0]);
+       result[0] = 0;
+       hr = dataSource.request (result);
+       dataSource.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebURLRequest request = new IWebURLRequest (result[0]);
+       result[0] = 0;
+       hr = request.URL (result);
+       request.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       String url2 = WebKit.extractBSTR (result[0]);
+       COM.SysFreeString (result[0]);
+       if (url2.length() == 0) return COM.S_OK;
+       /*
+        * If the URI indicates that the page is being rendered from memory
+        * (via setText()) then set it to about:blank to be consistent with IE.
+        */
+       if (url2.equals (WebKit.URI_FILEROOT)) {
+               url2 = WebKit.ABOUT_BLANK;
+       } else {
+               int length = WebKit.URI_FILEROOT.length ();
+               if (url2.startsWith (WebKit.URI_FILEROOT) && url2.charAt (length) == '#') {
+                       url2 = WebKit.ABOUT_BLANK + url2.substring (length);
+               }
+       }
+       final Display display = browser.getDisplay ();
+       result[0] = 0;
+       IWebView iWebView = new IWebView (webView);
+       hr = iWebView.mainFrame (result);
+       boolean top = false;
+       if (hr == COM.S_OK && result[0] != 0) {
+               top = frame == result[0];
+               new IWebFrame (result[0]).Release ();
+       }
+       if (top) {
+               StatusTextEvent statusText = new StatusTextEvent (browser);
+               statusText.display = display;
+               statusText.widget = browser;
+               statusText.text = url2;
+               StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners;
+               for (int i = 0; i < statusTextListeners.length; i++) {
+                       statusTextListeners[i].changed (statusText);
+               }
+       }
+
+       LocationEvent location = new LocationEvent (browser);
+       location.display = display;
+       location.widget = browser;
+       location.location = url2;
+       location.top = top;
+       LocationListener[] locationListeners = browser.webBrowser.locationListeners;
+       for (int i = 0; i < locationListeners.length; i++) {
+               locationListeners[i].changed (location);
+       }
+       return COM.S_OK;
+}
+
+int didClearWindowObject (long webView, long context, long windowScriptObject, long frame) {
+       WebKit_win32.JSGlobalContextRetain (context);
+       long globalObject = WebKit_win32.JSContextGetGlobalObject (context);
+       long privateData = ((WebKit)browser.webBrowser).webViewData;
+       long externalObject = WebKit_win32.JSObjectMake (context, WebKit.ExternalClass, privateData);
+       byte[] bytes = (OBJECTNAME_EXTERNAL + '\0').getBytes (StandardCharsets.UTF_8);
+       long name = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
+       WebKit_win32.JSObjectSetProperty (context, globalObject, name, externalObject, 0, null);
+       WebKit_win32.JSStringRelease (name);
+
+       for (BrowserFunction current : browser.webBrowser.functions.values()) {
+               browser.execute (current.functionString);
+       }
+
+       IWebView iwebView = new IWebView (webView);
+       long[] mainFrame = new long[1];
+       iwebView.mainFrame (mainFrame);
+       boolean top = mainFrame[0] == frame;
+       new IWebFrame (mainFrame[0]).Release ();
+       addEventHandlers (top);
+       return COM.S_OK;
+}
+
+int didCommitLoadForFrame (long webview, long frame) {
+       IWebFrame iWebFrame = new IWebFrame (frame);
+       long[] result = new long[1];
+       int hr = iWebFrame.dataSource (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebDataSource dataSource = new IWebDataSource (result[0]);
+       result[0] = 0;
+       hr = dataSource.request (result);
+       dataSource.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
+       result[0] = 0;
+       hr = request.URL (result);
+       request.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       String url2 = WebKit.extractBSTR (result[0]);
+       COM.SysFreeString (result[0]);
+       if (url2.length () == 0) return COM.S_OK;
+       /*
+        * If the URI indicates that the page is being rendered from memory
+        * (via setText()) then set it to about:blank to be consistent with IE.
+        */
+       if (url2.equals (WebKit.URI_FILEROOT)) {
+               url2 = WebKit.ABOUT_BLANK;
+       } else {
+               int length = WebKit.URI_FILEROOT.length ();
+               if (url2.startsWith (WebKit.URI_FILEROOT) && url2.charAt (length) == '#') {
+                       url2 = WebKit.ABOUT_BLANK + url2.substring (length);
+               }
+       }
+       Display display = browser.getDisplay ();
+       result[0] = 0;
+       IWebView iwebView = new IWebView (webview);
+       hr = iwebView.mainFrame (result);
+       boolean top = false;
+       if (hr == COM.S_OK && result[0] != 0) {
+               top = frame == result[0];
+               new IWebFrame (result[0]).Release ();
+       }
+       if (top) {
+               /* reset resource status variables */
+               this.url = url2;
+
+               /*
+               * Each invocation of setText() causes webView_didCommitLoadForFrame to be invoked
+               * twice, once for the initial navigate to about:blank, and once for the auto-navigate
+               * to about:blank that WebKit does when loadHTMLString is invoked.  If this is the
+               * first webView_didCommitLoadForFrame callback received for a setText() invocation
+               * then do not send any events or re-install registered BrowserFunctions.
+               */
+               if (url2.startsWith (WebKit.ABOUT_BLANK) && html != null) return COM.S_OK;
+
+               /* re-install registered functions */
+               for (BrowserFunction function : browser.webBrowser.functions.values()) {
+                       browser.webBrowser.execute (function.functionString);
+               }
+
+               ProgressEvent progress = new ProgressEvent (browser);
+               progress.display = display;
+               progress.widget = browser;
+               progress.current = 1;
+               progress.total = WebKit.MAX_PROGRESS;
+               ProgressListener[] progressListeners = browser.webBrowser.progressListeners;
+               for (int i = 0; i < progressListeners.length; i++) {
+                       progressListeners[i].changed (progress);
+               }
+               if (browser.isDisposed ()) return COM.S_OK;
+
+               StatusTextEvent statusText = new StatusTextEvent (browser);
+               statusText.display = display;
+               statusText.widget = browser;
+               statusText.text = url2;
+               StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners;
+               for (int i = 0; i < statusTextListeners.length; i++) {
+                       statusTextListeners[i].changed (statusText);
+               }
+               if (browser.isDisposed ()) return COM.S_OK;
+       }
+       LocationEvent location = new LocationEvent (browser);
+       location.display = display;
+       location.widget = browser;
+       location.location = url2;
+       location.top = top;
+       LocationListener[] locationListeners = browser.webBrowser.locationListeners;
+       for (int i = 0; i < locationListeners.length; i++) {
+               locationListeners[i].changed (location);
+       }
+       return COM.S_OK;
+}
+
+int didFailProvisionalLoadWithError (long webView, long error, long frame) {
+       IWebError iweberror = new IWebError (error);
+       int[] errorCode = new int[1];
+       int hr = iweberror.code (errorCode);
+       if (WebKit_win32.WebURLErrorBadURL < errorCode[0]) return COM.S_OK;
+
+       String failingURLString = null;
+       long[] failingURL = new long[1];
+       hr = iweberror.failingURL (failingURL);
+       if (hr == COM.S_OK && failingURL[0] != 0) {
+               failingURLString = WebKit.extractBSTR (failingURL[0]);
+               COM.SysFreeString (failingURL[0]);
+       }
+       if (failingURLString != null && WebKit_win32.WebURLErrorServerCertificateNotYetValid <= errorCode[0] && errorCode[0] <= WebKit_win32.WebURLErrorSecureConnectionFailed) {
+               /* handle invalid certificate error */
+               long[] result = new long[1];
+               hr = iweberror.localizedDescription (result);
+               if (hr != COM.S_OK || result[0] == 0) {
+                       return COM.S_OK;
+               }
+               String description = WebKit.extractBSTR (result[0]);
+               COM.SysFreeString (result[0]);
+
+               result[0] = 0;
+               hr = iweberror.QueryInterface (WebKit_win32.IID_IWebErrorPrivate, result);
+               if (hr != COM.S_OK || result[0] == 0) {
+                       return COM.S_OK;
+               }
+
+               IWebErrorPrivate webErrorPrivate = new IWebErrorPrivate (result[0]);
+               result[0] = 0;
+               long[] certificate = new long[1];
+               hr = webErrorPrivate.sslPeerCertificate (certificate);
+               webErrorPrivate.Release ();
+               if (hr != COM.S_OK || certificate[0] == 0) {
+                       return COM.S_OK;
+               }
+               if (showCertificateDialog (webView, failingURLString, description, certificate[0])) {
+                       IWebFrame iWebFrame = new IWebFrame (frame);
+                       hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result);
+                       if (hr != COM.S_OK || result[0] == 0) {
+                               certificate[0] = 0;
+                               return COM.S_OK;
+                       }
+                       IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
+                       request.setURL (failingURL[0]);
+                       request.setAllowsAnyHTTPSCertificate ();
+                       iWebFrame.loadRequest (request.getAddress ());
+                       request.Release ();
+               }
+               certificate[0] = 0;
+               return COM.S_OK;
+       }
+
+       /* handle other types of errors */
+       long[] result = new long[1];
+       hr = iweberror.localizedDescription (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       String description = WebKit.extractBSTR (result[0]);
+       COM.SysFreeString (result[0]);
+       if (!browser.isDisposed ()) {
+               String message = failingURLString != null ? failingURLString + "\n\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$
+               message += Compatibility.getMessage ("SWT_Page_Load_Failed", new Object[] {description}); //$NON-NLS-1$
+               MessageBox messageBox = new MessageBox (browser.getShell (), SWT.OK | SWT.ICON_ERROR);
+               messageBox.setMessage (message);
+               messageBox.open ();
+       }
+       return COM.S_OK;
+}
+
+int didFinishLoadForFrame (long webview, long frame) {
+       IWebView iWebView = new IWebView (webview);
+       long[] iWebFrame = new long[1];
+       int hr = iWebView.mainFrame (iWebFrame);
+       if (hr != COM.S_OK || iWebFrame[0] == 0) {
+               return COM.S_OK;
+       }
+       boolean top = frame == iWebFrame[0];
+       new IWebFrame (iWebFrame[0]).Release();
+       if (!top) return COM.S_OK;
+
+       /*
+        * If html is not null then there is html from a previous setText() call
+        * waiting to be set into the about:blank page once it has completed loading.
+        */
+       if (html != null) {
+               if (getUrl ().startsWith (WebKit.ABOUT_BLANK)) {
+                       ((WebKit)browser.webBrowser).loadingText = true;
+                       long string = WebKit.createBSTR (html);
+                       long URLString;
+                       if (((WebKit)browser.webBrowser).untrustedText) {
+                               URLString = WebKit.createBSTR (WebKit.ABOUT_BLANK);
+                       } else {
+                               URLString = WebKit.createBSTR (WebKit.URI_FILEROOT);
+                       }
+                       IWebFrame mainFrame = new IWebFrame (frame);
+                       mainFrame.loadHTMLString (string, URLString);
+                       html = null;
+               }
+       }
+
+       /*
+       * The loadHTMLString() invocation above will trigger a second didFinishLoadForFrame
+       * callback when it is completed.  If text was just set into the browser then wait for this
+       * second callback to come before sending the title or completed events.
+       */
+       if (!((WebKit)browser.webBrowser).loadingText) {
+               if (browser.isDisposed ()) return COM.S_OK;
+               /*
+               * To be consistent with other platforms a title event should be fired when a
+               * page has completed loading.  A page with a <title> tag will do this
+               * automatically when the didReceiveTitle callback is received.  However a page
+               * without a <title> tag will not do this by default, so fire the event
+               * here with the page's url as the title.
+               */
+               Display display = browser.getDisplay ();
+               IWebFrame mainFrame = new IWebFrame (frame);
+               long[] result = new long[1];
+               hr = mainFrame.dataSource (result);
+               if (hr != COM.S_OK || result[0] == 0) {
+                       return COM.S_OK;
+               }
+               IWebDataSource dataSource = new IWebDataSource (result[0]);
+               result[0] = 0;
+               hr = dataSource.pageTitle (result);
+               dataSource.Release ();
+               if (hr != COM.S_OK) {
+                       return COM.S_OK;
+               }
+               String title = null;
+               if (result[0] != 0) {
+                       title = WebKit.extractBSTR (result[0]);
+                       COM.SysFreeString (result[0]);
+               }
+               if (title == null || title.length () == 0) {    /* page has no title */
+                       TitleEvent newEvent = new TitleEvent (browser);
+                       newEvent.display = display;
+                       newEvent.widget = browser;
+                       newEvent.title = getUrl ();
+                       TitleListener[] titleListeners = browser.webBrowser.titleListeners;
+                       for (int i = 0; i < titleListeners.length; i++) {
+                               titleListeners[i].changed (newEvent);
+                       }
+                       if (browser.isDisposed ()) return COM.S_OK;
+               }
+
+               ProgressEvent progress = new ProgressEvent (browser);
+               progress.display = display;
+               progress.widget = browser;
+               progress.current = WebKit.MAX_PROGRESS;
+               progress.total = WebKit.MAX_PROGRESS;
+               ProgressListener[] progressListeners = browser.webBrowser.progressListeners;
+               for (int i = 0; i < progressListeners.length; i++) {
+                       progressListeners[i].completed (progress);
+               }
+               if (browser.isDisposed ()) return COM.S_OK;
+       }
+       ((WebKit)browser.webBrowser).loadingText = false;
+       return COM.S_OK;
+}
+
+int didReceiveTitle (long webView, long title, long frame) {
+       long[] mainFrame = new long[1];
+       IWebView iWebView = new IWebView (webView);
+       int hr = iWebView.mainFrame (mainFrame);
+       if (hr != COM.S_OK || frame == 0) {
+               return COM.S_OK;
+       }
+       if (frame == mainFrame[0]) {
+               String newTitle = WebKit.extractBSTR (title);
+               TitleEvent newEvent = new TitleEvent (browser);
+               newEvent.display = browser.getDisplay ();
+               newEvent.widget = browser;
+               newEvent.title = newTitle;
+               TitleListener[] titleListeners = browser.webBrowser.titleListeners;
+               for (int i = 0; i < titleListeners.length; i++) {
+                       titleListeners[i].changed (newEvent);
+               }
+       }
+       new IWebFrame (mainFrame[0]).Release ();
+       return COM.S_OK;
+}
+
+int didStartProvisionalLoadForFrame (long webView, long frame) {
+       return COM.S_OK;
+}
+
+void disposeCOMInterfaces () {
+       if (iWebFrameLoadDelegate != null) {
+               iWebFrameLoadDelegate.dispose ();
+               iWebFrameLoadDelegate = null;
+       }
+}
+
+long getAddress () {
+       return iWebFrameLoadDelegate.getAddress ();
+}
+
+String getUrl () {
+       /* WebKit auto-navigates to about:blank at startup */
+       if (url == null || url.length () == 0) return WebKit.ABOUT_BLANK;
+       return url;
+}
+
+int QueryInterface (long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID ();
+       COM.MoveMemory (guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebFrameLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebFrameLoadDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebFrameLoadDelegate)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebFrameLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebFrameLoadDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+int Release () {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces ();
+       }
+       return refCount;
+}
+
+boolean showCertificateDialog (long webView, final String failingUrlString, final String description, final long certificate) {
+       Shell parent = browser.getShell ();
+       final Shell shell = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+       shell.setText (Compatibility.getMessage ("SWT_InvalidCert_Title")); //$NON-NLS-1$
+       shell.setLayout (new GridLayout ());
+       Label label = new Label (shell, SWT.WRAP);
+       String host = null;
+       try {
+               host = new URL (failingUrlString).getHost ();
+       } catch (MalformedURLException e) {
+               /* show the url instead */
+               host = failingUrlString;
+       }
+       StringBuilder message = new StringBuilder ("\n"); //$NON-NLS-1$
+       message.append (Compatibility.getMessage ("SWT_InvalidCert_Message", new String[] {host})); //$NON-NLS-1$
+       message.append ("\n\n"); //$NON-NLS-1$
+       message.append (Compatibility.getMessage (description));
+       message.append ("\n"); //$NON-NLS-1$
+       message.append (Compatibility.getMessage ("SWT_InvalidCert_Connect")); //$NON-NLS-1$
+       message.append ("\n"); //$NON-NLS-1$
+       label.setText(message.toString ());
+
+       GridData data = new GridData ();
+       Monitor monitor = browser.getMonitor ();
+       int maxWidth = monitor.getBounds ().width * 2 / 3;
+       int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       data.widthHint = Math.min (width, maxWidth);
+       data.horizontalAlignment = GridData.FILL;
+       data.grabExcessHorizontalSpace = true;
+       label.setLayoutData (data);
+
+       final boolean[] result = new boolean[1];
+       final Button[] buttons = new Button[3];
+       Listener listener = event -> {
+               if (event.widget == buttons[2]) {
+                       showCertificate (shell, certificate);
+               } else {
+                       result[0] = event.widget == buttons[0];
+                       shell.close();
+               }
+       };
+
+       Composite composite = new Composite (shell, SWT.NONE);
+       data = new GridData ();
+       data.horizontalAlignment = GridData.END;
+       composite.setLayoutData (data);
+       composite.setLayout (new GridLayout (3, true));
+       buttons[0] = new Button (composite, SWT.PUSH);
+       buttons[0].setText (SWT.getMessage("SWT_Continue")); //$NON-NLS-1$
+       buttons[0].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       buttons[0].addListener (SWT.Selection, listener);
+       buttons[1] = new Button (composite, SWT.PUSH);
+       buttons[1].setText (SWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
+       buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       buttons[1].addListener (SWT.Selection, listener);
+       buttons[2] = new Button (composite, SWT.PUSH);
+       buttons[2].setText (SWT.getMessage("SWT_ViewCertificate")); //$NON-NLS-1$
+       buttons[2].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       buttons[2].addListener (SWT.Selection, listener);
+
+       shell.setDefaultButton (buttons[0]);
+       shell.pack ();
+
+       Rectangle parentSize = parent.getBounds ();
+       Rectangle shellSize = shell.getBounds ();
+       int x = parent.getLocation ().x + (parentSize.width - shellSize.width) / 2;
+       int y = parent.getLocation ().y + (parentSize.height - shellSize.height) / 2;
+       shell.setLocation (x, y);
+       shell.open ();
+       Display display = browser.getDisplay ();
+       while (!shell.isDisposed ()) {
+               if (!display.readAndDispatch ()) display.sleep ();
+       }
+       return result[0];
+}
+
+void showCertificate (Shell parent, long certificate) {
+       CERT_CONTEXT context = new CERT_CONTEXT ();
+       OS.MoveMemory (context, certificate, CERT_CONTEXT.sizeof);
+       CERT_INFO info = new CERT_INFO ();
+       OS.MoveMemory (info, context.pCertInfo, CERT_INFO.sizeof);
+
+       int length = OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Issuer, OS.CERT_SIMPLE_NAME_STR, null, 0);
+       char [] buffer = new char [length];
+       OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Issuer, OS.CERT_SIMPLE_NAME_STR, buffer, length);
+       String issuer = new String (buffer, 0, length - 1);
+
+       length = OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Subject, OS.CERT_SIMPLE_NAME_STR, null, 0);
+       buffer = new char [length];
+       OS.CertNameToStr (OS.X509_ASN_ENCODING, info.Subject, OS.CERT_SIMPLE_NAME_STR, buffer, length);
+       String subject = new String (buffer, 0, length - 1);
+
+       final String SEPARATOR_DATE = "/"; //$NON-NLS-1$
+       final String SEPARATOR_TIME = ":"; //$NON-NLS-1$
+       SYSTEMTIME systemTime = new SYSTEMTIME ();
+       OS.FileTimeToSystemTime (info.NotBefore, systemTime);
+       String validFrom = systemTime.wDay + SEPARATOR_DATE + systemTime.wMonth + SEPARATOR_DATE + systemTime.wYear;
+       String validFromTime = systemTime.wHour + SEPARATOR_TIME + systemTime.wMinute + SEPARATOR_TIME + systemTime.wSecond;
+
+       systemTime = new SYSTEMTIME ();
+       OS.FileTimeToSystemTime (info.NotAfter, systemTime);
+       String validTo = systemTime.wDay + SEPARATOR_DATE + systemTime.wMonth + SEPARATOR_DATE + systemTime.wYear;
+       String validToTime = systemTime.wHour + SEPARATOR_TIME + systemTime.wMinute + SEPARATOR_TIME + systemTime.wSecond;
+
+       length = info.SerialNumber.cbData;
+       byte[] serialNumber = new byte[length];
+       OS.MoveMemory (serialNumber, info.SerialNumber.pbData, length);
+       String hexSerialNumber = new String ();
+       for (int i = length - 1; i >= 0; i--) {
+               int number = 0xFF & serialNumber[i];
+               String hex = Integer.toHexString (number);
+               if (hex.length () == 1) hexSerialNumber += "0"; //$NON-NLS-1$
+               hexSerialNumber += hex + " "; //$NON-NLS-1$
+       }
+
+       final Shell dialog = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+       dialog.setText (SWT.getMessage ("SWT_Certificate")); //$NON-NLS-1$
+       dialog.setLayout (new GridLayout (1, false));
+
+       TabFolder tabFolder = new TabFolder (dialog, SWT.NONE);
+       tabFolder.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true, 1, 1));
+       tabFolder.setLayout (new FillLayout ());
+
+       TabItem general = new TabItem (tabFolder, SWT.NONE);
+       general.setText (SWT.getMessage ("SWT_General")); //$NON-NLS-1$
+       Composite composite = new Composite (tabFolder, SWT.BORDER);
+       composite.setLayout (new GridLayout (1, false));
+       Label issuedTo = new Label (composite, SWT.NONE);
+       issuedTo.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false));
+       issuedTo.setText (Compatibility.getMessage ("SWT_IssuedTo", new Object[] {subject})); //$NON-NLS-1$
+       Label issuedBy = new Label (composite, SWT.NONE);
+       issuedBy.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false));
+       issuedBy.setText (Compatibility.getMessage ("SWT_IssuedFrom", new Object[] {issuer}));  //$NON-NLS-1$
+       Label valid = new Label (composite, SWT.NONE);
+       valid.setLayoutData (new GridData (SWT.BEGINNING, SWT.CENTER, false, false));
+       valid.setText (Compatibility.getMessage ("SWT_ValidFromTo", new Object[] {validFrom, validTo})); //$NON-NLS-1$
+       general.setControl (composite);
+
+       TabItem details = new TabItem (tabFolder, SWT.NONE);
+       details.setText (SWT.getMessage ("SWT_Details")); //$NON-NLS-1$
+       Table table = new Table (tabFolder, SWT.SINGLE | SWT.BORDER| SWT.FULL_SELECTION);
+       table.setHeaderVisible (true);
+       TableColumn tableColumn = new TableColumn (table, SWT.LEAD);
+       tableColumn.setText (SWT.getMessage ("SWT_Field")); //$NON-NLS-1$
+       tableColumn = new TableColumn (table, SWT.NONE);
+       tableColumn.setText (SWT.getMessage ("SWT_Value")); //$NON-NLS-1$
+       TableItem tableItem = new TableItem(table, SWT.NONE);
+       String version = "V" + String.valueOf (info.dwVersion + 1); //$NON-NLS-1$
+       tableItem.setText (new String[]{SWT.getMessage ("SWT_Version"), version}); //$NON-NLS-1$
+       tableItem = new TableItem (table, SWT.NONE);
+       tableItem.setText (new String[] {SWT.getMessage ("SWT_SerialNumber"), hexSerialNumber}); //$NON-NLS-1$
+       tableItem = new TableItem (table, SWT.NONE);
+       tableItem.setText (new String[] {SWT.getMessage ("SWT_Issuer"), issuer}); //$NON-NLS-1$
+
+       tableItem = new TableItem (table, SWT.NONE);
+       StringBuilder stringBuilder2 = new StringBuilder ();
+       stringBuilder2.append (validFrom);
+       stringBuilder2.append (", "); //$NON-NLS-1$
+       stringBuilder2.append (validFromTime);
+       stringBuilder2.append (" GMT"); //$NON-NLS-1$
+       tableItem.setText (new String[] {SWT.getMessage ("SWT_ValidFrom"), stringBuilder2.toString ()}); //$NON-NLS-1$
+
+       tableItem = new TableItem (table, SWT.NONE);
+       StringBuilder stringBuilder = new StringBuilder ();
+       stringBuilder.append (validTo);
+       stringBuilder.append (", "); //$NON-NLS-1$
+       stringBuilder.append (validToTime);
+       stringBuilder.append (" GMT"); //$NON-NLS-1$
+       tableItem.setText (new String[] {SWT.getMessage ("SWT_ValidTo"), stringBuilder.toString ()}); //$NON-NLS-1$
+
+       tableItem = new TableItem (table, SWT.NONE);
+       tableItem.setText (new String[] {SWT.getMessage ("SWT_Subject"), subject}); //$NON-NLS-1$
+       for (int i = 0; i < table.getColumnCount (); i++) {
+               table.getColumn (i).pack ();
+       }
+       details.setControl (table);
+
+       Button ok = new Button (dialog, SWT.PUSH);
+       GridData layoutData = new GridData (SWT.END, SWT.CENTER, false, false);
+       layoutData.widthHint = 75;
+       ok.setLayoutData (layoutData);
+       ok.setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
+       ok.addSelectionListener (new SelectionAdapter() {
+               @Override
+               public void widgetSelected (SelectionEvent e) {
+                       dialog.dispose ();
+               }
+       });
+
+       dialog.setDefaultButton (ok);
+       dialog.pack ();
+       Rectangle parentSize = parent.getBounds ();
+       Rectangle dialogSize = dialog.getBounds ();
+       int x = parent.getLocation ().x + (parentSize.width - dialogSize.width) / 2;
+       int y = parent.getLocation ().y + (parentSize.height - dialogSize.height) / 2;
+       dialog.setLocation (x, y);
+       dialog.open ();
+       Display display = browser.getDisplay ();
+       while (!dialog.isDisposed ()) {
+               if (!display.readAndDispatch ()) display.sleep ();
+       }
+
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebKit.java
new file mode 100644 (file)
index 0000000..e935db2
--- /dev/null
@@ -0,0 +1,1310 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+
+import java.io.*;
+import java.net.*;
+import java.nio.charset.*;
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.webkit.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+class WebKit extends WebBrowser {
+       IWebView webView;
+       long webViewWindowHandle, webViewData;
+       int refCount = 0;
+       int lastKeyCode, lastCharCode;
+
+       WebDownloadDelegate webDownloadDelegate;
+       WebFrameLoadDelegate webFrameLoadDelegate;
+       WebPolicyDelegate webPolicyDelegate;
+       WebResourceLoadDelegate webResourceLoadDelegate;
+       WebUIDelegate webUIDelegate;
+
+       boolean ignoreDispose;
+       boolean loadingText = false;
+       boolean traverseNext = true;
+       boolean traverseOut = false;
+       boolean untrustedText;
+       String lastNavigateURL;
+       BrowserFunction eventFunction;
+
+       static int prefsIdentifier;
+       static long ExternalClass;
+       static boolean LibraryLoaded = false;
+       static String LibraryLoadError;
+       static Callback JSObjectHasPropertyProc;
+       static Callback JSObjectGetPropertyProc;
+       static Callback JSObjectCallAsFunctionProc;
+       static final int MAX_PROGRESS = 100;
+       static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
+       static final String CLASSNAME_EXTERNAL = "External"; //$NON-NLS-1$
+       static final String EMPTY_STRING = ""; //$NON-NLS-1$
+       static final String FUNCTIONNAME_CALLJAVA = "callJava"; //$NON-NLS-1$
+       static final String HEADER_SETCOOKIE = "Set-Cookie"; //$NON-NLS-1$
+       static final String POST = "POST"; //$NON-NLS-1$
+       static final String PROPERTY_LENGTH = "length"; //$NON-NLS-1$
+       static final String PROTOCOL_HTTPS = "https://"; //$NON-NLS-1$
+       static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$
+       static final String PROTOCOL_HTTP = "http://"; //$NON-NLS-1$
+       static final String USER_AGENT = "user-agent"; //$NON-NLS-1$
+       static final String URI_FILEROOT = "file:///"; //$NON-NLS-1$
+
+       /* event strings */
+       static final String DOMEVENT_DRAGSTART = "dragstart"; //$NON-NLS-1$
+       static final String DOMEVENT_KEYDOWN = "keydown"; //$NON-NLS-1$
+       static final String DOMEVENT_KEYPRESS = "keypress"; //$NON-NLS-1$
+       static final String DOMEVENT_KEYUP = "keyup"; //$NON-NLS-1$
+       static final String DOMEVENT_MOUSEDOWN = "mousedown"; //$NON-NLS-1$
+       static final String DOMEVENT_MOUSEUP = "mouseup"; //$NON-NLS-1$
+       static final String DOMEVENT_MOUSEMOVE = "mousemove"; //$NON-NLS-1$
+       static final String DOMEVENT_MOUSEOUT = "mouseout"; //$NON-NLS-1$
+       static final String DOMEVENT_MOUSEOVER = "mouseover"; //$NON-NLS-1$
+       static final String DOMEVENT_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$
+
+static {
+       /*
+       * Attempt to load the swt-webkit library.  This will only succeed if the Apple
+       * Application Support package is on the user's Windows Path environment variable.
+       */
+       try {
+               Library.loadLibrary ("swt-webkit"); // $NON-NLS-1$
+               LibraryLoaded = true;
+       } catch (Throwable e) {
+       }
+
+       /*
+       * If needed, add the Apple Application Support package's directory to the library
+       * lookup path and try to load the swt-webkit library again.
+       */
+       if (!LibraryLoaded) {
+               /*
+                * Locate the Apple Application Support directory (if installed) and add its path to the library lookup path.
+                *
+                * As of Safari 5.1.4, the Apple Application Support directory is in the Safari installation directory,
+                * which is pointed to by registry entry "HKEY_LOCAL_MACHINE\SOFTWARE\Apple Computer, Inc.\Safari".
+                *
+                * With earlier versions of Safari the Apple Application Support is installed in a stand-alone location, which
+                * is pointed to by registry entry "HKEY_LOCAL_MACHINE\SOFTWARE\Apple Inc.\Apple Application Support\InstallDir".
+                */
+
+               String AASDirectory = readInstallDir ("SOFTWARE\\Apple Computer, Inc.\\Safari"); //$NON-NLS-1$
+               if (AASDirectory != null) {
+                       AASDirectory += "\\Apple Application Support"; //$NON-NLS-1$
+                       if (!new File(AASDirectory).exists()) {
+                               AASDirectory = null;
+                       }
+               }
+
+               if (AASDirectory == null) {
+                       AASDirectory = readInstallDir ("SOFTWARE\\Apple Inc.\\Apple Application Support"); //$NON-NLS-1$
+               }
+
+               if (AASDirectory != null) {
+                       TCHAR buffer = new TCHAR (0, AASDirectory, true);
+                       boolean success = OS.SetDllDirectory (buffer); /* should succeed on XP+SP1 and newer */
+                       if (success) {
+                               try {
+                                       Library.loadLibrary ("swt-webkit"); //$NON-NLS-1$
+                                       LibraryLoaded = true;
+                               } catch (Throwable e) {
+                                       LibraryLoadError = "Failed to load the swt-webkit library"; //$NON-NLS-1$
+                                       if (Device.DEBUG) System.out.println ("Failed to load swt-webkit library. Apple Application Support directory path: " + AASDirectory); //$NON-NLS-1$
+                               }
+                       } else {
+                               LibraryLoadError = "Failed to add the Apple Application Support package to the library lookup path.  "; //$NON-NLS-1$
+                               LibraryLoadError += "To use a SWT.WEBKIT-style Browser prepend " + AASDirectory + " to your Windows 'Path' environment variable and restart."; //$NON-NLS-1$ //$NON-NLS-2$
+                       }
+               } else {
+                       LibraryLoadError = "Safari must be installed to use a SWT.WEBKIT-style Browser"; //$NON-NLS-1$
+               }
+       }
+
+       if (LibraryLoaded) {
+               JSObjectHasPropertyProc = new Callback (WebKit.class, "JSObjectHasPropertyProc", 3); //$NON-NLS-1$
+               if (JSObjectHasPropertyProc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+               JSObjectGetPropertyProc = new Callback (WebKit.class, "JSObjectGetPropertyProc", 4); //$NON-NLS-1$
+               if (JSObjectGetPropertyProc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+               JSObjectCallAsFunctionProc = new Callback (WebKit.class, "JSObjectCallAsFunctionProc", 6); //$NON-NLS-1$
+               if (JSObjectCallAsFunctionProc.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+               NativeClearSessions = () -> {
+                       long[] result = new long[1];
+                       int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebCookieManager, 0, WebKit_win32.IID_IWebCookieManager, result);
+                       if (hr != COM.S_OK || result[0] == 0) {
+                               return;
+                       }
+                       IWebCookieManager cookieManager = new IWebCookieManager (result[0]);
+                       long[] storage = new long[1];
+                       hr = cookieManager.cookieStorage (storage);
+                       cookieManager.Release ();
+                       if (hr != COM.S_OK || storage[0] == 0) {
+                               return;
+                       }
+                       long cookies = WebKit_win32.CFHTTPCookieStorageCopyCookies (storage[0]);
+                       if (cookies != 0) {
+                               int count = WebKit_win32.CFArrayGetCount (cookies);
+                               for (int i = 0; i < count; i++) {
+                                       long cookie = WebKit_win32.CFArrayGetValueAtIndex (cookies, i);
+                                       long flags = WebKit_win32.CFHTTPCookieGetFlags (cookie);
+                                       if ((flags & WebKit_win32.CFHTTPCookieSessionOnlyFlag) != 0) {
+                                               WebKit_win32.CFHTTPCookieStorageDeleteCookie (storage[0], cookie);
+                                       }
+                               }
+                               WebKit_win32.CFRelease (cookies);
+                       }
+                       // WebKit_win32.CFRelease (storage[0]); //intentionally commented, causes crash
+               };
+
+               NativeGetCookie = () -> {
+                       long[] result = new long[1];
+                       int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebCookieManager, 0, WebKit_win32.IID_IWebCookieManager, result);
+                       if (hr != COM.S_OK || result[0] == 0) {
+                               return;
+                       }
+                       IWebCookieManager cookieManager = new IWebCookieManager (result[0]);
+                       long[] storage = new long[1];
+                       hr = cookieManager.cookieStorage (storage);
+                       cookieManager.Release ();
+                       if (hr != COM.S_OK || storage[0] == 0) {
+                               return;
+                       }
+                       char[] chars = CookieUrl.toCharArray ();
+                       long string = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
+                       if (string != 0) {
+                               long cfUrl = WebKit_win32.CFURLCreateWithString (0, string, 0);
+                               if (cfUrl != 0) {
+                                       boolean secure = CookieUrl.startsWith (PROTOCOL_HTTPS);
+                                       long cookiesArray = WebKit_win32.CFHTTPCookieStorageCopyCookiesForURL (storage[0], cfUrl, secure);
+                                       if (cookiesArray != 0) {
+                                               int count = WebKit_win32.CFArrayGetCount (cookiesArray);
+                                               for (int i = 0; i < count; i++) {
+                                                       long cookie = WebKit_win32.CFArrayGetValueAtIndex (cookiesArray, i);
+                                                       if (cookie != 0) {
+                                                               long cookieName = WebKit_win32.CFHTTPCookieGetName (cookie);
+                                                               if (cookieName != 0) {
+                                                                       String name = stringFromCFString (cookieName);
+                                                                       if (CookieName.equals (name)) {
+                                                                               long value = WebKit_win32.CFHTTPCookieGetValue (cookie);
+                                                                               if (value != 0) CookieValue = stringFromCFString (value);
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               WebKit_win32.CFRelease (cookiesArray);
+                                       }
+                                       WebKit_win32.CFRelease (cfUrl);
+                               }
+                               WebKit_win32.CFRelease (string);
+                       }
+                       // WebKit_win32.CFRelease (storage[0]); //intentionally commented, causes crash
+               };
+
+               NativeSetCookie = () -> {
+                       long[] result = new long[1];
+                       int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebCookieManager, 0, WebKit_win32.IID_IWebCookieManager, result);
+                       if (hr != COM.S_OK || result[0] == 0) {
+                               return;
+                       }
+                       IWebCookieManager cookieManager = new IWebCookieManager (result[0]);
+                       long[] storage = new long[1];
+                       hr = cookieManager.cookieStorage (storage);
+                       cookieManager.Release ();
+                       if (hr != COM.S_OK || storage[0] == 0) {
+                               return;
+                       }
+
+                       char[] chars = CookieUrl.toCharArray ();
+                       long string = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
+                       if (string != 0) {
+                               long cfUrl = WebKit_win32.CFURLCreateWithString (0, string, 0);
+                               if (cfUrl != 0) {
+                                       chars = CookieValue.toCharArray ();
+                                       long value = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
+                                       if (value != 0) {
+                                               chars = HEADER_SETCOOKIE.toCharArray ();
+                                               long key = WebKit_win32.CFStringCreateWithCharacters (0, chars, chars.length);
+                                               if (key != 0) {
+                                                       long headers = WebKit_win32.CFDictionaryCreate (0, new long[] {key}, new long[] {value}, 1, WebKit_win32.kCFCopyStringDictionaryKeyCallBacks (), WebKit_win32.kCFTypeDictionaryValueCallBacks ());
+                                                       if (headers != 0) {
+                                                               long cookies = WebKit_win32.CFHTTPCookieCreateWithResponseHeaderFields (0, headers, cfUrl);
+                                                               if (cookies != 0) {
+                                                                       long cookie = WebKit_win32.CFArrayGetValueAtIndex (cookies, 0);
+                                                                       if (cookie != 0) {
+                                                                               WebKit_win32.CFHTTPCookieStorageSetCookie (storage[0], cookie);
+                                                                               CookieResult = true;
+                                                                       }
+                                                                       WebKit_win32.CFRelease (cookies);
+                                                               }
+                                                               WebKit_win32.CFRelease (headers);
+                                                       }
+                                                       WebKit_win32.CFRelease (key);
+                                               }
+                                               WebKit_win32.CFRelease (value);
+                                       }
+                                       WebKit_win32.CFRelease (cfUrl);
+                               }
+                               WebKit_win32.CFRelease (string);
+                       }
+                       // WebKit_win32.CFRelease (storage[0]); //intentionally commented, causes crash
+               };
+
+               if (NativePendingCookies != null) {
+                       SetPendingCookies (NativePendingCookies);
+               }
+               NativePendingCookies = null;
+       }
+}
+
+static long createBSTR (String string) {
+       char[] data = (string + '\0').toCharArray ();
+       return COM.SysAllocString (data);
+}
+
+static String error (int code) {
+       throw new SWTError ("WebKit error " + code); //$NON-NLS-1$
+}
+
+static String extractBSTR (long bstrString) {
+       int size = COM.SysStringByteLen (bstrString);
+       if (size == 0) return EMPTY_STRING;
+       char[] buffer = new char[(size + 1) / 2]; // add one to avoid rounding errors
+       OS.MoveMemory (buffer, bstrString, size);
+       return new String (buffer);
+}
+
+static Browser findBrowser (long webView) {
+       if (webView == 0) return null;
+       IWebView iwebView = new IWebView (webView);
+       long[] result = new long[1];
+       int hr = iwebView.hostWindow (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               Widget widget = Display.getCurrent ().findWidget (result[0]);
+               if (widget != null && widget instanceof Browser) return (Browser)widget;
+       }
+       return null;
+}
+
+static long JSObjectCallAsFunctionProc (long ctx, long function, long thisObject, long argumentCount, long arguments, long exception) {
+       WebKit_win32.JSGlobalContextRetain (ctx);
+       if (WebKit_win32.JSValueIsObjectOfClass (ctx, thisObject, ExternalClass) == 0) {
+               return WebKit_win32.JSValueMakeUndefined (ctx);
+       }
+       long ptr = WebKit_win32.JSObjectGetPrivate (thisObject);
+       long[] handle = new long[1];
+       C.memmove (handle, ptr, C.PTR_SIZEOF);
+       Browser browser = findBrowser (handle[0]);
+       if (browser == null) return WebKit_win32.JSValueMakeUndefined (ctx);
+       WebKit webkit = (WebKit)browser.webBrowser;
+       return webkit.callJava (ctx, function, thisObject, argumentCount, arguments, exception);
+}
+
+static long JSObjectGetPropertyProc (long ctx, long object, long propertyName, long exception) {
+       byte[] bytes = (FUNCTIONNAME_CALLJAVA + '\0').getBytes (StandardCharsets.UTF_8);
+       long name = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
+       long addr = WebKit_win32.JSObjectCallAsFunctionProc_CALLBACK (WebKit.JSObjectCallAsFunctionProc.getAddress ());
+       long function = WebKit_win32.JSObjectMakeFunctionWithCallback (ctx, name, addr);
+       WebKit_win32.JSStringRelease (name);
+       return function;
+}
+
+static long JSObjectHasPropertyProc (long ctx, long object, long propertyName) {
+       byte[] bytes = (FUNCTIONNAME_CALLJAVA + '\0').getBytes (StandardCharsets.UTF_8);
+       return WebKit_win32.JSStringIsEqualToUTF8CString (propertyName, bytes);
+}
+
+static String readInstallDir (String keyString) {
+       long[] phkResult = new long[1];
+       TCHAR key = new TCHAR (0, keyString, true);
+       if (OS.RegOpenKeyEx (OS.HKEY_LOCAL_MACHINE, key, 0, OS.KEY_READ, phkResult) == 0) {
+               int[] lpcbData = new int[1];
+               TCHAR buffer = new TCHAR (0, "InstallDir", true); //$NON-NLS-1$
+               int result = OS.RegQueryValueEx (phkResult[0], buffer, 0, null, (TCHAR)null, lpcbData);
+               if (result == 0) {
+                       TCHAR lpData = new TCHAR (0, lpcbData[0] / TCHAR.sizeof);
+                       result = OS.RegQueryValueEx (phkResult[0], buffer, 0, null, lpData, lpcbData);
+                       if (result == 0) {
+                               OS.RegCloseKey (phkResult[0]);
+                               return lpData.toString (0, lpData.strlen ());
+                       }
+               }
+               OS.RegCloseKey (phkResult[0]);
+       }
+       return null;
+}
+
+static String stringFromCFString (long cfString) {
+       if (cfString == 0) return null;
+       int length = WebKit_win32.CFStringGetLength (cfString);
+       long ptr = WebKit_win32.CFStringGetCharactersPtr (cfString);
+       char[] chars = new char[length];
+       if (ptr != 0) {
+               OS.MoveMemory (chars, ptr, length);
+       } else {
+               for (int j = 0; j < length; j++) {
+                       chars[j] = WebKit_win32.CFStringGetCharacterAtIndex (cfString, j);
+               }
+       }
+       return new String (chars);
+}
+
+static String stringFromJSString (long jsString) {
+       if (jsString == 0) return null;
+       int length = WebKit_win32.JSStringGetLength (jsString);
+       byte[] bytes = new byte[length + 1];
+       WebKit_win32.JSStringGetUTF8CString (jsString, bytes, length + 1);
+       return new String (bytes);
+}
+
+@Override
+public boolean back () {
+       int[] result = new int[1];
+       webView.goBack (result);
+       return result[0] != 0;
+}
+
+long callJava (long ctx, long func, long thisObject, long argumentCount, long arguments, long exception) {
+       Object returnValue = null;
+       if (argumentCount == 3) {
+               long[] result = new long[1];
+               C.memmove (result, arguments, C.PTR_SIZEOF);
+               int type = WebKit_win32.JSValueGetType (ctx, result[0]);
+               if (type == WebKit_win32.kJSTypeNumber) {
+                       int index = ((Double)convertToJava (ctx, result[0])).intValue ();
+                       result[0] = 0;
+                       if (index > 0) {
+                               C.memmove (result, arguments + C.PTR_SIZEOF, C.PTR_SIZEOF);
+                               type = WebKit_win32.JSValueGetType (ctx, result[0]);
+                               if (type == WebKit_win32.kJSTypeString) {
+                                       String token = (String)convertToJava (ctx, result[0]);
+                                       BrowserFunction function = (BrowserFunction)functions.get (index);
+                                       if (function != null && token.equals (function.token)) {
+                                               try {
+                                                       C.memmove (result, arguments + 2 * C.PTR_SIZEOF, C.PTR_SIZEOF);
+                                                       Object temp = convertToJava (ctx, result[0]);
+                                                       if (temp instanceof Object[]) {
+                                                               Object[] args = (Object[])temp;
+                                                               try {
+                                                                       returnValue = function.function (args);
+                                                               } catch (Exception e) {
+                                                                       /* exception during function invocation */
+                                                                       returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
+                                                               }
+                                                       }
+                                               } catch (IllegalArgumentException e) {
+                                                       /* invalid argument value type */
+                                                       if (function.isEvaluate) {
+                                                               /* notify the function so that a java exception can be thrown */
+                                                               function.function (new String[] {WebBrowser.CreateErrorString (new SWTException (SWT.ERROR_INVALID_RETURN_VALUE).getLocalizedMessage ())});
+                                                       }
+                                                       returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return convertToJS (ctx, returnValue);
+}
+
+@Override
+public boolean close () {
+       return shouldClose ();
+}
+
+Object convertToJava (long ctx, long value) {
+       int type = WebKit_win32.JSValueGetType (ctx, value);
+       switch (type) {
+               case WebKit_win32.kJSTypeBoolean: {
+                       int result = (int)WebKit_win32.JSValueToNumber (ctx, value, null);
+                       return result != 0;
+               }
+               case WebKit_win32.kJSTypeNumber: {
+                       double result = WebKit_win32.JSValueToNumber (ctx, value, null);
+                       return result;
+               }
+               case WebKit_win32.kJSTypeString: {
+                       long string = WebKit_win32.JSValueToStringCopy (ctx, value, null);
+                       if (string == 0) return ""; //$NON-NLS-1$
+                       long length = WebKit_win32.JSStringGetMaximumUTF8CStringSize (string);
+                       byte[] bytes = new byte[(int)length];
+                       length = WebKit_win32.JSStringGetUTF8CString (string, bytes, length);
+                       WebKit_win32.JSStringRelease (string);
+                       /* length-1 is needed below to exclude the terminator character */
+                       return new String (bytes, 0, (int)length - 1, StandardCharsets.UTF_8);
+               }
+               case WebKit_win32.kJSTypeNull:
+                       // FALL THROUGH
+               case WebKit_win32.kJSTypeUndefined: return null;
+               case WebKit_win32.kJSTypeObject: {
+                       byte[] bytes = (PROPERTY_LENGTH + '\0').getBytes (StandardCharsets.UTF_8);
+                       long propertyName = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
+                       long valuePtr = WebKit_win32.JSObjectGetProperty (ctx, value, propertyName, null);
+                       WebKit_win32.JSStringRelease (propertyName);
+                       type = WebKit_win32.JSValueGetType (ctx, valuePtr);
+                       if (type == WebKit_win32.kJSTypeNumber) {
+                               int length = (int)WebKit_win32.JSValueToNumber (ctx, valuePtr, null);
+                               Object[] result = new Object[length];
+                               for (int i = 0; i < length; i++) {
+                                       long current = WebKit_win32.JSObjectGetPropertyAtIndex (ctx, value, i, null);
+                                       if (current != 0) {
+                                               result[i] = convertToJava (ctx, current);
+                                       }
+                               }
+                               return result;
+                       }
+               }
+       }
+       SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       return null;
+}
+
+long convertToJS (long ctx, Object value) {
+       if (value == null) {
+               return WebKit_win32.JSValueMakeNull (ctx);
+       }
+       if (value instanceof String) {
+               byte[] bytes = ((String)value + '\0').getBytes (StandardCharsets.UTF_8);
+               long stringRef = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
+               long result = WebKit_win32.JSValueMakeString (ctx, stringRef);
+               WebKit_win32.JSStringRelease (stringRef);
+               return result;
+       }
+       if (value instanceof Boolean) {
+               return WebKit_win32.JSValueMakeBoolean (ctx, ((Boolean)value).booleanValue () ? 1 : 0);
+       }
+       if (value instanceof Number) {
+               return WebKit_win32.JSValueMakeNumber (ctx, ((Number)value).doubleValue ());
+       }
+       if (value instanceof Object[]) {
+               Object[] arrayValue = (Object[]) value;
+               int length = arrayValue.length;
+               long[] arguments = new long[length];
+               for (int i = 0; i < length; i++) {
+                       Object javaObject = arrayValue[i];
+                       long jsObject = convertToJS (ctx, javaObject);
+                       arguments[i] = jsObject;
+               }
+               return WebKit_win32.JSObjectMakeArray (ctx, length, arguments, null);
+       }
+       SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
+       return 0;
+}
+
+@Override
+public void create (Composite parent, int style) {
+       if (!LibraryLoaded) {
+               browser.dispose ();
+               SWT.error (SWT.ERROR_NO_HANDLES, null, LibraryLoadError == null ? null : " [" + LibraryLoadError + ']'); //$NON-NLS-1$
+       }
+
+       if (ExternalClass == 0) {
+               JSClassDefinition jsClassDefinition = new JSClassDefinition ();
+               byte[] bytes = (CLASSNAME_EXTERNAL + '\0').getBytes ();
+               jsClassDefinition.className = C.malloc (bytes.length);
+               C.memmove (jsClassDefinition.className, bytes, bytes.length);
+
+               /* custom callbacks for hasProperty, getProperty and callAsFunction */
+               long addr = WebKit_win32.JSObjectHasPropertyProc_CALLBACK (JSObjectHasPropertyProc.getAddress ());
+               jsClassDefinition.hasProperty = addr;
+               addr = WebKit_win32.JSObjectGetPropertyProc_CALLBACK (JSObjectGetPropertyProc.getAddress ());
+               jsClassDefinition.getProperty = addr;
+
+               long classDefinitionPtr = C.malloc (JSClassDefinition.sizeof);
+               WebKit_win32.memmove (classDefinitionPtr, jsClassDefinition, JSClassDefinition.sizeof);
+               ExternalClass = WebKit_win32.JSClassCreate (classDefinitionPtr);
+               WebKit_win32.JSClassRetain (ExternalClass);
+       }
+
+       long[] result = new long[1];
+       int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebView, 0, WebKit_win32.IID_IWebView, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               browser.dispose ();
+               error (hr);
+       }
+       webView = new IWebView (result[0]);
+       webViewData = C.malloc (C.PTR_SIZEOF);
+       C.memmove (webViewData, new long[] {webView.getAddress ()}, C.PTR_SIZEOF);
+       hr = webView.setHostWindow (browser.handle);
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+       hr = webView.initWithFrame (new RECT (), 0, 0);
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+       result[0] = 0;
+       hr = webView.QueryInterface (WebKit_win32.IID_IWebViewPrivate, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               browser.dispose ();
+               error (hr);
+       }
+       IWebViewPrivate webViewPrivate = new IWebViewPrivate (result[0]);
+       result[0] = 0;
+       hr = webViewPrivate.viewWindow (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               browser.dispose ();
+               error (hr);
+       }
+       webViewPrivate.Release ();
+       webViewWindowHandle = result[0];
+
+       webFrameLoadDelegate = new WebFrameLoadDelegate (browser);
+       hr = webView.setFrameLoadDelegate (webFrameLoadDelegate.getAddress ());
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+       webUIDelegate = new WebUIDelegate (browser);
+       hr = webView.setUIDelegate (webUIDelegate.getAddress ());
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+
+       webResourceLoadDelegate = new WebResourceLoadDelegate (browser);
+       hr = webView.setResourceLoadDelegate (webResourceLoadDelegate.getAddress ());
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+
+       webDownloadDelegate = new WebDownloadDelegate (browser);
+       hr = webView.setDownloadDelegate (webDownloadDelegate.getAddress ());
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+
+       webPolicyDelegate = new WebPolicyDelegate (browser);
+       hr = webView.setPolicyDelegate (webPolicyDelegate.getAddress ());
+       if (hr != COM.S_OK) {
+               browser.dispose ();
+               error (hr);
+       }
+
+       initializeWebViewPreferences ();
+
+       Listener listener = e -> {
+               switch (e.type) {
+                       case SWT.Dispose: {
+                               /* make this handler run after other dispose listeners */
+                               if (ignoreDispose) {
+                                       ignoreDispose = false;
+                                       break;
+                               }
+                               ignoreDispose = true;
+                               browser.notifyListeners (e.type, e);
+                               e.type = SWT.NONE;
+                               onDispose ();
+                               break;
+                       }
+                       case SWT.FocusIn: {
+                               OS.SetFocus (webViewWindowHandle);
+                               break;
+                       }
+                       case SWT.Resize: {
+                               Rectangle bounds = DPIUtil.autoScaleUp(browser.getClientArea ()); // To Pixels
+                               OS.SetWindowPos (webViewWindowHandle, 0, bounds.x, bounds.y, bounds.width, bounds.height, OS.SWP_DRAWFRAME);
+                               break;
+                       }
+                       case SWT.Traverse: {
+                               if (traverseOut) {
+                                       e.doit = true;
+                                       traverseOut = false;
+                               } else {
+                                       e.doit = false;
+                               }
+                               break;
+                       }
+               }
+       };
+       browser.addListener (SWT.Dispose, listener);
+       browser.addListener (SWT.KeyDown, listener); /* needed for tabbing into the Browser */
+       browser.addListener (SWT.FocusIn, listener);
+       browser.addListener (SWT.Resize, listener);
+       browser.addListener (SWT.Traverse, listener);
+
+       eventFunction = new BrowserFunction (browser, "HandleWebKitEvent") { //$NON-NLS-1$
+               @Override
+               public Object function (Object[] arguments) {
+                       return handleEvent (arguments) ? Boolean.TRUE : Boolean.FALSE;
+               };
+       };
+}
+
+@Override
+public boolean execute (String script) {
+       long[] result = new long[1];
+       int hr = webView.mainFrame (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return false;
+       }
+       IWebFrame frame = new IWebFrame (result[0]);
+       long context = frame.globalContext ();
+       frame.Release ();
+       if (context == 0) {
+               return false;
+       }
+       byte[] bytes = (script + '\0').getBytes (StandardCharsets.UTF_8); //$NON-NLS-1$
+       long scriptString = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
+       if (scriptString == 0) return false;
+       bytes = (getUrl () + '\0').getBytes (StandardCharsets.UTF_8); //$NON-NLS-1$
+       long urlString = WebKit_win32.JSStringCreateWithUTF8CString (bytes);
+       if (urlString == 0) {
+               WebKit_win32.JSStringRelease (scriptString);
+               return false;
+       }
+       long evalResult = WebKit_win32.JSEvaluateScript (context, scriptString, 0, urlString, 0, null);
+       WebKit_win32.JSStringRelease (urlString);
+       WebKit_win32.JSStringRelease (scriptString);
+       return evalResult != 0;
+}
+
+@Override
+public boolean forward () {
+       int[] result = new int[1];
+       webView.goForward (result);
+       return result[0] != 0;
+}
+
+@Override
+public String getBrowserType () {
+       return "webkit"; //$NON-NLS-1$
+}
+
+@Override
+public String getText () {
+       long[] result = new long[1];
+       int hr = webView.mainFrame (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return EMPTY_STRING;
+       }
+       IWebFrame mainFrame = new IWebFrame (result[0]);
+       result[0] = 0;
+       hr = mainFrame.dataSource (result);
+       mainFrame.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return EMPTY_STRING;
+       }
+       IWebDataSource dataSource = new IWebDataSource (result[0]);
+       result[0] = 0;
+       hr = dataSource.representation (result);
+       dataSource.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return EMPTY_STRING;
+       }
+       IWebDocumentRepresentation representation = new IWebDocumentRepresentation (result[0]);
+       result[0] = 0;
+       hr = representation.documentSource (result);
+       representation.Release ();
+       if (hr != COM.S_OK || result[0] == 0) {
+               return EMPTY_STRING;
+       }
+       String source = extractBSTR (result[0]);
+       COM.SysFreeString (result[0]);
+       return source;
+}
+
+@Override
+public String getUrl () {
+       return webFrameLoadDelegate.getUrl ();
+}
+
+boolean handleEvent (Object[] arguments) {
+
+       /*
+       * DOM events are currently received by hooking DOM listeners
+       * in javascript that invoke this method via a BrowserFunction.
+       * Document.addListener is not implemented on WebKit on windows.
+       * The argument lists received here are:
+       *
+       * For key events:
+       *       argument 0: type (String)
+       *       argument 1: keyCode (Double)
+       *       argument 2: charCode (Double)
+       *       argument 3: altKey (Boolean)
+       *       argument 4: ctrlKey (Boolean)
+       *       argument 5: shiftKey (Boolean)
+       *       argument 6: metaKey (Boolean)
+       *       returns doit
+       *
+       * For mouse events
+       *       argument 0: type (String)
+       *       argument 1: screenX (Double)
+       *       argument 2: screenY (Double)
+       *       argument 3: detail (Double)
+       *       argument 4: button (Double)
+       *       argument 5: altKey (Boolean)
+       *       argument 6: ctrlKey (Boolean)
+       *       argument 7: shiftKey (Boolean)
+       *       argument 8: metaKey (Boolean)
+       *       argument 9: hasRelatedTarget (Boolean)
+       *       returns doit
+       */
+
+       String type = (String)arguments[0];
+       if (type.equals (DOMEVENT_KEYDOWN)) {
+               int keyCode = translateKey (((Double)arguments[1]).intValue ());
+               lastKeyCode = keyCode;
+               switch (keyCode) {
+                       case SWT.SHIFT:
+                       case SWT.CONTROL:
+                       case SWT.ALT:
+                       case SWT.CAPS_LOCK:
+                       case SWT.NUM_LOCK:
+                       case SWT.SCROLL_LOCK:
+                       case SWT.COMMAND:
+//                     case SWT.ESC:
+                       case SWT.TAB:
+                       case SWT.PAUSE:
+//                     case SWT.BS:
+                       case SWT.INSERT:
+                       case SWT.DEL:
+                       case SWT.HOME:
+                       case SWT.END:
+                       case SWT.PAGE_UP:
+                       case SWT.PAGE_DOWN:
+                       case SWT.ARROW_DOWN:
+                       case SWT.ARROW_UP:
+                       case SWT.ARROW_LEFT:
+                       case SWT.ARROW_RIGHT:
+                       case SWT.F1:
+                       case SWT.F2:
+                       case SWT.F3:
+                       case SWT.F4:
+                       case SWT.F5:
+                       case SWT.F6:
+                       case SWT.F7:
+                       case SWT.F8:
+                       case SWT.F9:
+                       case SWT.F10:
+                       case SWT.F11:
+                       case SWT.F12: {
+                               /* keypress events will not be received for these keys, so send KeyDowns for them now */
+
+                               Event keyEvent = new Event ();
+                               keyEvent.widget = browser;
+                               keyEvent.type = type.equals (DOMEVENT_KEYDOWN) ? SWT.KeyDown : SWT.KeyUp;
+                               keyEvent.keyCode = keyCode;
+                               switch (keyCode) {
+                                       case SWT.BS: keyEvent.character = SWT.BS; break;
+                                       case SWT.DEL: keyEvent.character = SWT.DEL; break;
+                                       case SWT.ESC: keyEvent.character = SWT.ESC; break;
+                                       case SWT.TAB: keyEvent.character = SWT.TAB; break;
+                               }
+                               lastCharCode = keyEvent.character;
+                               keyEvent.stateMask =
+                                       (((Boolean)arguments[3]).booleanValue () ? SWT.ALT : 0) |
+                                       (((Boolean)arguments[4]).booleanValue () ? SWT.CTRL : 0) |
+                                       (((Boolean)arguments[5]).booleanValue () ? SWT.SHIFT : 0) |
+                                       (((Boolean)arguments[6]).booleanValue () ? SWT.COMMAND : 0);
+                               keyEvent.stateMask &= ~keyCode;         /* remove current keydown if it's a state key */
+                               if (!sendKeyEvent (keyEvent) || browser.isDisposed ()) return false;
+                               break;
+                       }
+               }
+               return true;
+       }
+
+       if (type.equals (DOMEVENT_KEYPRESS)) {
+               /*
+               * if keydown could not determine a keycode for this key then it's a
+               * key for which key events are not sent (eg.- the Windows key)
+               */
+               if (lastKeyCode == 0) return true;
+
+               lastCharCode = ((Double)arguments[2]).intValue ();
+               if (((Boolean)arguments[4]).booleanValue () && (0 <= lastCharCode && lastCharCode <= 0x7F)) {
+                       if ('a' <= lastCharCode && lastCharCode <= 'z') lastCharCode -= 'a' - 'A';
+                       if (64 <= lastCharCode && lastCharCode <= 95) lastCharCode -= 64;
+               }
+
+               Event keyEvent = new Event ();
+               keyEvent.widget = browser;
+               keyEvent.type = SWT.KeyDown;
+               keyEvent.keyCode = lastKeyCode;
+               keyEvent.character = (char)lastCharCode;
+               keyEvent.stateMask =
+                       (((Boolean)arguments[3]).booleanValue () ? SWT.ALT : 0) |
+                       (((Boolean)arguments[4]).booleanValue () ? SWT.CTRL : 0) |
+                       (((Boolean)arguments[5]).booleanValue () ? SWT.SHIFT : 0) |
+                       (((Boolean)arguments[6]).booleanValue () ? SWT.COMMAND : 0);
+               return sendKeyEvent (keyEvent) && !browser.isDisposed ();
+       }
+
+       if (type.equals (DOMEVENT_KEYUP)) {
+               int keyCode = translateKey (((Double)arguments[1]).intValue ());
+               if (keyCode == 0) {
+                       /* indicates a key for which key events are not sent */
+                       return true;
+               }
+               if (keyCode != lastKeyCode) {
+                       /* keyup does not correspond to the last keydown */
+                       lastKeyCode = keyCode;
+                       lastCharCode = 0;
+               }
+
+               Event keyEvent = new Event ();
+               keyEvent.widget = browser;
+               keyEvent.type = SWT.KeyUp;
+               keyEvent.keyCode = lastKeyCode;
+               keyEvent.character = (char)lastCharCode;
+               keyEvent.stateMask =
+                       (((Boolean)arguments[3]).booleanValue () ? SWT.ALT : 0) |
+                       (((Boolean)arguments[4]).booleanValue () ? SWT.CTRL : 0) |
+                       (((Boolean)arguments[5]).booleanValue () ? SWT.SHIFT : 0) |
+                       (((Boolean)arguments[6]).booleanValue () ? SWT.COMMAND : 0);
+               switch (lastKeyCode) {
+                       case SWT.SHIFT:
+                       case SWT.CONTROL:
+                       case SWT.ALT:
+                       case SWT.COMMAND: {
+                               keyEvent.stateMask |= lastKeyCode;
+                       }
+               }
+               browser.notifyListeners (keyEvent.type, keyEvent);
+               lastKeyCode = lastCharCode = 0;
+               return keyEvent.doit && !browser.isDisposed ();
+       }
+
+       /* mouse events */
+
+       /*
+        * MouseOver and MouseOut events are fired any time the mouse enters or exits
+        * any element within the Browser.  To ensure that SWT events are only
+        * fired for mouse movements into or out of the Browser, do not fire an
+        * event if there is a related target element.
+        */
+       if (type.equals (DOMEVENT_MOUSEOVER) || type.equals (DOMEVENT_MOUSEOUT)) {
+               if (((Boolean)arguments[9]).booleanValue ()) return true;
+       }
+
+       /*
+        * The position of mouse events is received in screen-relative coordinates
+        * in order to handle pages with frames, since frames express their event
+        * coordinates relative to themselves rather than relative to their top-
+        * level page.  Convert screen-relative coordinates to be browser-relative.
+        */
+       Point position = new Point (((Double)arguments[1]).intValue (), ((Double)arguments[2]).intValue ());// Points or Pixles ?
+       position = browser.getDisplay ().map (null, browser, position);
+
+       Event mouseEvent = new Event ();
+       mouseEvent.widget = browser;
+       mouseEvent.x = position.x;
+       mouseEvent.y = position.y;
+       int mask =
+               (((Boolean)arguments[5]).booleanValue () ? SWT.ALT : 0) |
+               (((Boolean)arguments[6]).booleanValue () ? SWT.CTRL : 0) |
+               (((Boolean)arguments[7]).booleanValue () ? SWT.SHIFT : 0);
+       mouseEvent.stateMask = mask;
+
+       if (type.equals (DOMEVENT_MOUSEDOWN)) {
+               mouseEvent.type = SWT.MouseDown;
+               mouseEvent.count = ((Double)arguments[3]).intValue ();
+               mouseEvent.button = ((Double)arguments[4]).intValue ();
+               browser.notifyListeners (mouseEvent.type, mouseEvent);
+               if (browser.isDisposed ()) return true;
+               if (((Double)arguments[3]).intValue () == 2) {
+                       mouseEvent = new Event ();
+                       mouseEvent.type = SWT.MouseDoubleClick;
+                       mouseEvent.widget = browser;
+                       mouseEvent.x = position.x;
+                       mouseEvent.y = position.y;
+                       mouseEvent.stateMask = mask;
+                       mouseEvent.count = ((Double)arguments[3]).intValue ();
+                       mouseEvent.button = ((Double)arguments[4]).intValue ();
+                       browser.notifyListeners (mouseEvent.type, mouseEvent);
+               }
+               return true;
+       }
+
+       if (type.equals (DOMEVENT_MOUSEUP)) {
+               mouseEvent.type = SWT.MouseUp;
+               mouseEvent.count = ((Double)arguments[3]).intValue ();
+               mouseEvent.button = ((Double)arguments[4]).intValue ();
+               switch (mouseEvent.button) {
+                       case 1: mouseEvent.stateMask |= SWT.BUTTON1; break;
+                       case 2: mouseEvent.stateMask |= SWT.BUTTON2; break;
+                       case 3: mouseEvent.stateMask |= SWT.BUTTON3; break;
+                       case 4: mouseEvent.stateMask |= SWT.BUTTON4; break;
+                       case 5: mouseEvent.stateMask |= SWT.BUTTON5; break;
+               }
+       } else if (type.equals (DOMEVENT_MOUSEMOVE)) {
+               mouseEvent.type = SWT.MouseMove;
+       } else if (type.equals (DOMEVENT_MOUSEWHEEL)) {
+               mouseEvent.type = SWT.MouseWheel;
+               mouseEvent.count = ((Double)arguments[3]).intValue ();
+       } else if (type.equals (DOMEVENT_MOUSEOVER)) {
+               mouseEvent.type = SWT.MouseEnter;
+       } else if (type.equals (DOMEVENT_MOUSEOUT)) {
+               mouseEvent.type = SWT.MouseExit;
+               if (mouseEvent.x < 0) mouseEvent.x = -1;
+               if (mouseEvent.y < 0) mouseEvent.y = -1;
+       } else if (type.equals (DOMEVENT_DRAGSTART)) {
+               mouseEvent.type = SWT.DragDetect;
+               mouseEvent.button = ((Double)arguments[4]).intValue () + 1;
+               switch (mouseEvent.button) {
+                       case 1: mouseEvent.stateMask |= SWT.BUTTON1; break;
+                       case 2: mouseEvent.stateMask |= SWT.BUTTON2; break;
+                       case 3: mouseEvent.stateMask |= SWT.BUTTON3; break;
+                       case 4: mouseEvent.stateMask |= SWT.BUTTON4; break;
+                       case 5: mouseEvent.stateMask |= SWT.BUTTON5; break;
+               }
+       }
+
+       browser.notifyListeners (mouseEvent.type, mouseEvent);
+       return true;
+}
+
+@Override
+public boolean isBackEnabled () {
+       long[] address = new long[1];
+       int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, address);
+       if (hr != COM.S_OK || address[0] == 0) {
+               return false;
+       }
+       IWebIBActions webIBActions = new IWebIBActions (address[0]);
+       int[] result = new int[1];
+       webIBActions.canGoBack (webView.getAddress (), result);
+       webIBActions.Release ();
+       return result[0] != 0;
+}
+
+@Override
+public boolean isFocusControl () {
+       long hwndFocus = OS.GetFocus ();
+       return hwndFocus != 0 && hwndFocus == webViewWindowHandle;
+}
+
+@Override
+public boolean isForwardEnabled () {
+       long[] address = new long[1];
+       int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, address);
+       if (hr != COM.S_OK || address[0] == 0) {
+               return false;
+       }
+       IWebIBActions webIBActions = new IWebIBActions (address[0]);
+       int[] result = new int[1];
+       webIBActions.canGoForward (webView.getAddress (), result);
+       webIBActions.Release ();
+       return result[0] != 0;
+}
+
+void onDispose () {
+       /* Browser could have been disposed by one of the Dispose listeners */
+       if (!browser.isDisposed ()) {
+               /* invoke onbeforeunload handlers but don't prompt with message box */
+               if (!browser.isClosing) {
+                       webUIDelegate.prompt = false;
+                       shouldClose ();
+                       webUIDelegate.prompt = true;
+               }
+       }
+
+       Iterator<BrowserFunction> elements = functions.values().iterator ();
+       while (elements.hasNext ()) {
+               elements.next ().dispose (false);
+       }
+       functions = null;
+
+       eventFunction.dispose();
+       eventFunction = null;
+       C.free (webViewData);
+
+       webView.setPreferences (0);
+       webView.setHostWindow (0);
+       webView.setFrameLoadDelegate (0);
+       webView.setResourceLoadDelegate (0);
+       webView.setUIDelegate (0);
+       webView.setPolicyDelegate (0);
+       webView.setDownloadDelegate (0);
+       webView.Release();
+       webView = null;
+       webDownloadDelegate = null;
+       webFrameLoadDelegate = null;
+       webPolicyDelegate = null;
+       webResourceLoadDelegate = null;
+       webUIDelegate = null;
+       lastNavigateURL = null;
+}
+
+@Override
+public void refresh () {
+       webFrameLoadDelegate.html = null;
+       long[] result = new long[1];
+       int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return;
+       }
+       IWebIBActions webIBActions = new IWebIBActions (result[0]);
+       webIBActions.reload (webView.getAddress ());
+       webIBActions.Release ();
+}
+
+@Override
+boolean sendKeyEvent (Event event) {
+       /*
+        * browser.traverse() is called through dislay.translateTraversal() for all
+        * traversal types except SWT.TRAVERSE_MNEMONIC. So, override
+        * WebBrowser.sendKeyEvent() so that when it is called from handleEvent(),
+        * browser.traverse() is not called again.
+        */
+       boolean doit = true;
+       switch (event.keyCode) {
+               case SWT.ESC:
+               case SWT.CR:
+               case SWT.ARROW_DOWN:
+               case SWT.ARROW_RIGHT:
+               case SWT.ARROW_UP:
+               case SWT.ARROW_LEFT:
+               case SWT.TAB:
+               case SWT.PAGE_DOWN:
+               case SWT.PAGE_UP:
+                       break;
+               default: {
+                       if (translateMnemonics ()) {
+                               if (event.character != 0 && (event.stateMask & (SWT.ALT | SWT.CTRL)) == SWT.ALT) {
+                                       int traversal = SWT.TRAVERSE_MNEMONIC;
+                                       boolean oldEventDoit = event.doit;
+                                       event.doit = true;
+                                       doit = !browser.traverse (traversal, event);
+                                       event.doit = oldEventDoit;
+                               }
+                       }
+                       break;
+               }
+       }
+       if (doit) {
+               browser.notifyListeners (event.type, event);
+               doit = event.doit;
+       }
+       return doit;
+}
+
+@Override
+public boolean setText (String html, boolean trusted) {
+       /*
+       * If this.html is not null then the about:blank page is already being loaded,
+       * so no navigate is required.  Just set the html that is to be shown.
+       */
+       boolean blankLoading = webFrameLoadDelegate.html != null;
+       webFrameLoadDelegate.html = html;
+       untrustedText = !trusted;
+       if (blankLoading) return true;
+
+       long[] result = new long[1];
+       int hr = webView.mainFrame (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return false;
+       }
+       IWebFrame frame = new IWebFrame (result[0]);
+
+       result[0] = 0;
+       hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               frame.Release ();
+               return false;
+       }
+       IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
+
+       long urlString = createBSTR (ABOUT_BLANK);
+       hr = request.setURL (urlString);
+       COM.SysFreeString (urlString);
+
+       if (hr == COM.S_OK) {
+               hr = frame.loadRequest (request.getAddress ());
+       }
+       frame.Release ();
+       request.Release ();
+       return hr == COM.S_OK;
+}
+
+@Override
+public boolean setUrl (String url, String postData, String[] headers) {
+       if (url.length () == 0) return false;
+       /*
+       * WebKit attempts to open the exact url string that is passed to it and
+       * will not infer a protocol if it's not specified.  Detect the case of an
+       * invalid URL string and try to fix it by prepending an appropriate protocol.
+       */
+       try {
+               new URL (url);
+       } catch (MalformedURLException e) {
+               String testUrl = null;
+               if (new File (url).isAbsolute ()) {
+                       /* appears to be a local file */
+                       testUrl = PROTOCOL_FILE + url;
+               } else {
+                       testUrl = PROTOCOL_HTTP + url;
+               }
+               try {
+                       new URL (testUrl);
+                       url = testUrl;          /* adding the protocol made the url valid */
+               } catch (MalformedURLException e2) {
+                       /* adding the protocol did not make the url valid, so do nothing */
+               }
+       }
+       webFrameLoadDelegate.html = null;
+       lastNavigateURL = url;
+       long[] result = new long[1];
+       int hr = webView.mainFrame (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return false;
+       }
+       IWebFrame frame = new IWebFrame (result[0]);
+
+       result[0] = 0;
+       hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebMutableURLRequest, 0, WebKit_win32.IID_IWebMutableURLRequest, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               frame.Release ();
+               return false;
+       }
+       IWebMutableURLRequest request = new IWebMutableURLRequest (result[0]);
+
+       if (postData != null) { //TODO: POST
+//     webResourceLoadDelegate.postData = postData;
+//     long postString = createBSTR (POST);
+//             hr = request.setHTTPMethod (postString);
+//             COM.SysFreeString (postString);
+//
+//             result[0] = 0;
+//             hr = request.QueryInterface (WebKit_win32.IID_IWebMutableURLRequestPrivate, result);
+//             if (hr == COM.S_OK && result[0] != 0) {
+//                     IWebMutableURLRequestPrivate requestPrivate = new IWebMutableURLRequestPrivate(result[0]);
+//                     int cfRequest = requestPrivate.cfRequest();
+//                     byte[] bytes = postData.getBytes();
+//                     long data = WebKit_win32.CFDataCreate(0, bytes, bytes.length);
+//                     if (data != 0)WebKit_win32.CFURLRequestSetHTTPRequestBody(cfRequest, data);
+//
+//                     long dataGet = WebKit_win32.CFURLRequestCopyHTTPRequestBody(cfRequest);
+//                     int length = WebKit_win32.CFDataGetLength(dataGet);
+//                     long bytePtr = WebKit_win32.CFDataGetBytePtr(dataGet);
+//             }
+       }
+       hr = COM.S_OK;  //TODO: once post code is completed, remove this line if not required
+       if (headers != null) {
+               for (int i = 0; i < headers.length; i++) {
+                       String current = headers[i];
+                       if (current != null) {
+                               int index = current.indexOf (':');
+                               if (index != -1) {
+                                       String key = current.substring (0, index).trim ();
+                                       String value = current.substring (index + 1).trim ();
+                                       if (key.length () > 0 && value.length () > 0) {
+                                               long valueString = createBSTR (value);
+                                               if (key.equalsIgnoreCase (USER_AGENT)) {
+                                                       /*
+                                                       * Feature of WebKit.  The user-agent header value cannot be overridden
+                                                       * here.  The workaround is to temporarily set the value on the WebView
+                                                       * and then remove it after the loading of the request has begun.
+                                                       */
+                                                       hr = webView.setCustomUserAgent (valueString);
+                                               } else {
+                                                       long keyString = createBSTR (key);
+                                                       hr = request.setValue (valueString, keyString);
+                                                       COM.SysFreeString (keyString);
+                                               }
+                                               COM.SysFreeString (valueString);
+                                       }
+                               }
+                       }
+               }
+       }
+       if (hr == COM.S_OK) {
+               long urlString = createBSTR (url);
+               hr = request.setURL (urlString);
+               COM.SysFreeString (urlString);
+               if (hr == COM.S_OK) {
+                       hr = frame.loadRequest (request.getAddress ());
+               }
+               webView.setCustomUserAgent (0);
+       }
+       frame.Release ();
+       request.Release ();
+       return hr == COM.S_OK;
+}
+
+boolean shouldClose () {
+       if (!jsEnabled) return true;
+
+       long[] address = new long[1];
+       int hr = webView.QueryInterface (WebKit_win32.IID_IWebViewPrivate, address);
+       if (hr != COM.S_OK || address[0] == 0) {
+               return false;
+       }
+       IWebViewPrivate webViewPrivate = new IWebViewPrivate (address[0]);
+       int[] result = new int[1];
+       /* This function will fire the before unload handler for a page */
+       webViewPrivate.shouldClose (result);
+       webViewPrivate.Release ();
+       return result[0] != 0;
+}
+
+@Override
+public void stop () {
+       webFrameLoadDelegate.html = null;
+       long[] result = new long[1];
+       int hr = webView.QueryInterface (WebKit_win32.IID_IWebIBActions, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return;
+       }
+       IWebIBActions webIBActions = new IWebIBActions (result[0]);
+       webIBActions.stopLoading (webView.getAddress ());
+       webIBActions.Release ();
+}
+
+void initializeWebViewPreferences () {
+       /*
+        * Try to create separate preferences for each webview using different identifier for each webview.
+        * Otherwise all the webviews use the shared preferences.
+        */
+       long[] result = new long[1];
+       int hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebPreferences, 0, WebKit_win32.IID_IWebPreferences, result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               IWebPreferences preferences = new IWebPreferences (result[0]);
+               result[0] = 0;
+               hr = preferences.initWithIdentifier (createBSTR (String.valueOf (prefsIdentifier++)), result);
+               preferences.Release ();
+               if (hr == COM.S_OK && result[0] != 0) {
+                       preferences = new IWebPreferences (result[0]);
+                       webView.setPreferences (preferences.getAddress());
+                       preferences.Release ();
+               }
+       }
+
+       result[0] = 0;
+       hr = webView.preferences (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               IWebPreferences preferences = new IWebPreferences (result[0]);
+               preferences.setJavaScriptEnabled (1);
+               preferences.setJavaScriptCanOpenWindowsAutomatically (1);
+               preferences.setJavaEnabled (0); /* disable applets */
+               preferences.setTabsToLinks (1);
+               preferences.setFontSmoothing (WebKit_win32.FontSmoothingTypeWindows);
+               preferences.Release ();
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebPolicyDelegate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebPolicyDelegate.java
new file mode 100644 (file)
index 0000000..1c63764
--- /dev/null
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.webkit.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+class WebPolicyDelegate {
+       COMObject iWebPolicyDelegate;
+       int refCount = 0;
+
+       Browser browser;
+
+WebPolicyDelegate (Browser browser) {
+       createCOMInterfaces ();
+       this.browser = browser;
+}
+
+int AddRef () {
+       refCount++;
+       return refCount;
+}
+
+void createCOMInterfaces () {
+       iWebPolicyDelegate = new COMObject (new int[] {2, 0, 0, 5, 5, 5, 3}) {
+               @Override
+               public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
+               @Override
+               public long method1 (long[] args) {return AddRef ();}
+               @Override
+               public long method2 (long[] args) {return Release ();}
+               @Override
+               public long method3 (long[] args) {return decidePolicyForNavigationAction (args[0], args[1], args[2], args[3], args[4]);}
+               @Override
+               public long method4 (long[] args) {return decidePolicyForNewWindowAction (args[0], args[1], args[2], args[3], args[4]);}
+               @Override
+               public long method5 (long[] args) {return decidePolicyForMIMEType (args[0], args[1], args[2], args[3], args[4]);}
+               @Override
+               public long method6 (long[] args) {return unableToImplementPolicyWithError (args[0], args[1], args[2]);}
+       };
+}
+
+int decidePolicyForMIMEType (long webView, long type, long request, long frame, long listener) {
+       IWebView iwebView = new IWebView (webView);
+       int[] canShow = new int[1];
+       iwebView.canShowMIMEType (type, canShow);
+       IWebPolicyDecisionListener pdListener = new IWebPolicyDecisionListener (listener);
+       if (canShow[0] != 0) {
+               pdListener.use ();
+       } else {
+               pdListener.download ();
+       }
+       return COM.S_OK;
+}
+
+int decidePolicyForNavigationAction (long webView, long actionInformation, long request, long frame, long listener) {
+       IWebURLRequest iwebUrlRequest = new IWebURLRequest (request);
+       long[] result = new long[1];
+       int hr = iwebUrlRequest.URL (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       String url = WebKit.extractBSTR (result[0]);
+       COM.SysFreeString (result[0]);
+       IWebPolicyDecisionListener pdListener = new IWebPolicyDecisionListener (listener);
+       WebKit webKit = (WebKit)browser.webBrowser;
+       if (webKit.loadingText) {
+               /*
+                * WebKit is auto-navigating to about:blank in response to a loadHTMLString()
+                * invocation.  This navigate should always proceed without sending an event
+                * since it is preceded by an explicit navigate to about:blank in setText().
+                */
+               pdListener.use ();
+               return COM.S_OK;
+       }
+       if (url.length () == 0) {
+               pdListener.ignore ();
+               return COM.S_OK;
+       }
+       if (url.startsWith (WebKit.PROTOCOL_FILE) && webKit.getUrl ().startsWith (WebKit.ABOUT_BLANK) && webKit.untrustedText) {
+               /* indicates an attempt to access the local file system from untrusted content */
+               pdListener.ignore ();
+               return COM.S_OK;
+       }
+       /*
+        * If the URI indicates that the page is being rendered from memory
+        * (via setText()) then set it to about:blank to be consistent with IE.
+        */
+       if (url.equals (WebKit.URI_FILEROOT)) {
+               url = WebKit.ABOUT_BLANK;
+       } else {
+               int length = WebKit.URI_FILEROOT.length ();
+               if (url.startsWith (WebKit.URI_FILEROOT) && url.charAt (length) == '#') {
+                       url = WebKit.ABOUT_BLANK + url.substring (length);
+               }
+       }
+       LocationEvent newEvent = new LocationEvent (browser);
+       newEvent.display = browser.getDisplay ();
+       newEvent.widget = browser;
+       newEvent.location = url;
+       newEvent.doit = true;
+       LocationListener[] locationListeners = webKit.locationListeners;
+       if (locationListeners != null) {
+               for (int i = 0; i < locationListeners.length; i++) {
+                       locationListeners[i].changing (newEvent);
+               }
+       }
+       if (newEvent.doit) {
+               if (webKit.jsEnabled != webKit.jsEnabledOnNextPage) {
+                       webKit.jsEnabled = webKit.jsEnabledOnNextPage;
+                       IWebView view = new IWebView (webView);
+                       result[0] = 0;
+                       hr = view.preferences (result);
+                       if (hr == COM.S_OK && result[0] != 0) {
+                               IWebPreferences preferences = new IWebPreferences (result[0]);
+                               hr = preferences.setJavaScriptEnabled (webKit.jsEnabled ? 1 : 0);
+                               view.setPreferences (preferences.getAddress());
+                               preferences.Release ();
+                       }
+               }
+               pdListener.use ();
+               webKit.lastNavigateURL = url;
+       } else {
+               pdListener.ignore ();
+       }
+       return COM.S_OK;
+}
+
+int decidePolicyForNewWindowAction (long webView, long actionInformation, long request, long frameName, long listener) {
+       IWebPolicyDecisionListener pdListener = new IWebPolicyDecisionListener (listener);
+       pdListener.use();
+       return COM.S_OK;
+}
+
+protected void disposeCOMInterfaces () {
+       if (iWebPolicyDelegate != null) {
+               iWebPolicyDelegate.dispose ();
+               iWebPolicyDelegate = null;
+       }
+}
+
+long getAddress () {
+       return iWebPolicyDelegate.getAddress ();
+}
+
+int QueryInterface (long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID ();
+       COM.MoveMemory (guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebPolicyDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebPolicyDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebPolicyDelegate)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebPolicyDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebPolicyDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+int Release () {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces ();
+       }
+       return refCount;
+}
+
+int unableToImplementPolicyWithError (long webView, long error, long frame) {
+       if (browser.isDisposed ()) return COM.S_OK;
+
+       IWebError iweberror = new IWebError (error);
+       String failingURL = null;
+       long[] result = new long[1];
+       int hr = iweberror.failingURL (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               failingURL = WebKit.extractBSTR (result[0]);
+               COM.SysFreeString (result[0]);
+       }
+       result[0] = 0;
+       hr = iweberror.localizedDescription (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       String description = WebKit.extractBSTR (result[0]);
+       COM.SysFreeString (result[0]);
+
+       String message = failingURL != null ? failingURL + "\n\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$
+       message += Compatibility.getMessage ("SWT_Page_Load_Failed", new Object[] {description}); //$NON-NLS-1$
+       MessageBox messageBox = new MessageBox (browser.getShell (), SWT.OK | SWT.ICON_ERROR);
+       messageBox.setMessage (message);
+       messageBox.open ();
+       return COM.S_OK;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebResourceLoadDelegate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebResourceLoadDelegate.java
new file mode 100644 (file)
index 0000000..9924b68
--- /dev/null
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.webkit.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+class WebResourceLoadDelegate {
+       COMObject iWebResourceLoadDelegate;
+       int refCount = 0;
+
+       Browser browser;
+       String postData;
+
+WebResourceLoadDelegate (Browser browser) {
+       createCOMInterfaces ();
+       this.browser = browser;
+}
+
+int AddRef () {
+       refCount++;
+       return refCount;
+}
+
+void createCOMInterfaces () {
+       iWebResourceLoadDelegate = new COMObject (new int[] {2, 0, 0, 4, 6, 4, 4, 4, 4, 3, 4, 3}) {
+               @Override
+               public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
+               @Override
+               public long method1 (long[] args) {return AddRef ();}
+               @Override
+               public long method2 (long[] args) {return Release ();}
+               @Override
+               public long method3 (long[] args) {return identifierForInitialRequest (args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method4 (long[] args) {return willSendRequest (args[0], args[1], args[2], args[3], args[4], args[5]);}
+               @Override
+               public long method5 (long[] args) {return didReceiveAuthenticationChallenge (args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method6 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method7 (long[] args) {return COM.S_OK;}
+               @Override
+               public long method8 (long[] args) {return COM.S_OK;}
+               @Override
+               public long method9 (long[] args) {return COM.S_OK;}
+               @Override
+               public long method10 (long[] args) {return COM.S_OK;}
+               @Override
+               public long method11 (long[] args) {return COM.E_NOTIMPL;}
+       };
+}
+
+int didReceiveAuthenticationChallenge (long webView, long identifier, long challenge, long dataSource) {
+       IWebURLAuthenticationChallenge authenticationChallenge = new IWebURLAuthenticationChallenge (challenge);
+       /*
+        * Do not invoke the listeners if this challenge has been failed too many
+        * times because a listener is likely giving incorrect credentials repeatedly
+        * and will do so indefinitely.
+        */
+       int[] count = new int[1];
+       int hr = authenticationChallenge.previousFailureCount (count);
+       long[] result = new long[1];
+       if (hr == COM.S_OK && count[0] < 3) {
+               AuthenticationListener[] authenticationListeners = browser.webBrowser.authenticationListeners;
+               for (int i = 0; i < authenticationListeners.length; i++) {
+                       AuthenticationEvent event = new AuthenticationEvent (browser);
+                       event.location = ((WebKit)browser.webBrowser).lastNavigateURL;
+                       authenticationListeners[i].authenticate (event);
+                       if (!event.doit) {
+                               hr = authenticationChallenge.sender (result);
+                               if (hr != COM.S_OK || result[0] == 0) {
+                                       return COM.S_OK;
+                               }
+                               IWebURLAuthenticationChallengeSender challengeSender = new IWebURLAuthenticationChallengeSender (result[0]);
+                               challengeSender.cancelAuthenticationChallenge (challenge);
+                               challengeSender.Release ();
+                               return COM.S_OK;
+                       }
+                       if (event.user != null && event.password != null) {
+                               hr = authenticationChallenge.sender (result);
+                               if (hr != COM.S_OK || result[0] == 0) continue;
+
+                               IWebURLAuthenticationChallengeSender challengeSender = new IWebURLAuthenticationChallengeSender (result[0]);
+                               result[0] = 0;
+                               hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebURLCredential, 0, WebKit_win32.IID_IWebURLCredential, result);
+                               if (hr == COM.S_OK && result[0] != 0) {
+                                       IWebURLCredential credential = new IWebURLCredential (result[0]);
+                                       long user = WebKit.createBSTR (event.user);
+                                       long password = WebKit.createBSTR (event.password);
+                                       credential.initWithUser (user, password, WebKit_win32.WebURLCredentialPersistenceForSession);
+                                       challengeSender.useCredential (credential.getAddress (), challenge);
+                                       credential.Release ();
+                               }
+                               challengeSender.Release ();
+                               return COM.S_OK;
+                       }
+               }
+       }
+
+       /* show a custom authentication dialog */
+
+       String[] userReturn = new String[1], passwordReturn = new String[1];
+       result[0] = 0;
+       hr = authenticationChallenge.proposedCredential (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               IWebURLCredential proposedCredential = new IWebURLCredential(result[0]);
+               result[0] = 0;
+               hr = proposedCredential.user (result);
+               if (hr == COM.S_OK && result[0] != 0) {
+                       userReturn[0] = WebKit.extractBSTR (result[0]);
+                       COM.SysFreeString (result[0]);
+                       int[] value = new int[1];
+                       hr = proposedCredential.hasPassword (value);
+                       if (hr == COM.S_OK && value[0] != 0) {
+                               result[0] = 0;
+                               hr = proposedCredential.password (result);
+                               if (hr == COM.S_OK && result[0] != 0) {
+                                       passwordReturn[0] = WebKit.extractBSTR (result[0]);
+                                       COM.SysFreeString (result[0]);
+                               }
+                       }
+               }
+               proposedCredential.Release ();
+       }
+       result[0] = 0;
+       hr = authenticationChallenge.protectionSpace (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebURLProtectionSpace space = new IWebURLProtectionSpace (result[0]);
+       String host = null, realm = null;
+       result[0] = 0;
+       hr = space.host (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               host = WebKit.extractBSTR (result[0]);
+               COM.SysFreeString (result[0]);
+               int[] port = new int[1];
+               hr = space.port (port);
+               if (hr == COM.S_OK) {
+                       host += ":" + port[0]; //$NON-NLS-1$
+                       result[0] = 0;
+                       hr = space.realm (result);
+                       if (hr == COM.S_OK && result[0] != 0) {
+                               realm = WebKit.extractBSTR (result[0]);
+                               COM.SysFreeString (result[0]);
+                       }
+               }
+       }
+       space.Release ();
+       boolean response = showAuthenticationDialog (userReturn, passwordReturn, host, realm);
+       result[0] = 0;
+       hr = authenticationChallenge.sender (result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebURLAuthenticationChallengeSender challengeSender = new IWebURLAuthenticationChallengeSender (result[0]);
+       if (!response) {
+               challengeSender.cancelAuthenticationChallenge (challenge);
+               challengeSender.Release ();
+               return COM.S_OK;
+       }
+       result[0] = 0;
+       hr = WebKit_win32.WebKitCreateInstance (WebKit_win32.CLSID_WebURLCredential, 0, WebKit_win32.IID_IWebURLCredential, result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               IWebURLCredential credential = new IWebURLCredential (result[0]);
+               long user = WebKit.createBSTR (userReturn[0]);
+               long password = WebKit.createBSTR (passwordReturn[0]);
+               credential.initWithUser (user, password, WebKit_win32.WebURLCredentialPersistenceForSession);
+               challengeSender.useCredential (credential.getAddress (), challenge);
+               credential.Release ();
+       }
+       challengeSender.Release ();
+       return COM.S_OK;
+}
+
+void disposeCOMInterfaces () {
+       if (iWebResourceLoadDelegate != null) {
+               iWebResourceLoadDelegate.dispose ();
+               iWebResourceLoadDelegate = null;
+       }
+}
+
+long getAddress () {
+       return iWebResourceLoadDelegate.getAddress ();
+}
+
+int identifierForInitialRequest (long webView, long request, long dataSource, long identifier) {
+       if (browser.isDisposed ()) return COM.S_OK;
+
+       /* send progress event iff request is for top-level frame */
+
+       IWebDataSource source = new IWebDataSource (dataSource);
+       long[] frame = new long[1];
+       int hr = source.webFrame (frame);
+       if (hr != COM.S_OK || frame[0] == 0) {
+               return COM.S_OK;
+       }
+       new IWebFrame (frame[0]).Release ();
+       long[] mainFrame = new long[1];
+       IWebView iWebView = new IWebView (webView);
+       hr = iWebView.mainFrame (mainFrame);
+       if (hr != COM.S_OK || mainFrame[0] == 0) {
+               return COM.S_OK;
+       }
+       new IWebFrame (mainFrame[0]).Release ();
+       if (frame[0] == mainFrame[0]) {
+               long ptr = C.malloc (8);
+               iWebView.estimatedProgress (ptr);
+               double[] estimate = new double[1];
+               OS.MoveMemory (estimate, ptr, 8);
+               C.free (ptr);
+               int progress = (int)(estimate[0] * 100);
+
+               ProgressEvent progressEvent = new ProgressEvent (browser);
+               progressEvent.display = browser.getDisplay ();
+               progressEvent.widget = browser;
+               progressEvent.current = progress;
+               progressEvent.total = Math.max (progress, WebKit.MAX_PROGRESS);
+               ProgressListener[] progressListeners = browser.webBrowser.progressListeners;
+               for (int i = 0; i < progressListeners.length; i++) {
+                       progressListeners[i].changed (progressEvent);
+               }
+       }
+       return COM.S_OK;
+}
+
+int QueryInterface (long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID ();
+       COM.MoveMemory (guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebResourceLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebResourceLoadDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebResourceLoadDelegate)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebResourceLoadDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebResourceLoadDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+int Release () {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces ();
+       }
+       return refCount;
+}
+
+boolean showAuthenticationDialog (final String[] user, final String[] password, String host, String realm) {
+       Shell parent = browser.getShell ();
+       final Shell shell = new Shell (parent);
+       shell.setLayout (new GridLayout ());
+       String title = SWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$
+       shell.setText (title);
+       Label label = new Label (shell, SWT.WRAP);
+       label.setText (Compatibility.getMessage ("SWT_Enter_Username_and_Password", new String[] {realm, host})); //$NON-NLS-1$
+
+       GridData data = new GridData ();
+       Monitor monitor = browser.getMonitor ();
+       int maxWidth = monitor.getBounds ().width * 2 / 3;
+       int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       data.widthHint = Math.min (width, maxWidth);
+       data.horizontalAlignment = GridData.FILL;
+       data.grabExcessHorizontalSpace = true;
+       label.setLayoutData (data);
+
+       Label userLabel = new Label (shell, SWT.NONE);
+       userLabel.setText (SWT.getMessage ("SWT_Username")); //$NON-NLS-1$
+
+       final Text userText = new Text (shell, SWT.BORDER);
+       if (user[0] != null) userText.setText (user[0]);
+       data = new GridData ();
+       data.horizontalAlignment = GridData.FILL;
+       data.grabExcessHorizontalSpace = true;
+       userText.setLayoutData (data);
+
+       Label passwordLabel = new Label (shell, SWT.NONE);
+       passwordLabel.setText (SWT.getMessage ("SWT_Password")); //$NON-NLS-1$
+
+       final Text passwordText = new Text (shell, SWT.PASSWORD | SWT.BORDER);
+       if (password[0] != null) passwordText.setText (password[0]);
+       data = new GridData ();
+       data.horizontalAlignment = GridData.FILL;
+       data.grabExcessHorizontalSpace = true;
+       passwordText.setLayoutData (data);
+
+       final boolean[] result = new boolean[1];
+       final Button[] buttons = new Button[2];
+       Listener listener = event -> {
+               user[0] = userText.getText ();
+               password[0] = passwordText.getText ();
+               result[0] = event.widget == buttons[1];
+               shell.close ();
+       };
+
+       Composite composite = new Composite (shell, SWT.NONE);
+       data = new GridData ();
+       data.horizontalAlignment = GridData.END;
+       composite.setLayoutData (data);
+       composite.setLayout (new GridLayout (2, true));
+       buttons[0] = new Button (composite, SWT.PUSH);
+       buttons[0].setText (SWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+       buttons[0].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       buttons[0].addListener (SWT.Selection, listener);
+       buttons[1] = new Button (composite, SWT.PUSH);
+       buttons[1].setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
+       buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       buttons[1].addListener (SWT.Selection, listener);
+
+       shell.setDefaultButton (buttons[1]);
+       shell.pack ();
+       Rectangle parentSize = parent.getBounds ();
+       Rectangle shellSize = shell.getBounds ();
+       int x = parent.getLocation().x + (parentSize.width - shellSize.width) / 2;
+       int y = parent.getLocation().y + (parentSize.height - shellSize.height) / 2;
+       shell.setLocation (x, y);
+       shell.open ();
+       Display display = browser.getDisplay ();
+       while (!shell.isDisposed ()) {
+               if (!display.readAndDispatch ()) display.sleep ();
+       }
+
+       return result[0];
+}
+
+int willSendRequest (long webView, long identifier, long request, long redirectResponse, long dataSource, long newRequest) {
+       IWebURLRequest req = new IWebURLRequest (request);
+       long[] result = new long [1];
+       int hr = req.URL (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               String url = WebKit.extractBSTR (result[0]);
+               COM.SysFreeString (result[0]);
+               /*
+                * file://c|/ doesn't work on Webkit but works on other browsers.
+                * So change file:// to file:/// to be consistent
+                */
+               if (url.startsWith (WebKit.PROTOCOL_FILE) && !url.startsWith (WebKit.URI_FILEROOT)) {
+                       int length = WebKit.PROTOCOL_FILE.length ();
+                       url = WebKit.URI_FILEROOT + url.substring (length);
+                       result[0] = 0;
+
+                       hr = req.mutableCopy (result);
+                       if (hr == COM.S_OK && result[0] != 0) {
+                               IWebMutableURLRequest mReq = new IWebMutableURLRequest (result[0]);
+                               long urlString = WebKit.createBSTR (url);
+                               mReq.setURL (urlString);
+                               OS.MoveMemory (newRequest, new long[] {mReq.getAddress ()}, C.PTR_SIZEOF);
+                               return COM.S_OK;
+                       }
+               }
+       }
+       req.AddRef ();
+       OS.MoveMemory (newRequest, new long[] {request}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebSite.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebSite.java
new file mode 100644 (file)
index 0000000..4fc0d9f
--- /dev/null
@@ -0,0 +1,994 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.ole.win32.*;
+import org.eclipse.swt.widgets.*;
+
+class WebSite extends OleControlSite {
+       COMObject iDocHostUIHandler;
+       COMObject iDocHostShowUI;
+       COMObject iServiceProvider;
+       COMObject iInternetSecurityManager;
+       COMObject iOleCommandTarget;
+       COMObject iAuthenticate;
+       COMObject iDispatch;
+       boolean ignoreNextMessage, ignoreAllMessages;
+       boolean isForceTrusted;
+       Boolean canExecuteApplets;
+
+       static final int OLECMDID_SHOWSCRIPTERROR = 40;
+       static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
+       static final String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
+
+public WebSite(Composite parent, int style, String progId) {
+       super(parent, style, progId);
+}
+
+@Override
+protected void createCOMInterfaces () {
+       super.createCOMInterfaces();
+       iDocHostUIHandler = new COMObject(new int[]{2, 0, 0, 4, 1, 5, 0, 0, 1, 1, 1, 3, 3, 2, 2, 1, 3, 2}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return ShowContextMenu((int)args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method4(long[] args) {return GetHostInfo(args[0]);}
+               @Override
+               public long method5(long[] args) {return ShowUI((int)args[0], args[1], args[2], args[3], args[4]);}
+               @Override
+               public long method6(long[] args) {return HideUI();}
+               @Override
+               public long method7(long[] args) {return UpdateUI();}
+               @Override
+               public long method8(long[] args) {return EnableModeless((int)args[0]);}
+               @Override
+               public long method9(long[] args) {return OnDocWindowActivate((int)args[0]);}
+               @Override
+               public long method10(long[] args) {return OnFrameWindowActivate((int)args[0]);}
+               @Override
+               public long method11(long[] args) {return ResizeBorder(args[0], args[1], (int)args[2]);}
+               @Override
+               public long method12(long[] args) {return TranslateAccelerator(args[0], args[1], (int)args[2]);}
+               @Override
+               public long method13(long[] args) {return GetOptionKeyPath(args[0], (int)args[1]);}
+               @Override
+               public long method14(long[] args) {return GetDropTarget(args[0], args[1]);}
+               @Override
+               public long method15(long[] args) {return GetExternal(args[0]);}
+               @Override
+               public long method16(long[] args) {return TranslateUrl((int)args[0], args[1], args[2]);}
+               @Override
+               public long method17(long[] args) {return FilterDataObject(args[0], args[1]);}
+       };
+       iDocHostShowUI = new COMObject(new int[]{2, 0, 0, 7, 6}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return ShowMessage(args[0], args[1], args[2], (int)args[3], args[4], (int)args[5], args[6]);}
+               @Override
+               public long method4(long[] args) {return ShowHelp(args[0], args[1], (int)args[2], (int)args[3], args[4], args[5]);}
+       };
+       iServiceProvider = new COMObject(new int[]{2, 0, 0, 3}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return QueryService(args[0], args[1], args[2]);}
+       };
+       iInternetSecurityManager = new COMObject(new int[]{2, 0, 0, 1, 1, 3, 4, 8, 7, 3, 3}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return SetSecuritySite(args[0]);}
+               @Override
+               public long method4(long[] args) {return GetSecuritySite(args[0]);}
+               @Override
+               public long method5(long[] args) {return MapUrlToZone(args[0], args[1], (int)args[2]);}
+               @Override
+               public long method6(long[] args) {return GetSecurityId(args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method7(long[] args) {return ProcessUrlAction(args[0], (int)args[1], args[2], (int)args[3], args[4], (int)args[5], (int)args[6], (int)args[7]);}
+               @Override
+               public long method8(long[] args) {return QueryCustomPolicy(args[0], args[1], args[2], args[3], args[4], (int)args[5], (int)args[6]);}
+               @Override
+               public long method9(long[] args) {return SetZoneMapping((int)args[0], args[1], (int)args[2]);}
+               @Override
+               public long method10(long[] args) {return GetZoneMappings((int)args[0], args[1], (int)args[2]);}
+       };
+       iOleCommandTarget = new COMObject(new int[]{2, 0, 0, 4, 5}) {
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return QueryStatus(args[0], (int)args[1], args[2], args[3]);}
+               @Override
+               public long method4(long[] args) {return Exec(args[0], (int)args[1], (int)args[2], args[3], args[4]);}
+       };
+       iAuthenticate = new COMObject(new int[]{2, 0, 0, 3}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return Authenticate(args[0], args[1], args[2]);}
+       };
+       iDispatch = new COMObject (new int[] {2, 0, 0, 1, 3, 5, 8}) {
+               @Override
+               public long method0 (long[] args) {
+                       /*
+                        * IDispatch check must be done here instead of in the shared QueryInterface
+                        * implementation, to avoid answering the superclass's IDispatch implementation
+                        * instead of this one.
+                        */
+                       GUID guid = new GUID ();
+                       COM.MoveMemory (guid, args[0], GUID.sizeof);
+                       if (COM.IsEqualGUID (guid, COM.IIDIDispatch)) {
+                               OS.MoveMemory (args[1], new long[] {iDispatch.getAddress ()}, C.PTR_SIZEOF);
+                               AddRef ();
+                               return COM.S_OK;
+                       }
+                       return QueryInterface (args[0], args[1]);
+               }
+               @Override
+               public long method1 (long[] args) {return AddRef ();}
+               @Override
+               public long method2 (long[] args) {return Release ();}
+               @Override
+               public long method3 (long[] args) {return GetTypeInfoCount (args[0]);}
+               @Override
+               public long method4 (long[] args) {return GetTypeInfo ((int)args[0], (int)args[1], args[2]);}
+               @Override
+               public long method5 (long[] args) {return GetIDsOfNames ((int)args[0], args[1], (int)args[2], (int)args[3], args[4]);}
+               @Override
+               public long method6 (long[] args) {return Invoke ((int)args[0], (int)args[1], (int)args[2], (int)args[3], args[4], args[5], args[6], args[7]);}
+       };
+}
+
+@Override
+protected void disposeCOMInterfaces() {
+       super.disposeCOMInterfaces();
+       if (iDocHostUIHandler != null) {
+               iDocHostUIHandler.dispose();
+               iDocHostUIHandler = null;
+       }
+       if (iDocHostShowUI != null) {
+               iDocHostShowUI.dispose();
+               iDocHostShowUI = null;
+       }
+       if (iServiceProvider != null) {
+               iServiceProvider.dispose();
+               iServiceProvider = null;
+       }
+       if (iInternetSecurityManager != null) {
+               iInternetSecurityManager.dispose();
+               iInternetSecurityManager = null;
+       }
+       if (iOleCommandTarget != null) {
+               iOleCommandTarget.dispose();
+               iOleCommandTarget = null;
+       }
+       if (iAuthenticate != null) {
+               iAuthenticate.dispose();
+               iAuthenticate = null;
+       }
+       if (iDispatch != null) {
+               iDispatch.dispose ();
+               iDispatch = null;
+       }
+}
+
+@Override
+protected int AddRef() {
+       /* Workaround for javac 1.1.8 bug */
+       return super.AddRef();
+}
+
+@Override
+protected int QueryInterface(long riid, long ppvObject) {
+       int result = super.QueryInterface(riid, ppvObject);
+       if (result == COM.S_OK) return result;
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIDocHostUIHandler)) {
+               OS.MoveMemory(ppvObject, new long[] {iDocHostUIHandler.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIDocHostShowUI)) {
+               OS.MoveMemory(ppvObject, new long[] {iDocHostShowUI.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) {
+               OS.MoveMemory(ppvObject, new long[] {iServiceProvider.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) {
+               OS.MoveMemory(ppvObject, new long[] {iInternetSecurityManager.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIOleCommandTarget)) {
+               OS.MoveMemory(ppvObject, new long[] {iOleCommandTarget.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+/* IDocHostUIHandler */
+
+int EnableModeless(int EnableModeless) {
+       return COM.E_NOTIMPL;
+}
+
+int FilterDataObject(long pDO, long ppDORet) {
+       return COM.E_NOTIMPL;
+}
+
+int GetDropTarget(long pDropTarget, long ppDropTarget) {
+       return COM.E_NOTIMPL;
+}
+
+int GetExternal(long ppDispatch) {
+       OS.MoveMemory (ppDispatch, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
+       AddRef ();
+       return COM.S_OK;
+}
+
+int GetHostInfo(long pInfo) {
+       int info = IE.DOCHOSTUIFLAG_THEME | IE.DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION | IE.DOCHOSTUIFLAG_DPI_AWARE;
+       IE browser = (IE)((Browser)getParent().getParent()).webBrowser;
+       if ((browser.style & SWT.BORDER) == 0) info |= IE.DOCHOSTUIFLAG_NO3DOUTERBORDER;
+       DOCHOSTUIINFO uiInfo = new DOCHOSTUIINFO ();
+       OS.MoveMemory(uiInfo, pInfo, DOCHOSTUIINFO.sizeof);
+       uiInfo.dwFlags = info;
+       OS.MoveMemory(pInfo, uiInfo, DOCHOSTUIINFO.sizeof);
+       return COM.S_OK;
+}
+
+int GetOptionKeyPath(long pchKey, int dw) {
+       return COM.E_NOTIMPL;
+}
+
+int HideUI() {
+       return COM.E_NOTIMPL;
+}
+
+int OnDocWindowActivate(int fActivate) {
+       return COM.E_NOTIMPL;
+}
+
+int OnFrameWindowActivate(int fActivate) {
+       return COM.E_NOTIMPL;
+}
+
+@Override
+protected int Release() {
+       /* Workaround for javac 1.1.8 bug */
+       return super.Release();
+}
+
+int ResizeBorder(long prcBorder, long pUIWindow, int fFrameWindow) {
+       return COM.E_NOTIMPL;
+}
+
+int ShowContextMenu(int dwID, long ppt, long pcmdtReserved, long pdispReserved) {
+       Browser browser = (Browser)getParent().getParent();
+       Event event = new Event();
+       POINT pt = new POINT();
+       OS.MoveMemory(pt, ppt, POINT.sizeof);
+       pt.x = DPIUtil.autoScaleDown(pt.x); // To Points
+       pt.y = DPIUtil.autoScaleDown(pt.y); // To Points
+       event.x = pt.x;
+       event.y = pt.y;
+       browser.notifyListeners(SWT.MenuDetect, event);
+       if (!event.doit) return COM.S_OK;
+       Menu menu = browser.getMenu();
+       if (menu != null && !menu.isDisposed ()) {
+               if (pt.x != event.x || pt.y != event.y) {
+                       menu.setLocation (event.x, event.y);
+               }
+               menu.setVisible (true);
+               return COM.S_OK;
+       }
+       /* Show default IE popup menu */
+       return COM.S_FALSE;
+}
+
+int ShowUI(int dwID, long pActiveObject, long pCommandTarget, long pFrame, long pDoc) {
+       return COM.S_FALSE;
+}
+
+int TranslateAccelerator(long lpMsg, long pguidCmdGroup, int nCmdID) {
+       /*
+       * Feature in Internet Explorer.  By default the embedded Internet Explorer control runs
+       * the Internet Explorer shortcuts (e.g. Ctrl+F for Find).  This overrides the shortcuts
+       * defined by SWT.  The workaround is to forward the accelerator keys to the parent window
+       * and have Internet Explorer ignore the ones handled by the parent window.
+       */
+       Menu menubar = getShell().getMenuBar();
+       if (menubar != null && !menubar.isDisposed() && menubar.isEnabled()) {
+               Shell shell = menubar.getShell();
+               long hwnd = shell.handle;
+               long hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+               if (hAccel != 0) {
+                       MSG msg = new MSG();
+                       OS.MoveMemory(msg, lpMsg, MSG.sizeof);
+                       if (OS.TranslateAccelerator(hwnd, hAccel, msg) != 0) return COM.S_OK;
+               }
+       }
+       /*
+       * By default the IE shortcuts are run.  However, the shortcuts below should not run
+       * in this context.  The workaround is to block IE from handling these shortcuts by
+       * answering COM.S_OK.
+       *
+       * - F5 causes a refresh, which is not appropriate when rendering HTML from memory
+       * - CTRL+L and CTRL+O show an Open Location dialog in IE8, which is undesirable and
+       * can crash in some contexts
+       * - CTRL+N opens a standalone IE, which is undesirable and can crash in some contexts
+       */
+       int result = COM.S_FALSE;
+       MSG msg = new MSG();
+       OS.MoveMemory(msg, lpMsg, MSG.sizeof);
+       if (msg.message == OS.WM_KEYDOWN) {
+               switch ((int)msg.wParam) {
+                       case OS.VK_F5:
+                               OleAutomation auto = new OleAutomation(this);
+                               int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
+                               Variant pVarResult = auto.getProperty(rgdispid[0]);
+                               auto.dispose();
+                               if (pVarResult != null) {
+                                       if (pVarResult.getType() == OLE.VT_BSTR) {
+                                               String url = pVarResult.getString();
+                                               if (url.equals(IE.ABOUT_BLANK)) result = COM.S_OK;
+                                       }
+                                       pVarResult.dispose();
+                               }
+                               break;
+                       case OS.VK_TAB:
+                               /*
+                                * Do not interfere with tab traversal since it's not known
+                                * if it will be within IE or out to another Control.
+                                */
+                               break;
+                       case OS.VK_UP:
+                       case OS.VK_DOWN:
+                       case OS.VK_LEFT:
+                       case OS.VK_RIGHT:
+                       case OS.VK_HOME:
+                       case OS.VK_END:
+                       case OS.VK_PRIOR:
+                       case OS.VK_NEXT:
+                               /* Do not translate/consume IE's keys for scrolling content. */
+                               break;
+                       case OS.VK_SPACE:
+                       case OS.VK_BACK:
+                       case OS.VK_RETURN:
+                               /*
+                                * Translating OS.VK_BACK, OS.VK_RETURN or OS.VK_SPACE results in the native
+                                * control handling them twice (eg.- inserting two lines instead of one). So
+                                * these keys are not translated here, and instead are explicitly handled
+                                * in the keypress handler.
+                                */
+                               break;
+                       case OS.VK_L:
+                       case OS.VK_N:
+                       case OS.VK_O:
+                               if (OS.GetKeyState (OS.VK_CONTROL) < 0 && OS.GetKeyState (OS.VK_MENU) >= 0 && OS.GetKeyState (OS.VK_SHIFT) >= 0) {
+                                       if (msg.wParam == OS.VK_N || IE.IEVersion >= 8) {
+                                               frame.setData(CONSUME_KEY, "false"); //$NON-NLS-1$
+                                               result = COM.S_OK;
+                                               break;
+                                       }
+                               }
+                               // FALL THROUGH
+                       default:
+                               OS.TranslateMessage(msg);
+                               frame.setData(CONSUME_KEY, "true"); //$NON-NLS-1$
+                               break;
+               }
+       }
+
+       switch (msg.message) {
+               case OS.WM_KEYDOWN:
+               case OS.WM_KEYUP: {
+                       boolean isAccent = false;
+                       switch ((int)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: {
+                                       int mapKey = OS.MapVirtualKey ((int)msg.wParam, 2);
+                                       if (mapKey != 0) {
+                                               isAccent = (mapKey & 0x80000000) != 0;
+                                               if (!isAccent) {
+                                                       for (int i=0; i<ACCENTS.length; i++) {
+                                                               int value = OS.VkKeyScan (ACCENTS [i]);
+                                                               if (value != -1 && (value & 0xFF) == msg.wParam) {
+                                                                       int state = value >> 8;
+                                                                       if ((OS.GetKeyState (OS.VK_SHIFT) < 0) == ((state & 0x1) != 0) &&
+                                                                               (OS.GetKeyState (OS.VK_CONTROL) < 0) == ((state & 0x2) != 0) &&
+                                                                               (OS.GetKeyState (OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
+                                                                                       if ((state & 0x7) != 0) isAccent = true;
+                                                                                       break;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               }
+                       }
+                       if (isAccent) result = COM.S_OK;
+               }
+       }
+       return result;
+}
+
+int TranslateUrl(int dwTranslate, long pchURLIn, long ppchURLOut) {
+       return COM.E_NOTIMPL;
+}
+
+int UpdateUI() {
+       return COM.E_NOTIMPL;
+}
+
+/* IDocHostShowUI */
+
+int ShowMessage(long hwnd, long lpstrText, long lpstrCaption, int dwType, long lpstrHelpFile, int dwHelpContext, long plResult) {
+       boolean ignore = ignoreNextMessage || ignoreAllMessages;
+       ignoreNextMessage = false;
+       return ignore ? COM.S_OK : COM.S_FALSE;
+}
+
+int ShowHelp(long hwnd, long pszHelpFile, int uCommand, int dwData, long pt, long pDispatchObjectHit) {
+       Browser browser = (Browser)getParent().getParent();
+       Event event = new Event();
+       event.type = SWT.Help;
+       event.display = getDisplay();
+       event.widget = browser;
+       Shell shell = browser.getShell();
+       Control control = browser;
+       do {
+               if (control.isListening(SWT.Help)) {
+                       control.notifyListeners(SWT.Help, event);
+                       break;
+               }
+               if (control == shell) break;
+               control = control.getParent();
+       } while (true);
+       return COM.S_OK;
+}
+
+/* IServiceProvider */
+
+int QueryService(long guidService, long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) {
+               OS.MoveMemory(ppvObject, new long[] {iInternetSecurityManager.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIAuthenticate)) {
+               OS.MoveMemory(ppvObject, new long[] {iAuthenticate.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+/* IInternetSecurityManager */
+
+int SetSecuritySite(long pSite) {
+       return IE.INET_E_DEFAULT_ACTION;
+}
+
+int GetSecuritySite(long ppSite) {
+       return IE.INET_E_DEFAULT_ACTION;
+}
+
+int MapUrlToZone(long pwszUrl, long pdwZone, int dwFlags) {
+       /*
+       * Feature in IE.  HTML rendered in memory does not enable local links
+       * but the same HTML document loaded through a local file is permitted
+       * to follow local links.  The workaround is to return URLZONE_INTRANET
+       * instead of the default value URLZONE_LOCAL_MACHINE.
+       */
+       if (isForceTrusted) {
+               OS.MoveMemory(pdwZone, new int[] {IE.URLZONE_INTRANET}, 4);
+               return COM.S_OK;
+       }
+       return IE.INET_E_DEFAULT_ACTION;
+}
+
+int GetSecurityId(long pwszUrl, long pbSecurityId, long pcbSecurityId, long dwReserved) {
+       return IE.INET_E_DEFAULT_ACTION;
+}
+
+int ProcessUrlAction(long pwszUrl, int dwAction, long pPolicy, int cbPolicy, long pContext, int cbContext, int dwFlags, int dwReserved) {
+       ignoreNextMessage = false;
+
+       /*
+       * If the current page is about:blank and is trusted then
+       * override default zone elevation settings to allow the action.
+       */
+       if (dwAction == IE.URLACTION_FEATURE_ZONE_ELEVATION) {
+               IE ie = (IE)((Browser)getParent().getParent()).webBrowser;
+               if (ie.auto != null && ie._getUrl().startsWith(IE.ABOUT_BLANK) && !ie.untrustedText) {
+                       if (cbPolicy >= 4) OS.MoveMemory(pPolicy, new int[] {IE.URLPOLICY_ALLOW}, 4);
+                       return COM.S_OK;
+               }
+       }
+
+       int policy = IE.INET_E_DEFAULT_ACTION;
+
+       if (dwAction >= IE.URLACTION_JAVA_MIN && dwAction <= IE.URLACTION_JAVA_MAX) {
+               if (canExecuteApplets ()) {
+                       policy = IE.URLPOLICY_JAVA_LOW;
+               } else {
+                       policy = IE.URLPOLICY_JAVA_PROHIBIT;
+                       ignoreNextMessage = true;
+               }
+       }
+       if (dwAction == IE.URLACTION_ACTIVEX_RUN && pContext != 0) {
+               GUID guid = new GUID();
+               COM.MoveMemory(guid, pContext, GUID.sizeof);
+               if (COM.IsEqualGUID(guid, COM.IIDJavaBeansBridge) && !canExecuteApplets ()) {
+                       policy = IE.URLPOLICY_DISALLOW;
+                       ignoreNextMessage = true;
+               }
+               if (COM.IsEqualGUID(guid, COM.IIDShockwaveActiveXControl)) {
+                       policy = IE.URLPOLICY_DISALLOW;
+                       ignoreNextMessage = true;
+               }
+       }
+       if (dwAction == IE.URLACTION_SCRIPT_RUN) {
+               IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
+               policy = browser.jsEnabled ? IE.URLPOLICY_ALLOW : IE.URLPOLICY_DISALLOW;
+       }
+
+       if (policy == IE.INET_E_DEFAULT_ACTION) return IE.INET_E_DEFAULT_ACTION;
+       if (cbPolicy >= 4) OS.MoveMemory(pPolicy, new int[] {policy}, 4);
+       return policy == IE.URLPOLICY_ALLOW ? COM.S_OK : COM.S_FALSE;
+}
+
+boolean canExecuteApplets () {
+       /*
+       * Executing an applet in embedded IE will crash if IE's Java plug-in
+       * launches its jre in IE's process, because this new jre conflicts
+       * with the one running eclipse.  These cases need to be avoided by
+       * vetoing the running of applets.
+       *
+       * However as of Sun jre 1.6u10, applets can be launched in a separate
+       * process, which avoids the conflict with the jre running eclipse.
+       * Therefore if this condition is detected, and if the required jar
+       * libraries are available, then applets can be executed.
+       */
+
+       /*
+       * executing applets with IE6 embedded can crash, so do not
+       * attempt this if the version is less than IE7
+       */
+       if (IE.IEVersion < 7) return false;
+
+       if (canExecuteApplets == null) {
+               WebBrowser webBrowser = ((Browser)getParent ().getParent ()).webBrowser;
+               String script = "try {var element = document.createElement('object');element.classid='clsid:CAFEEFAC-DEC7-0000-0000-ABCDEFFEDCBA';return element.object.isPlugin2();} catch (err) {};return false;"; //$NON-NLS-1$
+               canExecuteApplets = ((Boolean)webBrowser.evaluate (script));
+               if (canExecuteApplets.booleanValue ()) {
+                       try {
+                               Class.forName ("sun.plugin2.main.server.IExplorerPlugin"); /* plugin.jar */     //$NON-NLS-1$
+                               Class.forName ("com.sun.deploy.services.Service"); /* deploy.jar */     //$NON-NLS-1$
+                               Class.forName ("com.sun.javaws.Globals"); /* javaws.jar */      //$NON-NLS-1$
+                       } catch (ClassNotFoundException e) {
+                               /* one or more of the required jar libraries are not available */
+                               canExecuteApplets = Boolean.FALSE;
+                       }
+               }
+       }
+       return canExecuteApplets.booleanValue ();
+}
+
+int QueryCustomPolicy(long pwszUrl, long guidKey, long ppPolicy, long pcbPolicy, long pContext, int cbContext, int dwReserved) {
+       return IE.INET_E_DEFAULT_ACTION;
+}
+
+int SetZoneMapping(int dwZone, long lpszPattern, int dwFlags) {
+       return IE.INET_E_DEFAULT_ACTION;
+}
+
+int GetZoneMappings(int dwZone, long ppenumString, int dwFlags) {
+       return COM.E_NOTIMPL;
+}
+
+/* IOleCommandTarget */
+int QueryStatus(long pguidCmdGroup, int cCmds, long prgCmds, long pCmdText) {
+       return COM.E_NOTSUPPORTED;
+}
+
+int Exec(long pguidCmdGroup, int nCmdID, int nCmdExecOpt, long pvaIn, long pvaOut) {
+       if (pguidCmdGroup != 0) {
+               GUID guid = new GUID();
+               COM.MoveMemory(guid, pguidCmdGroup, GUID.sizeof);
+
+               /*
+               * If a javascript error occurred then suppress IE's default script error dialog.
+               */
+               if (COM.IsEqualGUID(guid, COM.CGID_DocHostCommandHandler)) {
+                       if (nCmdID == OLECMDID_SHOWSCRIPTERROR) return COM.S_OK;
+               }
+
+               /*
+               * Bug in Internet Explorer.  OnToolBar TRUE is also fired when any of the
+               * address bar or menu bar are requested but not the tool bar.  A workaround
+               * has been posted by a Microsoft developer on the public webbrowser_ctl
+               * newsgroup. The workaround is to implement the IOleCommandTarget interface
+               * to test the argument of an undocumented command.
+               */
+               if (nCmdID == 1 && COM.IsEqualGUID(guid, COM.CGID_Explorer) && ((nCmdExecOpt & 0xFFFF) == 0xA)) {
+                       IE browser = (IE)((Browser)getParent().getParent()).webBrowser;
+                       browser.toolBar = (nCmdExecOpt & 0xFFFF0000) != 0;
+               }
+       }
+       return COM.E_NOTSUPPORTED;
+}
+
+/* IAuthenticate */
+
+int Authenticate (long hwnd, long szUsername, long szPassword) {
+       IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
+       for (int i = 0; i < browser.authenticationListeners.length; i++) {
+               AuthenticationEvent event = new AuthenticationEvent (browser.browser);
+               event.location = browser.lastNavigateURL;
+               browser.authenticationListeners[i].authenticate (event);
+               if (!event.doit) return COM.E_ACCESSDENIED;
+               if (event.user != null && event.password != null) {
+                       TCHAR user = new TCHAR (0, event.user, true);
+                       int size = user.length () * TCHAR.sizeof;
+                       long userPtr = OS.CoTaskMemAlloc (size);
+                       OS.MoveMemory (userPtr, user, size);
+                       TCHAR password = new TCHAR (0, event.password, true);
+                       size = password.length () * TCHAR.sizeof;
+                       long passwordPtr = OS.CoTaskMemAlloc (size);
+                       OS.MoveMemory (passwordPtr, password, size);
+                       C.memmove (hwnd, new long[] {0}, C.PTR_SIZEOF);
+                       C.memmove (szUsername, new long[] {userPtr}, C.PTR_SIZEOF);
+                       C.memmove (szPassword, new long[] {passwordPtr}, C.PTR_SIZEOF);
+                       return COM.S_OK;
+               }
+       }
+
+       /* no listener handled the challenge, so defer to the native dialog */
+       C.memmove (hwnd, new long[] {getShell().handle}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+
+/* IDispatch */
+
+int GetTypeInfoCount (long pctinfo) {
+       C.memmove (pctinfo, new int[] {0}, 4);
+       return COM.S_OK;
+}
+
+int GetTypeInfo (int iTInfo, int lcid, long ppTInfo) {
+       return COM.S_OK;
+}
+
+int GetIDsOfNames (int riid, long rgszNames, int cNames, int lcid, long rgDispId) {
+       long[] ptr = new long[1];
+       OS.MoveMemory (ptr, rgszNames, C.PTR_SIZEOF);
+       int length = OS.wcslen (ptr[0]);
+       char[] buffer = new char[length];
+       OS.MoveMemory (buffer, ptr[0], length * 2);
+       String functionName = String.valueOf (buffer);
+       int result = COM.S_OK;
+       int[] ids = new int[cNames];    /* DISPIDs */
+       if (functionName.equals ("callJava")) { //$NON-NLS-1$
+               for (int i = 0; i < cNames; i++) {
+                       ids[i] = i + 1;
+               }
+       } else {
+               result = COM.DISP_E_UNKNOWNNAME;
+               for (int i = 0; i < cNames; i++) {
+                       ids[i] = COM.DISPID_UNKNOWN;
+               }
+       }
+       OS.MoveMemory (rgDispId, ids, cNames * 4);
+       return result;
+}
+
+int Invoke (int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr) {
+       IE ie = (IE)((Browser)getParent ().getParent ()).webBrowser;
+       Map<Integer, BrowserFunction> functions = ie.functions;
+       if (functions == null) {
+               if (pVarResult != 0) {
+                       OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
+               }
+               return COM.S_OK;
+       }
+
+       DISPPARAMS dispParams = new DISPPARAMS ();
+       COM.MoveMemory (dispParams, pDispParams, DISPPARAMS.sizeof);
+       if (dispParams.cArgs != 3) {
+               if (pVarResult != 0) {
+                       OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
+               }
+               return COM.S_OK;
+       }
+
+       long ptr = dispParams.rgvarg + 2 * Variant.sizeof;
+       Variant variant = Variant.win32_new (ptr);
+       if (variant.getType () != COM.VT_I4) {
+               variant.dispose ();
+               if (pVarResult != 0) {
+                       OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
+               }
+               return COM.S_OK;
+       }
+       int index = variant.getInt ();
+       variant.dispose ();
+       if (index <= 0) {
+               if (pVarResult != 0) {
+                       OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
+               }
+               return COM.S_OK;
+       }
+
+       ptr = dispParams.rgvarg + Variant.sizeof;
+       variant = Variant.win32_new (ptr);
+       int type = variant.getType ();
+       if (type != COM.VT_BSTR) {
+               variant.dispose ();
+               if (pVarResult != 0) {
+                       OS.MoveMemory (pVarResult, new long[] {0}, C.PTR_SIZEOF);
+               }
+               return COM.S_OK;
+       }
+       String token = variant.getString ();
+       variant.dispose ();
+
+       variant = Variant.win32_new (dispParams.rgvarg);
+       BrowserFunction function = functions.get (index);
+       Object returnValue = null;
+       if (function != null && token.equals (function.token)) {
+               try {
+                       Object temp = convertToJava (variant);
+                       if (temp instanceof Object[]) {
+                               Object[] args = (Object[])temp;
+                               try {
+                                       returnValue = function.function (args);
+                               } catch (Exception e) {
+                                       /* exception during function invocation */
+                                       returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
+                               }
+                       }
+               } catch (IllegalArgumentException e) {
+                       /* invalid argument value type */
+                       if (function.isEvaluate) {
+                               /* notify the function so that a java exception can be thrown */
+                               function.function (new String[] {WebBrowser.CreateErrorString (new SWTException (SWT.ERROR_INVALID_RETURN_VALUE).getLocalizedMessage ())});
+                       }
+                       returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
+               }
+       }
+       variant.dispose ();
+
+       if (pVarResult != 0) {
+               try {
+                       variant = convertToJS (returnValue);
+               } catch (SWTException e) {
+                       /* invalid return value type */
+                       variant = convertToJS (WebBrowser.CreateErrorString (e.getLocalizedMessage ()));
+               }
+               Variant.win32_copy (pVarResult, variant);
+               variant.dispose ();
+       }
+       return COM.S_OK;
+}
+
+Object convertToJava (Variant variant) {
+       switch (variant.getType ()) {
+               case OLE.VT_EMPTY:
+               case OLE.VT_NULL: return null;
+               case OLE.VT_BSTR: return variant.getString ();
+               case OLE.VT_BOOL: return variant.getBoolean ();
+               case OLE.VT_I2:
+               case OLE.VT_I4:
+               case OLE.VT_I8:
+               case OLE.VT_R4:
+               case OLE.VT_R8:
+                       return variant.getDouble ();
+               case OLE.VT_DISPATCH: {
+                       Object[] args = null;
+                       OleAutomation auto = variant.getAutomation ();
+                       TYPEATTR typeattr = auto.getTypeInfoAttributes ();
+                       if (typeattr != null) {
+                               GUID guid = new GUID ();
+                               guid.Data1 = typeattr.guid_Data1;
+                               guid.Data2 = typeattr.guid_Data2;
+                               guid.Data3 = typeattr.guid_Data3;
+                               guid.Data4 = typeattr.guid_Data4;
+                               if (COM.IsEqualGUID (guid, COM.IIDIJScriptTypeInfo)) {
+                                       int[] rgdispid = auto.getIDsOfNames (new String[] {"length"}); //$NON-NLS-1$
+                                       if (rgdispid != null) {
+                                               Variant varLength = auto.getProperty (rgdispid[0]);
+                                               int length = varLength.getInt ();
+                                               varLength.dispose ();
+                                               args = new Object[length];
+                                               for (int i = 0; i < length; i++) {
+                                                       rgdispid = auto.getIDsOfNames (new String[] {String.valueOf (i)});
+                                                       if (rgdispid != null) {
+                                                               Variant current = auto.getProperty (rgdispid[0]);
+                                                               try {
+                                                                       args[i] = convertToJava (current);
+                                                                       current.dispose ();
+                                                               } catch (IllegalArgumentException e) {
+                                                                       /* invalid argument value type */
+                                                                       current.dispose ();
+                                                                       auto.dispose ();
+                                                                       throw e;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       auto.dispose ();
+                                       SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+                               }
+                       }
+                       auto.dispose ();
+                       return args;
+               }
+       }
+       SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       return null;
+}
+
+Variant convertToJS (Object value) {
+       if (value == null) {
+               return Variant.NULL;
+       }
+       if (value instanceof String) {
+               return new Variant ((String)value);
+       }
+       if (value instanceof Boolean) {
+               return new Variant (((Boolean)value).booleanValue ());
+       }
+       if (value instanceof Number) {
+               return new Variant (((Number)value).doubleValue ());
+       }
+       if (value instanceof Object[]) {
+               /* get IHTMLDocument2 */
+               IE browser = (IE)((Browser)getParent ().getParent ()).webBrowser;
+               OleAutomation auto = browser.auto;
+               int[] rgdispid = auto.getIDsOfNames (new String[] {"Document"}); //$NON-NLS-1$
+               if (rgdispid == null) return new Variant ();
+               Variant pVarResult = auto.getProperty (rgdispid[0]);
+               if (pVarResult == null) return new Variant ();
+               if (pVarResult.getType () == COM.VT_EMPTY) {
+                       pVarResult.dispose ();
+                       return new Variant ();
+               }
+               OleAutomation document = pVarResult.getAutomation ();
+               pVarResult.dispose ();
+
+               /* get IHTMLWindow2 */
+               rgdispid = document.getIDsOfNames (new String[] {"parentWindow"}); //$NON-NLS-1$
+               if (rgdispid == null) {
+                       document.dispose ();
+                       return new Variant ();
+               }
+               pVarResult = document.getProperty (rgdispid[0]);
+               if (pVarResult == null || pVarResult.getType () == COM.VT_EMPTY) {
+                       if (pVarResult != null) pVarResult.dispose ();
+                       document.dispose ();
+                       return new Variant ();
+               }
+               OleAutomation ihtmlWindow2 = pVarResult.getAutomation ();
+               pVarResult.dispose ();
+               document.dispose ();
+
+               /* create a new JS array to be returned */
+               rgdispid = ihtmlWindow2.getIDsOfNames (new String[] {"Array"}); //$NON-NLS-1$
+               if (rgdispid == null) {
+                       ihtmlWindow2.dispose ();
+                       return new Variant ();
+               }
+               Variant arrayType = ihtmlWindow2.getProperty (rgdispid[0]);
+               ihtmlWindow2.dispose ();
+               IDispatch arrayTypeDispatch = arrayType.getDispatch ();
+               long[] result = new long[1];
+               int rc = arrayTypeDispatch.QueryInterface (COM.IIDIDispatchEx, result);
+               arrayType.dispose ();
+               if (rc != COM.S_OK) return new Variant ();
+
+               IDispatchEx arrayTypeDispatchEx = new IDispatchEx (result[0]);
+               result[0] = 0;
+               long resultPtr = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+               DISPPARAMS params = new DISPPARAMS ();
+               rc = arrayTypeDispatchEx.InvokeEx (COM.DISPID_VALUE, COM.LOCALE_USER_DEFAULT, COM.DISPATCH_CONSTRUCT, params, resultPtr, null, 0);
+               if (rc != COM.S_OK) {
+                       OS.GlobalFree (resultPtr);
+                       return new Variant ();
+               }
+               Variant array = Variant.win32_new (resultPtr);
+               OS.GlobalFree (resultPtr);
+
+               /* populate the array */
+               Object[] arrayValue = (Object[])value;
+               int length = arrayValue.length;
+               auto = array.getAutomation ();
+               int[] rgdispids = auto.getIDsOfNames (new String[] {"push"}); //$NON-NLS-1$
+               if (rgdispids != null) {
+                       for (int i = 0; i < length; i++) {
+                               Object currentObject = arrayValue[i];
+                               try {
+                                       Variant variant = convertToJS (currentObject);
+                                       auto.invoke (rgdispids[0], new Variant[] {variant});
+                                       variant.dispose ();
+                               } catch (SWTException e) {
+                                       /* invalid return value type */
+                                       auto.dispose ();
+                                       array.dispose ();
+                                       throw e;
+                               }
+                       }
+               }
+               auto.dispose ();
+               return array;
+       }
+       SWT.error (SWT.ERROR_INVALID_RETURN_VALUE);
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebUIDelegate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WebUIDelegate.java
new file mode 100644 (file)
index 0000000..a829684
--- /dev/null
@@ -0,0 +1,738 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.webkit.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+class WebUIDelegate {
+       COMObject iWebUIDelegate;
+       int refCount = 0;
+
+       String lastHoveredLinkURL;
+       Browser browser;
+       Point size;
+       Point location;
+       boolean menuBar = true, toolBar = true, statusBar = true;
+       boolean prompt = true;
+
+WebUIDelegate (Browser browser) {
+       createCOMInterfaces ();
+       this.browser = browser;
+}
+
+int AddRef () {
+       refCount++;
+       return refCount;
+}
+
+int canTakeFocus (long sender, int forward, long result) {
+       OS.MoveMemory (result, new int[] {1}, 4); /* BOOL */
+       return COM.S_OK;
+}
+
+int contextMenuItemsForElement (long sender, long element, long defaultItemsHMenu, long resultHMenu) {
+       Point pt = browser.getDisplay ().getCursorLocation ();
+       Event event = new Event ();
+       event.x = pt.x;
+       event.y = pt.y;
+       browser.notifyListeners (SWT.MenuDetect, event);
+       if (event.doit) {
+               Menu menu = browser.getMenu ();
+               if (menu != null && !menu.isDisposed ()) {
+                       if (event.x != pt.x || event.y != pt.y) {
+                               menu.setLocation (event.x, event.y);
+                       }
+                       menu.setVisible (true);
+               } else {
+                       OS.MoveMemory (resultHMenu, new long[] {defaultItemsHMenu}, C.PTR_SIZEOF);
+                       return COM.S_OK;
+               }
+       }
+       OS.MoveMemory (resultHMenu, new long[] {0}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+
+void createCOMInterfaces () {
+       iWebUIDelegate = new COMObject (new int[] {2, 0, 0, 3, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 4, 2, 3, 4, 4, 3, 3, 3, 3, 5, 3, 1, 3, 2, 2, 2, 2, 3, 2, 3, 1, 1, 0, 0, 1, 1, 2, 2, 2, 2, 3, 5, 2, 2, 3, 1, 2, 2, 4, 10, 3}) {
+               @Override
+               public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
+               @Override
+               public long method1 (long[] args) {return AddRef ();}
+               @Override
+               public long method2 (long[] args)  {return Release ();}
+               @Override
+               public long method3 (long[] args)  {return createWebViewWithRequest (args[0], args[1], args[2]);}
+               @Override
+               public long method4 (long[] args)  {return webViewShow (args[0]);}
+               @Override
+               public long method5 (long[] args)  {return webViewClose (args[0]);}
+               @Override
+               public long method6 (long[] args)  {return COM.E_NOTIMPL;}
+               @Override
+               public long method7 (long[] args)  {return COM.E_NOTIMPL;}
+               @Override
+               public long method8 (long[] args)  {return COM.E_NOTIMPL;}
+               @Override
+               public long method9 (long[] args)  {return COM.E_NOTIMPL;}
+               @Override
+               public long method10 (long[] args) {return setStatusText (args[0], args[1]);}
+               @Override
+               public long method11 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method12 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method13 (long[] args) {return setToolbarsVisible (args[0], (int)args[1]);}
+               @Override
+               public long method14 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method15 (long[] args) {return setStatusBarVisible (args[0], (int)args[1]);}
+               @Override
+               public long method16 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method17 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method18 (long[] args) {return setFrame (args[0], args[1]);}
+               @Override
+               public long method19 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method20 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method21 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method22 (long[] args) {return runJavaScriptAlertPanelWithMessage (args[0], args[1]);}
+               @Override
+               public long method23 (long[] args) {return runJavaScriptConfirmPanelWithMessage (args[0], args[1], args[2]);}
+               @Override
+               public long method24 (long[] args) {return runJavaScriptTextInputPanelWithPrompt (args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method25 (long[] args) {return runBeforeUnloadConfirmPanelWithMessage (args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method26 (long[] args) {return runOpenPanelForFileButtonWithResultListener (args[0], args[1]);}
+               @Override
+               public long method27 (long[] args) {return mouseDidMoveOverElement (args[0], args[1], (int)args[2]);}
+               @Override
+               public long method28 (long[] args) {return contextMenuItemsForElement (args[0], args[1], args[2], args[3]);}
+               @Override
+               public long method29 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method30 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method31 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method32 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method33 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method34 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method35 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method36 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method37 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method38 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method39 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method40 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method41 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method42 (long[] args) {return canTakeFocus (args[0], (int)args[1], args[2]);}
+               @Override
+               public long method43 (long[] args) {return takeFocus (args[0], (int)args[1]);}
+               @Override
+               public long method44 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method45 (long[] args) {return COM.S_OK;}
+               @Override
+               public long method46 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method47 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method48 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method49 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method50 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method51 (long[] args) {return printFrame (args[0], args[1]);}
+               @Override
+               public long method52 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method53 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method54 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method55 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method56 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method57 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method58 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method59 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method60 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method61 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method62 (long[] args) {return setMenuBarVisible (args[0], (int)args[1]);}
+               @Override
+               public long method63 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method64 (long[] args) {return COM.E_NOTIMPL;}
+               @Override
+               public long method65 (long[] args) {return COM.E_NOTIMPL;}
+       };
+}
+
+int createWebViewWithRequest (long sender, long request, long webView) {
+       WindowEvent newEvent = new WindowEvent (browser);
+       newEvent.display = browser.getDisplay ();
+       newEvent.widget = browser;
+       newEvent.required = true;
+       OpenWindowListener[] openWindowListeners = browser.webBrowser.openWindowListeners;
+       for (int i = 0; i < openWindowListeners.length; i++) {
+               openWindowListeners[i].open (newEvent);
+       }
+       IWebView iwebview = null;
+       Browser browser = null;
+       if (newEvent.browser != null && newEvent.browser.webBrowser instanceof WebKit) {
+               browser = newEvent.browser;
+       }
+       if (browser != null && !browser.isDisposed ()) {
+               iwebview = ((WebKit)browser.webBrowser).webView;
+               OS.MoveMemory (webView, new long[] {iwebview.getAddress ()}, C.PTR_SIZEOF);
+               if (request != 0) {
+                       IWebURLRequest req = new IWebURLRequest (request);
+                       long[] result = new long[1];
+                       int hr = req.URL (result);
+                       if (hr != COM.S_OK || result[0] == 0) {
+                               return COM.S_OK;
+                       }
+                       String sUrl = WebKit.extractBSTR (result[0]);
+                       COM.SysFreeString (result[0]);
+                       if (sUrl.length () != 0) {
+                               result[0] = 0;
+                               hr = iwebview.mainFrame (result);
+                               if (hr != COM.S_OK || result[0] == 0) {
+                                       return COM.S_OK;
+                               }
+                               IWebFrame mainFrame = new IWebFrame (result[0]);
+                               mainFrame.loadRequest (req.getAddress ());
+                               mainFrame.Release ();
+                       }
+               }
+               return COM.S_OK;
+       }
+       return COM.E_NOTIMPL;
+}
+
+protected void disposeCOMInterfaces () {
+       if (iWebUIDelegate != null) {
+               iWebUIDelegate.dispose ();
+               iWebUIDelegate = null;
+       }
+}
+
+long getAddress () {
+       return iWebUIDelegate.getAddress ();
+}
+
+int mouseDidMoveOverElement (long sender, long elementInformation, int modifierFlags) {
+       if (elementInformation == 0) return COM.S_OK;
+
+       IPropertyBag info = new IPropertyBag (elementInformation);
+       long key = WebKit.createBSTR ("WebElementLinkURLKey"); //$NON-NLS-N$
+       long hHeap = OS.GetProcessHeap ();
+       long resultPtr = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, VARIANT.sizeof);
+       int hr = info.Read (key, resultPtr, null);
+       if (hr != COM.S_OK || resultPtr == 0) {
+               return COM.S_OK;
+       }
+       String value = null;
+       VARIANT v = new VARIANT ();
+       COM.MoveMemory (v, resultPtr, VARIANT.sizeof);
+       if (v.vt == COM.VT_BSTR) value = WebKit.extractBSTR (v.lVal);
+       OS.HeapFree (hHeap, 0, resultPtr);
+       StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners;
+       if (value == null || value.length () == 0) {
+               /* not currently over a link */
+               if (lastHoveredLinkURL == null) return COM.S_OK;
+               lastHoveredLinkURL = null;
+               StatusTextEvent statusText = new StatusTextEvent (browser);
+               statusText.display = browser.getDisplay ();
+               statusText.widget = browser;
+               statusText.text = "";   //$NON-NLS-1$
+               for (int i = 0; i < statusTextListeners.length; i++) {
+                       statusTextListeners[i].changed (statusText);
+               }
+               return COM.S_OK;
+       }
+       if (value.equals (lastHoveredLinkURL)) return COM.S_OK;
+       lastHoveredLinkURL = value;
+       StatusTextEvent statusText = new StatusTextEvent (browser);
+       statusText.display = browser.getDisplay ();
+       statusText.widget = browser;
+       statusText.text = value;
+       for (int i = 0; i < statusTextListeners.length; i++) {
+               statusTextListeners[i].changed (statusText);
+       }
+       return COM.S_OK;
+}
+
+int printFrame (long webView, long frame) {
+       IWebFrame iwebFrame = new IWebFrame (frame);
+       PRINTDLG pd = new PRINTDLG ();
+       pd.lStructSize = PRINTDLG.sizeof;
+       pd.Flags = OS.PD_RETURNDC;
+       Display display = browser.getDisplay ();
+       String externalLoopKey = "org.eclipse.swt.internal.win32.externalEventLoop";
+       display.setData(externalLoopKey, Boolean.TRUE);
+       display.sendPreExternalEventDispatchEvent ();
+       boolean success = OS.PrintDlg (pd);
+       display.setData(externalLoopKey, Boolean.FALSE);
+       display.sendPostExternalEventDispatchEvent ();
+       if (!success) return COM.S_OK;
+       long printDC = pd.hDC;
+
+       long[] result = new long[1];
+       int hr = iwebFrame.QueryInterface (WebKit_win32.IID_IWebFramePrivate, result);
+       if (hr != COM.S_OK || result[0] == 0) {
+               return COM.S_OK;
+       }
+       IWebFramePrivate privateFrame = new IWebFramePrivate (result[0]);
+       privateFrame.setInPrintingMode (1, printDC);
+       int[] count = new int[1];
+       hr = privateFrame.getPrintedPageCount (printDC, count);
+       if (hr != COM.S_OK || count[0] == 0) {
+               privateFrame.Release ();
+               return COM.S_OK;
+       }
+       int pageCount = count[0];
+       String jobName = null;
+       result[0] = 0;
+       hr = iwebFrame.dataSource (result);
+       if (hr == COM.S_OK && result[0] != 0) {
+               IWebDataSource dataSource = new IWebDataSource (result[0]);
+               result[0] = 0;
+               hr = dataSource.pageTitle (result);
+               dataSource.Release ();
+               if (hr == COM.S_OK && result[0] != 0) {
+                       jobName = WebKit.extractBSTR (result[0]);
+                       COM.SysFreeString (result[0]);
+               }
+       }
+       DOCINFO di = new DOCINFO ();
+       di.cbSize = DOCINFO.sizeof;
+       long hHeap = OS.GetProcessHeap ();
+       long lpszDocName = 0;
+       if (jobName != null && jobName.length () != 0) {
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR (0, jobName, true);
+               int byteCount = buffer.length () * TCHAR.sizeof;
+               lpszDocName = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory (lpszDocName, buffer, byteCount);
+               di.lpszDocName = lpszDocName;
+       }
+       int rc = OS.StartDoc (printDC, di);
+       if (lpszDocName != 0) OS.HeapFree (hHeap, 0, lpszDocName);
+       if (rc >= 0) {
+               for (int i = 0; i < pageCount; i++) {
+                       OS.StartPage (printDC);
+                       privateFrame.spoolPages (printDC, i, i, null);
+                       OS.EndPage (printDC);
+               }
+               privateFrame.setInPrintingMode (0, printDC);
+               OS.EndDoc (printDC);
+       }
+       privateFrame.Release ();
+       return COM.S_OK;
+}
+
+int QueryInterface (long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID ();
+       COM.MoveMemory (guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebUIDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebUIDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebUIDelegate)) {
+               OS.MoveMemory (ppvObject, new long[] {iWebUIDelegate.getAddress ()}, C.PTR_SIZEOF);
+               new IUnknown (iWebUIDelegate.getAddress ()).AddRef ();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+int Release () {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces ();
+       }
+       return refCount;
+}
+
+int runBeforeUnloadConfirmPanelWithMessage (long sender, long message, long initiatedByFrame, long result) {
+       if (!prompt) return COM.S_OK;
+
+       Shell parent = browser.getShell ();
+       String string = WebKit.extractBSTR (message);
+       StringBuilder text = new StringBuilder (Compatibility.getMessage ("SWT_OnBeforeUnload_Message1")); //$NON-NLS-1$
+       text.append ("\n\n"); //$NON-NLS-1$
+       text.append (string);
+       text.append ("\n\n"); //$NON-NLS-1$
+       text.append (Compatibility.getMessage ("SWT_OnBeforeUnload_Message2")); //$NON-NLS-1$
+       MessageBox box = new MessageBox (parent, SWT.OK | SWT.CANCEL | SWT.ICON_QUESTION);
+       box.setMessage (text.toString ());
+       int[] response = new int[1];
+       response[0] = box.open () == SWT.OK ? 1 : 0;
+       OS.MoveMemory (result, response, 4); /* BOOL */
+       return COM.S_OK;
+}
+
+int runJavaScriptAlertPanelWithMessage (long sender, long message) {
+       String messageString = WebKit.extractBSTR (message);
+       showAlertMessage ("Javascript", messageString); //$NON-NLS-1$
+       return COM.S_OK;
+}
+
+int runJavaScriptConfirmPanelWithMessage (long sender, long message, long result) {
+       String messageString = WebKit.extractBSTR (message);
+       int[] response = new int[1];
+       response[0] = showConfirmPanel ("Javascript", messageString) == SWT.OK ? 1 : 0; //$NON-NLS-1$
+       OS.MoveMemory (result, response, 4); /* BOOL */
+       return COM.S_OK;
+}
+
+int runJavaScriptTextInputPanelWithPrompt (long sender, long message, long defaultText, long result) {
+       String messageString = WebKit.extractBSTR (message);
+       String defaultTextString = WebKit.extractBSTR (defaultText);
+       String resultString = showTextPrompter ("Javascript", messageString, defaultTextString); //$NON-NLS-1$
+       long[] response = new long[1];
+       if (resultString != null) {
+               response[0] = WebKit.createBSTR (resultString);
+       }
+       OS.MoveMemory (result, response, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+
+int runOpenPanelForFileButtonWithResultListener (long sender, long resultListener) {
+       Shell parent = browser.getShell ();
+       FileDialog dialog = new FileDialog (parent, SWT.NONE);
+       String result = dialog.open ();
+       IWebOpenPanelResultListener listener = new IWebOpenPanelResultListener (resultListener);
+       if (result == null) {
+               listener.cancel ();
+       } else {
+               listener.chooseFilename (WebKit.createBSTR (result));
+       }
+       return COM.S_OK;
+}
+
+int setFrame (long sender, long frame) {
+       RECT rect = new RECT ();
+       COM.MoveMemory (rect, frame, RECT.sizeof);
+       /* convert to SWT system coordinates */
+       location = DPIUtil.autoScaleUp(browser.getDisplay ().map (browser, null, DPIUtil.autoScaleDown(new Point(rect.left, rect.top)))); // To Pixels
+       int x = rect.right - rect.left;
+       int y = rect.bottom - rect.top;
+       if (y < 0 || x < 0 || (x == 0 && y == 0)) return COM.S_OK;
+       size = new Point (x, y);
+       return COM.S_OK;
+}
+
+int setMenuBarVisible (long sender, int visible) {
+       /* Note.  Webkit only emits the notification when the status bar should be hidden. */
+       menuBar = visible == 1;
+       return COM.S_OK;
+}
+
+int setStatusBarVisible (long sender, int visible) {
+       /* Note.  Webkit only emits the notification when the status bar should be hidden. */
+       statusBar = visible == 1;
+       return COM.S_OK;
+}
+
+int setStatusText (long sender, long text) {
+       String statusText = WebKit.extractBSTR (text);
+       if (statusText.length () == 0) return COM.S_OK;
+       StatusTextEvent statusTextEvent = new StatusTextEvent (browser);
+       statusTextEvent.display = browser.getDisplay ();
+       statusTextEvent.widget = browser;
+       statusTextEvent.text = statusText;
+       StatusTextListener[] statusTextListeners = browser.webBrowser.statusTextListeners;
+       for (int i = 0; i < statusTextListeners.length; i++) {
+               statusTextListeners[i].changed (statusTextEvent);
+       }
+       return COM.S_OK;
+}
+
+int setToolbarsVisible (long sender, int visible) {
+       /* Note.  Webkit only emits the notification when the status bar should be hidden. */
+       toolBar = visible == 1;
+       return COM.S_OK;
+}
+
+void showAlertMessage (String title, String message) {
+       Shell parent = browser.getShell ();
+       final Shell dialog = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+       GridLayout layout = new GridLayout (2, false);
+       layout.horizontalSpacing = 10;
+       layout.verticalSpacing = 20;
+       layout.marginWidth = layout.marginHeight = 10;
+       dialog.setLayout (layout);
+       dialog.setText (title);
+
+       Label label = new Label (dialog, SWT.NONE);
+       Image image = dialog.getDisplay ().getSystemImage (SWT.ICON_WARNING);
+       label.setImage (image);
+
+       label = new Label (dialog, SWT.WRAP);
+       label.setText (message);
+       Monitor monitor = parent.getMonitor ();
+       int maxWidth = monitor.getBounds().width * 2 / 3;
+       int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       GridData data = new GridData (SWT.FILL, SWT.CENTER, true, false);
+       data.widthHint = Math.min (width, maxWidth);
+       label.setLayoutData (data);
+
+       Button ok = new Button (dialog, SWT.PUSH);
+       ok.setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
+       width = ok.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       GridData layoutData = new GridData ();
+       layoutData.horizontalAlignment = SWT.CENTER;
+       layoutData.verticalAlignment = SWT.CENTER;
+       layoutData.horizontalSpan = 2;
+       layoutData.widthHint = Math.max (width, 75);
+       ok.setLayoutData (layoutData);
+
+       ok.addSelectionListener (new SelectionAdapter () {
+               @Override
+               public void widgetSelected (SelectionEvent e) {
+                       dialog.dispose ();
+               }
+       });
+
+       dialog.setDefaultButton (ok);
+       dialog.pack ();
+       Rectangle parentSize = parent.getBounds ();
+       Rectangle dialogSize = dialog.getBounds ();
+       int x = parent.getLocation ().x + (parentSize.width - dialogSize.width) / 2;
+       int y = parent.getLocation ().y + (parentSize.height - dialogSize.height) / 2;
+       dialog.setLocation (x, y);
+       dialog.open ();
+       Display display = browser.getDisplay ();
+       while (!dialog.isDisposed ()) {
+               if (!display.readAndDispatch ()) display.sleep ();
+       }
+}
+
+int showConfirmPanel (String title, String message) {
+       Shell parent = browser.getShell ();
+       final Shell dialog = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+       GridLayout layout = new GridLayout (2, false);
+       layout.horizontalSpacing = 10;
+       layout.verticalSpacing = 20;
+       layout.marginWidth = layout.marginHeight = 10;
+       dialog.setLayout (layout);
+       dialog.setText (title);
+
+       Label label = new Label (dialog, SWT.NONE);
+       Image image = dialog.getDisplay ().getSystemImage (SWT.ICON_QUESTION);
+       label.setImage (image);
+       label.setLayoutData (new GridData ());
+
+       label = new Label (dialog, SWT.WRAP);
+       label.setText (message);
+       Monitor monitor = parent.getMonitor ();
+       int maxWidth = monitor.getBounds ().width * 2 / 3;
+       int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       GridData data = new GridData (SWT.FILL, SWT.CENTER, true, false);
+       data.widthHint = Math.min (width, maxWidth);
+       label.setLayoutData (data);
+
+       Composite buttons = new Composite (dialog, SWT.NONE);
+       data = new GridData (SWT.CENTER, SWT.CENTER, true, true, 2, 1);
+       buttons.setLayoutData (data);
+       buttons.setLayout (new GridLayout (2, true));
+
+       Button ok = new Button (buttons, SWT.PUSH);
+       ok.setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
+       GridData layoutData = new GridData ();
+       layoutData.horizontalAlignment = SWT.CENTER;
+       layoutData.verticalAlignment = SWT.CENTER;
+       ok.setLayoutData (layoutData);
+
+       Button cancel = new Button (buttons, SWT.PUSH);
+       cancel.setText (SWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+       cancel.setLayoutData (layoutData);
+       width = cancel.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
+       layoutData.widthHint = Math.max (width, 75);
+
+       final int[] result = new int[1];
+       ok.addSelectionListener (new SelectionAdapter () {
+               @Override
+               public void widgetSelected (SelectionEvent e) {
+                       result[0] = SWT.OK;
+                       dialog.dispose ();
+               }
+       });
+       cancel.addSelectionListener (new SelectionAdapter () {
+               @Override
+               public void widgetSelected (SelectionEvent e) {
+                       result[0] = SWT.CANCEL;
+                       dialog.dispose ();
+               }
+       });
+
+       dialog.setDefaultButton (ok);
+       dialog.pack ();
+       Rectangle parentSize = parent.getBounds ();
+       Rectangle dialogSize = dialog.getBounds ();
+       int x = parent.getLocation ().x + (parentSize.width - dialogSize.width) / 2;
+       int y = parent.getLocation ().y + (parentSize.height - dialogSize.height) / 2;
+       dialog.setLocation (x, y);
+       dialog.open ();
+       Display display = browser.getDisplay ();
+       while (!dialog.isDisposed ()) {
+               if (!display.readAndDispatch ()) display.sleep ();
+       }
+       return result[0];
+}
+
+String showTextPrompter (String title, String message, String defaultText) {
+       Shell parent = browser.getShell ();
+       final Shell dialog = new Shell (parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+       dialog.setLayout (new GridLayout ());
+       dialog.setText (title);
+
+       Label label = new Label (dialog, SWT.NONE);
+       label.setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       label.setText (message);
+
+       final Text textBox = new Text (dialog, SWT.SINGLE | SWT.BORDER);
+       GridData data = new GridData (GridData.FILL_HORIZONTAL);
+       data.widthHint = 300;
+       textBox.setLayoutData (data);
+       textBox.setText (defaultText);
+
+       Composite buttons = new Composite (dialog, SWT.NONE);
+       buttons.setLayout (new GridLayout (2, true));
+       buttons.setLayoutData (new GridData (GridData.HORIZONTAL_ALIGN_CENTER));
+       Button ok = new Button (buttons, SWT.PUSH);
+       ok.setText (SWT.getMessage ("SWT_OK")); //$NON-NLS-1$
+       ok.setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+
+       final String[] result = new String[1];
+       ok.addSelectionListener (new SelectionAdapter () {
+               @Override
+               public void widgetSelected (SelectionEvent e) {
+                       result[0] = textBox.getText ();
+                       dialog.dispose ();
+               }
+       });
+       Button cancel = new Button (buttons, SWT.PUSH);
+       cancel.setText (SWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+       cancel.setLayoutData (new GridData (GridData.FILL_HORIZONTAL));
+       cancel.addSelectionListener (new SelectionAdapter () {
+               @Override
+               public void widgetSelected (SelectionEvent e) {
+                       dialog.dispose ();
+               }
+       });
+
+       dialog.setDefaultButton (ok);
+       dialog.pack ();
+       Rectangle parentSize = parent.getBounds ();
+       Rectangle dialogSize = dialog.getBounds ();
+       int x = parent.getLocation ().x + (parentSize.width - dialogSize.width) / 2;
+       int y = parent.getLocation ().y + (parentSize.height - dialogSize.height) / 2;
+       dialog.setLocation (x, y);
+       dialog.open ();
+       Display display = browser.getDisplay ();
+       while (!dialog.isDisposed ()) {
+               if (!display.readAndDispatch ()) display.sleep ();
+       }
+       return result[0];
+}
+
+int takeFocus (long sender, int forward) {
+       int traveralCode = forward == 0 ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT;
+       ((WebKit)browser.webBrowser).traverseOut = true;
+       browser.traverse (traveralCode);
+       return COM.S_OK;
+}
+
+int webViewClose (long sender) {
+       WindowEvent newEvent = new WindowEvent (browser);
+       newEvent.display = browser.getDisplay ();
+       newEvent.widget = browser;
+       CloseWindowListener[] closeWindowListeners = browser.webBrowser.closeWindowListeners;
+       for (int i = 0; i < closeWindowListeners.length; i++) {
+               closeWindowListeners[i].close (newEvent);
+       }
+       browser.dispose ();
+       return COM.S_OK;
+}
+
+int webViewFrame (long sender, long frame) {
+       RECT rect = new RECT ();
+       OS.MoveMemory (frame, rect, RECT.sizeof);
+       return COM.S_OK;
+}
+
+int webViewShow (long sender) {
+       WindowEvent newEvent = new WindowEvent (browser);
+       newEvent.display = browser.getDisplay ();
+       newEvent.widget = browser;
+       if (location != null) newEvent.location = location;
+       if (size != null) newEvent.size = size;
+       /*
+       * Feature in WebKit.  WebKit's tool bar contains
+       * the address bar.  The address bar is displayed
+       * if the tool bar is displayed. There is no separate
+       * notification for the address bar.
+       */
+       newEvent.addressBar = toolBar;
+       newEvent.menuBar = menuBar;
+       newEvent.statusBar = statusBar;
+       newEvent.toolBar = toolBar;
+       VisibilityWindowListener[] visibilityWindowListeners = browser.webBrowser.visibilityWindowListeners;
+       for (int i = 0; i < visibilityWindowListeners.length; i++) {
+               visibilityWindowListeners[i].show (newEvent);
+       }
+       location = null;
+       size = null;
+       return COM.S_OK;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WindowEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/WindowEvent.java
new file mode 100644 (file)
index 0000000..e4012ac
--- /dev/null
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A <code>WindowEvent</code> is sent by a {@link Browser} when
+ * a new window needs to be created or when an existing window needs to be
+ * closed. This notification occurs when a javascript command such as
+ * <code>window.open</code> or <code>window.close</code> gets executed by
+ * a <code>Browser</code>.
+ *
+ * <p>
+ * The following example shows how <code>WindowEvent</code>'s are typically
+ * handled.</p>
+ *
+ * <pre><code>
+ *     public static void main(String[] args) {
+ *             Display display = new Display();
+ *             Shell shell = new Shell(display);
+ *             shell.setText("Main Window");
+ *             shell.setLayout(new FillLayout());
+ *             Browser browser = new Browser(shell, SWT.NONE);
+ *             initialize(display, browser);
+ *             shell.open();
+ *             browser.setUrl("http://www.eclipse.org");
+ *             while (!shell.isDisposed()) {
+ *                     if (!display.readAndDispatch())
+ *                             display.sleep();
+ *             }
+ *             display.dispose();
+ *     }
+ *
+ *     static void initialize(final Display display, Browser browser) {
+ *             browser.addOpenWindowListener(new OpenWindowListener() {
+ *                     public void open(WindowEvent event) {
+ *                             // Certain platforms can provide a default full browser.
+ *                             // simply return in that case if the application prefers
+ *                             // the default full browser to the embedded one set below.
+ *                             if (!event.required) return;
+ *
+ *                             // Embed the new window
+ *                             Shell shell = new Shell(display);
+ *                             shell.setText("New Window");
+ *                             shell.setLayout(new FillLayout());
+ *                             Browser browser = new Browser(shell, SWT.NONE);
+ *                             initialize(display, browser);
+ *                             event.browser = browser;
+ *                     }
+ *             });
+ *             browser.addVisibilityWindowListener(new VisibilityWindowListener() {
+ *                     public void hide(WindowEvent event) {
+ *                             Browser browser = (Browser)event.widget;
+ *                             Shell shell = browser.getShell();
+ *                             shell.setVisible(false);
+ *                     }
+ *                     public void show(WindowEvent event) {
+ *                             Browser browser = (Browser)event.widget;
+ *                             Shell shell = browser.getShell();
+ *                             if (event.location != null) shell.setLocation(event.location);
+ *                             if (event.size != null) {
+ *                                     Point size = event.size;
+ *                                     shell.setSize(shell.computeSize(size.x, size.y));
+ *                             }
+ *                             if (event.addressBar || event.menuBar || event.statusBar || event.toolBar) {
+ *                                     // Create widgets for the address bar, menu bar, status bar and/or tool bar
+ *                                     // leave enough space in the Shell to accommodate a Browser of the size
+ *                                     // given by event.size
+ *                             }
+ *                             shell.open();
+ *                     }
+ *             });
+ *             browser.addCloseWindowListener(new CloseWindowListener() {
+ *                     public void close(WindowEvent event) {
+ *                             Browser browser = (Browser)event.widget;
+ *                             Shell shell = browser.getShell();
+ *                             shell.close();
+ *                     }
+ *             });
+ *     }
+ * </code></pre>
+ *
+ * The following notifications are emitted when the user selects a hyperlink that targets a new window
+ * or as the result of a javascript that executes window.open.
+ *
+ * <p>Main Browser</p>
+ * <ul>
+ *    <li>User selects a link that opens in a new window or javascript requests a new window</li>
+ *    <li>OpenWindowListener.open() notified
+ *    <ul>
+ *             <li>Application creates a new Shell and a second Browser inside that Shell</li>
+ *             <li>Application registers WindowListener's on that second Browser, such as VisibilityWindowListener</li>
+ *             <li>Application returns the second Browser as the host for the new window content</li>
+ *    </ul>
+ *    </li>
+ * </ul>
+ *
+ * <p>Second Browser</p>
+ * <ul>
+ *    <li>VisibilityWindowListener.show() notified
+ *    <ul>
+ *             <li>Application sets navigation tool bar, status bar, menu bar and Shell size
+ *             <li>Application makes the Shell hosting the second Browser visible
+ *             <li>User now sees the new window
+ *    </ul>
+ *    </li>
+ * </ul>
+ *
+ * @see CloseWindowListener
+ * @see OpenWindowListener
+ * @see VisibilityWindowListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class WindowEvent extends TypedEvent {
+
+       /**
+        * Specifies whether the platform requires the user to provide a
+        * <code>Browser</code> to handle the new window.
+        *
+        * @since 3.1
+        */
+       public boolean required;
+
+
+       /**
+        * <code>Browser</code> provided by the application.
+        */
+       public Browser browser;
+
+       /**
+        * Requested location for the <code>Shell</code> hosting the <code>Browser</code>.
+        * It is <code>null</code> if no location has been requested.
+        */
+       public Point location;
+
+       /**
+        * Requested <code>Browser</code> size. The client area of the <code>Shell</code>
+        * hosting the <code>Browser</code> should be large enough to accommodate that size.
+        * It is <code>null</code> if no size has been requested.
+        */
+       public Point size;
+
+       /**
+        * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+        * display an address bar.
+        *
+        * @since 3.1
+        */
+       public boolean addressBar;
+
+       /**
+        * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+        * display a menu bar.  Note that this is always <code>true</code> on OS X.
+        *
+        * @since 3.1
+        */
+       public boolean menuBar;
+
+       /**
+        * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+        * display a status bar.
+        *
+        * @since 3.1
+        */
+       public boolean statusBar;
+
+       /**
+        * Specifies whether the <code>Shell</code> hosting the <code>Browser</code> should
+        * display a tool bar.
+        *
+        * @since 3.1
+        */
+       public boolean toolBar;
+
+       static final long serialVersionUID = 3617851997387174969L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param widget the widget that fired the event
+ *
+ * @since 3.5
+ */
+public WindowEvent(Widget widget) {
+       super(widget);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " required=" + required
+               + " browser=" + browser
+               + " location=" + location
+               + " size=" + size
+               + " addressBar=" + addressBar
+               + " menuBar=" + menuBar
+               + " statusBar=" + statusBar
+               + " toolBar=" + toolBar
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/browser/package.html
new file mode 100644 (file)
index 0000000..f64b6c4
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Browser widget.
+<h2>
+Package Specification</h2>
+This package provides the classes to implement the browser user interface
+metaphor.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/AnimatedProgress.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/AnimatedProgress.java
new file mode 100644 (file)
index 0000000..6a5308c
--- /dev/null
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ */
+@Deprecated
+public class AnimatedProgress extends Canvas {
+
+       static final int SLEEP = 70;
+       static final int DEFAULT_WIDTH = 160;
+       static final int DEFAULT_HEIGHT = 18;
+       boolean active = false;
+       boolean showStripes = false;
+       int value;
+       int orientation = SWT.HORIZONTAL;
+       boolean 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 AnimatedProgress(Composite parent, int style) {
+       super(parent, checkStyle(style));
+
+       if ((style & SWT.VERTICAL) != 0) {
+               orientation = SWT.VERTICAL;
+       }
+       showBorder = (style & SWT.BORDER) != 0;
+
+       addControlListener(ControlListener.controlResizedAdapter(e -> redraw()));
+       addPaintListener(e -> paint(e));
+       addDisposeListener(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();
+}
+@Override
+public Point computeSize(int wHint, int hHint, boolean changed) {
+       checkWidget();
+       Point size = null;
+       if (orientation == SWT.HORIZONTAL) {
+               size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+       } else {
+               size = new Point(DEFAULT_HEIGHT, DEFAULT_WIDTH);
+       }
+       if (wHint != SWT.DEFAULT) size.x = wHint;
+       if (hHint != 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 == 0 ? step - 2 : value - 2;
+       if (orientation == 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;
+
+       final Display display = getDisplay();
+       final Runnable [] timer = new Runnable [1];
+       timer [0] = () -> {
+               if (!active) return;
+               GC gc = new GC(AnimatedProgress.this);
+               paintStripes(gc);
+               gc.dispose();
+               display.timerExec (SLEEP, timer [0]);
+       };
+       display.timerExec (SLEEP, timer [0]);
+}
+/**
+* Stop the animation.   Freeze the presentation at its current appearance.
+*/
+public synchronized void stop() {
+       //checkWidget();
+       active = false;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BidiSegmentEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BidiSegmentEvent.java
new file mode 100644 (file)
index 0000000..628f0be
--- /dev/null
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.events.*;
+
+/**
+ * This event is sent to BidiSegmentListeners when a line is to
+ * be measured or rendered in a bidi locale.
+ * The segments field can be used in conjunction with the segmentsChars
+ * field or by itself. Setting only the segmentsChars field has no effect.
+ * When used by itself, the segments field 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:</p>
+ * <ul>
+ * <li>elements must be in ascending order and must not have duplicates
+ * <li>elements must not exceed the line length
+ * </ul>
+ * In addition, the first element may be set to zero and the last element may
+ * be set to the end of the line but this is not required.
+ * <p>
+ * 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>
+ *
+ * <p>
+ * The segments and segmentsChars fields can be used together to obtain different
+ * types of bidi reordering and text display. The application can use these two fields
+ * to insert Unicode Control Characters in specific offsets in the line, the character
+ * at segmentsChars[i] is inserted at the offset specified by segments[i]. When both fields
+ * are set, the rules for the segments field are less restrictive:
+ * </p>
+ * <ul>
+ * <li>elements must be in ascending order, duplicates are allowed
+ * <li>elements must not exceed the line length
+ * </ul>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class BidiSegmentEvent extends SegmentEvent {
+
+       static final long serialVersionUID = -3712986188155944253L;
+
+BidiSegmentEvent(StyledTextEvent e) {
+       super(e);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BidiSegmentListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BidiSegmentListener.java
new file mode 100644 (file)
index 0000000..ed56921
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * BidiSegmentEvents.
+ * @see BidiSegmentEvent
+ */
+@FunctionalInterface
+public interface BidiSegmentListener extends 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>
+ * <li>event.segmentsChars characters that should be inserted (output, optional)</li>
+ * </ul>
+ *
+ * @param event the given event
+ * @see BidiSegmentEvent
+ */
+public void lineGetSegments(BidiSegmentEvent event);
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/Bullet.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/Bullet.java
new file mode 100644 (file)
index 0000000..8a14833
--- /dev/null
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 Bullet(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 Bullet(int type, StyleRange style) {
+       if (style == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (style.metrics == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       this.type = type;
+       this.style = style;
+}
+void addIndices (int startLine, int lineCount) {
+       if (linesIndices == 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] == lineIndex) return i;
+       }
+       return -1;
+}
+@Override
+public int hashCode() {
+       return style.hashCode() ^ type;
+}
+int[] removeIndices (int startLine, int replaceLineCount, int newLineCount, boolean update) {
+       if (count == 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BusyIndicator.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/BusyIndicator.java
new file mode 100644 (file)
index 0000000..c100fb7
--- /dev/null
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 final String BUSYID_NAME = "SWT BusyIndicator"; //$NON-NLS-1$
+       static final 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 == null)
+                       SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               if (display == null) {
+                       display = Display.getCurrent();
+                       if (display == null) {
+                               runnable.run();
+                               return;
+                       }
+               }
+
+               Integer busyId = Integer.valueOf(nextBusyId);
+               nextBusyId++;
+               Cursor cursor = display.getSystemCursor(SWT.CURSOR_WAIT);
+               Shell[] shells = display.getShells();
+               for (Shell shell : shells) {
+                       Integer id = (Integer)shell.getData(BUSYID_NAME);
+                       if (id == null) {
+                               setCursorAndId(shell, cursor, busyId);
+                       }
+               }
+
+               try {
+                       runnable.run();
+               } finally {
+                       shells = display.getShells();
+                       for (Shell shell : shells) {
+                               Integer id = (Integer)shell.getData(BUSYID_NAME);
+                               if (id == busyId) {
+                                       setCursorAndId(shell, null, null);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Paranoia code to make sure we don't break UI because of one shell disposed, see bug 532632 comment 20
+        */
+       private static void setCursorAndId(Shell shell, Cursor cursor, Integer busyId) {
+               if (!shell.isDisposed()) {
+                       shell.setCursor(cursor);
+               }
+               if (!shell.isDisposed()) {
+                       shell.setData(BUSYID_NAME, busyId);
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CBanner.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CBanner.java
new file mode 100644 (file)
index 0000000..a975ccf
--- /dev/null
@@ -0,0 +1,560 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class CBanner extends Composite {
+
+       Control left;
+       Control right;
+       Control bottom;
+
+       boolean simple = true;
+
+       int[] curve = new int[0];
+       int curveStart = 0;
+       Rectangle curveRect = new Rectangle(0, 0, 0, 0);
+       int curve_width = 5;
+       int curve_indent = -2;
+
+       int rightWidth = SWT.DEFAULT;
+       int rightMinWidth = 0;
+       int rightMinHeight = 0;
+       Cursor resizeCursor;
+       boolean dragging = false;
+       int rightDragDisplacement = 0;
+       Listener listener;
+
+       static final int OFFSCREEN = -200;
+       static final int BORDER_BOTTOM = 2;
+       static final int BORDER_TOP = 3;
+       static final int BORDER_STRIPE = 1;
+       static final int CURVE_TAIL = 200;
+       static final int BEZIER_RIGHT = 30;
+       static final int BEZIER_LEFT = 30;
+       static final 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 CBanner(Composite parent, int style) {
+       super(parent, checkStyle(style));
+       super.setLayout(new CBannerLayout());
+       resizeCursor = getDisplay().getSystemCursor(SWT.CURSOR_SIZEWE);
+
+       listener = e -> {
+               switch (e.type) {
+                       case SWT.Dispose:
+                               onDispose(e); 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;
+               }
+       };
+       int[] events = new int[] {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 = (double)i / (double)count;
+               polygon[2*i] = (int)(a0 + a1*t + a2*t*t + a3*t*t*t);
+               polygon[2*i + 1] = (int)(b0 + b1*t + b2*t*t + b3*t*t*t);
+       }
+       return polygon;
+}
+static int checkStyle (int style) {
+       return SWT.NONE;
+}
+/*
+* This class was not intended to be subclassed but this restriction
+* cannot be enforced without breaking backward compatibility.
+*/
+//protected void checkSubclass () {
+//     String name = getClass ().getName ();
+//     int index = name.lastIndexOf ('.');
+//     if (!name.substring (0, index + 1).equals ("org.eclipse.swt.custom.")) {
+//             SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+//     }
+//}
+/**
+* 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;
+}
+@Override
+public 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 == null) return 0;
+       if (rightWidth == 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 boolean getSimple() {
+       checkWidget();
+       return simple;
+}
+void onDispose(Event event) {
+       removeListener(SWT.Dispose, listener);
+       notifyListeners(SWT.Dispose, event);
+       event.type = SWT.None;
+
+       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 == 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 == null && right == null) return;
+       Point size = getSize();
+       Color border1 = getDisplay().getSystemColor(BORDER1);
+       if (bottom != null) {
+               int y = bottom.getBounds().y - BORDER_STRIPE - 1;
+               gc.setForeground(border1);
+               gc.drawLine(0, y, size.x, y);
+       }
+       if (left == null || right == 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 != null && control.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (bottom != 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>
+ */
+@Override
+public 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 != null && control.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (left != 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 != null && control.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (right != 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 == 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(boolean simple) {
+       checkWidget();
+       if (this.simple != 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 = new int[] {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);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CBannerLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CBannerLayout.java
new file mode 100644 (file)
index 0000000..292f218
--- /dev/null
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class provides the layout for CBanner
+ *
+ * @see CBanner
+ */
+class CBannerLayout extends Layout {
+
+@Override
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+       CBanner banner = (CBanner)composite;
+       Control left = banner.left;
+       Control right = banner.right;
+       Control bottom = banner.bottom;
+       boolean showCurve = left != null && right != null;
+       int height = hHint;
+       int width = wHint;
+
+       // Calculate component sizes
+       Point bottomSize = new Point(0, 0);
+       if (bottom != null) {
+               int trim = computeTrim(bottom);
+               int w = wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(0, width - trim);
+               bottomSize = computeChildSize(bottom, w, SWT.DEFAULT, flushCache);
+       }
+       Point rightSize = new Point(0, 0);
+       if (right != null) {
+               int trim = computeTrim(right);
+               int w = SWT.DEFAULT;
+               if (banner.rightWidth != SWT.DEFAULT) {
+                       w = banner.rightWidth - trim;
+                       if (left != 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 != SWT.DEFAULT) {
+                       width -= rightSize.x + banner.curve_width - 2* banner.curve_indent;
+               }
+       }
+       Point leftSize = new Point(0, 0);
+       if (left != null) {
+               int trim = computeTrim(left);
+               int w = wHint == 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 != null && (left != null || right != null)) {
+               height += CBanner.BORDER_STRIPE + 2;
+       }
+       if (left != null) {
+               if (right == null) {
+                       height += leftSize.y;
+               } else {
+                       height += Math.max(leftSize.y, banner.rightMinHeight == 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 != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+
+       return new Point(width, height);
+}
+Point computeChildSize(Control control, int wHint, int hHint, boolean flushCache) {
+       Object data = control.getLayoutData();
+       if (data == null || !(data instanceof CLayoutData)) {
+               data = new CLayoutData();
+               control.setLayoutData(data);
+       }
+       return ((CLayoutData)data).computeSize(control, wHint, hHint, flushCache);
+}
+int computeTrim(Control c) {
+       if (c instanceof Scrollable) {
+               Rectangle rect = ((Scrollable) c).computeTrim (0, 0, 0, 0);
+               return rect.width;
+       }
+       return c.getBorderWidth () * 2;
+}
+@Override
+protected boolean flushCache(Control control) {
+       Object data = control.getLayoutData();
+       if (data != null && data instanceof CLayoutData) ((CLayoutData)data).flushCache();
+       return true;
+}
+@Override
+protected void layout(Composite composite, boolean flushCache) {
+       CBanner banner = (CBanner)composite;
+       Control left = banner.left;
+       Control right = banner.right;
+       Control bottom = banner.bottom;
+
+       Point size = banner.getSize();
+       boolean showCurve = left != null && right != null;
+       int width = size.x - 2*banner.getBorderWidth();
+       int height = size.y - 2*banner.getBorderWidth();
+
+       Point bottomSize = new Point(0, 0);
+       if (bottom != 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 != null) {
+               int trim = computeTrim(right);
+               int w = SWT.DEFAULT;
+               if (banner.rightWidth != SWT.DEFAULT) {
+                       w = banner.rightWidth - trim;
+                       if (left != 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 != 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 != 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 != 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 != null) {
+               if (left != null) {
+                       rightSize.y = Math.max(leftSize.y, banner.rightMinHeight == 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 != null) bottom.setBounds(bottomRect);
+       if (rightRect != null) right.setBounds(rightRect);
+       if (leftRect != null) left.setBounds(leftRect);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CCombo.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CCombo.java
new file mode 100644 (file)
index 0000000..9656349
--- /dev/null
@@ -0,0 +1,2031 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Paul Pazderski - Bug 349112: allow setting alignment on the text field
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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&amp;F, but the decision should not be taken lightly.
+ * There 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, LEAD, LEFT, CENTER, TRAIL, RIGHT</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 class CCombo extends Composite {
+
+       Text text;
+       List list;
+       int visibleItemCount = 5;
+       Shell popup;
+       Button arrow;
+       boolean hasFocus;
+       Listener listener, filter;
+       Color foreground, background;
+       Font font;
+       Shell _shell;
+
+       static final String PACKAGE_PREFIX = "org.eclipse.swt.custom."; //$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#BORDER
+ * @see SWT#READ_ONLY
+ * @see SWT#FLAT
+ * @see SWT#LEAD
+ * @see SWT#LEFT
+ * @see SWT#CENTER
+ * @see SWT#RIGHT
+ * @see SWT#TRAIL
+ * @see Widget#getStyle()
+ */
+public CCombo (Composite parent, int style) {
+       super (parent, style = checkStyle (style));
+       _shell = super.getShell ();
+
+       listener = event -> {
+               if (isDisposed ()) return;
+               if (popup == event.widget) {
+                       popupEvent (event);
+                       return;
+               }
+               if (text == event.widget) {
+                       textEvent (event);
+                       return;
+               }
+               if (list == event.widget) {
+                       listEvent (event);
+                       return;
+               }
+               if (arrow == event.widget) {
+                       arrowEvent (event);
+                       return;
+               }
+               if (CCombo.this == event.widget) {
+                       comboEvent (event);
+                       return;
+               }
+               if (getShell () == event.widget) {
+                       getDisplay().asyncExec(() -> {
+                               if (isDisposed ()) return;
+                               handleFocus (SWT.FocusOut);
+                       });
+               }
+       };
+
+       createText(style);
+
+       int arrowStyle = SWT.ARROW | SWT.DOWN;
+       if ((style & SWT.FLAT) != 0) arrowStyle |= SWT.FLAT;
+       arrow = new Button (this, arrowStyle);
+       filter = event -> {
+               if (isDisposed ()) return;
+               if (event.type == SWT.Selection) {
+                       if (event.widget instanceof ScrollBar) {
+                               handleScroll(event);
+                       }
+                       return;
+               }
+               Shell shell = ((Control)event.widget).getShell ();
+               if (shell == CCombo.this.getShell ()) {
+                       handleFocus (SWT.FocusOut);
+               }
+       };
+
+       int [] comboEvents = {SWT.Dispose, SWT.FocusIn, SWT.Move, SWT.Resize, SWT.FocusOut};
+       for (int i=0; i<comboEvents.length; i++) this.addListener (comboEvents [i], listener);
+
+       int [] arrowEvents = {SWT.DragDetect, SWT.MouseDown, SWT.MouseEnter, SWT.MouseExit, SWT.MouseHover,
+               SWT.MouseMove, SWT.MouseUp, SWT.MouseWheel, SWT.Selection, SWT.FocusIn};
+       for (int i=0; i<arrowEvents.length; i++) arrow.addListener (arrowEvents [i], listener);
+
+       createPopup(null, -1);
+       if ((style & SWT.SIMPLE) == 0) {
+               int itemHeight = list.getItemHeight ();
+               if (itemHeight != 0) {
+                       int maxHeight = getMonitor().getClientArea().height / 3;
+                       visibleItemCount = Math.max(visibleItemCount, maxHeight / itemHeight);
+               }
+       }
+
+       initAccessible();
+}
+static int checkStyle (int style) {
+       int mask = SWT.BORDER | SWT.READ_ONLY | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.LEAD | SWT.CENTER | SWT.TRAIL;
+       return SWT.NO_FOCUS | (style & mask);
+}
+void createText(int comboStyle) {
+       String textValue = null, tooltip = null;
+       Point selection = null;
+       int limit = 0;
+       boolean enabled = false, focus = false, editable = false;
+       Font font = null;
+       Color fg = null, bg = null;
+       Menu menu = null;
+       if (text != null) {
+               textValue = text.getText();
+               tooltip = text.getToolTipText();
+               selection = text.getSelection();
+               limit = text.getTextLimit();
+               enabled = text.isEnabled();
+               editable = text.getEditable();
+               focus = text.isFocusControl();
+               font = text.getFont();
+               fg = text.getForeground();
+               bg = text.getBackground();
+               menu = text.getMenu();
+               text.dispose();
+       }
+
+       int textStyle = SWT.SINGLE;
+       if ((comboStyle & SWT.READ_ONLY) != 0) textStyle |= SWT.READ_ONLY;
+       if ((comboStyle & SWT.FLAT) != 0) textStyle |= SWT.FLAT;
+       textStyle |= comboStyle & (SWT.LEAD | SWT.CENTER | SWT.TRAIL);
+       text = new Text (this, textStyle);
+       if (textValue != null) {
+               text.setText(textValue);
+               text.setToolTipText(tooltip);
+               if (selection != null) text.setSelection(selection);
+               text.setTextLimit(limit);
+               text.setEnabled(enabled);
+               text.setEditable(editable);
+               if (focus) text.setFocus();
+               if (font != null && !font.isDisposed()) text.setFont(font);
+               if (fg != null && !fg.isDisposed()) text.setForeground(fg);
+               if (bg != null && !bg.isDisposed()) text.setBackground(bg);
+               if (menu != null && !menu.isDisposed()) text.setMenu(menu);
+               internalLayout(true);
+       }
+
+       int [] textEvents = {SWT.DefaultSelection, SWT.DragDetect, SWT.KeyDown, SWT.KeyUp, SWT.MenuDetect, SWT.Modify,
+                       SWT.MouseDown, SWT.MouseUp, SWT.MouseDoubleClick, SWT.MouseEnter, SWT.MouseExit, SWT.MouseHover,
+                       SWT.MouseMove, SWT.MouseWheel, SWT.Traverse, SWT.FocusIn, SWT.Verify};
+       for (int i=0; i<textEvents.length; i++) text.addListener (textEvents [i], listener);
+}
+/**
+ * Adds the argument to the end of the receiver's list.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new item
+ *
+ * @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>
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+       checkWidget();
+       if (string == 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><p>
+ * Also note, if control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ *    <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();
+       if (string == 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 == 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 == 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 == 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.DragDetect:
+               case SWT.MouseDown:
+               case SWT.MouseUp:
+               case SWT.MouseMove:
+               case SWT.MouseEnter:
+               case SWT.MouseExit:
+               case SWT.MouseHover: {
+                       Point pt = getDisplay ().map (arrow, this, event.x, event.y);
+                       event.x = pt.x; event.y = pt.y;
+                       notifyListeners (event.type, event);
+                       event.type = SWT.None;
+                       break;
+               }
+               case SWT.MouseWheel: {
+                       Point pt = getDisplay ().map (arrow, this, event.x, event.y);
+                       event.x = pt.x; event.y = pt.y;
+                       notifyListeners (SWT.MouseWheel, event);
+                       event.type = SWT.None;
+                       if (isDisposed ()) break;
+                       if (!event.doit) break;
+                       if (event.count != 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 != getSelectionIndex ()) {
+                                       Event e = new Event();
+                                       e.time = event.time;
+                                       e.stateMask = event.stateMask;
+                                       notifyListeners (SWT.Selection, e);
+                               }
+                               if (isDisposed ()) break;
+                       }
+                       break;
+               }
+               case SWT.Selection: {
+                       text.setFocus();
+                       dropDown (!isDropped ());
+                       break;
+               }
+       }
+}
+@Override
+protected void checkSubclass () {
+       String name = getClass ().getName ();
+       int index = name.lastIndexOf ('.');
+       if (!name.substring (0, index + 1).equals (PACKAGE_PREFIX)) {
+               SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+       }
+}
+/**
+ * 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:
+                       removeListener(SWT.Dispose, listener);
+                       notifyListeners(SWT.Dispose, event);
+                       event.type = SWT.None;
+
+                       if (popup != 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;
+                       _shell = null;
+                       break;
+               case SWT.FocusIn:
+                       Control focusControl = getDisplay ().getFocusControl ();
+                       if (focusControl == arrow || focusControl == list) return;
+                       if (isDropped()) {
+                               list.setFocus();
+                       } else {
+                               text.setFocus();
+                       }
+                       break;
+               case SWT.FocusOut:
+                       text.clearSelection();
+                       break;
+               case SWT.Move:
+                       dropDown (false);
+                       break;
+               case SWT.Resize:
+                       internalLayout (false);
+                       break;
+       }
+}
+
+@Override
+public Point computeSize (int wHint, int hHint, boolean 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 != SWT.DEFAULT) width = wHint;
+       if (hHint != 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 | SWT.H_SCROLL;
+       if ((style & SWT.FLAT) != 0) listStyle |= SWT.FLAT;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) listStyle |= SWT.RIGHT_TO_LEFT;
+       if ((style & SWT.LEFT_TO_RIGHT) != 0) listStyle |= SWT.LEFT_TO_RIGHT;
+       list = new List (popup, listStyle);
+       if (font != null) list.setFont (font);
+       if (foreground != null) list.setForeground (foreground);
+       if (background != null) list.setBackground (background);
+
+       int [] popupEvents = {SWT.Close, SWT.Paint};
+       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.FocusOut, SWT.Dispose};
+       for (int i=0; i<listEvents.length; i++) list.addListener (listEvents [i], listener);
+
+       if (items != null) list.setItems (items);
+       if (selectionIndex != -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 == 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 (boolean drop) {
+       if (drop == isDropped ()) return;
+       Display display = getDisplay ();
+       if (!drop) {
+               display.removeFilter (SWT.Selection, filter);
+               popup.setVisible (false);
+               if (!isDisposed () && isFocusControl()) {
+                       text.setFocus();
+               }
+               return;
+       }
+       if (!isVisible()) return;
+       if (getShell() != 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 comboSize = getSize ();
+       int itemCount = list.getItemCount ();
+       itemCount = (itemCount == 0) ? visibleItemCount : Math.min(visibleItemCount, itemCount);
+       int itemHeight = list.getItemHeight () * itemCount;
+       Point listSize = list.computeSize (SWT.DEFAULT, itemHeight, false);
+       Rectangle displayRect = getMonitor ().getClientArea ();
+       list.setBounds (1, 1, Math.max (comboSize.x - 2, Math.min(listSize.x, displayRect.width - 2)), listSize.y);
+
+       int index = list.getSelectionIndex ();
+       if (index != -1) list.setTopIndex (index);
+       Rectangle listRect = list.getBounds ();
+       Rectangle parentRect = display.map (getParent (), null, getBounds ());
+       int width = listRect.width + 2;
+       int height = listRect.height + 2;
+       int x = parentRect.x;
+       if (x + width > displayRect.x + displayRect.width) {
+               x = displayRect.x + displayRect.width - width;
+       }
+       int y = parentRect.y + comboSize.y;
+       if (y + height > displayRect.y + displayRect.height) {
+               int popUpwardsHeight = (parentRect.y - height < displayRect.y) ? parentRect.y - displayRect.y : height;
+               int popDownwardsHeight = displayRect.y + displayRect.height - y;
+               if (popUpwardsHeight > popDownwardsHeight) {
+                       height = popUpwardsHeight;
+                       y = parentRect.y - popUpwardsHeight;
+               } else {
+                       height = popDownwardsHeight;
+               }
+               listRect.height = height - 2;
+       }
+       /*
+        * Invisible HScrollBar lead to empty space at end of CCombo drop-down.
+        * Fix is to reduce height of list and shell in that case, bug 388126.
+        */
+       ScrollBar hBar = list.getHorizontalBar();
+       int emptyHBarSpace = hBar.isVisible () ? 0 : hBar.getSize ().y;
+       list.setSize (listRect.width, listRect.height - emptyHBarSpace);
+       popup.setBounds (x, y, width, height - emptyHBarSpace);
+       popup.setVisible (true);
+       if (isFocusControl()) list.setFocus ();
+
+       /*
+        * Add a filter to listen to scrolling of the parent composite, when the
+        * drop-down is visible. Remove the filter when drop-down is not
+        * visible.
+        */
+       display.removeFilter (SWT.Selection, filter);
+       display.addFilter (SWT.Selection, filter);
+}
+/*
+ * 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'.
+ */
+char _findMnemonic (String string) {
+       if (string == null) return '\0';
+       int index = 0;
+       int length = string.length ();
+       do {
+               while (index < length && string.charAt (index) != '&') index++;
+               if (++index >= length) return '\0';
+               if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
+               index++;
+       } while (index < length);
+       return '\0';
+}
+/*
+ * Return the Label immediately preceding the receiver in the z-order,
+ * or null if none.
+ */
+String getAssociatedLabel () {
+       Control[] siblings = getParent ().getChildren ();
+       for (int i = 0; i < siblings.length; i++) {
+               if (siblings [i] == this) {
+                       if (i > 0) {
+                               Control sibling = siblings [i-1];
+                               if (sibling instanceof Label) return ((Label) sibling).getText();
+                               if (sibling instanceof CLabel) return ((CLabel) sibling).getText();
+                       }
+                       break;
+               }
+       }
+       return null;
+}
+/**
+ * Returns the horizontal alignment.
+ * The alignment style (LEFT, CENTER or RIGHT) is returned.
+ *
+ * @return SWT.LEFT, SWT.RIGHT or SWT.CENTER
+ * @since 3.113
+ */
+public int getAlignment() {
+       return text.getStyle() & (SWT.LEFT | SWT.CENTER | SWT.RIGHT);
+}
+@Override
+public 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 boolean 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 boolean getListVisible () {
+       checkWidget ();
+       return isDropped();
+}
+@Override
+public 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 ();
+}
+@Override
+public Shell getShell () {
+       checkWidget ();
+       Shell shell = super.getShell ();
+       if (shell != _shell) {
+               if (_shell != null && !_shell.isDisposed ()) {
+                       _shell.removeListener (SWT.Deactivate, listener);
+               }
+               _shell = shell;
+       }
+       return _shell;
+}
+@Override
+public int getStyle () {
+       int style = super.getStyle ();
+       style &= ~SWT.READ_ONLY;
+       if (!text.getEditable()) style |= SWT.READ_ONLY;
+       style &= ~(SWT.LEFT | SWT.CENTER | SWT.RIGHT);
+       style |= getAlignment();
+       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) {
+       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 == arrow || focusControl == list || focusControl == 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;
+               }
+       }
+}
+void handleScroll(Event event) {
+       ScrollBar scrollBar = (ScrollBar)event.widget;
+       Control scrollableParent = scrollBar.getParent();
+       if (scrollableParent.equals(list)) return;
+       if (isParentScrolling(scrollableParent)) dropDown(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 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>
+ */
+public int indexOf (String string) {
+       checkWidget ();
+       if (string == 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 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>
+ */
+public int indexOf (String string, int start) {
+       checkWidget ();
+       if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return list.indexOf (string, start);
+}
+
+void initAccessible() {
+       AccessibleAdapter accessibleAdapter = new AccessibleAdapter () {
+               @Override
+               public void getName (AccessibleEvent e) {
+                       String name = null;
+                       String text = getAssociatedLabel ();
+                       if (text != null) {
+                               name = stripMnemonic (text);
+                       }
+                       e.result = name;
+               }
+               @Override
+               public void getKeyboardShortcut(AccessibleEvent e) {
+                       String shortcut = null;
+                       String text = getAssociatedLabel ();
+                       if (text != null) {
+                               char mnemonic = _findMnemonic (text);
+                               if (mnemonic != '\0') {
+                                       shortcut = "Alt+"+mnemonic; //$NON-NLS-1$
+                               }
+                       }
+                       e.result = shortcut;
+               }
+               @Override
+               public void getHelp (AccessibleEvent e) {
+                       e.result = getToolTipText ();
+               }
+       };
+       getAccessible ().addAccessibleListener (accessibleAdapter);
+       text.getAccessible ().addAccessibleListener (accessibleAdapter);
+       list.getAccessible ().addAccessibleListener (accessibleAdapter);
+
+       arrow.getAccessible ().addAccessibleListener (new AccessibleAdapter() {
+               @Override
+               public void getName (AccessibleEvent e) {
+                       e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$
+               }
+               @Override
+               public void getKeyboardShortcut (AccessibleEvent e) {
+                       e.result = "Alt+Down Arrow"; //$NON-NLS-1$
+               }
+               @Override
+               public void getHelp (AccessibleEvent e) {
+                       e.result = getToolTipText ();
+               }
+       });
+
+       getAccessible().addAccessibleTextListener (new AccessibleTextAdapter() {
+               @Override
+               public void getCaretOffset (AccessibleTextEvent e) {
+                       e.offset = text.getCaretPosition ();
+               }
+               @Override
+               public void getSelectionRange(AccessibleTextEvent e) {
+                       Point sel = text.getSelection();
+                       e.offset = sel.x;
+                       e.length = sel.y - sel.x;
+               }
+       });
+
+       getAccessible().addAccessibleControlListener (new AccessibleControlAdapter() {
+               @Override
+               public void getChildAtPoint (AccessibleControlEvent e) {
+                       Point testPoint = toControl (e.x, e.y);
+                       if (getBounds ().contains (testPoint)) {
+                               e.childID = ACC.CHILDID_SELF;
+                       }
+               }
+
+               @Override
+               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;
+               }
+
+               @Override
+               public void getChildCount (AccessibleControlEvent e) {
+                       e.detail = 0;
+               }
+
+               @Override
+               public void getRole (AccessibleControlEvent e) {
+                       e.detail = ACC.ROLE_COMBOBOX;
+               }
+
+               @Override
+               public void getState (AccessibleControlEvent e) {
+                       e.detail = ACC.STATE_NORMAL;
+               }
+
+               @Override
+               public void getValue (AccessibleControlEvent e) {
+                       e.result = getText ();
+               }
+       });
+
+       text.getAccessible ().addAccessibleControlListener (new AccessibleControlAdapter () {
+               @Override
+               public void getRole (AccessibleControlEvent e) {
+                       e.detail = text.getEditable () ? ACC.ROLE_TEXT : ACC.ROLE_LABEL;
+               }
+       });
+
+       arrow.getAccessible ().addAccessibleControlListener (new AccessibleControlAdapter() {
+               @Override
+               public void getDefaultAction (AccessibleControlEvent e) {
+                       e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$
+               }
+       });
+}
+boolean isDropped () {
+       return !isDisposed() && popup.getVisible ();
+}
+@Override
+public boolean isFocusControl () {
+       checkWidget();
+       Predicate<Control> checkFocusControl = (control) -> (control != null && !control.isDisposed() && control.isFocusControl ());
+       if (checkFocusControl.test(text) || checkFocusControl.test(arrow) ||
+                       checkFocusControl.test(list) || checkFocusControl.test(popup)) {
+               return true;
+       }
+       return super.isFocusControl ();
+}
+
+boolean isParentScrolling(Control scrollableParent) {
+       Control parent = this.getParent();
+       while (parent != null) {
+               if (parent.equals(scrollableParent))
+                       return true;
+               parent = parent.getParent();
+       }
+       return false;
+}
+void internalLayout (boolean 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 () != 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.FocusOut: {
+                       /*
+                        * Behavior in Windows, GTK & Cocoa: When the arrow button is pressed
+                        * with the popup list visible, the following events are received-
+                        * popup control receives a deactivate event,
+                        * list receives focus lost event, and then
+                        * arrow button receives a selection event.
+                        * If we hide the popup in the focus out event, the selection event will
+                        * show it again. To prevent the popup from showing again, we will detect
+                        * this case and let the selection event of the arrow button hide the popup.
+                        */
+                       Point point = arrow.toControl(getDisplay().getCursorLocation());
+                       Point size = arrow.getSize();
+                       Rectangle rect = new Rectangle(0, 0, size.x, size.y);
+                       if (rect.contains(point)) {
+                               boolean comboShellActivated = getDisplay ().getActiveShell () == getShell ();
+                               if (!comboShellActivated) dropDown (false);
+                               break;
+                       }
+                       dropDown (false);
+                       break;
+               }
+               case SWT.MouseUp: {
+                       if (event.button != 1) return;
+                       dropDown (false);
+                       break;
+               }
+               case SWT.Selection: {
+                       int index = list.getSelectionIndex ();
+                       if (index == -1) return;
+                       text.setText (list.getItem (index));
+                       if (text.getEditable() && text.isFocusControl()) 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;
+                       }
+                       Event e = new Event ();
+                       e.time = event.time;
+                       e.detail = event.detail;
+                       e.doit = event.doit;
+                       e.character = event.character;
+                       e.keyCode = event.keyCode;
+                       e.keyLocation = event.keyLocation;
+                       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.keyLocation = event.keyLocation;
+                       e.stateMask = event.stateMask;
+                       notifyListeners (SWT.KeyUp, e);
+                       event.doit = e.doit;
+                       break;
+               }
+               case SWT.KeyDown: {
+                       if (event.character == SWT.ESC) {
+                               // Escape key cancels popup list
+                               dropDown (false);
+                       }
+                       if ((event.stateMask & SWT.ALT) != 0 && (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN)) {
+                               dropDown (false);
+                       }
+                       if (event.character == 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.keyLocation = event.keyLocation;
+                       e.stateMask = event.stateMask;
+                       notifyListeners(SWT.KeyDown, e);
+                       event.doit = e.doit;
+                       break;
+
+               }
+       }
+}
+/**
+ * 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;
+       }
+}
+@Override
+public void redraw () {
+       super.redraw();
+       text.redraw();
+       arrow.redraw();
+       if (popup.isVisible()) list.redraw();
+}
+@Override
+public void redraw (int x, int y, int width, int height, boolean 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_NULL_ARGUMENT - if the string is null</li>
+ *    <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();
+       if (string == 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.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 == 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 == 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 == 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 == -1) {
+               list.deselectAll ();
+               text.setText (""); //$NON-NLS-1$
+               return;
+       }
+       if (0 <= index && index < list.getItemCount()) {
+               if (index != getSelectionIndex()) {
+                       text.setText (list.getItem (index));
+                       if (text.getEditable() && text.isFocusControl()) text.selectAll ();
+                       list.select (index);
+                       list.showSelection ();
+               }
+       }
+}
+
+/**
+ * Set the horizontal alignment of the CCombo.
+ * 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>
+ * @since 3.113
+ */
+public void setAlignment(int align) {
+       checkWidget();
+       int styleWithoutAlign = getStyle() & ~(SWT.LEFT | SWT.CENTER | SWT.RIGHT);
+       createText(styleWithoutAlign | align);
+}
+@Override
+public void setBackground (Color color) {
+       super.setBackground(color);
+       background = color;
+       if (text != null) text.setBackground(color);
+       if (list != null) list.setBackground(color);
+       if (arrow != 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 (boolean editable) {
+       checkWidget ();
+       text.setEditable(editable);
+}
+@Override
+public void setEnabled (boolean enabled) {
+       super.setEnabled(enabled);
+       if (popup != null) popup.setVisible (false);
+       if (text != null) text.setEnabled(enabled);
+       if (arrow != null) arrow.setEnabled(enabled);
+}
+@Override
+public boolean setFocus () {
+       checkWidget();
+       if (!isEnabled () || !getVisible ()) return false;
+       if (isFocusControl ()) return true;
+       return text.setFocus ();
+}
+@Override
+public void setFont (Font font) {
+       super.setFont (font);
+       this.font = font;
+       text.setFont (font);
+       list.setFont (font);
+       internalLayout (true);
+}
+@Override
+public void setForeground (Color color) {
+       super.setForeground(color);
+       foreground = color;
+       if (text != null) text.setForeground(color);
+       if (list != null) list.setForeground(color);
+       if (arrow != 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>
+ *    <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>
+ */
+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_NULL_ARGUMENT - if the items array is null</li>
+ *    <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>
+ */
+@Override
+public 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 (boolean visible) {
+       checkWidget ();
+       dropDown(visible);
+}
+@Override
+public 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 == 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><p>
+ * Also note, if control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @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>
+ */
+public void setText (String string) {
+       checkWidget();
+       if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       int index = list.indexOf (string);
+       if (index == -1) {
+               list.deselectAll ();
+               text.setText (string);
+               return;
+       }
+       text.setText (string);
+       if (text.getEditable() && text.isFocusControl()) 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);
+}
+
+@Override
+public void setToolTipText (String string) {
+       checkWidget();
+       super.setToolTipText(string);
+       arrow.setToolTipText (string);
+       text.setToolTipText (string);
+}
+
+@Override
+public void setVisible (boolean 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 == 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.charAt (index) != '&')) index++;
+               if (++index >= length) return string;
+               if (string.charAt (index) != '&') {
+                       return string.substring(0, index-1) + string.substring(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.DragDetect:
+               case SWT.MouseDoubleClick:
+               case SWT.MouseMove:
+               case SWT.MouseEnter:
+               case SWT.MouseExit:
+               case SWT.MouseHover: {
+                       Point pt = getDisplay ().map (text, this, event.x, event.y);
+                       event.x = pt.x; event.y = pt.y;
+                       notifyListeners (event.type, event);
+                       event.type = SWT.None;
+                       break;
+               }
+               case SWT.KeyDown: {
+                       Event keyEvent = new Event ();
+                       keyEvent.time = event.time;
+                       keyEvent.character = event.character;
+                       keyEvent.keyCode = event.keyCode;
+                       keyEvent.keyLocation = event.keyLocation;
+                       keyEvent.stateMask = event.stateMask;
+                       notifyListeners (SWT.KeyDown, keyEvent);
+                       if (isDisposed ()) break;
+                       event.doit = keyEvent.doit;
+                       if (!event.doit) break;
+                       if (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN) {
+                               event.doit = false;
+                               if ((event.stateMask & SWT.ALT) != 0) {
+                                       boolean dropped = isDropped ();
+                                       if (text.getEditable() && text.isFocusControl()) text.selectAll ();
+                                       if (!dropped) setFocus ();
+                                       dropDown (!dropped);
+                                       break;
+                               }
+
+                               int oldIndex = getSelectionIndex ();
+                               if (event.keyCode == SWT.ARROW_UP) {
+                                       select (Math.max (oldIndex - 1, 0));
+                               } else {
+                                       select (Math.min (oldIndex + 1, getItemCount () - 1));
+                               }
+                               if (oldIndex != 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.keyLocation = event.keyLocation;
+                       e.stateMask = event.stateMask;
+                       notifyListeners (SWT.KeyUp, e);
+                       event.doit = e.doit;
+                       break;
+               }
+               case SWT.MenuDetect: {
+                       Event e = new Event ();
+                       e.time = event.time;
+                       e.detail = event.detail;
+                       e.x = event.x;
+                       e.y = event.y;
+                       if (event.detail == SWT.MENU_KEYBOARD) {
+                               Point pt = getDisplay().map(text, null, text.getCaretLocation());
+                               e.x = pt.x;
+                               e.y = pt.y;
+                       }
+                       notifyListeners (SWT.MenuDetect, e);
+                       event.doit = e.doit;
+                       event.x = e.x;
+                       event.y = e.y;
+                       break;
+               }
+               case SWT.Modify: {
+                       list.deselectAll ();
+                       Event e = new Event ();
+                       e.time = event.time;
+                       notifyListeners (SWT.Modify, e);
+                       break;
+               }
+               case SWT.MouseDown: {
+                       Point pt = getDisplay ().map (text, this, event.x, event.y);
+                       Event mouseEvent = new Event ();
+                       mouseEvent.button = event.button;
+                       mouseEvent.count = event.count;
+                       mouseEvent.stateMask = event.stateMask;
+                       mouseEvent.time = event.time;
+                       mouseEvent.x = pt.x; mouseEvent.y = pt.y;
+                       notifyListeners (SWT.MouseDown, mouseEvent);
+                       if (isDisposed ()) break;
+                       event.doit = mouseEvent.doit;
+                       if (!event.doit) break;
+                       if (event.button != 1) return;
+                       if (text.getEditable ()) return;
+                       boolean dropped = isDropped ();
+                       if (text.getEditable() && text.isFocusControl()) text.selectAll ();
+                       if (!dropped) setFocus ();
+                       dropDown (!dropped);
+                       break;
+               }
+               case SWT.MouseUp: {
+                       Point pt = getDisplay ().map (text, this, event.x, event.y);
+                       Event mouseEvent = new Event ();
+                       mouseEvent.button = event.button;
+                       mouseEvent.count = event.count;
+                       mouseEvent.stateMask = event.stateMask;
+                       mouseEvent.time = event.time;
+                       mouseEvent.x = pt.x; mouseEvent.y = pt.y;
+                       notifyListeners (SWT.MouseUp, mouseEvent);
+                       if (isDisposed ()) break;
+                       event.doit = mouseEvent.doit;
+                       if (!event.doit) break;
+                       if (event.button != 1) return;
+                       if (text.getEditable ()) return;
+                       if (text.getEditable() && text.isFocusControl()) text.selectAll ();
+                       break;
+               }
+               case SWT.MouseWheel: {
+                       notifyListeners (SWT.MouseWheel, event);
+                       event.type = SWT.None;
+                       if (isDisposed ()) break;
+                       if (!event.doit) break;
+                       if (event.count != 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 != 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;
+                       }
+                       Event e = new Event ();
+                       e.time = event.time;
+                       e.detail = event.detail;
+                       e.doit = event.doit;
+                       e.character = event.character;
+                       e.keyCode = event.keyCode;
+                       e.keyLocation = event.keyLocation;
+                       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.keyLocation = event.keyLocation;
+                       e.stateMask = event.stateMask;
+                       notifyListeners (SWT.Verify, e);
+                       event.text = e.text;
+                       event.doit = e.doit;
+                       break;
+               }
+       }
+}
+@Override
+public boolean traverse(int event){
+       /*
+        * When the traverse event is sent to the CCombo, it will create a list of
+        * controls to tab to next. Since the CCombo is a composite, the next control is
+        * the Text field which is a child of the CCombo. It will set focus to the text
+        * field which really is itself. So, call the traverse next events directly on the text.
+        */
+       if (event == SWT.TRAVERSE_ARROW_NEXT || event == SWT.TRAVERSE_TAB_NEXT) {
+               return text.traverse(event);
+       }
+       return super.traverse(event);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CLabel.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CLabel.java
new file mode 100644 (file)
index 0000000..832db17
--- /dev/null
@@ -0,0 +1,1029 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>LEFT, RIGHT, CENTER, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
+ * <dt><b>Events:</b>
+ * <dd>(NONE)</dd>
+ * </dl>
+ *
+ *<p>
+ * This class may be subclassed for the purpose of overriding the default string
+ * shortening algorithm that is implemented in method <code>shortenText()</code>.
+ * </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>
+ * @see CLabel#shortenText(GC, String, int)
+ */
+public class CLabel extends Canvas {
+
+       /** Gap between icon and text */
+       private static final int GAP = 5;
+       /** Left and right margins */
+       private static final int DEFAULT_MARGIN = 3;
+       /** a string inserted in the middle of text that has been shortened */
+       private static final 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 leftMargin = DEFAULT_MARGIN;
+       private int topMargin = DEFAULT_MARGIN;
+       private int rightMargin = DEFAULT_MARGIN;
+       private int bottomMargin = DEFAULT_MARGIN;
+       /** 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 boolean ignoreDispose;
+
+       private Image backgroundImage;
+       private Color[] gradientColors;
+       private int[] gradientPercents;
+       private boolean 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 CLabel(Composite parent, int style) {
+       super(parent, checkStyle(style));
+       if ((style & (SWT.CENTER | SWT.RIGHT)) == 0) style |= SWT.LEFT;
+       if ((style & SWT.CENTER) != 0) align = SWT.CENTER;
+       if ((style & SWT.RIGHT) != 0)  align = SWT.RIGHT;
+       if ((style & SWT.LEFT) != 0)   align = SWT.LEFT;
+
+       addPaintListener(event -> onPaint(event));
+
+       addTraverseListener(event -> {
+               if (event.detail == SWT.TRAVERSE_MNEMONIC) {
+                       onMnemonic(event);
+               }
+       });
+
+       addListener(SWT.Dispose, event -> onDispose(event));
+
+       initAccessible();
+
+}
+/**
+ * Check the style bits to ensure that no invalid styles are applied.
+ */
+private static int checkStyle (int style) {
+       if ((style & SWT.BORDER) != 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;
+}
+
+@Override
+public Point computeSize(int wHint, int hHint, boolean changed) {
+       checkWidget();
+       Point e = getTotalSize(image, text);
+       if (wHint == SWT.DEFAULT){
+               e.x += leftMargin + rightMargin;
+       } else {
+               e.x = wHint;
+       }
+       if (hHint == SWT.DEFAULT) {
+               e.y += topMargin + bottomMargin;
+       } 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'.
+ */
+char _findMnemonic (String string) {
+       if (string == null) return '\0';
+       int index = 0;
+       int length = string.length ();
+       do {
+               while (index < length && string.charAt (index) != '&') index++;
+               if (++index >= length) return '\0';
+               if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
+               index++;
+       } while (index < length);
+       return '\0';
+}
+/**
+ * Returns the horizontal alignment.
+ * The alignment style (LEFT, CENTER or RIGHT) is returned.
+ *
+ * @return SWT.LEFT, SWT.RIGHT or SWT.CENTER
+ */
+public int getAlignment() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return align;
+}
+/**
+ * Return the CLabel's bottom margin.
+ *
+ * @return the bottom margin of the label
+ *
+ * @since 3.6
+ */
+public int getBottomMargin() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return bottomMargin;
+}
+/**
+ * Return the CLabel's image or <code>null</code>.
+ *
+ * @return the image of the label or null
+ */
+public Image getImage() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return image;
+}
+/**
+ * Return the CLabel's left margin.
+ *
+ * @return the left margin of the label
+ *
+ * @since 3.6
+ */
+public int getLeftMargin() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return leftMargin;
+}
+/**
+ * Return the CLabel's right margin.
+ *
+ * @return the right margin of the label
+ *
+ * @since 3.6
+ */
+public int getRightMargin() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return rightMargin;
+}
+/**
+ * Compute the minimum size.
+ */
+private Point getTotalSize(Image image, String text) {
+       Point size = new Point(0, 0);
+
+       if (image != null) {
+               Rectangle r = image.getBounds();
+               size.x += r.width;
+               size.y += r.height;
+       }
+
+       GC gc = new GC(this);
+       if (text != 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 != null) size.x += GAP;
+       } else {
+               size.y = Math.max(size.y, gc.getFontMetrics().getHeight());
+       }
+       gc.dispose();
+
+       return size;
+}
+@Override
+public 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;
+       }
+       return style;
+}
+
+/**
+ * Return the Label's text.
+ *
+ * @return the text of the label or null
+ */
+public String getText() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return text;
+}
+@Override
+public String getToolTipText () {
+       checkWidget();
+       return appToolTipText;
+}
+/**
+ * Return the CLabel's top margin.
+ *
+ * @return the top margin of the label
+ *
+ * @since 3.6
+ */
+public int getTopMargin() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return topMargin;
+}
+private void initAccessible() {
+       Accessible accessible = getAccessible();
+       accessible.addAccessibleListener(new AccessibleAdapter() {
+               @Override
+               public void getName(AccessibleEvent e) {
+                       e.result = getText();
+               }
+
+               @Override
+               public void getHelp(AccessibleEvent e) {
+                       e.result = getToolTipText();
+               }
+
+               @Override
+               public void getKeyboardShortcut(AccessibleEvent e) {
+                       char mnemonic = _findMnemonic(CLabel.this.text);
+                       if (mnemonic != '\0') {
+                               e.result = "Alt+"+mnemonic; //$NON-NLS-1$
+                       }
+               }
+       });
+
+       accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
+               @Override
+               public void getChildAtPoint(AccessibleControlEvent e) {
+                       e.childID = ACC.CHILDID_SELF;
+               }
+
+               @Override
+               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;
+               }
+
+               @Override
+               public void getChildCount(AccessibleControlEvent e) {
+                       e.detail = 0;
+               }
+
+               @Override
+               public void getRole(AccessibleControlEvent e) {
+                       e.detail = ACC.ROLE_LABEL;
+               }
+
+               @Override
+               public void getState(AccessibleControlEvent e) {
+                       e.detail = ACC.STATE_READONLY;
+               }
+       });
+}
+void onDispose(Event event) {
+       /* make this handler run after other dispose listeners */
+       if (ignoreDispose) {
+               ignoreDispose = false;
+               return;
+       }
+       ignoreDispose = true;
+       notifyListeners (event.type, event);
+       event.type = SWT.NONE;
+
+       gradientColors = null;
+       gradientPercents = null;
+       backgroundImage = null;
+       text = null;
+       image = null;
+       appToolTipText = null;
+}
+void onMnemonic(TraverseEvent event) {
+       char mnemonic = _findMnemonic(text);
+       if (mnemonic == '\0') return;
+       if (Character.toLowerCase(event.character) != mnemonic) return;
+       Composite control = this.getParent();
+       while (control != null) {
+               Control [] children = control.getChildren();
+               int index = 0;
+               while (index < children.length) {
+                       if (children [index] == 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 == 0 || rect.height == 0) return;
+
+       boolean shortenText = false;
+       String t = text;
+       Image img = image;
+       int availableWidth = Math.max(0, rect.width - (leftMargin + rightMargin));
+       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 == 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 == null) {
+                       super.setToolTipText(text);
+               }
+       } else {
+               super.setToolTipText(appToolTipText);
+       }
+
+       // determine horizontal position
+       int x = rect.x + leftMargin;
+       if (align == SWT.CENTER) {
+               x = (rect.width - extent.x)/2;
+       }
+       if (align == SWT.RIGHT) {
+               x = rect.width - rightMargin - extent.x;
+       }
+
+       // draw a background image behind the text
+       try {
+               if (backgroundImage != 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 != null) {
+                       // draw a gradient behind the text
+                       final Color oldBackground = gc.getBackground();
+                       if (gradientColors.length == 1) {
+                               if (gradientColors[0] != 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 == null) lastColor = oldBackground;
+                               int pos = 0;
+                               for (int i = 0; i < gradientPercents.length; ++i) {
+                                       gc.setForeground(lastColor);
+                                       lastColor = gradientColors[i + 1];
+                                       if (lastColor == 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 != null || (getStyle() & SWT.DOUBLE_BUFFERED) == 0) && background.getAlpha() > 0) {
+                               gc.setBackground(getBackground());
+                               gc.fillRectangle(rect);
+                       }
+               }
+       } catch (SWTException e) {
+               if ((getStyle() & SWT.DOUBLE_BUFFERED) == 0) {
+                       gc.setBackground(getBackground());
+                       gc.fillRectangle(rect);
+               }
+       }
+
+       // draw border
+       int style = getStyle();
+       if ((style & SWT.SHADOW_IN) != 0 || (style & SWT.SHADOW_OUT) != 0) {
+               paintBorder(gc, rect);
+       }
+
+       /*
+        * Compute text height and image height. If image height is more than
+        * the text height, draw image starting from top margin. Else draw text
+        * starting from top margin.
+        */
+       Rectangle imageRect = null;
+       int lineHeight = 0, textHeight = 0, imageHeight = 0;
+
+       if (img != null) {
+               imageRect = img.getBounds();
+               imageHeight = imageRect.height;
+       }
+       if (lines != null) {
+               lineHeight = gc.getFontMetrics().getHeight();
+               textHeight = lines.length * lineHeight;
+       }
+
+       int imageY = 0, midPoint = 0, lineY = 0;
+       if (imageHeight > textHeight ) {
+               if (topMargin == DEFAULT_MARGIN && bottomMargin == DEFAULT_MARGIN) imageY = rect.y + (rect.height - imageHeight) / 2;
+               else imageY = topMargin;
+               midPoint = imageY + imageHeight/2;
+               lineY = midPoint - textHeight / 2;
+       }
+       else {
+               if (topMargin == DEFAULT_MARGIN && bottomMargin == DEFAULT_MARGIN) lineY = rect.y + (rect.height - textHeight) / 2;
+               else lineY = topMargin;
+               midPoint = lineY + textHeight/2;
+               imageY = midPoint - imageHeight / 2;
+       }
+
+       // draw the image
+       if (img != null) {
+               gc.drawImage(img, 0, 0, imageRect.width, imageHeight,
+                                               x, imageY, imageRect.width, imageHeight);
+               x +=  imageRect.width + GAP;
+               extent.x -= imageRect.width + GAP;
+       }
+
+       // draw the text
+       if (lines != null) {
+               gc.setForeground(getForeground());
+               for (int i = 0; i < lines.length; i++) {
+                       int lineX = x;
+                       if (lines.length > 1) {
+                               if (align == SWT.CENTER) {
+                                       int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+                                       lineX = x + Math.max(0, (extent.x - lineWidth) / 2);
+                               }
+                               if (align == SWT.RIGHT) {
+                                       int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+                                       lineX = Math.max(x, rect.x + rect.width - rightMargin - 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) != 0) {
+               c1 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+               c2 = disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+       }
+       if ((style & SWT.SHADOW_OUT) != 0) {
+               c1 = disp.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+               c2 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+       }
+
+       if (c1 != null && c2 != null) {
+               gc.setLineWidth(1);
+               drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2);
+       }
+}
+/**
+ * Set the horizontal 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 != SWT.LEFT && align != SWT.RIGHT && align != SWT.CENTER) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (this.align != align) {
+               this.align = align;
+               redraw();
+       }
+}
+
+@Override
+public void setBackground (Color color) {
+       super.setBackground (color);
+       // Are these settings the same as before?
+       if (backgroundImage == null &&
+               gradientColors == null &&
+               gradientPercents == null) {
+               if (color == null) {
+                       if (background == null) return;
+               } else {
+                       if (color.equals(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, boolean vertical) {
+       checkWidget();
+       if (colors != null) {
+               if (percents == null || percents.length != colors.length - 1) {
+                       SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+               if (getDisplay().getDepth() < 15) {
+                       // Don't use gradients on low color displays
+                       colors = new Color[] {colors[colors.length - 1]};
+                       percents = new int[] { };
+               }
+               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 == null) {
+               if ((gradientColors != null) && (colors != null) &&
+                       (gradientColors.length == colors.length)) {
+                       boolean same = false;
+                       for (int i = 0; i < gradientColors.length; i++) {
+                               same = (gradientColors[i] == colors[i]) ||
+                                       ((gradientColors[i] == null) && (colors[i] == background)) ||
+                                       ((gradientColors[i] == background) && (colors[i] == null));
+                               if (!same) break;
+                       }
+                       if (same) {
+                               for (int i = 0; i < gradientPercents.length; i++) {
+                                       same = gradientPercents[i] == percents[i];
+                                       if (!same) break;
+                               }
+                       }
+                       if (same && this.gradientVertical == vertical) return;
+               }
+       } else {
+               backgroundImage = null;
+       }
+       // Store the new settings
+       if (colors == 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] != 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 == backgroundImage) return;
+       if (image != null) {
+               gradientColors = null;
+               gradientPercents = null;
+       }
+       backgroundImage = image;
+       redraw();
+
+}
+/**
+ * Set the label's bottom margin, in points.
+ *
+ * @param bottomMargin the bottom margin of the label, which must be equal to or 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>
+ *
+ * @since 3.6
+ */
+public void setBottomMargin(int bottomMargin) {
+       checkWidget();
+       if (this.bottomMargin == bottomMargin || bottomMargin < 0) return;
+       this.bottomMargin = bottomMargin;
+       redraw();
+}
+@Override
+public 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 != this.image) {
+               this.image = image;
+               redraw();
+       }
+}
+/**
+ * Set the label's horizontal left margin, in points.
+ *
+ * @param leftMargin the left margin of the label, which must be equal to or 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>
+ *
+ * @since 3.6
+ */
+public void setLeftMargin(int leftMargin) {
+       checkWidget();
+       if (this.leftMargin == leftMargin || leftMargin < 0) return;
+       this.leftMargin = leftMargin;
+       redraw();
+}
+/**
+ * Set the label's margins, in points.
+ *
+ * @param leftMargin the left margin.
+ * @param topMargin the top margin.
+ * @param rightMargin the right margin.
+ * @param bottomMargin the bottom margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.6
+ */
+public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
+       checkWidget();
+       this.leftMargin = Math.max(0, leftMargin);
+       this.topMargin = Math.max(0, topMargin);
+       this.rightMargin = Math.max(0, rightMargin);
+       this.bottomMargin = Math.max(0, bottomMargin);
+       redraw();
+}
+/**
+ * Set the label's right margin, in points.
+ *
+ * @param rightMargin the right margin of the label, which must be equal to or 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>
+ *
+ * @since 3.6
+ */
+public void setRightMargin(int rightMargin) {
+       checkWidget();
+       if (this.rightMargin == rightMargin || rightMargin < 0) return;
+       this.rightMargin = rightMargin;
+       redraw();
+}
+/**
+ * Set the label's text.
+ * The value <code>null</code> clears it.
+ * <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><p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @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 == null) text = ""; //$NON-NLS-1$
+       if (! text.equals(this.text)) {
+               this.text = text;
+               redraw();
+       }
+}
+@Override
+public void setToolTipText (String string) {
+       super.setToolTipText (string);
+       appToolTipText = super.getToolTipText();
+}
+/**
+ * Set the label's top margin, in points.
+ *
+ * @param topMargin the top margin of the label, which must be equal to or 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>
+ *
+ * @since 3.6
+ */
+public void setTopMargin(int topMargin) {
+       checkWidget();
+       if (this.topMargin == topMargin || topMargin < 0) return;
+       this.topMargin = topMargin;
+       redraw();
+}
+/**
+ * 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 points
+ * @return the shortened text
+ */
+protected String shortenText(GC gc, String t, int width) {
+       if (t == 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.substring(0, mid);
+               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 == 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 != 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 = text.indexOf('\n', start);
+               if (pos == -1) {
+                       lines[lines.length - 1] = text.substring(start);
+               } else {
+                       boolean crlf = (pos > 0) && (text.charAt(pos - 1) == '\r');
+                       lines[lines.length - 1] = text.substring(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 != -1);
+       return lines;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CLayoutData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CLayoutData.java
new file mode 100644 (file)
index 0000000..659291f
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+class CLayoutData {
+
+       int defaultWidth = -1, defaultHeight = -1;
+       int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+
+Point computeSize (Control control, int wHint, int hHint, boolean flushCache) {
+       if (flushCache) flushCache();
+       if (wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
+               if (defaultWidth == -1 || defaultHeight == -1) {
+                       Point size = control.computeSize (wHint, hHint, flushCache);
+                       defaultWidth = size.x;
+                       defaultHeight = size.y;
+               }
+               return new Point(defaultWidth, defaultHeight);
+       }
+       if (currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder.java
new file mode 100644 (file)
index 0000000..63d9676
--- /dev/null
@@ -0,0 +1,4137 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.DPIUtil.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ *
+ * 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>
+ * <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>
+ * Note: Only one of the styles TOP and BOTTOM
+ * may be specified.
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class CTabFolder extends Composite {
+
+       /**
+        * marginWidth specifies the number of points 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 points 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)
+        */
+       @Deprecated
+       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
+        */
+       @Deprecated
+       public static RGB borderInsideRGB  = new RGB (132, 130, 132);
+       /**
+        * 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
+        */
+       @Deprecated
+       public static RGB borderMiddleRGB  = new RGB (143, 141, 138);
+       /**
+        * 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
+        */
+       @Deprecated
+       public static RGB borderOutsideRGB = new RGB (171, 168, 165);
+
+       /* sizing, positioning */
+       boolean onBottom = false;
+       boolean single = false;
+       boolean simple = true;
+       int fixedTabHeight = SWT.DEFAULT;
+       int tabHeight;
+       int minChars = 20;
+       boolean borderVisible = false;
+
+       /* item management */
+       CTabFolderRenderer renderer;
+       CTabItem items[] = new CTabItem[0];
+       /** index of the left most visible tab. */
+       int firstIndex = -1;
+       int selectedIndex = -1;
+
+       /**
+        * Indices of the elements in the {@link #items} array, used to manage tab
+        * visibility and candidates to be hidden/shown next.
+        * <p>
+        * If there is not enough place for all tabs, tabs starting from the end of
+        * the {@link #priority} array will be hidden first (independently from the
+        * {@link #mru} flag!) =&gt; the right most elements have the highest priority
+        * to be hidden.
+        * <p>
+        * If there is more place to show previously hidden tabs, tabs starting from
+        * the beginning of the {@link #priority} array will be made visible first
+        * (independently from the {@link #mru} flag!) =&gt; the left most elements
+        * have the highest priority to be shown.
+        * <p>
+        * The update strategy of the {@link #priority} array however depends on the
+        * {@link #mru} flag.
+        * <p>
+        * If {@link #mru} flag is set, the first index is always the index of the
+        * currently selected tab, next one is the tab selected before current
+        * etc...
+        * <p>
+        * Example: [4,2,5,1,3,0], just representing the last selection order.
+        * <p>
+        * If {@link #mru} flag is not set, the first index is always the index of
+        * the left most visible tab ({@link #firstIndex} field), next indices are
+        * incremented by one up to <code>priority.length-1</code>, and the rest
+        * filled with indices starting with <code>firstIndex-1</code> and
+        * decremented by one until 0 index is reached.
+        * <p>
+        * The tabs between first index and the index of the currently selected tab
+        * are always visible.
+        * <p>
+        * Example: 6 tabs, 2 and 3 are indices of currently shown tabs:
+        * [2,3,4,5,1,0]. The array consists of two blocks: sorted ascending from
+        * first visible (2) to last available (5), and the rest sorted descending
+        * (1,0). 4 and 5 are the hidden tabs on the right side, 0 and 1 are the
+        * hidden tabs on the left side from the visible tabs 2 and 3.
+        *
+        * @see #updateItems(int)
+        * @see #setItemLocation(GC)
+        */
+       int[] priority = new int[0];
+       boolean mru = false;
+       Listener listener;
+       boolean ignoreTraverse;
+       boolean useDefaultRenderer;
+
+       /* External Listener management */
+       CTabFolder2Listener[] folderListeners = new CTabFolder2Listener[0];
+       // support for deprecated listener mechanism
+       CTabFolderListener[] tabListeners = new CTabFolderListener[0];
+
+       /* Selected item appearance */
+       Image selectionBgImage;
+       Color[] selectionGradientColors;
+       int[] selectionGradientPercents;
+       boolean selectionGradientVertical;
+       Color selectionForeground;
+       Color selectionBackground;
+
+       /* Unselected item appearance */
+       Color[] gradientColors;
+       int[] gradientPercents;
+       boolean gradientVertical;
+       boolean showUnselectedImage = true;
+
+       // close, min/max and chevron buttons
+       boolean showClose = false;
+       boolean showUnselectedClose = true;
+
+       boolean showMin = false;
+       boolean minimized = false;
+       boolean showMax = false;
+       boolean maximized = false;
+       ToolBar minMaxTb;
+       ToolItem maxItem;
+       ToolItem minItem;
+       Image maxImage;
+       Image minImage;
+       boolean hoverTb;
+       Rectangle hoverRect = new Rectangle(0,0,0,0);
+       boolean hovering;
+       boolean hoverTimerRunning;
+       boolean highlight;
+       boolean highlightEnabled = true;
+
+       boolean showChevron = false;
+       Menu showMenu;
+       ToolBar chevronTb;
+       ToolItem chevronItem;
+       int chevronCount;
+       boolean chevronVisible = true;
+
+       Image chevronImage;
+       Control topRight;
+       int topRightAlignment = SWT.RIGHT;
+       boolean ignoreResize;
+       Control[] controls;
+       int[] controlAlignments;
+       Rectangle[] controlRects;
+       Image[] controlBkImages;
+
+       int updateFlags;
+       final static int REDRAW = 1 << 1;
+       final static int REDRAW_TABS = 1 << 2;
+       final static int UPDATE_TAB_HEIGHT = 1 << 3;
+       Runnable updateRun;
+
+       // when disposing CTabFolder, don't try to layout the items or
+       // change the selection as each child is destroyed.
+       boolean inDispose = false;
+
+       // keep track of size changes in order to redraw only affected area
+       // on Resize
+       Point oldSize;
+       Font oldFont;
+
+       // internal constants
+       static final int DEFAULT_WIDTH = 64;
+       static final int DEFAULT_HEIGHT = 64;
+
+       static final int SELECTION_FOREGROUND = SWT.COLOR_LIST_FOREGROUND;
+       static final int SELECTION_BACKGROUND = SWT.COLOR_LIST_BACKGROUND;
+
+       static final int FOREGROUND = SWT.COLOR_WIDGET_FOREGROUND;
+       static final int BACKGROUND = SWT.COLOR_WIDGET_BACKGROUND;
+
+       //TODO: add setter for spacing?
+       static final int SPACING = 3;
+/**
+ * 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 CTabFolder(Composite parent, int style) {
+       super(parent, checkStyle (parent, style));
+       init(style);
+}
+
+void init(int style) {
+       super.setLayout(new CTabFolderLayout());
+       int style2 = super.getStyle();
+       oldFont = getFont();
+       onBottom = (style2 & SWT.BOTTOM) != 0;
+       showClose = (style2 & SWT.CLOSE) != 0;
+//     showMin = (style2 & SWT.MIN) != 0; - conflicts with SWT.TOP
+//     showMax = (style2 & SWT.MAX) != 0; - conflicts with SWT.BOTTOM
+       single = (style2 & SWT.SINGLE) != 0;
+       borderVisible = (style & SWT.BORDER) != 0;
+       //set up default colors
+       Display display = getDisplay();
+       selectionForeground = display.getSystemColor(SELECTION_FOREGROUND);
+       selectionBackground = display.getSystemColor(SELECTION_BACKGROUND);
+       renderer = new CTabFolderRenderer(this);
+       useDefaultRenderer = true;
+       controls = new Control[0];
+       controlAlignments = new int[0];
+       controlRects = new Rectangle[0];
+       controlBkImages = new Image[0];
+       updateTabHeight(false);
+
+       // Add all listeners
+       listener = 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.MenuDetect:       onMenuDetect(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.MouseHover:       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(event);     break;
+                       case SWT.Traverse:         onTraverse(event); break;
+                       case SWT.Selection:        onSelection(event); break;
+                       case SWT.Activate:         onActivate(event); break;
+                       case SWT.Deactivate:       onDeactivate(event); break;
+               }
+       };
+
+       int[] folderEvents = new int[]{
+               SWT.Dispose,
+               SWT.DragDetect,
+               SWT.FocusIn,
+               SWT.FocusOut,
+               SWT.KeyDown,
+               SWT.MenuDetect,
+               SWT.MouseDoubleClick,
+               SWT.MouseDown,
+               SWT.MouseEnter,
+               SWT.MouseExit,
+               SWT.MouseHover,
+               SWT.MouseMove,
+               SWT.MouseUp,
+               SWT.Paint,
+               SWT.Resize,
+               SWT.Traverse,
+               SWT.Activate,
+               SWT.Deactivate
+       };
+       for (int i = 0; i < folderEvents.length; i++) {
+               addListener(folderEvents[i], listener);
+       }
+
+       initAccessible();
+}
+void onDeactivate(Event event) {
+       if (!highlightEnabled) {
+               return;
+       }
+       this.highlight = false;
+       redraw();
+}
+
+void onActivate(Event event) {
+       if (!highlightEnabled) {
+               return;
+       }
+       this.highlight = true;
+       redraw();
+}
+
+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) != 0) style = style & ~SWT.BOTTOM;
+       // SINGLE and MULTI are mutually exclusive.
+       // MULTI is the default
+       if ((style & SWT.MULTI) != 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
+       /*
+        * 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) != 0) return style;
+       if ((parent.getStyle() & SWT.MIRRORED) != 0 && (style & SWT.LEFT_TO_RIGHT) == 0) return style;
+
+       return style | SWT.DOUBLE_BUFFERED;
+}
+
+/**
+ *
+ * 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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       // add to array
+       CTabFolder2Listener[] newListeners = new CTabFolder2Listener[folderListeners.length + 1];
+       System.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)
+ */
+@Deprecated
+public void addCTabFolderListener(CTabFolderListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       // add to array
+       CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length + 1];
+       System.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;
+               updateFolder(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 == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       TypedListener typedListener = new TypedListener(listener);
+       addListener(SWT.Selection, typedListener);
+       addListener(SWT.DefaultSelection, typedListener);
+}
+
+Rectangle[] computeControlBounds (Point size, boolean[][] position) {
+       if (controls == null || controls.length == 0) return new Rectangle[0];
+       Rectangle[] rects = new Rectangle[controls.length];
+       for (int i = 0; i < rects.length; i++) {
+               rects[i] = new Rectangle(0, 0, 0, 0);
+       }
+       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+       int borderRight = trim.width + trim.x;
+       int borderLeft = -trim.x;
+       int borderBottom = trim.height + trim.y;
+       int borderTop = -trim.y;
+
+       Point[] tabControlSize = new Point[controls.length];
+       boolean[] overflow = new boolean [controls.length];
+       //Left Control
+       int leftWidth = 0;
+       int x = borderLeft + SPACING;
+       int rightWidth = 0;
+       int allWidth = 0;
+       for (int i = 0; i < controls.length; i++) {
+               Point ctrlSize = tabControlSize[i] = !controls[i].isDisposed() && controls[i].getVisible() ? controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT) : new Point(0,0);
+               int alignment = controlAlignments[i];
+               if ((alignment & SWT.LEAD) != 0) {
+                       rects[i].width = ctrlSize.x;
+                       rects[i].height = getControlHeight(ctrlSize);
+                       rects[i].x = x;
+                       rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+                       x += ctrlSize.x;
+                       leftWidth += ctrlSize.x;
+               } else {
+                       if ((alignment & (SWT.FILL | SWT.WRAP)) == 0) {
+                               rightWidth += ctrlSize.x;
+                       }
+                       allWidth += ctrlSize.x;
+               }
+       }
+       if (leftWidth > 0) leftWidth += SPACING * 2;
+
+       int itemWidth = 0;
+       for (int i = 0; i < items.length; i++) {
+               if (items[i].showing) itemWidth += items[i].width;
+       }
+
+       int maxWidth = size.x - borderLeft - leftWidth - borderRight;
+       int availableWidth = Math.max(0, maxWidth - itemWidth - rightWidth);
+       if (rightWidth > 0) availableWidth -= SPACING * 2;
+       x =  size.x  - borderRight - SPACING;
+       if (itemWidth + allWidth <= maxWidth) {
+               //Everything fits
+               for (int i = 0; i < controls.length; i++) {
+                       int alignment = controlAlignments[i];
+                       if ((alignment & SWT.TRAIL) != 0) {
+                               Point ctrlSize = tabControlSize[i];
+                               x -= ctrlSize.x;
+                               rects[i].width = ctrlSize.x;
+                               rects[i].height = getControlHeight(ctrlSize);
+                               rects[i].x = x;
+                               rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+                               if ((alignment & (SWT.FILL | SWT.WRAP)) != 0) availableWidth -= ctrlSize.x;
+                       }
+                       if (tabControlSize[i].y >= tabHeight && fixedTabHeight == SWT.DEFAULT) {
+                               overflow[i] = true;
+                       }
+               }
+       } else {
+               for (int i = 0; i < controls.length; i++) {
+                       int alignment = controlAlignments[i];
+                       Point ctrlSize = tabControlSize[i];
+                       if ((alignment & SWT.TRAIL) != 0) {
+                               if ((alignment & (SWT.FILL | SWT.WRAP)) == 0) {
+                                       x -= ctrlSize.x;
+                                       rects[i].width = ctrlSize.x;
+                                       rects[i].height = getControlHeight(ctrlSize);
+                                       rects[i].x = x;
+                                       rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+                               } else if (((alignment & (SWT.WRAP)) != 0 && ctrlSize.x < availableWidth)) {
+                                       x -= ctrlSize.x;
+                                       rects[i].width = ctrlSize.x;
+                                       rects[i].height = getControlHeight(ctrlSize);
+                                       rects[i].x = x;
+                                       rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+                                       availableWidth -= ctrlSize.x;
+                               } else if ((alignment & (SWT.FILL)) != 0 && (alignment & (SWT.WRAP)) == 0) {
+                                       rects[i].width = 0;
+                                       rects[i].height = getControlHeight(ctrlSize);
+                                       rects[i].x = x;
+                                       rects[i].y = getControlY(size, rects, borderBottom, borderTop, i);
+                               } else {
+                                       if ((alignment & (SWT.WRAP)) != 0) {
+                                               overflow[i] = true;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       //Any space, distribute amongst FILL
+       if (availableWidth > 0) {
+               int fillCount = 0;
+               for (int i = 0; i < controls.length; i++) {
+                       int alignment = controlAlignments[i];
+                       if ((alignment & SWT.TRAIL) != 0 && (alignment & SWT.FILL) != 0 && !overflow[i]) {
+                               fillCount++;
+                       }
+               }
+               if (fillCount != 0) {
+                       int extraSpace = availableWidth/fillCount;
+                       int addedSpace = 0;
+                       for (int i = 0; i < controls.length; i++) {
+                               int alignment = controlAlignments[i];
+                               if ((alignment & SWT.TRAIL) != 0) {
+                                       if ((alignment & SWT.FILL) != 0 && !overflow[i]) {
+                                               rects[i].width += extraSpace;
+                                               addedSpace += extraSpace;
+                                       }
+                                       if (!overflow[i]) {
+                                               rects[i].x -= addedSpace;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       //Go through overflow laying out all wrapped controls
+       Rectangle bodyTrim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
+       int bodyRight = bodyTrim.width + bodyTrim.x;
+       int bodyLeft = -bodyTrim.x;
+       int bodyWidth = size.x - bodyLeft - bodyRight;
+       x = size.x - bodyRight;
+       int y = onBottom ? this.getSize().y - getTabHeight() + 2*bodyTrim.y : -bodyTrim.y;
+       availableWidth = bodyWidth;
+       int maxHeight = 0;
+       for (int i = 0; i < controls.length; i++) {
+               Point ctrlSize = tabControlSize[i];
+               if (overflow[i]) {
+                       if (availableWidth > ctrlSize.x) {
+                               x -= ctrlSize.x;
+                               rects[i].width = ctrlSize.x;
+                               rects[i].y = onBottom ? y - ctrlSize.y : y;
+                               rects[i].height = ctrlSize.y;
+                               rects[i].x = x;
+                               availableWidth -= ctrlSize.x;
+                               maxHeight = Math.max(maxHeight, ctrlSize.y);
+                       } else {
+                               x = size.x - bodyRight;
+                               y += maxHeight;
+                               maxHeight = 0;
+                               availableWidth = bodyWidth;
+                               if (availableWidth > ctrlSize.x) {
+                                       //Relayout this control in the next line
+                                       i--;
+                               } else {
+                                       ctrlSize = controls[i].isDisposed() ? new Point(0,0) : controls[i].computeSize(bodyWidth, SWT.DEFAULT);
+                                       rects[i].width = bodyWidth;
+                                       rects[i].y = onBottom ? y - ctrlSize.y : y;
+                                       rects[i].height = ctrlSize.y;
+                                       rects[i].x = size.x - ctrlSize.x - bodyRight;
+                                       y += ctrlSize.y;
+                               }
+                       }
+               }
+       }
+
+       if (showChevron) {
+               int i = 0, lastIndex = -1;
+               while (i < priority.length && items[priority[i]].showing) {
+                       lastIndex = Math.max(lastIndex, priority[i++]);
+               }
+               if (lastIndex == -1) lastIndex = selectedIndex;
+               if (lastIndex != -1) {
+                       CTabItem lastItem = items[lastIndex];
+                       int w = lastItem.x + lastItem.width + SPACING;
+                       if (!simple && lastIndex == selectedIndex) w -= (renderer.curveIndent - 7);
+                       rects[controls.length - 1].x = w;
+               }
+       }
+
+       if (position != null) position[0] = overflow;
+       return rects;
+}
+
+int getControlHeight(Point ctrlSize) {
+       return fixedTabHeight == SWT.DEFAULT ?  Math.max(tabHeight - 1, ctrlSize.y) : ctrlSize.y;
+}
+/*
+* This class was not intended to be subclassed but this restriction
+* cannot be enforced without breaking backward compatibility.
+*/
+//protected void checkSubclass () {
+//     String name = getClass ().getName ();
+//     int index = name.lastIndexOf ('.');
+//     if (!name.substring (0, index + 1).equals ("org.eclipse.swt.custom.")) {
+//             SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+//     }
+//}
+@Override
+public Rectangle computeTrim (int x, int y, int width, int height) {
+       checkWidget();
+       Rectangle trim =  renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, x, y, width, height);
+       Point size = new Point(width, height);
+       int wrapHeight = getWrappedHeight(size);
+       if (onBottom) {
+               trim.height += wrapHeight;
+       } else {
+               trim.y -= wrapHeight;
+               trim.height += wrapHeight;
+       }
+       return trim;
+}
+Image createButtonImage(Display display, int button) {
+       GC tempGC = new GC (this);
+       Point size = renderer.computeSize(button, SWT.NONE, tempGC, SWT.DEFAULT, SWT.DEFAULT);
+       tempGC.dispose();
+
+       Rectangle trim = renderer.computeTrim(button, SWT.NONE, 0, 0, 0, 0);
+       Image image = new Image (display, size.x - trim.width, size.y - trim.height);
+       GC gc = new GC (image);
+       Color transColor = renderer.parent.getBackground();
+       gc.setBackground(transColor);
+       gc.fillRectangle(image.getBounds());
+       renderer.draw(button, SWT.NONE, new Rectangle(trim.x, trim.y, size.x, size.y), gc);
+       gc.dispose ();
+
+       final ImageData imageData = image.getImageData (DPIUtil.getDeviceZoom ());
+       imageData.transparentPixel = imageData.palette.getPixel(transColor.getRGB());
+       image.dispose();
+       image = new Image(display, new AutoScaleImageDataProvider(display, imageData, DPIUtil.getDeviceZoom()));
+       return image;
+}
+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] == index) {
+                       priorityIndex = next++;
+               }
+               newPriority[next++] = priority[i] >= index ? priority[i] + 1 : priority[i];
+       }
+       newPriority[priorityIndex] = index;
+       priority = newPriority;
+
+       if (items.length == 1) {
+               updateFolder(UPDATE_TAB_HEIGHT | REDRAW);
+       } else {
+               updateFolder(REDRAW_TABS);
+       }
+}
+void destroyItem (CTabItem item) {
+       if (inDispose) return;
+       int index = indexOf(item);
+       if (index == -1) return;
+
+       if (items.length == 1) {
+               items = new CTabItem[0];
+               priority = new int[0];
+               firstIndex = -1;
+               selectedIndex = -1;
+
+               Control control = item.control;
+               if (control != null && !control.isDisposed()) {
+                       control.setVisible(false);
+               }
+               setToolTipText(null);
+               GC gc = new GC(this);
+               setButtonBounds(gc);
+               gc.dispose();
+               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] == index) continue;
+               newPriority[next++] = priority[i] > index ? priority[i] - 1 : priority [i];
+       }
+       priority = newPriority;
+
+       // move the selection if this item is selected
+       if (selectedIndex == index) {
+               Control control = item.getControl();
+               selectedIndex = -1;
+               int nextSelection = mru ? priority[0] : Math.max(0, index - 1);
+               setSelection(nextSelection, true);
+               if (control != null && !control.isDisposed()) {
+                       control.setVisible(false);
+               }
+       } else if (selectedIndex > index) {
+               selectedIndex --;
+       }
+
+       requestLayout();
+       updateFolder(UPDATE_TAB_HEIGHT | REDRAW_TABS);
+}
+
+/**
+ * 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 boolean getBorderVisible() {
+       checkWidget();
+       return borderVisible;
+}
+ToolBar getChevron() {
+       if (chevronTb == null) {
+               chevronTb = new ToolBar(this, SWT.FLAT);
+               initAccessibleChevronTb();
+               addTabControl(chevronTb, SWT.TRAIL, -1, false);
+       }
+       if (chevronItem == null) {
+               chevronItem = new ToolItem(chevronTb, SWT.PUSH);
+               chevronItem.setToolTipText(SWT.getMessage("SWT_ShowList"));
+               chevronItem.addListener(SWT.Selection, listener);
+       }
+       return chevronTb;
+}
+/**
+ * Returns <code>true</code> if the chevron button
+ * is visible when necessary.
+ *
+ * @return the visibility of the chevron 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>
+ *
+ */
+/*public*/ boolean getChevronVisible() {
+       checkWidget();
+       return chevronVisible;
+}
+@Override
+public Rectangle getClientArea() {
+       checkWidget();
+       //TODO: HACK - find a better way to get padding
+       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.FILL, 0, 0, 0, 0);
+       Point size = getSize();
+       int wrapHeight = getWrappedHeight(size);
+       if (onBottom) {
+               trim.height += wrapHeight;
+       } else {
+               trim.y -= wrapHeight;
+               trim.height += wrapHeight;
+       }
+       if (minimized) return new Rectangle(-trim.x, -trim.y, 0, 0);
+       int width = size.x - trim.width;
+       int height = size.y - trim.height;
+       return new Rectangle(-trim.x, -trim.y, 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) {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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) {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       if (items.length == 0) return null;
+       runUpdate();
+       Point size = getSize();
+       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+       if (size.x <= trim.width) 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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       CTabItem[] tabItems = new CTabItem [items.length];
+       System.arraycopy(items, 0, tabItems, 0, items.length);
+       return tabItems;
+}
+int getLeftItemEdge (GC gc, int part){
+       Rectangle trim = renderer.computeTrim(part, SWT.NONE, 0, 0, 0, 0);
+       int x = -trim.x;
+       int width = 0;
+       for (int i = 0; i < controls.length; i++) {
+               if ((controlAlignments[i] & SWT.LEAD) != 0 && !controls[i].isDisposed() && controls[i].getVisible()) {
+                       width += controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+               }
+       }
+       if (width != 0) width += SPACING * 2;
+       x += width;
+       return Math.max(0, x);
+}
+/*
+ * 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'.
+ */
+char _findMnemonic (String string) {
+       if (string == null) return '\0';
+       int index = 0;
+       int length = string.length ();
+       do {
+               while (index < length && string.charAt (index) != '&') index++;
+               if (++index >= length) return '\0';
+               if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
+               index++;
+       } while (index < length);
+       return '\0';
+}
+String stripMnemonic (String string) {
+       int index = 0;
+       int length = string.length ();
+       do {
+               while ((index < length) && (string.charAt (index) != '&')) index++;
+               if (++index >= length) return string;
+               if (string.charAt (index) != '&') {
+                       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 boolean 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 boolean 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 boolean 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 boolean 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 boolean getMRUVisible() {
+       checkWidget();
+       return mru;
+}
+/**
+ * Returns the receiver's renderer.
+ *
+ * @return the receiver's renderer
+ *
+ * @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 #setRenderer(CTabFolderRenderer)
+ * @see CTabFolderRenderer
+ *
+ * @since 3.6
+ */
+public CTabFolderRenderer getRenderer() {
+       checkWidget();
+       return renderer;
+}
+int getRightItemEdge (GC gc){
+       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+       int x = getSize().x - (trim.width + trim.x);
+       int width = 0;
+       for (int i = 0; i < controls.length; i++) {
+               int align = controlAlignments[i];
+               if ((align & SWT.WRAP) == 0 && (align & SWT.LEAD) == 0 && !controls[i].isDisposed() && controls[i].getVisible()) {
+                       Point rightSize = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
+                       width += rightSize.x;
+               }
+       }
+       if (width != 0) width += SPACING * 2;
+       x -= width;
+       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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       if (selectedIndex == -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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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 boolean 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 boolean getSingle() {
+       checkWidget();
+       return single;
+}
+
+@Override
+public 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 (borderVisible) 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 != SWT.DEFAULT) return fixedTabHeight;
+       return tabHeight - 1; // -1 for line drawn across top of tab //TODO: replace w/ computeTrim of tab area?
+}
+/**
+ * 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 the alignment of the top right control.
+ *
+ * @return the alignment of the top right control which is either
+ * <code>SWT.RIGHT</code> or <code>SWT.FILL</code>
+ *
+ * @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.6
+ */
+public int getTopRightAlignment() {
+       checkWidget();
+       return topRightAlignment;
+}
+/**
+ * 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 boolean 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 boolean 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 == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       for (int i = 0; i < items.length; i++) {
+               if (items[i] == item) return i;
+       }
+       return -1;
+}
+void initAccessible() {
+       final Accessible accessible = getAccessible();
+       accessible.addAccessibleListener(new AccessibleAdapter() {
+               @Override
+               public void getName(AccessibleEvent e) {
+                       CTabItem item = null;
+                       int childID = e.childID;
+                       if (childID == ACC.CHILDID_SELF) {
+                               if (selectedIndex != -1) {
+                                       item = items[selectedIndex];
+                               }
+                       } else if (childID >= 0 && childID < items.length) {
+                               item = items[childID];
+                       }
+                       e.result = item == null ? null : stripMnemonic(item.getText());
+               }
+
+               @Override
+               public void getHelp(AccessibleEvent e) {
+                       String help = null;
+                       int childID = e.childID;
+                       if (childID == ACC.CHILDID_SELF) {
+                               help = getToolTipText();
+                       } else if (childID >= 0 && childID < items.length) {
+                               help = items[childID].getToolTipText();
+                       }
+                       e.result = help;
+               }
+
+               @Override
+               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 != null) {
+                                       char mnemonic = _findMnemonic(text);
+                                       if (mnemonic != '\0') {
+                                               shortcut = SWT.getMessage ("SWT_Page_Mnemonic", new Object[] {Character.valueOf(mnemonic)}); //$NON-NLS-1$
+                                       }
+                               }
+                       }
+                       if (childID == ACC.CHILDID_SELF) {
+                               shortcut = SWT.getMessage ("SWT_SwitchPage_Shortcut"); //$NON-NLS-1$
+                       }
+                       e.result = shortcut;
+               }
+       });
+
+       accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
+               @Override
+               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 == ACC.CHILDID_NONE) {
+                               Rectangle location = getBounds();
+                               location.x = location.y = 0;
+                               location.height = location.height - getClientArea().height;
+                               if (location.contains(testPoint)) {
+                                       childID = ACC.CHILDID_SELF;
+                               }
+                       }
+                       e.childID = childID;
+               }
+
+               @Override
+               public void getLocation(AccessibleControlEvent e) {
+                       Rectangle location = null;
+                       Point pt = null;
+                       int childID = e.childID;
+                       if (childID == ACC.CHILDID_SELF) {
+                               location = getBounds();
+                               pt = getParent().toDisplay(location.x, location.y);
+                       } else {
+                               if (childID >= 0 && childID < items.length && items[childID].showing) {
+                                       location = items[childID].getBounds();
+                               }
+                               if (location != null) {
+                                       pt = toDisplay(location.x, location.y);
+                               }
+                       }
+                       if (location != null && pt != null) {
+                               e.x = pt.x;
+                               e.y = pt.y;
+                               e.width = location.width;
+                               e.height = location.height;
+                       }
+               }
+
+               @Override
+               public void getChildCount(AccessibleControlEvent e) {
+                       e.detail = items.length;
+               }
+
+               @Override
+               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$
+                       }
+                       e.result = action;
+               }
+
+               @Override
+               public void getFocus(AccessibleControlEvent e) {
+                       int childID = ACC.CHILDID_NONE;
+                       if (isFocusControl()) {
+                               if (selectedIndex == -1) {
+                                       childID = ACC.CHILDID_SELF;
+                               } else {
+                                       childID = selectedIndex;
+                               }
+                       }
+                       e.childID = childID;
+               }
+
+               @Override
+               public void getRole(AccessibleControlEvent e) {
+                       int role = 0;
+                       int childID = e.childID;
+                       if (childID == ACC.CHILDID_SELF) {
+                               role = ACC.ROLE_TABFOLDER;
+                       } else if (childID >= 0 && childID < items.length) {
+                               role = ACC.ROLE_TABITEM;
+                       }
+                       e.detail = role;
+               }
+
+               @Override
+               public void getSelection(AccessibleControlEvent e) {
+                       e.childID = (selectedIndex == -1) ? ACC.CHILDID_NONE : selectedIndex;
+               }
+
+               @Override
+               public void getState(AccessibleControlEvent e) {
+                       int state = 0;
+                       int childID = e.childID;
+                       if (childID == 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 == childID) {
+                                       state |= ACC.STATE_SELECTED;
+                                       if (isFocusControl()) {
+                                               state |= ACC.STATE_FOCUSED;
+                                       }
+                               }
+                       }
+                       e.detail = state;
+               }
+
+               @Override
+               public void getChildren(AccessibleControlEvent e) {
+                       int childIdCount = items.length;
+                       Object[] children = new Object[childIdCount];
+                       for (int i = 0; i < childIdCount; i++) {
+                               children[i] = Integer.valueOf(i);
+                       }
+                       e.children = children;
+               }
+       });
+
+       addListener(SWT.Selection, event -> {
+               if (isFocusControl()) {
+                       if (selectedIndex == -1) {
+                               accessible.setFocus(ACC.CHILDID_SELF);
+                       } else {
+                               accessible.setFocus(selectedIndex);
+                       }
+               }
+       });
+
+       addListener(SWT.FocusIn, event -> {
+               if (selectedIndex == -1) {
+                       accessible.setFocus(ACC.CHILDID_SELF);
+               } else {
+                       accessible.setFocus(selectedIndex);
+               }
+       });
+}
+void initAccessibleMinMaxTb() {
+       minMaxTb.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+               @Override
+               public void getName(AccessibleEvent e) {
+                       if (e.childID != ACC.CHILDID_SELF) {
+                               if (minItem != null && e.childID == minMaxTb.indexOf(minItem)) {
+                                       e.result = minItem.getToolTipText();
+                               } else if (maxItem != null && e.childID == minMaxTb.indexOf(maxItem)) {
+                                       e.result = maxItem.getToolTipText();
+                               }
+                       }
+               }
+       });
+}
+void initAccessibleChevronTb() {
+       chevronTb.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+               @Override
+               public void getName(AccessibleEvent e) {
+                       if (e.childID != ACC.CHILDID_SELF) {
+                               if (chevronItem != null && e.childID == chevronTb.indexOf(chevronItem)) {
+                                       e.result = chevronItem.getToolTipText();
+                               }
+                       }
+               }
+       });
+}
+void onKeyDown (Event event) {
+       runUpdate();
+       switch (event.keyCode) {
+               case SWT.ARROW_LEFT:
+               case SWT.ARROW_RIGHT:
+                       int count = items.length;
+                       if (count == 0) return;
+                       if (selectedIndex  == -1) return;
+                       int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+                       int offset =  event.keyCode == 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 == selectedIndex) current = idx;
+                                               visible [idx++] = i;
+                                       }
+                               }
+                               if (current + offset >= 0 && current + offset < idx){
+                                       index = visible [current + offset];
+                               } else {
+                                       if (showChevron) {
+                                               Rectangle chevronRect = chevronItem.getBounds();
+                                               chevronRect = event.display.map(chevronTb, this, chevronRect);
+                                               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();
+       }
+}
+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 != null && !showMenu.isDisposed()) {
+               showMenu.dispose();
+               showMenu = null;
+       }
+       int length = items.length;
+       for (int i = 0; i < length; i++) {
+               if (items[i] != null) {
+                       items[i].dispose();
+               }
+       }
+
+       gradientColors = null;
+
+       selectionGradientColors = null;
+       selectionGradientPercents = null;
+       selectionBgImage = null;
+
+       selectionBackground = null;
+       selectionForeground = null;
+
+       if (controlBkImages != null) {
+               for (int i = 0; i < controlBkImages.length; i++) {
+                       if (controlBkImages[i] != null) {
+                               controlBkImages[i].dispose();
+                               controlBkImages[i] = null;
+                       }
+               }
+               controlBkImages = null;
+       }
+       controls = null;
+       controlAlignments = null;
+       controlRects = null;
+
+       if (maxImage != null) maxImage.dispose();
+       maxImage = null;
+
+       if (minImage != null) minImage.dispose();
+       minImage = null;
+
+       if (chevronImage != null) chevronImage.dispose();
+       chevronImage = null;
+
+       if (renderer != null) renderer.dispose();
+       renderer = null;
+
+       minItem = null;
+       maxItem = null;
+       minMaxTb = null;
+
+       chevronItem = null;
+       chevronTb = null;
+
+       if (folderListeners.length != 0) folderListeners = new CTabFolder2Listener[0];
+       if (tabListeners.length != 0) tabListeners = new CTabFolderListener[0];
+}
+void onDragDetect(Event event) {
+       boolean consume = false;
+       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);
+       }
+}
+boolean onMnemonic (Event event, boolean doit) {
+       char key = event.character;
+       for (int i = 0; i < items.length; i++) {
+               if (items[i] != null) {
+                       char mnemonic = _findMnemonic (items[i].getText ());
+                       if (mnemonic != '\0') {
+                               if (Character.toLowerCase (key) == mnemonic) {
+                                       if (doit) {
+                                               setSelection(i, true);
+                                               forceFocus();
+                                       }
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+void onMenuDetect(Event event) {
+       if (event.detail == SWT.MENU_KEYBOARD) {
+               if (selectedIndex != -1) {
+                       CTabItem item = items[selectedIndex];
+                       Rectangle rect = getDisplay().map(this, null, item.getBounds());
+                       if (!rect.contains(event.x, event.y)) {
+                               /* If the mouse is not in the currently-selected tab,
+                                * then pop up the menu near the top-right corner of the current tab.
+                                */
+                               Rectangle itemTrim = renderer.computeTrim(selectedIndex, SWT.NONE, 0, 0, 0, 0);
+                               Rectangle closeTrim = renderer.computeTrim(CTabFolderRenderer.PART_CLOSE_BUTTON, SWT.NONE, 0, 0, 0, 0);
+                               event.x = rect.x + rect.width - item.closeRect.width + itemTrim.x - closeTrim.width;
+                               event.y = rect.y - itemTrim.y - closeTrim.y;
+                       }
+               }
+       }
+}
+void onMouseDoubleClick(Event event) {
+       if (event.button != 1 ||
+               (event.stateMask & SWT.BUTTON2) != 0 ||
+               (event.stateMask & SWT.BUTTON3) != 0) return;
+       Event e = new Event();
+       e.item = getItem(new Point(event.x, event.y));
+       if (e.item != null) {
+               notifyListeners(SWT.DefaultSelection, e);
+       }
+}
+void onMouse(Event event) {
+       if( isDisposed() ) {
+               return;
+       }
+       int x = event.x, y = event.y;
+       switch (event.type) {
+               case SWT.MouseEnter: {
+                       setToolTipText(null);
+                       break;
+               }
+               case SWT.MouseExit: {
+                       for (int i=0; i<items.length; i++) {
+                               CTabItem item = items[i];
+                               if (i != selectedIndex && item.closeImageState != SWT.BACKGROUND) {
+                                       item.closeImageState = SWT.BACKGROUND;
+                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                               }
+                               if ((item.state & SWT.HOT) != 0) {
+                                       item.state &= ~SWT.HOT;
+                                       redraw(item.x, item.y, item.width, item.height, false);
+                               }
+                               if (i == selectedIndex && item.closeImageState != SWT.NONE) {
+                                       item.closeImageState = SWT.NONE;
+                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                               }
+                       }
+                       break;
+               }
+               case SWT.MouseHover:
+               case SWT.MouseDown: {
+                       if (hoverTb && hoverRect.contains(x, y) && !hovering) {
+                               hovering = true;
+                               updateItems();
+                               hoverTimerRunning = true;
+                               event.display.timerExec(2000, new Runnable() {
+                                       @Override
+                                       public void run() {
+                                               if (isDisposed()) return;
+                                               if (hovering) {
+                                                       Display display = getDisplay();
+                                                       Control c = display.getCursorControl();
+                                                       boolean reschedule = false;
+                                                       if (c != null) {
+                                                               for (int i = 0; i < controls.length; i++) {
+                                                                       Control temp = c;
+                                                                       do {
+                                                                               if (temp.equals(controls[i])) {
+                                                                                       reschedule = true;
+                                                                               } else {
+                                                                                       temp = temp.getParent();
+                                                                                       if (temp == null || temp.equals(CTabFolder.this)) break;
+                                                                               }
+                                                                       } while (!reschedule);
+                                                                       if (reschedule) break;
+                                                               }
+                                                       }
+                                                       if (reschedule && hoverTimerRunning) {
+                                                               display.timerExec(2000, this);
+                                                       } else {
+                                                               hovering = false;
+                                                               updateItems();
+                                                       }
+                                               }
+                                       }
+                               });
+                               return;
+                       }
+                       if (event.button != 1) return;
+                       CTabItem item = null;
+                       if (single) {
+                               if (selectedIndex != -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 != null) {
+                               if (item.closeRect.contains(x,y)){
+                                       item.closeImageState = SWT.SELECTED;
+                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                                       update();
+                                       return;
+                               }
+                               int index = indexOf(item);
+                               if (item.showing){
+                                       int oldSelectedIndex = selectedIndex;
+                                       setSelection(index, true);
+                                       if (oldSelectedIndex == selectedIndex) {
+                                               /* If the click is on the selected tabitem, then set focus to the tabfolder */
+                                               forceFocus();
+                                       }
+                               }
+                               return;
+                       }
+                       break;
+               }
+               case SWT.MouseMove: {
+                       _setToolTipText(event.x, event.y);
+                       boolean close = 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 != SWT.SELECTED && item.closeImageState != SWT.HOT) {
+                                                       item.closeImageState = SWT.HOT;
+                                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                                               }
+                                       } else {
+                                               if (item.closeImageState != SWT.NONE) {
+                                                       item.closeImageState = SWT.NONE;
+                                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                                               }
+                                       }
+                                       if ((item.state & SWT.HOT) == 0) {
+                                               item.state |= SWT.HOT;
+                                               redraw(item.x, item.y, item.width, item.height, false);
+                                       }
+                               }
+                               if (i != selectedIndex && item.closeImageState != SWT.BACKGROUND && !close) {
+                                       item.closeImageState = SWT.BACKGROUND;
+                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                               }
+                               if ((item.state & SWT.HOT) != 0 && !close) {
+                                       item.state &= ~SWT.HOT;
+                                       redraw(item.x, item.y, item.width, item.height, false);
+                               }
+                               if (i == selectedIndex && item.closeImageState != SWT.NONE && !close) {
+                                       item.closeImageState = SWT.NONE;
+                                       redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                               }
+                       }
+                       break;
+               }
+               case SWT.MouseUp: {
+                       if (event.button != 1) return;
+                       CTabItem item = null;
+                       if (single) {
+                               if (selectedIndex != -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 != null) {
+                               if (item.closeRect.contains(x,y)) {
+                                       boolean selected = item.closeImageState == SWT.SELECTED;
+                                       item.closeImageState = SWT.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 != null) {
+                                                       if (nextItem.closeRect.contains(pt)) {
+                                                               if (nextItem.closeImageState != SWT.SELECTED && nextItem.closeImageState != SWT.HOT) {
+                                                                       nextItem.closeImageState = SWT.HOT;
+                                                                       redraw(nextItem.closeRect.x, nextItem.closeRect.y, nextItem.closeRect.width, nextItem.closeRect.height, false);
+                                                               }
+                                                       } else {
+                                                               if (nextItem.closeImageState != SWT.NONE) {
+                                                                       nextItem.closeImageState = SWT.NONE;
+                                                                       redraw(nextItem.closeRect.x, nextItem.closeRect.y, nextItem.closeRect.width, nextItem.closeRect.height, false);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+void onPageTraversal(Event event) {
+       int count = items.length;
+       if (count == 0) return;
+       int index = selectedIndex;
+       if (index  == -1) {
+               index = 0;
+       } else {
+               int offset = (event.detail == 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 == selectedIndex) current = idx;
+                                       visible [idx++] = i;
+                               }
+                       }
+                       if (current + offset >= 0 && current + offset < idx){
+                               index = visible [current + offset];
+                       } else {
+                               if (showChevron) {
+                                       Rectangle chevronRect = chevronItem.getBounds();
+                                       chevronRect = event.display.map(chevronTb, this, chevronRect);
+                                       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);
+                                       }
+                               }
+                       }
+               }
+       }
+       setSelection (index, true);
+}
+void onPaint(Event event) {
+       if (inDispose) return;
+       Font font = getFont();
+       if (oldFont == null || !oldFont.equals(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);
+//}
+
+       Point size = getSize();
+       Rectangle bodyRect = new Rectangle(0, 0, size.x, size.y);
+       renderer.draw(CTabFolderRenderer.PART_BODY, SWT.BACKGROUND | SWT.FOREGROUND, bodyRect, gc);
+
+       gc.setFont(gcFont);
+       gc.setForeground(gcForeground);
+       gc.setBackground(gcBackground);
+
+       renderer.draw(CTabFolderRenderer.PART_HEADER, SWT.BACKGROUND | SWT.FOREGROUND, bodyRect, gc);
+
+       gc.setFont(gcFont);
+       gc.setForeground(gcForeground);
+       gc.setBackground(gcBackground);
+
+       if (!single) {
+               for (int i=0; i < items.length; i++) {
+                       Rectangle itemBounds = items[i].getBounds();
+                       if (i != selectedIndex && event.getBounds().intersects(itemBounds)) {
+                               renderer.draw(i, SWT.BACKGROUND | SWT.FOREGROUND | items[i].state , itemBounds, gc);
+                       }
+               }
+       }
+
+       gc.setFont(gcFont);
+       gc.setForeground(gcForeground);
+       gc.setBackground(gcBackground);
+
+       if (selectedIndex != -1) {
+               renderer.draw(selectedIndex, items[selectedIndex].state | SWT.BACKGROUND | SWT.FOREGROUND, items[selectedIndex].getBounds(), gc);
+       }
+
+       gc.setFont(gcFont);
+       gc.setForeground(gcForeground);
+       gc.setBackground(gcBackground);
+
+       if (hoverTb) {
+               Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+               int x = getSize().x - (trim.width + trim.x);
+               hoverRect = new Rectangle(x - 16 - SPACING, 2, 16, getTabHeight() - 2);
+               gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
+               x = hoverRect.x;
+               int y = hoverRect.y;
+               gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
+               gc.fillRectangle(x + hoverRect.width - 6, y, 5, 5);
+               gc.drawRectangle(x + hoverRect.width - 6, y, 5, 5);
+               gc.drawLine(x + hoverRect.width - 6, y+2, x + hoverRect.width - 6 + 5, y + 2);
+               gc.fillRectangle(x, y, 5 , 2);
+               gc.drawRectangle(x, y, 5 , 2);
+       }
+       gc.setFont(gcFont);
+       gc.setForeground(gcForeground);
+       gc.setBackground(gcBackground);
+}
+
+void onResize(Event event) {
+       if (inDispose) return;
+       if (ignoreResize) return;
+       if (updateItems()) {
+               redrawTabs();
+       }
+       Point size = getSize();
+       if (oldSize == null) {
+               redraw();
+       } else {
+               if (onBottom && size.y != oldSize.y) {
+                       redraw();
+               } else {
+                       int x1 = Math.min(size.x, oldSize.x);
+                       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
+                       if (size.x != oldSize.x) x1 -= trim.width + trim.x - marginWidth + 2;
+                       if (!simple) x1 -= 5; // rounded top right corner
+                       int y1 = Math.min(size.y, oldSize.y);
+                       if (size.y != oldSize.y) y1 -= trim.height + trim.y - marginHeight;
+                       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);
+                       if (hoverTb) {
+                               redraw(hoverRect.x, hoverRect.y, hoverRect.width, hoverRect.height, false);
+                       }
+               }
+       }
+       oldSize = size;
+}
+void onSelection(Event event) {
+       if (hovering) {
+               hovering = false;
+               updateItems();
+       }
+       if (event.widget == maxItem) {
+               CTabFolderEvent e = new CTabFolderEvent(this);
+               e.widget = CTabFolder.this;
+               e.time = event.time;
+               for (int i = 0; i < folderListeners.length; i++) {
+                       if (maximized) {
+                               folderListeners[i].restore(e);
+                       } else {
+                               folderListeners[i].maximize(e);
+                       }
+               }
+       } else if (event.widget == minItem) {
+               CTabFolderEvent e = new CTabFolderEvent(this);
+               e.widget = CTabFolder.this;
+               e.time = event.time;
+               for (int i = 0; i < folderListeners.length; i++) {
+                       if (minimized) {
+                               folderListeners[i].restore(e);
+                       } else {
+                               folderListeners[i].minimize(e);
+                       }
+               }
+       } else if (event.widget == chevronItem) {
+               Rectangle chevronRect = chevronItem.getBounds();
+               chevronRect = event.display.map(chevronTb, this, chevronRect);
+               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);
+               }
+       }
+}
+void onTraverse (Event event) {
+       if (ignoreTraverse) return;
+       runUpdate();
+       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 == this) event.doit = true;
+                       break;
+               case SWT.TRAVERSE_MNEMONIC:
+                       event.doit = onMnemonic(event, false);
+                       break;
+               case SWT.TRAVERSE_PAGE_NEXT:
+               case SWT.TRAVERSE_PAGE_PREVIOUS:
+                       event.doit = items.length > 0;
+                       break;
+       }
+       ignoreTraverse = true;
+       notifyListeners(SWT.Traverse, event);
+       ignoreTraverse = false;
+       event.type = SWT.None;
+       if (isDisposed()) return;
+       if (!event.doit) return;
+       switch (event.detail) {
+               case SWT.TRAVERSE_MNEMONIC:
+                       onMnemonic(event, true);
+                       event.detail = SWT.TRAVERSE_NONE;
+                       break;
+               case SWT.TRAVERSE_PAGE_NEXT:
+               case SWT.TRAVERSE_PAGE_PREVIOUS:
+                       onPageTraversal(event);
+                       event.detail = SWT.TRAVERSE_NONE;
+                       break;
+       }
+}
+void redrawTabs() {
+       Point size = getSize();
+       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BODY, SWT.NONE, 0, 0, 0, 0);
+       if (onBottom) {
+               int h = trim.height + trim.y - marginHeight;
+               redraw(0, size.y - h - 1, size.x, h + 1, false);
+       } else {
+               redraw(0, 0, size.x, -trim.y - marginHeight + 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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (folderListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < folderListeners.length; i++) {
+               if (listener == folderListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (folderListeners.length == 1) {
+               folderListeners = new CTabFolder2Listener[0];
+               return;
+       }
+       CTabFolder2Listener[] newTabListeners = new CTabFolder2Listener[folderListeners.length - 1];
+       System.arraycopy(folderListeners, 0, newTabListeners, 0, index);
+       System.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)
+ */
+@Deprecated
+public void removeCTabFolderListener(CTabFolderListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (tabListeners.length == 0) return;
+       int index = -1;
+       for (int i = 0; i < tabListeners.length; i++) {
+               if (listener == tabListeners[i]){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+       if (tabListeners.length == 1) {
+               tabListeners = new CTabFolderListener[0];
+               return;
+       }
+       CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length - 1];
+       System.arraycopy(tabListeners, 0, newTabListeners, 0, index);
+       System.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 == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       removeListener(SWT.Selection, listener);
+       removeListener(SWT.DefaultSelection, listener);
+}
+
+@Override
+public void reskin(int flags) {
+       super.reskin(flags);
+       for (int i = 0; i < items.length; i++) {
+               items[i].reskin(flags);
+       }
+}
+
+@Override
+public void setBackground (Color color) {
+       super.setBackground(color);
+       renderer.createAntialiasColors(); //TODO: need better caching strategy
+       updateBkImages();
+       redraw();
+}
+/**
+ * Specify a gradient of colors 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 <code>percents</code>
+ *                 array must be one less than the size of the <code>colors</code> 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.6
+ */
+public void setBackground(Color[] colors, int[] percents) {
+       setBackground(colors, percents, false);
+}
+/**
+ * Specify a gradient of colors 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 <code>percents</code>
+ *                 array must be one less than the size of the <code>colors</code> array.
+ *
+ * @param vertical indicate the direction of the gradient. <code>True</code> is vertical and <code>false</code> 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.6
+ */
+public void setBackground(Color[] colors, int[] percents, boolean vertical) {
+       checkWidget();
+       if (colors != null) {
+               if (percents == null || percents.length != 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 = new Color[] {colors[colors.length - 1]};
+                       percents = new int[] {};
+               }
+       }
+
+       // Are these settings the same as before?
+       if ((gradientColors != null) && (colors != null) &&
+               (gradientColors.length == colors.length)) {
+               boolean same = false;
+               for (int i = 0; i < gradientColors.length; i++) {
+                       if (gradientColors[i] == null) {
+                       same = colors[i] == null;
+                       } else {
+                       same = gradientColors[i].equals(colors[i]);
+                       }
+                       if (!same) break;
+               }
+               if (same) {
+                       for (int i = 0; i < gradientPercents.length; i++) {
+                       same = gradientPercents[i] == percents[i];
+                       if (!same) break;
+                       }
+               }
+               if (same && this.gradientVertical == vertical) return;
+       }
+       // Store the new settings
+       if (colors == null) {
+               gradientColors = null;
+               gradientPercents = null;
+               gradientVertical = false;
+               setBackground((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();
+}
+@Override
+public void setBackgroundImage(Image image) {
+               super.setBackgroundImage(image);
+               renderer.createAntialiasColors(); //TODO: need better caching strategy
+               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(boolean show) {
+       checkWidget();
+       if (borderVisible == show) return;
+       this.borderVisible = show;
+       updateFolder(REDRAW);
+}
+void setButtonBounds(GC gc) {
+       Point size = getSize();
+       // max button
+       Display display = getDisplay();
+       if (showMax) {
+               if (minMaxTb == null) {
+                       minMaxTb = new ToolBar(this, SWT.FLAT);
+                       initAccessibleMinMaxTb();
+                       addTabControl(minMaxTb, SWT.TRAIL, 0, false);
+               }
+               if (maxItem == null) {
+                       maxItem = new ToolItem(minMaxTb, SWT.PUSH);
+                       if (maxImage == null) {
+                               maxImage = createButtonImage(display, CTabFolderRenderer.PART_MAX_BUTTON);
+                       }
+                       maxItem.setImage(maxImage);
+                       maxItem.setToolTipText(maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize")); //$NON-NLS-1$ //$NON-NLS-2$
+                       maxItem.addListener(SWT.Selection, listener);
+               }
+       } else {
+               //might need to remove it if already there
+               if (maxItem != null) {
+                       maxItem.dispose();
+                       maxItem = null;
+               }
+       }
+       // min button
+       if (showMin) {
+               if (minMaxTb == null) {
+                       minMaxTb = new ToolBar(this, SWT.FLAT);
+                       initAccessibleMinMaxTb();
+                       addTabControl(minMaxTb, SWT.TRAIL, 0, false);
+               }
+               if (minItem == null) {
+                       minItem = new ToolItem(minMaxTb, SWT.PUSH, 0);
+                       if (minImage == null) {
+                               minImage = createButtonImage(display, CTabFolderRenderer.PART_MIN_BUTTON);
+                       }
+                       minItem.setImage(minImage);
+                       minItem.setToolTipText(minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize")); //$NON-NLS-1$ //$NON-NLS-2$
+                       minItem.addListener(SWT.Selection, listener);
+               }
+       } else {
+               //might need to remove it if already there
+               if (minItem != null) {
+                       minItem.dispose();
+                       minItem = null;
+               }
+       }
+       if (minMaxTb != null && minMaxTb.getItemCount() == 0) {
+               removeTabControl(minMaxTb, false);
+               minMaxTb.dispose();
+               minMaxTb = null;
+       }
+       if (showChevron) {
+               int itemCount = items.length;
+               int count;
+               if (single) {
+                       count = selectedIndex == -1 ? itemCount : itemCount - 1;
+               } else {
+                       int showCount = 0;
+                       while (showCount < priority.length && items[priority[showCount]].showing) {
+                               showCount++;
+                       }
+                       count = itemCount - showCount;
+               }
+               if (count != chevronCount) {
+                       chevronCount = count;
+                       if (chevronImage != null) chevronImage.dispose();
+                       chevronImage = createButtonImage(display, CTabFolderRenderer.PART_CHEVRON_BUTTON);
+                       chevronItem.setImage(chevronImage);
+               }
+       }
+
+       boolean[][] overflow = new boolean[1][0];
+       Rectangle[] rects = computeControlBounds(size, overflow);
+       if (fixedTabHeight != SWT.DEFAULT) {
+               int height = fixedTabHeight;
+               if (!hovering) {
+                       hoverTb = false;
+                       Rectangle tabBounds = this.getBounds();
+                       for (int i = 0; i < rects.length; i++) {
+                               if (!(overflow[0][i])) {
+                                       if (rects[i].height > height) {
+                                               hoverTb = true;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (hoverTb) {
+                               for (int i = 0; i < rects.length; i++) {
+                                       if (!(overflow[0][i])) {
+                                               if (rects[i].height > height) {
+                                                       rects[i].x = tabBounds.width + 20;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       int headerHeight = 0;
+       for (int i = 0; i < rects.length; i++) {
+               if (!overflow[0][i]) headerHeight = Math.max(rects[i].height, headerHeight);
+       }
+       boolean changed = false;
+       ignoreResize = true;
+       for (int i = 0; i < controls.length; i++) {
+               if (!controls[i].isDisposed()) {
+                       if (overflow[0][i]) {
+                               controls[i].setBounds(rects[i]);
+                       } else {
+                               controls[i].moveAbove(null);
+                               controls[i].setBounds(rects[i].x, rects[i].y, rects[i].width, headerHeight);
+                       }
+               }
+               if (!changed && !rects[i].equals(controlRects[i])) changed = true;
+       }
+       ignoreResize = false;
+       controlRects = rects;
+       if (changed || hovering) updateBkImages();
+}
+@Override
+public boolean setFocus () {
+       checkWidget ();
+
+       /*
+       * Feature in SWT.  When a new tab item is selected
+       * and the previous tab item had focus, removing focus
+       * from the previous tab item causes fixFocus() to give
+       * focus to the first child, which is usually one of the
+       * toolbars. This is unexpected.
+       * The fix is to try to set focus on the first tab item
+       * if fixFocus() is called.
+       */
+       Control focusControl = getDisplay().getFocusControl ();
+       boolean fixFocus = isAncestor (focusControl);
+       if (fixFocus) {
+               CTabItem item = getSelection();
+               if (item != null) {
+                       if (item.setFocus ()) return true;
+               }
+       }
+       return super.setFocus ();
+}
+/* Copy of isFocusAncestor from Control. */
+boolean isAncestor (Control control) {
+       while (control != null && control != this && !(control instanceof Shell)) {
+               control = control.getParent();
+       }
+       return control == this;
+}
+@Override
+public void setFont(Font font) {
+       checkWidget();
+       if (font != null && font.equals(getFont())) return;
+       super.setFont(font);
+       oldFont = getFont();
+       updateFolder(REDRAW);
+}
+@Override
+public 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, boolean 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 -1
+ *
+ * @param after true if the mark should be displayed after the specified item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT when the index is invalid</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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, boolean after) {
+       checkWidget();
+       if (index < -1 || index >= getItemCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+}
+boolean setItemLocation(GC gc) {
+       boolean changed = false;
+       if (items.length == 0) return false;
+       Rectangle trim = renderer.computeTrim(CTabFolderRenderer.PART_BORDER, SWT.NONE, 0, 0, 0, 0);
+       int borderBottom = trim.height + trim.y;
+       int borderTop = -trim.y;
+       Point size = getSize();
+       int y = onBottom ? Math.max(borderBottom, size.y - borderBottom - tabHeight) : borderTop;
+       Point closeButtonSize = renderer.computeSize(CTabFolderRenderer.PART_CLOSE_BUTTON, 0, gc, SWT.DEFAULT, SWT.DEFAULT);
+       int leftItemEdge = getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER);
+       if (single) {
+               int defaultX = getDisplay().getBounds().width + 10; // off screen
+               for (int i = 0; i < items.length; i++) {
+                       CTabItem item = items[i];
+                       if (i == selectedIndex) {
+                               firstIndex = selectedIndex;
+                               int oldX = item.x, oldY = item.y;
+                               item.x = leftItemEdge;
+                               item.y = y;
+                               item.showing = true;
+                               if (showClose || item.showClose) {
+                                       item.closeRect.x = leftItemEdge - renderer.computeTrim(i, SWT.NONE, 0, 0, 0, 0).x;
+                                       item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - closeButtonSize.y)/2: borderTop + (tabHeight - closeButtonSize.y)/2;
+                               }
+                               if (item.x != oldX || item.y != oldY) changed = true;
+                       } else {
+                               item.x = defaultX;
+                               item.showing = false;
+                       }
+               }
+       } else {
+               int rightItemEdge = getRightItemEdge(gc);
+               int maxWidth = rightItemEdge - leftItemEdge;
+               int width = 0;
+               for (int i = 0; i < priority.length; i++) {
+                       CTabItem item = items[priority[i]];
+                       width += item.width;
+                       item.showing = i == 0 ? true : item.width > 0 && width <= maxWidth;
+               }
+               int x = getLeftItemEdge(gc, CTabFolderRenderer.PART_HEADER);
+               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 != defaultX) changed = true;
+                               item.x = defaultX;
+                       } else {
+                               firstIndex = Math.min(firstIndex, i);
+                               if (item.x != x || item.y != y) changed = true;
+                               item.x = x;
+                               item.y = y;
+                               int state = SWT.NONE;
+                               if (i == selectedIndex) state |= SWT.SELECTED;
+                               Rectangle edgeTrim = renderer.computeTrim(i, state, 0, 0, 0, 0);
+                               item.closeRect.x = item.x + item.width  - (edgeTrim.width + edgeTrim.x) - closeButtonSize.x;
+                               item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - closeButtonSize.y)/2: borderTop + (tabHeight - closeButtonSize.y)/2;
+                               x = x + item.width;
+                               if (!simple && i == selectedIndex) x -= renderer.curveIndent; //TODO: fix next item position
+                       }
+               }
+       }
+       return changed;
+}
+/**
+ * Reorder the items of the receiver.
+ * @param indices an array containing the new indices for all items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the indices array is not the same length as the number of items,
+ *    if there are duplicate indices or an index is out of range.</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+/*public*/ void setItemOrder (int[] indices) {
+       checkWidget();
+       if (indices == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (indices.length != items.length) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       int newSelectedIndex = -1;
+       boolean[] seen = new boolean[items.length];
+       CTabItem[] temp = new CTabItem[items.length];
+       for (int i=0; i<indices.length; i++) {
+               int index = indices[i];
+               if (!(0 <= index && index < items.length)) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+               if (seen[index]) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+               seen[index] = true;
+               if (index == selectedIndex) newSelectedIndex = i;
+               temp[i] = items[index];
+       }
+       items = temp;
+       selectedIndex = newSelectedIndex;
+       updateFolder(REDRAW);
+}
+boolean setItemSize(GC gc) {
+       boolean changed = false;
+       if (isDisposed()) return changed;
+       Point size = getSize();
+       if (size.x <= 0 || size.y <= 0) return changed;
+       ToolBar chevron = getChevron();
+       if (chevron != null) chevron.setVisible(false);
+       showChevron = false;
+       if (single) {
+               showChevron = chevronVisible && items.length > 1;
+               if (showChevron) {
+                       chevron.setVisible(true);
+               }
+               if (selectedIndex != -1) {
+                       CTabItem tab = items[selectedIndex];
+                       int width = renderer.computeSize(selectedIndex, SWT.SELECTED, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                       width = Math.min(width, getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER));
+                       if (tab.height != tabHeight || tab.width != 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) {
+                                       Point closeSize = renderer.computeSize(CTabFolderRenderer.PART_CLOSE_BUTTON, SWT.SELECTED, gc, SWT.DEFAULT, SWT.DEFAULT);
+                                       tab.closeRect.width = closeSize.x;
+                                       tab.closeRect.height = closeSize.y;
+                               }
+                       }
+               }
+               return changed;
+       }
+
+       if (items.length == 0) return changed;
+       int[] widths;
+       int tabAreaWidth = Math.max(0, getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER));
+       // 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];
+               int state = CTabFolderRenderer.MINIMUM_SIZE;
+               if (index == selectedIndex) state |= SWT.SELECTED;
+               minWidths[index] = renderer.computeSize(index, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+               minWidth += minWidths[index];
+               if (minWidth > tabAreaWidth) break;
+       }
+       if (minWidth > tabAreaWidth) {
+               // full compression required and a chevron
+               showChevron = chevronVisible && items.length > 1;
+               if (showChevron) {
+                       tabAreaWidth -= chevron.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+                       chevron.setVisible(true);
+               }
+               widths = minWidths;
+               int index = selectedIndex != -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++) {
+                       int state = 0;
+                       if (i == selectedIndex) state |= SWT.SELECTED;
+                       maxWidths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                       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 == 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);
+                       }
+               }
+       }
+
+       for (int i = 0; i < items.length; i++) {
+               CTabItem tab = items[i];
+               int width = widths[i];
+               if (tab.height != tabHeight || tab.width != 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 == selectedIndex || showUnselectedClose) {
+                                       Point closeSize = renderer.computeSize(CTabFolderRenderer.PART_CLOSE_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT);
+                                       tab.closeRect.width = closeSize.x;
+                                       tab.closeRect.height = closeSize.y;
+                               }
+                       }
+               }
+       }
+       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(boolean visible) {
+       checkWidget();
+       if (showMax == visible) return;
+       // display maximize button
+       showMax = visible;
+       updateFolder(UPDATE_TAB_HEIGHT | 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>
+ */
+@Override
+public 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(boolean maximize) {
+       checkWidget ();
+       if (this.maximized == maximize) return;
+       if (maximize && this.minimized) setMinimized(false);
+       this.maximized = maximize;
+       if (minMaxTb != null && maxItem != null) {
+               if (maxImage != null) maxImage.dispose();
+               maxImage = createButtonImage(getDisplay(), CTabFolderRenderer.PART_MAX_BUTTON);
+               maxItem.setImage(maxImage);
+               maxItem.setToolTipText(maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize")); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+}
+/**
+ * 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(boolean visible) {
+       checkWidget();
+       if (showMin == visible) return;
+       // display minimize button
+       showMin = visible;
+       updateFolder(UPDATE_TAB_HEIGHT | 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(boolean minimize) {
+       checkWidget ();
+       if (this.minimized == minimize) return;
+       if (minimize && this.maximized) setMaximized(false);
+       this.minimized = minimize;
+       if (minMaxTb != null && minItem != null) {
+               if (minImage != null) minImage.dispose();
+               minImage = createButtonImage(getDisplay(), CTabFolderRenderer.PART_MIN_BUTTON);
+               minItem.setImage(minImage);
+               minItem.setToolTipText(minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize")); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+}
+
+/**
+ * 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 == count) return;
+       minChars = count;
+       updateFolder(REDRAW_TABS);
+}
+
+/**
+ * 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(boolean show) {
+       checkWidget();
+       if (mru == show) return;
+       mru = show;
+       if (!mru) {
+               if (firstIndex == -1) return;
+               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;
+               }
+               updateFolder(REDRAW_TABS);
+       }
+}
+/**
+ * Sets the renderer which is associated with the receiver to be
+ * the argument which may be null. In the case of null, the default
+ * renderer is used.
+ *
+ * @param renderer a new renderer
+ *
+ * @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 CTabFolderRenderer
+ *
+ * @since 3.6
+ */
+public void setRenderer(CTabFolderRenderer renderer) {
+       checkWidget();
+       if (this.renderer == renderer || (useDefaultRenderer && renderer == null)) return;
+       if (this.renderer != null) this.renderer.dispose();
+       useDefaultRenderer = renderer == null;
+       if (useDefaultRenderer) renderer = new CTabFolderRenderer(this);
+       this.renderer = renderer;
+       updateFolder(REDRAW);
+}
+/**
+ * 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 == 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 == index) {
+               showItem(selection);
+               return;
+       }
+
+       int oldIndex = selectedIndex;
+       selectedIndex = index;
+       if (oldIndex != -1) {
+               items[oldIndex].closeImageState = SWT.BACKGROUND;
+               items[oldIndex].state &= ~SWT.SELECTED;
+       }
+       selection.closeImageState = SWT.NONE;
+       selection.showing = false;
+       selection.state |= SWT.SELECTED;
+
+       Control newControl = selection.control;
+       Control oldControl = null;
+       if (oldIndex != -1) {
+               oldControl = items[oldIndex].control;
+       }
+
+       if (newControl != oldControl) {
+               if (newControl != null && !newControl.isDisposed()) {
+                       newControl.setBounds(getClientArea());
+                       newControl.setVisible(true);
+               }
+               if (oldControl != null && !oldControl.isDisposed()) {
+                       oldControl.setVisible(false);
+               }
+       }
+       showItem(selection);
+       redraw();
+}
+void setSelection(int index, boolean notify) {
+       int oldSelectedIndex = selectedIndex;
+       setSelection(index);
+       if (notify && selectedIndex != oldSelectedIndex && selectedIndex != -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) {
+       if (inDispose) return;
+       checkWidget();
+       setSelectionHighlightGradientColor(null);
+       if (selectionBackground == color) return;
+       if (color == null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND);
+       selectionBackground = color;
+       renderer.createAntialiasColors(); //TODO:  need better caching strategy
+       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, boolean vertical) {
+       checkWidget();
+       int colorsLength;
+       Color highlightBeginColor = null;  //null == no highlight
+
+       if (colors != 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 == null ||
+                               ! ((percents.length == colors.length - 1) || (percents.length == 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 == 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 = new Color[] {colors[colorsLength - 1]};
+                       colorsLength = colors.length;
+                       percents = new int[] {};
+               }
+       } else {
+               colorsLength = 0;
+       }
+
+       // Are these settings the same as before?
+       if (selectionBgImage == null) {
+               if ((selectionGradientColors != null) && (colors != null) &&
+                       (selectionGradientColors.length == colorsLength)) {
+                       boolean same = false;
+                       for (int i = 0; i < selectionGradientColors.length; i++) {
+                               if (selectionGradientColors[i] == null) {
+                                       same = colors[i] == null;
+                               } else {
+                                       same = selectionGradientColors[i].equals(colors[i]);
+                               }
+                               if (!same) break;
+                       }
+                       if (same) {
+                               for (int i = 0; i < selectionGradientPercents.length; i++) {
+                                       same = selectionGradientPercents[i] == percents[i];
+                                       if (!same) break;
+                               }
+                       }
+                       if (same && this.selectionGradientVertical == vertical) return;
+               }
+       } else {
+               selectionBgImage = null;
+       }
+       // Store the new settings
+       if (colors == null) {
+               selectionGradientColors = null;
+               selectionGradientPercents = null;
+               selectionGradientVertical = false;
+               setSelectionBackground((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) {
+       if (inDispose) return;
+       renderer.setSelectionHighlightGradientColor(start);  //TODO: need better caching strategy
+}
+
+/**
+ * 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 == selectionBgImage) return;
+       if (image != null) {
+               selectionGradientColors = null;
+               selectionGradientPercents = null;
+               renderer.disposeSelectionHighlightGradientColors(); //TODO: need better caching strategy
+       }
+       selectionBgImage = image;
+       renderer.createAntialiasColors(); //TODO:  need better caching strategy
+       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 == color) return;
+       if (color == null) color = getDisplay().getSystemColor(SELECTION_FOREGROUND);
+       selectionForeground = color;
+       if (selectedIndex > -1) redraw();
+}
+
+/**
+ * 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(boolean simple) {
+       checkWidget();
+       if (this.simple != simple) {
+               this.simple = simple;
+               updateFolder(UPDATE_TAB_HEIGHT | 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(boolean single) {
+       checkWidget();
+       if (this.single != single) {
+               this.single = single;
+               if (!single) {
+                       for (int i = 0; i < items.length; i++) {
+                               if (i != selectedIndex && items[i].closeImageState == SWT.NONE) {
+                                       items[i].closeImageState = SWT.BACKGROUND;
+                               }
+                       }
+               }
+               updateFolder(REDRAW);
+       }
+}
+
+int getControlY(Point size, Rectangle[] rects, int borderBottom, int borderTop, int i) {
+       int center = fixedTabHeight != SWT.DEFAULT ? 0 : (tabHeight - rects[i].height)/2;
+       return onBottom ? size.y - borderBottom - tabHeight + center : 1 + borderTop + center;
+}
+
+/**
+ * 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 point 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;
+       updateFolder(UPDATE_TAB_HEIGHT);
+}
+/**
+ * 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 != SWT.TOP && position != SWT.BOTTOM) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (onBottom != (position == SWT.BOTTOM)) {
+               onBottom = position == SWT.BOTTOM;
+               updateFolder(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 disposed, or 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.
+ * <code>SWT.RIGHT | SWT.WRAP</code> will allow the control to wrap below the
+ * tabs if there is not enough available space to the right of the last tab.
+ * </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> or <code>SWT.RIGHT | SWT.WRAP</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 disposed, or not a child of this CTabFolder</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void setTopRight(Control control, int alignment) {
+       checkWidget();
+       if (alignment != SWT.RIGHT && alignment != SWT.FILL && alignment != (SWT.RIGHT | SWT.WRAP)) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (control != null && (control.isDisposed() || control.getParent() != this)) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (topRight == control && topRightAlignment == alignment) return;
+       if (topRight != null && !topRight.isDisposed()) removeTabControl(topRight, false);
+       topRight = control;
+       topRightAlignment = alignment;
+       alignment &= ~SWT.RIGHT;
+       if (control != null) addTabControl(control, SWT.TRAIL | alignment, -1, false);
+       updateFolder(UPDATE_TAB_HEIGHT | 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(boolean visible) {
+       checkWidget();
+       if (showUnselectedClose == visible) return;
+       // display close button when mouse hovers
+       showUnselectedClose = visible;
+       updateFolder(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(boolean visible) {
+       checkWidget();
+       if (showUnselectedImage == visible) return;
+       // display image on unselected items
+       showUnselectedImage = visible;
+       updateFolder(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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       int index = indexOf(item);
+       if (index == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       int idx = -1;
+       for (int i = 0; i < priority.length; i++) {
+               if (priority[i] == 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.showing) return;
+       updateFolder(REDRAW_TABS);
+}
+void showList (Rectangle rect) {
+       if (items.length == 0 || !showChevron) return;
+       if (showMenu == null || showMenu.isDisposed()) {
+               showMenu = new Menu(getShell(), getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT));
+       } else {
+               MenuItem[] items = showMenu.getItems();
+               for (int i = 0; i < items.length; i++) {
+                       items[i].dispose();
+               }
+       }
+       final 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);
+               // Bug 533124 In the case where you have multi line tab text, we force the drop-down menu to have single line entries to ensure consistent behavior across platforms.
+               item.setText(tab.getText().replace("\n", " "));
+               item.setImage(tab.getImage());
+               item.setData(id, tab);
+               item.addSelectionListener(new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               MenuItem menuItem = (MenuItem)e.widget;
+                               int index = indexOf((CTabItem)menuItem.getData(id));
+                               CTabFolder.this.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 != -1) {
+               showItem(getSelection());
+       }
+}
+
+void _setToolTipText (int x, int y) {
+       String oldTip = getToolTipText();
+       String newTip = _getToolTip(x, y);
+       if (newTip == null || !newTip.equals(oldTip)) {
+               setToolTipText(newTip);
+       }
+}
+
+boolean updateItems() {
+       return updateItems(selectedIndex);
+}
+
+boolean updateItems (int showIndex) {
+       GC gc = new GC(this);
+       if (!single && !mru && showIndex != -1) {
+               // make sure selected item will be showing
+               int firstIndex = showIndex;
+               if (priority[0] < showIndex) {
+                       int maxWidth = getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER);
+                       int width = 0;
+                       int[] widths = new int[items.length];
+                       for (int i = priority[0]; i <= showIndex; i++) {
+                               int state = CTabFolderRenderer.MINIMUM_SIZE;
+                               if (i == selectedIndex) state |= SWT.SELECTED;
+                               widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                               width += widths[i];
+                               if (width > maxWidth) break;
+                       }
+                       if (width > maxWidth) {
+                               width = 0;
+                               for (int i = showIndex; i >= 0; i--) {
+                                       int state = CTabFolderRenderer.MINIMUM_SIZE;
+                                       if (i == selectedIndex) state |= SWT.SELECTED;
+                                       if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                                       width += widths[i];
+                                       if (width > maxWidth) break;
+                                       firstIndex = i;
+                               }
+                       } else {
+                               firstIndex = priority[0];
+                               for (int i = showIndex + 1; i < items.length; i++) {
+                                       int state = CTabFolderRenderer.MINIMUM_SIZE;
+                                       if (i == selectedIndex) state |= SWT.SELECTED;
+                                       widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                                       width += widths[i];
+                                       if (width >= maxWidth) break;
+                               }
+                               if (width < maxWidth) {
+                                       for (int i = priority[0] - 1; i >= 0; i--) {
+                                               int state = CTabFolderRenderer.MINIMUM_SIZE;
+                                               if (i == selectedIndex) state |= SWT.SELECTED;
+                                               if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                                               width += widths[i];
+                                               if (width > maxWidth) break;
+                                               firstIndex = i;
+                                       }
+                               }
+                       }
+
+               }
+               if (firstIndex != priority[0]) {
+                       int index = 0;
+                       // enumerate tabs from first visible to the last existing one (sorted ascending)
+                       for (int i = firstIndex; i < items.length; i++) {
+                               priority[index++] = i;
+                       }
+                       // enumerate hidden tabs on the left hand from first visible one
+                       // in the inverse order (sorted descending) so that the originally
+                       // first opened tab is always at the end of the list
+                       for (int i = firstIndex - 1; i >= 0; i--) {
+                               priority[index++] = i;
+                       }
+               }
+       }
+
+       boolean oldShowChevron = showChevron;
+       boolean changed = setItemSize(gc);
+       changed |= setItemLocation(gc);
+       setButtonBounds(gc);
+       changed |= showChevron != oldShowChevron;
+       if (changed && getToolTipText() != null) {
+               Point pt = getDisplay().getCursorLocation();
+               pt = toControl(pt);
+               _setToolTipText(pt.x, pt.y);
+       }
+       gc.dispose();
+       return changed;
+}
+boolean updateTabHeight(boolean force){
+       int oldHeight = tabHeight;
+       GC gc = new GC(this);
+       tabHeight = renderer.computeSize(CTabFolderRenderer.PART_HEADER, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).y;
+       gc.dispose();
+       if (fixedTabHeight == SWT.DEFAULT && controls != null && controls.length > 0) {
+               for (int i = 0; i < controls.length; i++) {
+                       if ((controlAlignments[i] & SWT.WRAP) == 0 && !controls[i].isDisposed() && controls[i].getVisible()) {
+                               int topHeight = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+                               topHeight +=  renderer.computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0,0,0,0).height + 1;
+                               tabHeight = Math.max(topHeight, tabHeight);
+                       }
+               }
+       }
+       if (!force && tabHeight == oldHeight) return false;
+       oldSize = null;
+       return true;
+}
+
+void updateFolder (int flags) {
+       updateFlags |= flags;
+       if (updateRun != null) return;
+       updateRun = () -> {
+               updateRun = null;
+               if (isDisposed()) return;
+               runUpdate();
+       };
+       getDisplay().asyncExec(updateRun);
+}
+
+void runUpdate() {
+       if (updateFlags == 0) return;
+       int flags = updateFlags;
+       updateFlags = 0;
+       Rectangle rectBefore = getClientArea();
+       updateTabHeight(false);
+       updateItems(selectedIndex);
+       if ((flags & REDRAW) != 0) {
+               redraw();
+       } else if ((flags & REDRAW_TABS) != 0) {
+               redrawTabs();
+       }
+       Rectangle rectAfter = getClientArea();
+       if (!rectBefore.equals(rectAfter)) {
+               notifyListeners(SWT.Resize, new Event());
+               layout();
+       }
+}
+
+void updateBkImages() {
+       if (controls != null && controls.length > 0) {
+               for (int i = 0; i < controls.length; i++) {
+                       Control control = controls[i];
+                       if (!control.isDisposed()) {
+                               if (hovering) {
+                                       if (control instanceof Composite) ((Composite) control).setBackgroundMode(SWT.INHERIT_NONE);
+                                       control.setBackgroundImage(null);
+                                       control.setBackground(getBackground());
+                               } else {
+                                       if (control instanceof Composite) ((Composite) control).setBackgroundMode(SWT.INHERIT_DEFAULT);
+                                       Rectangle bounds = control.getBounds();
+                                       int tabHeight = getTabHeight();
+                                       int height = this.getSize().y;
+                                       boolean wrapped = onBottom ? bounds.y + bounds.height < height - tabHeight : bounds.y > tabHeight;
+                                       if (wrapped || gradientColors == null) {
+                                               control.setBackgroundImage(null);
+                                               control.setBackground(getBackground());
+                                       } else {
+                                               bounds.width = 10;
+                                               if (!onBottom) {
+                                                       bounds.y = -bounds.y;
+                                                       bounds.height -= 2*bounds.y - 1;
+                                               } else {
+                                                       bounds.height += height - (bounds.y + bounds.height);
+                                                       bounds.y = -1;
+                                               }
+                                               bounds.x = 0;
+                                               if (controlBkImages[i] != null) controlBkImages[i].dispose();
+                                               controlBkImages[i] = new Image(control.getDisplay(), bounds);
+                                               GC gc = new GC(controlBkImages[i]);
+                                               renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc);
+                                               gc.dispose();
+                                               control.setBackground(null);
+                                               control.setBackgroundImage(controlBkImages[i]);
+                                       }
+                               }
+                       }
+               }
+
+       }
+}
+String _getToolTip(int x, int y) {
+       CTabItem item = getItem(new Point (x, y));
+       if (item == 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();
+}
+/**
+* Set a control that can appear to the left or to the right of the folder tabs.
+* This method can also be used instead of #setTopRight(Control). To remove a tab
+* control, see#removeTabControl(Control);
+* <p>
+* The flags parameter sets the layout of the control in the tab area.
+* <code>SWT.LEAD</code> will cause the control to be positioned on the left
+* of the tabs. <code>SWT.TRAIL</code> will cause the control to be positioned on
+* the far right of the folder and it will have its default size. <code>SWT.TRAIL</code>
+* can be combined with <code>SWT.FILL</code>to fill all the available space to the
+* right of the last tab. <code>SWT.WRAP</code> can also be added to <code>SWT.TRAIL</code>
+* only to cause a control to wrap if there is not enough space to display it in its
+* entirety.
+* </p>
+* @param control the control to be displayed in the top right corner or null
+*
+* @param flags valid combinations are:
+* <ul><li>SWT.LEAD
+* <li> SWT.TRAIL (| SWT.FILL | SWT.WRAP)
+* </ul>
+* @exception SWTException <ul>
+*    <li>ERROR_WIDGET_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>
+*/
+/*public*/ void addTabControl(Control control, int flags) {
+       checkWidget();
+       addTabControl(control, flags, -1, true);
+}
+
+void addTabControl(Control control, int flags, int index, boolean update) {
+       switch (flags) {
+               case SWT.TRAIL:
+               case SWT.TRAIL | SWT.WRAP:
+               case SWT.TRAIL | SWT.FILL:
+               case SWT.TRAIL | SWT.FILL | SWT.WRAP:
+               case SWT.LEAD:
+                       break;
+               default:
+                       SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+                       break;
+       }
+       if (control != null && control.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       //check for duplicates
+       for (int i = 0; i < controls.length; i++) {
+               if (controls[i] == control) {
+                       SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       int length = controls.length;
+
+       control.addListener(SWT.Resize, listener);
+
+       //Grow all 4 arrays
+       Control[] newControls = new Control [length + 1];
+       System.arraycopy(controls, 0, newControls, 0, length);
+       controls = newControls;
+       int[] newAlignment = new int [length + 1];
+       System.arraycopy(controlAlignments, 0, newAlignment, 0, length);
+       controlAlignments = newAlignment;
+       Rectangle[] newRect = new Rectangle [length + 1];
+       System.arraycopy(controlRects, 0, newRect, 0, length);
+       controlRects = newRect;
+       Image[] newImage = new Image [length + 1];
+       System.arraycopy(controlBkImages, 0, newImage, 0, length);
+       controlBkImages = newImage;
+       if (index == -1) {
+               index = length;
+               if (chevronTb != null && control != chevronTb) index--;
+       }
+       System.arraycopy (controls, index, controls, index + 1, length - index);
+       System.arraycopy (controlAlignments, index, controlAlignments, index + 1, length - index);
+       System.arraycopy (controlRects, index, controlRects, index + 1, length - index);
+       System.arraycopy (controlBkImages, index, controlBkImages, index + 1, length - index);
+       controls[index] = control;
+       controlAlignments[index] = flags;
+       controlRects[index] = new Rectangle(0, 0, 0, 0);
+       if (update) {
+               updateFolder(UPDATE_TAB_HEIGHT | REDRAW);
+       }
+}
+
+/**
+* Removes the control from the list of tab controls.
+*
+* @param control the control to 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>
+*    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this CTabFolder</li>
+* </ul>
+*/
+/*public*/ void removeTabControl (Control control) {
+       checkWidget();
+       removeTabControl (control, true);
+}
+
+void removeTabControl (Control control, boolean update) {
+       if (control != null && control.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int index = -1;
+       for (int i = 0; i < controls.length; i++) {
+               if (controls[i] == control){
+                       index = i;
+                       break;
+               }
+       }
+       if (index == -1) return;
+
+       if (!control.isDisposed()) {
+               control.removeListener(SWT.Resize, listener);
+               control.setBackground (null);
+               control.setBackgroundImage (null);
+               if (control instanceof Composite) ((Composite) control).setBackgroundMode(SWT.INHERIT_NONE);
+       }
+
+       if (controlBkImages[index] != null && !controlBkImages[index].isDisposed()) controlBkImages[index].dispose();
+       if (controls.length == 1) {
+               controls = new Control[0];
+               controlAlignments = new int[0];
+               controlRects = new Rectangle[0];
+               controlBkImages = new Image[0];
+       } else {
+               Control[] newControls = new Control [controls.length - 1];
+               System.arraycopy(controls, 0, newControls, 0, index);
+               System.arraycopy(controls, index + 1, newControls, index, controls.length - index - 1);
+               controls = newControls;
+
+               int[] newAlignments = new int [controls.length];
+               System.arraycopy(controlAlignments, 0, newAlignments, 0, index);
+               System.arraycopy(controlAlignments, index + 1, newAlignments, index, controls.length - index);
+               controlAlignments = newAlignments;
+
+               Rectangle[] newRects = new Rectangle [controls.length];
+               System.arraycopy(controlRects, 0, newRects, 0, index);
+               System.arraycopy(controlRects, index + 1, newRects, index, controls.length - index);
+               controlRects = newRects;
+
+               Image[] newBkImages = new Image [controls.length];
+               System.arraycopy(controlBkImages, 0, newBkImages, 0, index);
+               System.arraycopy(controlBkImages, index + 1, newBkImages, index, controls.length - index);
+               controlBkImages = newBkImages;
+       }
+       if (update) {
+               updateFolder(UPDATE_TAB_HEIGHT | REDRAW);
+       }
+}
+
+int getWrappedHeight (Point size) {
+       boolean[][] positions = new boolean[1][];
+       Rectangle[] rects = computeControlBounds(size, positions);
+       int minY = Integer.MAX_VALUE, maxY = 0, wrapHeight = 0;
+       for (int i = 0; i < rects.length; i++) {
+               if (positions[0][i]) {
+                       minY = Math.min(minY, rects[i].y);
+                       maxY = Math.max(maxY, rects[i].y + rects[i].height);
+                       wrapHeight = maxY - minY;
+               }
+       }
+       return wrapHeight;
+}
+
+/**
+ * Sets whether a chevron is shown when there are more items to be displayed.
+ *
+ * @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*/ void setChevronVisible(boolean visible) {
+       checkWidget();
+       if (chevronVisible == visible) return;
+       chevronVisible = visible;
+       updateFolder(UPDATE_TAB_HEIGHT | REDRAW);
+}
+
+       boolean shouldHighlight() {
+               return this.highlight && highlightEnabled;
+       }
+
+/**
+ * Sets whether the selected tab is rendered as highlighted.
+ *
+ * @param enabled
+ *            {@code true} if the selected tab should be highlighted,
+ *            {@code 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.106
+ */
+public void setHighlightEnabled(boolean enabled) {
+       checkWidget();
+       if (highlightEnabled == enabled) {
+               return;
+       }
+       highlightEnabled = enabled;
+       updateFolder(REDRAW);
+}
+
+/**
+ * Returns <code>true</code> if the selected tab is rendered as
+ * highlighted.
+ *
+ * @return <code>true</code> if the selected tab is rendered as
+ *         highlighted
+ *
+ * @exception SWTException
+ *                <ul>
+ *                <li>ERROR_WIDGET_DISPOSED - 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.106
+ */
+public boolean getHighlightEnabled() {
+       checkWidget();
+       return highlightEnabled;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder2Adapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder2Adapter.java
new file mode 100644 (file)
index 0000000..ad7d76e
--- /dev/null
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods in
+ * {@link CTabFolder2Listener},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </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 implements 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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+public void showList(CTabFolderEvent event){}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder2Listener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolder2Listener.java
new file mode 100644 (file)
index 0000000..084e479
--- /dev/null
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends 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
+ */
+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(boolean)
+ * @see CTabFolder#setMinimizeVisible(boolean)
+ */
+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(boolean)
+ * @see CTabFolder#setMaximizeVisible(boolean)
+ */
+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(boolean)
+ * @see CTabFolder#setMinimizeVisible(boolean)
+ * @see CTabFolder#setMaximized(boolean)
+ * @see CTabFolder#setMaximizeVisible(boolean)
+ */
+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);
+
+/**
+ * Static helper method to create a <code>CTabFolder2Listener</code> for the
+ * {@link #close(CTabFolderEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return CTabFolder2Listener
+ * @since 3.107
+ */
+public static CTabFolder2Listener closeAdapter(Consumer<CTabFolderEvent> c) {
+       return new CTabFolder2Adapter() {
+               @Override
+               public void close(CTabFolderEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>CTabFolder2Listener</code> for the
+ * {@link #minimize(CTabFolderEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return CTabFolder2Listener
+ * @since 3.107
+ */
+public static CTabFolder2Listener minimizeAdapter(Consumer<CTabFolderEvent> c) {
+       return new CTabFolder2Adapter() {
+               @Override
+               public void minimize(CTabFolderEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>CTabFolder2Listener</code> for the
+ * {@link #maximize(CTabFolderEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return CTabFolder2Listener
+ * @since 3.107
+ */
+public static CTabFolder2Listener maximizeAdapter(Consumer<CTabFolderEvent> c) {
+       return new CTabFolder2Adapter() {
+               @Override
+               public void maximize(CTabFolderEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>CTabFolder2Listener</code> for the
+ * {@link #restore(CTabFolderEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return CTabFolder2Listener
+ * @since 3.107
+ */
+public static CTabFolder2Listener restoreAdapter(Consumer<CTabFolderEvent> c) {
+       return new CTabFolder2Adapter() {
+               @Override
+               public void restore(CTabFolderEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>CTabFolder2Listener</code> for the
+ * {@link #showList(CTabFolderEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return CTabFolder2Listener
+ * @since 3.107
+ */
+public static CTabFolder2Listener showListAdapter(Consumer<CTabFolderEvent> c) {
+       return new CTabFolder2Adapter() {
+               @Override
+               public void showList(CTabFolderEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderAdapter.java
new file mode 100644 (file)
index 0000000..0c807ef
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+/**
+ * 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 implements CTabFolderListener {
+       @Override
+       public void itemClosed(CTabFolderEvent event){}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderEvent.java
new file mode 100644 (file)
index 0000000..8bc5afa
--- /dev/null
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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 boolean 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
+ */
+CTabFolderEvent(Widget w) {
+       super(w);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " item=" + item
+               + " doit=" + doit
+               + " x=" + x
+               + " y=" + y
+               + " width=" + width
+               + " height=" + height
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderLayout.java
new file mode 100644 (file)
index 0000000..5b653a4
--- /dev/null
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class provides the layout for CTabFolder
+ *
+ * @see CTabFolder
+ */
+class CTabFolderLayout extends Layout {
+@Override
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+       CTabFolder folder = (CTabFolder)composite;
+       CTabItem[] items = folder.items;
+       CTabFolderRenderer renderer = folder.renderer;
+       // preferred width of tab area to show all tabs
+       int tabW = 0;
+       int selectedIndex = folder.selectedIndex;
+       if (selectedIndex == -1) selectedIndex = 0;
+       GC gc = new GC(folder);
+       for (int i = 0; i < items.length; i++) {
+               if (folder.single) {
+                       tabW = Math.max(tabW, renderer.computeSize(i, SWT.SELECTED, gc, SWT.DEFAULT, SWT.DEFAULT).x);
+               } else {
+                       int state = 0;
+                       if (i == selectedIndex) state |= SWT.SELECTED;
+                       tabW += renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+               }
+       }
+
+       int width = 0, wrapHeight = 0;
+       boolean leftControl = false, rightControl = false;
+       if (wHint == SWT.DEFAULT) {
+               for (int i = 0; i < folder.controls.length; i++) {
+                       Control control = folder.controls[i];
+                       if (!control.isDisposed() && control.getVisible()) {
+                               if ((folder.controlAlignments[i] & SWT.LEAD) != 0) {
+                                       leftControl = true;
+                               } else {
+                                       rightControl = true;
+                               }
+                               width += control.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+                       }
+               }
+       } else {
+               Point size = new Point (wHint, hHint);
+               boolean[][] positions = new boolean[1][];
+               Rectangle[] rects = folder.computeControlBounds(size, positions);
+               int minY = Integer.MAX_VALUE, maxY = 0;
+               for (int i = 0; i < rects.length; i++) {
+                       if (positions[0][i]) {
+                               minY = Math.min(minY, rects[i].y);
+                               maxY = Math.max(maxY, rects[i].y + rects[i].height);
+                               wrapHeight = maxY - minY;
+                       } else {
+                               if ((folder.controlAlignments[i] & SWT.LEAD) != 0) {
+                                       leftControl = true;
+                               } else {
+                                       rightControl = true;
+                               }
+                               width += rects[i].width;
+                       }
+               }
+       }
+       if (leftControl) width += CTabFolder.SPACING * 2;
+       if (rightControl) width += CTabFolder.SPACING * 2;
+       tabW += width;
+
+       gc.dispose();
+
+       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].control;
+               if (control != 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 + folder.marginWidth);
+       int minHeight = (folder.minimized) ? 0 : controlH + wrapHeight;
+       if (minWidth == 0) minWidth = CTabFolder.DEFAULT_WIDTH;
+       if (minHeight == 0) minHeight = CTabFolder.DEFAULT_HEIGHT;
+
+       if (wHint != SWT.DEFAULT) minWidth  = wHint;
+       if (hHint != SWT.DEFAULT) minHeight = hHint;
+
+       return new Point (minWidth, minHeight);
+}
+@Override
+protected boolean flushCache(Control control) {
+       return true;
+}
+@Override
+protected void layout(Composite composite, boolean flushCache) {
+       CTabFolder folder = (CTabFolder)composite;
+       // resize content
+       if (folder.selectedIndex != -1) {
+               Control control = folder.items[folder.selectedIndex].control;
+               if (control != null && !control.isDisposed()) {
+                       control.setBounds(folder.getClientArea());
+               }
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderListener.java
new file mode 100644 (file)
index 0000000..ce2e1a2
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface CTabFolderListener extends 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderRenderer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabFolderRenderer.java
new file mode 100644 (file)
index 0000000..fdb509b
--- /dev/null
@@ -0,0 +1,1850 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 455263
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Instances of this class provide all of the measuring and drawing functionality
+ * required by <code>CTabFolder</code>. This class can be subclassed in order to
+ * customize the look of a CTabFolder.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @since 3.6
+ */
+public class CTabFolderRenderer {
+
+       protected CTabFolder parent;
+
+       int[] curve;
+       int[] topCurveHighlightStart;
+       int[] topCurveHighlightEnd;
+       int curveWidth = 0;
+       int curveIndent = 0;
+       int lastTabHeight = -1;
+
+       Color fillColor;
+       /* Selected item appearance */
+       Color selectionHighlightGradientBegin = null;  //null == 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
+       /* Colors for anti-aliasing */
+       Color selectedOuterColor = null;
+       Color selectedInnerColor = null;
+       Color tabAreaColor = null;
+       Color minMaxBorderColor = null;
+       /*
+        * Border color that was used in computing the cached anti-alias Colors.
+        * We have to recompute the colors if the border color changes
+        */
+       Color lastBorderColor = null;
+
+       Font chevronFont = null;
+
+       //TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom)
+       //so can fade in same direction as right swoop curve
+       static final int[] TOP_LEFT_CORNER_HILITE = new int[] {5,2, 4,2, 3,3, 2,4, 2,5, 1,6};
+
+       static final int[] TOP_LEFT_CORNER = new int[] {0,6, 1,5, 1,4, 4,1, 5,1, 6,0};
+       static final int[] TOP_RIGHT_CORNER = new int[] {-6,0, -5,1, -4,1, -1,4, -1,5, 0,6};
+       static final int[] BOTTOM_LEFT_CORNER = new int[] {0,-6, 1,-5, 1,-4, 4,-1, 5,-1, 6,0};
+       static final int[] BOTTOM_RIGHT_CORNER = new int[] {-6,0, -5,-1, -4,-1, -1,-4, -1,-5, 0,-6};
+
+       static final int[] SIMPLE_TOP_LEFT_CORNER = new int[] {0,2, 1,1, 2,0};
+       static final int[] SIMPLE_TOP_RIGHT_CORNER = new int[] {-2,0, -1,1, 0,2};
+       static final int[] SIMPLE_BOTTOM_LEFT_CORNER = new int[] {0,-2, 1,-1, 2,0};
+       static final int[] SIMPLE_BOTTOM_RIGHT_CORNER = new int[] {-2,0, -1,-1, 0,-2};
+       static final int[] SIMPLE_UNSELECTED_INNER_CORNER = new int[] {0,0};
+
+       static final int[] TOP_LEFT_CORNER_BORDERLESS = new int[] {0,6, 1,5, 1,4, 4,1, 5,1, 6,0};
+       static final int[] TOP_RIGHT_CORNER_BORDERLESS = new int[] {-7,0, -6,1, -5,1, -2,4, -2,5, -1,6};
+       static final int[] BOTTOM_LEFT_CORNER_BORDERLESS = new int[] {0,-6, 1,-6, 1,-5, 2,-4, 4,-2, 5,-1, 6,-1, 6,0};
+       static final int[] BOTTOM_RIGHT_CORNER_BORDERLESS = new int[] {-7,0, -7,-1, -6,-1, -5,-2, -3,-4, -2,-5, -2,-6, -1,-6};
+
+       static final int[] SIMPLE_TOP_LEFT_CORNER_BORDERLESS = new int[] {0,2, 1,1, 2,0};
+       static final int[] SIMPLE_TOP_RIGHT_CORNER_BORDERLESS= new int[] {-3,0, -2,1, -1,2};
+       static final int[] SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = new int[] {0,-3, 1,-2, 2,-1, 3,0};
+       static final int[] SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = new int[] {-4,0, -3,-1, -2,-2, -1,-3};
+
+       static final RGB CLOSE_FILL = new RGB(252, 160, 160);
+
+       static final int BUTTON_SIZE = 16;
+       static final int BUTTON_TRIM = 1;
+
+       static final int BUTTON_BORDER = SWT.COLOR_WIDGET_DARK_SHADOW;
+       static final int BUTTON_FILL = SWT.COLOR_LIST_BACKGROUND;
+       static final int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW;
+
+       static final int ITEM_TOP_MARGIN = 2;
+       static final int ITEM_BOTTOM_MARGIN = 2;
+       static final int ITEM_LEFT_MARGIN = 4;
+       static final int ITEM_RIGHT_MARGIN = 4;
+       static final int INTERNAL_SPACING = 4;
+       static final int FLAGS = SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC | SWT.DRAW_DELIMITER;
+       static final String ELLIPSIS = "..."; //$NON-NLS-1$
+       private static final String CHEVRON_ELLIPSIS = "99+"; //$NON-NLS-1$
+       private static final int CHEVRON_FONT_HEIGHT = 10;
+
+       //Part constants
+       /**
+        * Part constant indicating the body of the tab folder. The body is the
+        * underlying container for all of the tab folder and all other parts are
+        * drawn on top of it. (value is -1).
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_BODY = -1;
+       /**
+        * Part constant indicating the tab header of the folder (value is -2). The
+        * header is drawn on top of the body and provides an area for the tabs and
+        * other tab folder buttons to be rendered.
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_HEADER = -2;
+       /**
+        * Part constant indicating the border of the tab folder. (value is -3). The
+        * border is drawn around the body and is part of the body trim.
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_BORDER = -3;
+       /**
+        * Part constant indicating the background of the tab folder. (value is -4).
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_BACKGROUND = -4;
+       /**
+        * Part constant indicating the maximize button of the tab folder. (value is
+        * -5).
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_MAX_BUTTON = -5;
+       /**
+        * Part constant indicating the minimize button of the tab folder. (value is
+        * -6).
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_MIN_BUTTON = -6;
+       /**
+        * Part constant indicating the chevron button of the tab folder. (value is
+        * -7).
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_CHEVRON_BUTTON = -7;
+       /**
+        * Part constant indicating the close button of a tab item. (value is -8).
+        *
+        * @see #computeSize(int, int, GC, int, int)
+        * @see #computeTrim(int, int, int, int, int, int)
+        * @see #draw(int, int, Rectangle, GC)
+        */
+       public static final int PART_CLOSE_BUTTON = -8;
+
+       public static final int MINIMUM_SIZE = 1 << 24; //TODO: Should this be a state?
+
+
+       /**
+        * Constructs a new instance of this class given its parent.
+        *
+        * @param parent CTabFolder
+        *
+        * @exception IllegalArgumentException <ul>
+        *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+        * </ul>
+        *
+        * @see Widget#getStyle
+        */
+       protected CTabFolderRenderer(CTabFolder parent) {
+               if (parent == null) return;
+               if (parent.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+               this.parent = parent;
+       }
+
+       void antialias (int[] shape, Color innerColor, Color outerColor, GC gc){
+               // Don't perform anti-aliasing on Mac because the platform
+               // already does it.  The simple style also does not require anti-aliasing.
+               if (parent.simple) return;
+               String platform = SWT.getPlatform();
+               if ("cocoa".equals(platform)) return; //$NON-NLS-1$
+               // Don't perform anti-aliasing on low resolution displays
+               if (parent.getDisplay().getDepth() < 15) return;
+               if (outerColor != null) {
+                       int index = 0;
+                       boolean left = true;
+                       int oldY = parent.onBottom ? 0 : parent.getSize().y;
+                       int[] outer = new int[shape.length];
+                       for (int i = 0; i < shape.length/2; i++) {
+                               if (left && (index + 3 < shape.length)) {
+                                       left = parent.onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
+                                       oldY = shape[index+1];
+                               }
+                               outer[index] = shape[index++] + (left ? -1 : +1);
+                               outer[index] = shape[index++];
+                       }
+                       gc.setForeground(outerColor);
+                       gc.drawPolyline(outer);
+               }
+               if (innerColor != null) {
+                       int[] inner = new int[shape.length];
+                       int index = 0;
+                       boolean left = true;
+                       int oldY = parent.onBottom ? 0 : parent.getSize().y;
+                       for (int i = 0; i < shape.length/2; i++) {
+                               if (left && (index + 3 < shape.length)) {
+                                       left = parent.onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
+                                       oldY = shape[index+1];
+                               }
+                               inner[index] = shape[index++] + (left ? +1 : -1);
+                               inner[index] = shape[index++];
+                       }
+                       gc.setForeground(innerColor);
+                       gc.drawPolyline(inner);
+               }
+       }
+
+       /**
+        * Returns the preferred size of a part.
+        * <p>
+        * The <em>preferred size</em> of a part 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 part 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>
+        * The <code>part</code> value indicated what component the preferred size is
+        * to be calculated for. Valid values are any of the part constants:
+        * </p>
+        * <ul>
+        * <li>PART_BODY</li>
+        * <li>PART_HEADER</li>
+        * <li>PART_BORDER</li>
+        * <li>PART_BACKGROUND</li>
+        * <li>PART_MAX_BUTTON</li>
+        * <li>PART_MIN_BUTTON</li>
+        * <li>PART_CHEVRON_BUTTON</li>
+        * <li>PART_CLOSE_BUTTON</li>
+        * <li>A positive integer which is the index of an item in the CTabFolder.</li>
+        * </ul>
+        * <p>
+        * The <code>state</code> parameter may be one of the following:
+        * </p>
+        * <ul>
+        * <li>SWT.NONE</li>
+        * <li>SWT.SELECTED - whether the part is selected</li>
+        * </ul>
+        * @param part a part constant
+        * @param state current state
+        * @param gc the gc to use for measuring
+        * @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 part
+        *
+        * @since 3.6
+        */
+       protected Point computeSize (int part, int state, GC gc, int wHint, int hHint) {
+               int width = 0, height = 0;
+               switch (part) {
+                       case PART_HEADER:
+                               if (parent.fixedTabHeight != SWT.DEFAULT) {
+                                       height = parent.fixedTabHeight == 0 ? 0 : parent.fixedTabHeight + 1; // +1 for line drawn across top of tab
+                               } else {
+                                       CTabItem[] items = parent.items;
+                                       if (items.length == 0) {
+                                               height = gc.textExtent("Default", FLAGS).y + ITEM_TOP_MARGIN + ITEM_BOTTOM_MARGIN; //$NON-NLS-1$
+                                       } else {
+                                               for (int i=0; i < items.length; i++) {
+                                                       height = Math.max(height, computeSize(i, SWT.NONE, gc, wHint, hHint).y);
+                                               }
+                                       }
+                                       gc.dispose();
+                               }
+                               break;
+                       case PART_MAX_BUTTON:
+                       case PART_MIN_BUTTON:
+                       case PART_CLOSE_BUTTON:
+                               width = height = BUTTON_SIZE;
+                               break;
+                       case PART_CHEVRON_BUTTON:
+                               Font prevFont = gc.getFont();
+                               gc.setFont(getChevronFont(parent.getDisplay()));
+                               int widthOfDoubleArrows = 8; // see drawChevron method
+                               width = gc.textExtent(CHEVRON_ELLIPSIS).x + widthOfDoubleArrows;
+                               height = BUTTON_SIZE;
+                               gc.setFont(prevFont);
+                               break;
+                       default:
+                               if (0 <= part && part < parent.getItemCount()) {
+                                       updateCurves();
+                                       CTabItem item = parent.items[part];
+                                       if (item.isDisposed()) return new Point(0,0);
+                                       Image image = item.getImage();
+                                       if (image != null && !image.isDisposed()) {
+                                               Rectangle bounds = image.getBounds();
+                                               if ((state & SWT.SELECTED) != 0 || parent.showUnselectedImage) {
+                                                       width += bounds.width;
+                                               }
+                                               height =  bounds.height;
+                                       }
+                                       String text = null;
+                                       if ((state & MINIMUM_SIZE) != 0) {
+                                               int minChars = parent.minChars;
+                                               text = minChars == 0 ? null : item.getText();
+                                               if (text != null && text.length() > minChars) {
+                                                       if (useEllipses()) {
+                                                               int end = minChars < ELLIPSIS.length() + 1 ? minChars : minChars - ELLIPSIS.length();
+                                                               text = text.substring(0, end);
+                                                               if (minChars > ELLIPSIS.length() + 1) text += ELLIPSIS;
+                                                       } else {
+                                                               int end = minChars;
+                                                               text = text.substring(0, end);
+                                                       }
+                                               }
+                                       } else {
+                                               text = item.getText();
+                                       }
+                                       if (text != null) {
+                                               if (width > 0) width += INTERNAL_SPACING;
+                                               if (item.font == null) {
+                                                       Point size = gc.textExtent(text, FLAGS);
+                                                       width += size.x;
+                                                       height = Math.max(height, size.y);
+                                               } else {
+                                                       Font gcFont = gc.getFont();
+                                                       gc.setFont(item.font);
+                                                       Point size = gc.textExtent(text, FLAGS);
+                                                       width += size.x;
+                                                       height = Math.max(height, size.y);
+                                                       gc.setFont(gcFont);
+                                               }
+                                       }
+                                       if (parent.showClose || item.showClose) {
+                                               if ((state & SWT.SELECTED) != 0 || parent.showUnselectedClose) {
+                                                       if (width > 0) width += INTERNAL_SPACING;
+                                                       width += computeSize(PART_CLOSE_BUTTON, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).x;
+                                               }
+                                       }
+                               }
+                               break;
+               }
+               Rectangle trim = computeTrim(part, state, 0, 0, width, height);
+               width = trim.width;
+               height = trim.height;
+               return new Point(width, height);
+       }
+
+       /**
+        * Given a desired <em>client area</em> for the part
+        * (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
+        * part's bounds were set to that rectangle, the area
+        * of the part 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 part one of the part constants
+        * @param state the state of the part
+        * @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
+        *
+        * @see CTabFolderRenderer#computeSize(int, int, GC, int, int) valid part and state values
+        *
+        * @since 3.6
+        */
+       protected Rectangle computeTrim (int part, int state, int x, int y, int width, int height) {
+               int borderLeft = parent.borderVisible ? 1 : 0;
+               int borderRight = borderLeft;
+               int borderTop = parent.onBottom ? borderLeft : 0;
+               int borderBottom = parent.onBottom ? 0 : borderLeft;
+               int tabHeight = parent.tabHeight;
+               switch (part) {
+                       case PART_BODY:
+                               int style = parent.getStyle();
+                               int highlight_header = (style & SWT.FLAT) != 0 ? 1 : 3;
+                               int highlight_margin = (style & SWT.FLAT) != 0 ? 0 : 2;
+                               if (parent.fixedTabHeight == 0 && (style & SWT.FLAT) != 0 && (style & SWT.BORDER) == 0) {
+                                       highlight_header = 0;
+                               }
+                               int marginWidth = parent.marginWidth;
+                               int marginHeight = parent.marginHeight;
+                               x = x - marginWidth - highlight_margin - borderLeft;
+                               width = width + borderLeft + borderRight + 2*marginWidth + 2*highlight_margin;
+                               if (parent.minimized) {
+                                       y = parent.onBottom ? y - borderTop : y - highlight_header - tabHeight - borderTop;
+                                       height = borderTop + borderBottom + tabHeight + highlight_header;
+                               } else {
+                                       y = parent.onBottom ? y - marginHeight - highlight_margin - borderTop : y - marginHeight - highlight_header - tabHeight - borderTop;
+                                       height = height + borderTop + borderBottom + 2*marginHeight + tabHeight + highlight_header + highlight_margin;
+                               }
+                               break;
+                       case PART_HEADER:
+                               //no trim
+                               break;
+                       case PART_MAX_BUTTON:
+                       case PART_MIN_BUTTON:
+                       case PART_CLOSE_BUTTON:
+                       case PART_CHEVRON_BUTTON:
+                               x -= BUTTON_TRIM;
+                               y -= BUTTON_TRIM;
+                               width += BUTTON_TRIM*2;
+                               height += BUTTON_TRIM*2;
+                               break;
+                       case PART_BORDER:
+                               x = x - borderLeft;
+                               width = width + borderLeft + borderRight;
+                               if (!parent.simple) width += 2; // TOP_RIGHT_CORNER needs more space
+                               y = y - borderTop;
+                               height = height + borderTop + borderBottom;
+                               break;
+                       default:
+                               if (0 <= part && part < parent.getItemCount()) {
+                                       updateCurves();
+                                       x = x - ITEM_LEFT_MARGIN;
+                                       width = width + ITEM_LEFT_MARGIN + ITEM_RIGHT_MARGIN;
+                                       if (!parent.simple && !parent.single && (state & SWT.SELECTED) != 0) {
+                                               width += curveWidth - curveIndent;
+                                       }
+                                       y = y - ITEM_TOP_MARGIN;
+                                       height = height + ITEM_TOP_MARGIN + ITEM_BOTTOM_MARGIN;
+                               }
+                               break;
+               }
+               return new Rectangle(x, y, width, height);
+       }
+
+       void createAntialiasColors() {
+               disposeAntialiasColors();
+               lastBorderColor = parent.getDisplay().getSystemColor(BORDER1_COLOR);
+               RGB lineRGB = lastBorderColor.getRGB();
+               /* compute the selected color */
+               RGB innerRGB = parent.selectionBackground.getRGB();
+               if (parent.selectionBgImage != null ||
+                       (parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1)) {
+                       innerRGB = null;
+               }
+               RGB outerRGB = parent.getBackground().getRGB();
+               if (parent.gradientColors != null && parent.gradientColors.length > 1) {
+                       outerRGB = null;
+               }
+               if (outerRGB != null) {
+                       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;
+                       selectedOuterColor = new Color(parent.getDisplay(), red, green, blue);
+               }
+               if (innerRGB != null) {
+                       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;
+                       selectedInnerColor = new Color(parent.getDisplay(), red, green, blue);
+               }
+               /* compute the tabArea color */
+               outerRGB = parent.getParent().getBackground().getRGB();
+               if (outerRGB != null) {
+                       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;
+                       tabAreaColor = new Color(parent.getDisplay(), red, green, blue);
+               }
+       }
+
+       /*
+        * 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 == 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 = parent.tabHeight;
+
+               RGB from = start.getRGB();
+               RGB to = parent.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(parent.getDisplay(), red, green, blue);
+               }
+       }
+
+       /**
+        * Dispose of any operating system resources associated with
+        * the renderer. Called by the CTabFolder parent upon receiving
+        * the dispose event or when changing the renderer.
+        *
+        * @since 3.6
+        */
+       protected void dispose() {
+               disposeAntialiasColors();
+               disposeSelectionHighlightGradientColors();
+               if (fillColor != null) {
+                       fillColor.dispose();
+                       fillColor = null;
+               }
+               if (chevronFont != null) {
+                       chevronFont.dispose();
+                       chevronFont = null;
+               }
+               if (minMaxBorderColor != null) {
+                       minMaxBorderColor.dispose();
+                       minMaxBorderColor = null;
+               }
+       }
+
+       void disposeAntialiasColors() {
+               if (tabAreaColor != null) tabAreaColor.dispose();
+               if (selectedInnerColor != null) selectedInnerColor.dispose();
+               if (selectedOuterColor != null) selectedOuterColor.dispose();
+               tabAreaColor = selectedInnerColor = selectedOuterColor = null;
+       }
+
+       void disposeSelectionHighlightGradientColors() {
+               if(selectionHighlightGradientColorsCache == null)
+                       return;
+               for (Color element : selectionHighlightGradientColorsCache) {
+                       element.dispose();
+               }
+               selectionHighlightGradientColorsCache = null;
+       }
+
+       /**
+        * Draw a specified <code>part</code> of the CTabFolder using the provided <code>bounds</code> and <code>GC</code>.
+        * <p>The valid CTabFolder <code>part</code> constants are:
+        * </p>
+        * <ul>
+        * <li>PART_BODY - the entire body of the CTabFolder</li>
+        * <li>PART_HEADER - the upper tab area of the CTabFolder</li>
+        * <li>PART_BORDER - the border of the CTabFolder</li>
+        * <li>PART_BACKGROUND - the background of the CTabFolder</li>
+        * <li>PART_MAX_BUTTON</li>
+        * <li>PART_MIN_BUTTON</li>
+        * <li>PART_CHEVRON_BUTTON</li>
+        * <li>PART_CLOSE_BUTTON</li>
+        * <li>A positive integer which is the index of an item in the CTabFolder.</li>
+        * </ul>
+        * <p>
+        * The <code>state</code> parameter may be a combination of:
+        * </p>
+        * <ul>
+        * <li>SWT.BACKGROUND - whether the background should be drawn</li>
+        * <li>SWT.FOREGROUND - whether the foreground should be drawn</li>
+        * <li>SWT.SELECTED - whether the part is selected</li>
+        * <li>SWT.HOT - whether the part is hot (i.e. mouse is over the part)</li>
+        * </ul>
+        *
+        * @param part part to draw
+        * @param state state of the part
+        * @param bounds the bounds of the part
+        * @param gc the gc to draw the part on
+        *
+        * @since 3.6
+        */
+       protected void draw (int part, int state, Rectangle bounds, GC gc) {
+               if (minMaxBorderColor == null) {
+                       // this color has to be identical to the colors used in the PNG files of
+                       // the view drop down menu located in
+                       // org.eclipse.e4.ui.workbench.renderers.swt/icons/full/elcl16/view_menu.png
+                       minMaxBorderColor = new Color (gc.getDevice(), 105, 105, 105);
+               }
+               switch (part) {
+                       case PART_BACKGROUND:
+                               this.drawBackground(gc, bounds, state);
+                               break;
+                       case PART_BODY:
+                               drawBody(gc, bounds, state);
+                               break;
+                       case PART_HEADER:
+                               drawTabArea(gc, bounds, state);
+                               break;
+                       case PART_MAX_BUTTON:
+                               drawMaximize(gc, bounds, state);
+                               break;
+                       case PART_MIN_BUTTON:
+                               drawMinimize(gc, bounds, state);
+                               break;
+                       case PART_CHEVRON_BUTTON:
+                               drawChevron(gc, bounds, state);
+                               break;
+                       default:
+                               if (0 <= part && part < parent.getItemCount()) {
+                                       if (bounds.width == 0 || bounds.height == 0) return;
+                                       if ((state & SWT.SELECTED) != 0 ) {
+                                               drawSelected(part, gc, bounds, state);
+                                       } else {
+                                               drawUnselected(part, gc, bounds, state);
+                                       }
+                               }
+                               break;
+               }
+       }
+
+       void drawBackground(GC gc, Rectangle bounds, int state) {
+               boolean selected = (state & SWT.SELECTED) != 0;
+               Color defaultBackground = selected && parent.shouldHighlight() ? parent.selectionBackground : parent.getBackground();
+               Image image = selected ? parent.selectionBgImage : null;
+               Color[] colors = selected & parent.shouldHighlight() ? parent.selectionGradientColors : parent.gradientColors;
+               int[] percents = selected ? parent.selectionGradientPercents : parent.gradientPercents;
+               boolean vertical = selected ? parent.selectionGradientVertical : parent.gradientVertical;
+
+               drawBackground(gc, null, bounds.x, bounds.y, bounds.width, bounds.height, defaultBackground, image, colors, percents, vertical);
+       }
+
+       void drawBackground(GC gc, int[] shape, boolean selected) {
+               Color defaultBackground = selected && parent.shouldHighlight() ? parent.selectionBackground : parent.getBackground();
+               Image image = selected ? parent.selectionBgImage : null;
+               Color[] colors = selected && parent.shouldHighlight() ? parent.selectionGradientColors : parent.gradientColors;
+               int[] percents = selected ? parent.selectionGradientPercents : parent.gradientPercents;
+               boolean vertical = selected ? parent.selectionGradientVertical : parent.gradientVertical;
+               Point size = parent.getSize();
+               int width = size.x;
+               int height = parent.tabHeight + ((parent.getStyle() & SWT.FLAT) != 0 ? 1 : 3);
+               int x = 0;
+
+               int borderLeft = parent.borderVisible ? 1 : 0;
+               int borderTop = parent.onBottom ? borderLeft : 0;
+               int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+               if (borderLeft > 0) {
+                       x += 1; width -= 2;
+               }
+               int y = parent.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, boolean vertical) {
+               Region clipping = null, region = null;
+               if (shape != null) {
+                       clipping = new Region();
+                       gc.getClipping(clipping);
+                       region = new Region();
+                       region.add(shape);
+                       region.intersect(clipping);
+                       gc.setClipping(region);
+               }
+               if (image != 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 != null) {
+                       // draw gradient
+                       if (colors.length == 1) {
+                               Color background = colors[0] != null ? colors[0] : defaultBackground;
+                               gc.setBackground(background);
+                               gc.fillRectangle(x, y, width, height);
+                       } else {
+                               if (vertical) {
+                                       if (parent.onBottom) {
+                                               int pos = 0;
+                                               if (percents[percents.length - 1] < 100) {
+                                                       pos = (100 - percents[percents.length - 1]) * height / 100;
+                                                       gc.setBackground(defaultBackground);
+                                                       gc.fillRectangle(x, y, width, pos);
+                                               }
+                                               Color lastColor = colors[colors.length-1];
+                                               if (lastColor == null) lastColor = defaultBackground;
+                                               for (int i = percents.length-1; i >= 0; i--) {
+                                                       gc.setForeground(lastColor);
+                                                       lastColor = colors[i];
+                                                       if (lastColor == null) lastColor = defaultBackground;
+                                                       gc.setBackground(lastColor);
+                                                       int percentage = i > 0 ? percents[i] - percents[i-1] : percents[i];
+                                                       int gradientHeight = percentage * height / 100;
+                                                       gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
+                                                       pos += gradientHeight;
+                                               }
+                                       } else {
+                                               Color lastColor = colors[0];
+                                               if (lastColor == null) lastColor = defaultBackground;
+                                               int pos = 0;
+                                               for (int i = 0; i < percents.length; i++) {
+                                                       gc.setForeground(lastColor);
+                                                       lastColor = colors[i + 1];
+                                                       if (lastColor == null) lastColor = defaultBackground;
+                                                       gc.setBackground(lastColor);
+                                                       int percentage = i > 0 ? percents[i] - percents[i-1] : percents[i];
+                                                       int gradientHeight = percentage * 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 = parent.getSize().y;
+                                       Color lastColor = colors[0];
+                                       if (lastColor == null) lastColor = defaultBackground;
+                                       int pos = 0;
+                                       for (int i = 0; i < percents.length; ++i) {
+                                               gc.setForeground(lastColor);
+                                               lastColor = colors[i + 1];
+                                               if (lastColor == 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 ((parent.getStyle() & SWT.NO_BACKGROUND) != 0 || !defaultBackground.equals(parent.getBackground())) {
+                               gc.setBackground(defaultBackground);
+                               gc.fillRectangle(x, y, width, height);
+                       }
+               }
+               if (shape != null) {
+                       gc.setClipping(clipping);
+                       clipping.dispose();
+                       region.dispose();
+               }
+       }
+
+       /*
+        * Draw the border of the tab
+        *
+        * @param gc
+        * @param shape
+        */
+       void drawBorder(GC gc, int[] shape) {
+
+               gc.setForeground(parent.getDisplay().getSystemColor(BORDER1_COLOR));
+               gc.drawPolyline(shape);
+       }
+
+       void drawBody(GC gc, Rectangle bounds, int state) {
+               Point size = new Point(bounds.width, bounds.height);
+               int selectedIndex = parent.selectedIndex;
+               int tabHeight = parent.tabHeight;
+
+               int borderLeft = parent.borderVisible ? 1 : 0;
+               int borderRight = borderLeft;
+               int borderTop = parent.onBottom ? borderLeft : 0;
+               int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+               int style = parent.getStyle();
+               int highlight_header = (style & SWT.FLAT) != 0 ? 1 : 3;
+               int highlight_margin = (style & SWT.FLAT) != 0 ? 0 : 2;
+
+               // fill in body
+               if (!parent.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 (parent.onBottom) {
+                                       int x1 = borderLeft;
+                                       int y1 = borderTop;
+                                       int x2 = size.x - borderRight;
+                                       int y2 = size.y - borderBottom - tabHeight - highlight_header;
+                                       shape = new int[] {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 = new int[] {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 != -1 && parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1 && !parent.selectionGradientVertical) {
+                                       drawBackground(gc, shape, true);
+                               } else if (selectedIndex == -1 && parent.gradientColors != null && parent.gradientColors.length > 1 && !parent.gradientVertical) {
+                                       drawBackground(gc, shape, false);
+                               } else {
+                                       gc.setBackground(selectedIndex == -1 ? parent.getBackground() : parent.selectionBackground);
+                                       gc.fillPolygon(shape);
+                               }
+                       }
+                       //Draw client area
+                       if ((parent.getStyle() & SWT.NO_BACKGROUND) != 0) {
+                               gc.setBackground(parent.getBackground());
+                               int marginWidth = parent.marginWidth;
+                               int marginHeight = parent.marginHeight;
+                               int xClient = borderLeft + marginWidth + highlight_margin, yClient;
+                               if (parent.onBottom) {
+                                       yClient = borderTop + highlight_margin + marginHeight;
+                               } else {
+                                       yClient = borderTop + tabHeight + highlight_header + marginHeight;
+                               }
+                               gc.fillRectangle(xClient - marginWidth, yClient - marginHeight, width, height);
+                       }
+               } else {
+                       if ((parent.getStyle() & SWT.NO_BACKGROUND) != 0) {
+                               int height = borderTop + tabHeight + highlight_header + borderBottom;
+                               if (size.y > height) {
+                                       gc.setBackground(parent.getParent().getBackground());
+                                       gc.fillRectangle(0, height, size.x, size.y - height);
+                               }
+                       }
+               }
+
+               //draw 1 pixel border around outside
+               if (borderLeft > 0) {
+                       gc.setForeground(parent.getDisplay().getSystemColor(BORDER1_COLOR));
+                       int x1 = borderLeft - 1;
+                       int x2 = size.x - borderRight;
+                       int y1 = parent.onBottom ? borderTop - 1 : borderTop + tabHeight;
+                       int y2 = parent.onBottom ? size.y - tabHeight - borderBottom - 1 : size.y - borderBottom;
+                       gc.drawLine(x1, y1, x1, y2); // left
+                       gc.drawLine(x2, y1, x2, y2); // right
+                       if (parent.onBottom) {
+                               gc.drawLine(x1, y1, x2, y1); // top
+                       } else {
+                               gc.drawLine(x1, y2, x2, y2); // bottom
+                       }
+               }
+       }
+
+       void drawClose(GC gc, Rectangle closeRect, int closeImageState) {
+               if (closeRect.width == 0 || closeRect.height == 0) return;
+               Display display = parent.getDisplay();
+
+               // draw X 9x9
+               int x = closeRect.x + Math.max(1, (closeRect.width-9)/2);
+               int y = closeRect.y + Math.max(1, (closeRect.height-9)/2);
+               y += parent.onBottom ? -1 : 1;
+
+               Color closeBorder = display.getSystemColor(BUTTON_BORDER);
+               switch (closeImageState & (SWT.HOT | SWT.SELECTED | SWT.BACKGROUND)) {
+                       case SWT.NONE: {
+                               int[] shape = new int[] {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(BUTTON_FILL));
+                               gc.fillPolygon(shape);
+                               gc.setForeground(closeBorder);
+                               gc.drawPolygon(shape);
+                               break;
+                       }
+                       case SWT.HOT: {
+                               int[] shape = new int[] {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(getFillColor());
+                               gc.fillPolygon(shape);
+                               gc.setForeground(closeBorder);
+                               gc.drawPolygon(shape);
+                               break;
+                       }
+                       case SWT.SELECTED: {
+                               int[] shape = new int[] {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};
+                               gc.setBackground(getFillColor());
+                               gc.fillPolygon(shape);
+                               gc.setForeground(closeBorder);
+                               gc.drawPolygon(shape);
+                               break;
+                       }
+                       case SWT.BACKGROUND: {
+                               int[] shape = new int[] {x,y, x+10,y, x+10,y+10, x,y+10};
+                               drawBackground(gc, shape, false);
+                               break;
+                       }
+               }
+       }
+
+       void drawChevron(GC gc, Rectangle chevronRect, int chevronImageState) {
+               if (chevronRect.width == 0 || chevronRect.height == 0) return;
+               int selectedIndex = parent.selectedIndex;
+               // draw chevron (10x7)
+               Display display = parent.getDisplay();
+               Font font = getChevronFont(display);
+               int fontHeight = font.getFontData()[0].getHeight();
+               int indent = Math.max(2, (chevronRect.height - fontHeight - 4) /2);
+               int x = chevronRect.x + 2;
+               int y = chevronRect.y + indent;
+               int count;
+               int itemCount = parent.getItemCount();
+               if (parent.single) {
+                       count = selectedIndex == -1 ? itemCount : itemCount - 1;
+               } else {
+                       int showCount = 0;
+                       while (showCount < parent.priority.length && parent.items[parent.priority[showCount]].showing) {
+                               showCount++;
+                       }
+                       count = itemCount - showCount;
+               }
+               String chevronString = count > 99 ? CHEVRON_ELLIPSIS : String.valueOf(count);
+               switch (chevronImageState & (SWT.HOT | SWT.SELECTED)) {
+                       case SWT.NONE: {
+                               Color chevronBorder = parent.single ? parent.getSelectionForeground() : parent.getForeground();
+                               gc.setForeground(chevronBorder);
+                               gc.setFont(font);
+                               drawChevronContent(gc, x, y, chevronString);
+                               break;
+                       }
+                       case SWT.HOT: {
+                               gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+                               gc.setBackground(display.getSystemColor(BUTTON_FILL));
+                               gc.setFont(font);
+                               drawRoundRectangle(gc, chevronRect);
+                               drawChevronContent(gc, x, y, chevronString);
+                               break;
+                       }
+                       case SWT.SELECTED: {
+                               gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+                               gc.setBackground(display.getSystemColor(BUTTON_FILL));
+                               gc.setFont(font);
+                               drawRoundRectangle(gc, chevronRect);
+                               drawChevronContent(gc, x+1, y+1, chevronString);
+                               break;
+                       }
+               }
+       }
+
+       private void drawRoundRectangle(GC gc, Rectangle chevronRect) {
+               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);
+       }
+
+       private void drawChevronContent(GC gc, int x, int y, String chevronString) {
+               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+4,y+4);
+               gc.drawLine(x+5,y,   x+7,y+2);
+               gc.drawLine(x+7,y+2, x+5,y+4);
+               gc.drawString(chevronString, x+7, y+3, true);
+       }
+
+       /*
+        * 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, Rectangle bounds, int state, int rightEdge) {
+               //only draw for curvy tabs and only draw for top tabs
+               if(parent.simple || parent.onBottom)
+                       return;
+
+               if(selectionHighlightGradientBegin == null)
+                       return;
+
+               Color[] gradients = selectionHighlightGradientColorsCache;
+               if(gradients == null)
+                       return;
+               int gradientsSize = gradients.length;
+               if(gradientsSize == 0)
+                       return;         //shouldn't happen but just to be tidy
+
+               int x = bounds.x;
+               int y = bounds.y;
+
+               gc.setForeground(gradients[0]);
+
+               //draw top horizontal line
+               gc.drawLine(
+                               TOP_LEFT_CORNER_HILITE[0] + x + 1, //rely on fact that first pair is top/right of curve
+                               1 + y,
+                               rightEdge - curveIndent,
+                               1 + y);
+
+               int[] leftHighlightCurve = TOP_LEFT_CORNER_HILITE;
+
+               int d = parent.tabHeight - 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 - curveIndent;
+
+               //draw right swoop highlight up to diagonal portion
+               for (int i = 0; i < topCurveHighlightStart.length /2; i++) {
+                       int rawX = topCurveHighlightStart[i * 2];
+                       int rawY = 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 < topCurveHighlightEnd.length /2; i++) {
+                       int rawX = topCurveHighlightEnd[i * 2]; //d is already encoded in this value
+                       int rawY = 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 left.
+        *
+        * @param gc
+        */
+       void drawLeftUnselectedBorder(GC gc, Rectangle bounds, int state) {
+               int x = bounds.x;
+               int y = bounds.y;
+               int height = bounds.height;
+
+               int[] shape = null;
+               if (parent.onBottom) {
+                       int[] left = parent.simple
+                               ? SIMPLE_UNSELECTED_INNER_CORNER
+                               : 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
+                               ? SIMPLE_UNSELECTED_INNER_CORNER
+                               : 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 drawMaximize(GC gc, Rectangle maxRect, int maxImageState) {
+               if (maxRect.width == 0 || maxRect.height == 0) return;
+               Display display = parent.getDisplay();
+               // 5x4 or 7x9
+               int x = maxRect.x + (maxRect.width - 10)/2;
+               int y = maxRect.y + 3;
+
+               gc.setForeground(minMaxBorderColor);
+               gc.setBackground(display.getSystemColor(BUTTON_FILL));
+
+               switch (maxImageState & (SWT.HOT | SWT.SELECTED)) {
+                       case SWT.NONE: {
+                               if (!parent.getMaximized()) {
+                                       gc.fillRectangle(x, y, 9, 9);
+                                       gc.drawRectangle(x, y, 9, 9);
+                                       gc.drawLine(x, y+2, x+9, 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+2, y+1, x+7, y+1);
+                                       gc.drawLine(x, y+4, x+5, y+4);
+                               }
+                               break;
+                       }
+                       case SWT.HOT: {
+                               drawRoundRectangle(gc, maxRect);
+                               if (!parent.getMaximized()) {
+                                       gc.fillRectangle(x, y, 9, 9);
+                                       gc.drawRectangle(x, y, 9, 9);
+                                       gc.drawLine(x, y+2, x+9, 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+2, y+1, x+7, y+1);
+                                       gc.drawLine(x, y+4, x+5, y+4);
+                               }
+                               break;
+                       }
+                       case SWT.SELECTED: {
+                               drawRoundRectangle(gc, maxRect);
+                               if (!parent.getMaximized()) {
+                                       gc.fillRectangle(x+1, y+1, 9, 9);
+                                       gc.drawRectangle(x+1, y+1, 9, 9);
+                                       gc.drawLine(x+1, y+3, x+10, 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+3, y+2, x+8, y+2);
+                                       gc.drawLine(x+1, y+5, x+6, y+5);
+                               }
+                               break;
+                       }
+               }
+       }
+       void drawMinimize(GC gc, Rectangle minRect, int minImageState) {
+               if (minRect.width == 0 || minRect.height == 0) return;
+               Display display = parent.getDisplay();
+               // 5x4 or 9x3
+               int x = minRect.x + (minRect.width - 10)/2;
+               int y = minRect.y + 3;
+
+               gc.setForeground(minMaxBorderColor);
+               gc.setBackground(display.getSystemColor(BUTTON_FILL));
+
+               switch (minImageState & (SWT.HOT | SWT.SELECTED)) {
+                       case SWT.NONE: {
+                               if (!parent.getMinimized()) {
+                                       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 SWT.HOT: {
+                               drawRoundRectangle(gc, minRect);
+                               if (!parent.getMinimized()) {
+                                       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 SWT.SELECTED: {
+                               drawRoundRectangle(gc, minRect);
+                               if (!parent.getMinimized()) {
+                                       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;
+                       }
+               }
+       }
+
+       /*
+        * Draw the unselected border for the receiver on the right.
+        *
+        * @param gc
+        */
+       void drawRightUnselectedBorder(GC gc, Rectangle bounds, int state) {
+               int x = bounds.x;
+               int y = bounds.y;
+               int width = bounds.width;
+               int height = bounds.height;
+
+               int[] shape = null;
+               int startX = x + width - 1;
+
+               if (parent.onBottom) {
+                       int[] right = parent.simple
+                               ? SIMPLE_UNSELECTED_INNER_CORNER
+                               : 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
+                               ? SIMPLE_UNSELECTED_INNER_CORNER
+                               : 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);
+
+       }
+
+       void drawSelected(int itemIndex, GC gc, Rectangle bounds, int state ) {
+               CTabItem item = parent.items[itemIndex];
+               int x = bounds.x;
+               int y = bounds.y;
+               int height = bounds.height;
+               int width = bounds.width;
+               if (!parent.simple && !parent.single) width -= (curveWidth - curveIndent);
+               int borderLeft = parent.borderVisible ? 1 : 0;
+               int borderRight = borderLeft;
+               int borderTop = parent.onBottom ? borderLeft : 0;
+               int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+               Point size = parent.getSize();
+
+               int rightEdge = Math.min (x + width, parent.getRightItemEdge(gc));
+               //       Draw selection border across all tabs
+
+               if ((state & SWT.BACKGROUND) != 0) {
+                       int highlight_header = (parent.getStyle() & SWT.FLAT) != 0 ? 1 : 3;
+                       int xx = borderLeft;
+                       int yy = parent.onBottom ? size.y - borderBottom - parent.tabHeight - highlight_header : borderTop + parent.tabHeight + 1;
+                       int ww = size.x - borderLeft - borderRight;
+                       int hh = highlight_header - 1;
+                       int[] shape = new int[] {xx,yy, xx+ww,yy, xx+ww,yy+hh, xx,yy+hh};
+                       if (parent.selectionGradientColors != null && !parent.selectionGradientVertical) {
+                               drawBackground(gc, shape, parent.shouldHighlight());
+                       } else {
+                               gc.setBackground(parent.shouldHighlight() ? parent.selectionBackground : parent.getBackground());
+                               gc.fillRectangle(xx, yy, ww, hh);
+                       }
+
+                       if (parent.single) {
+                               if (!item.showing) return;
+                       } else {
+                               // if selected tab scrolled out of view or partially out of view
+                               // just draw bottom line
+                               if (!item.showing){
+                                       int x1 = Math.max(0, borderLeft - 1);
+                                       int y1 = (parent.onBottom) ? y - 1 : y + height;
+                                       int x2 = size.x - borderRight;
+                                       gc.setForeground(parent.getDisplay().getSystemColor(BORDER1_COLOR));
+                                       gc.drawLine(x1, y1, x2, y1);
+                                       return;
+                               }
+
+                               // draw selected tab background and outline
+                               shape = null;
+                               if (parent.onBottom) {
+                                       int[] left = parent.simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER;
+                                       int[] right = parent.simple ? SIMPLE_BOTTOM_RIGHT_CORNER : curve;
+                                       if (borderLeft == 0 && itemIndex == parent.firstIndex) {
+                                               left = new int[]{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 - 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 + curveWidth - curveIndent;
+                                       shape[index++] = y - 1;
+                                       shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+                                       shape[index++] = y - 1;
+                               } else {
+                                       int[] left = parent.simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
+                                       int[] right = parent.simple ? SIMPLE_TOP_RIGHT_CORNER : curve;
+                                       if (borderLeft == 0 && itemIndex == parent.firstIndex) {
+                                               left = new int[]{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 - curveIndent + right[2*i];
+                                               shape[index++] = y + right[2*i+1];
+                                       }
+                                       shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+                                       shape[index++] = y + height + 1;
+                                       shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + curveWidth - curveIndent;
+                                       shape[index++] = y + height + 1;
+                               }
+
+                               Rectangle clipping = gc.getClipping();
+                               Rectangle clipBounds = item.getBounds();
+                               clipBounds.height += 1;
+                               if (parent.onBottom) clipBounds.y -= 1;
+                               boolean tabInPaint = clipping.intersects(clipBounds);
+
+                               if (tabInPaint) {
+                                       // fill in tab background
+                                       if (parent.selectionGradientColors != null && !parent.selectionGradientVertical) {
+                                               drawBackground(gc, shape, true);
+                                       } else {
+                                               Color defaultBackground = parent.shouldHighlight() ? parent.selectionBackground : parent.getBackground();
+                                               Image image = parent.selectionBgImage;
+                                               Color[] colors = parent.selectionGradientColors;
+                                               int[] percents = parent.selectionGradientPercents;
+                                               boolean vertical = parent.selectionGradientVertical;
+                                               xx = x;
+                                               yy = parent.onBottom ? y -1 : y + 1;
+                                               ww = width;
+                                               hh = height;
+                                               if (!parent.single && !parent.simple) ww += curveWidth - curveIndent;
+                                               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, bounds, state, rightEdge);
+
+                               // draw outline
+                               shape[0] = Math.max(0, borderLeft - 1);
+                               if (borderLeft == 0 && itemIndex == parent.firstIndex) {
+                                       shape[1] = parent.onBottom ? y + height - 1 : y;
+                                       shape[5] = shape[3] = shape[1];
+                               }
+                               shape[shape.length - 2] = size.x - borderRight + 1;
+                               for (int i = 0; i < shape.length/2; i++) {
+                                       if (shape[2*i + 1] == y + height + 1) shape[2*i + 1] -= 1;
+                               }
+                               Color borderColor = parent.getDisplay().getSystemColor(BORDER1_COLOR);
+                               if (! borderColor.equals(lastBorderColor)) createAntialiasColors();
+                               antialias(shape, selectedInnerColor, selectedOuterColor, gc);
+                               gc.setForeground(borderColor);
+                               gc.drawPolyline(shape);
+
+                               if (!tabInPaint) return;
+                       }
+               }
+
+               if ((state & SWT.FOREGROUND) != 0) {
+                       // draw Image
+                       Rectangle trim = computeTrim(itemIndex, SWT.NONE, 0, 0, 0, 0);
+                       int xDraw = x - trim.x;
+                       if (parent.single && (parent.showClose || item.showClose)) xDraw += item.closeRect.width;
+                       Image image = item.getImage();
+                       if (image != null && !image.isDisposed()) {
+                               Rectangle imageBounds = image.getBounds();
+                               // only draw image if it won't overlap with close button
+                               int maxImageWidth = rightEdge - xDraw - (trim.width + trim.x);
+                               if (!parent.single && item.closeRect.width > 0) maxImageWidth -= item.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 - (trim.width + trim.x);
+                       if (!parent.single && item.closeRect.width > 0) textWidth -= item.closeRect.width + INTERNAL_SPACING;
+                       if (textWidth > 0) {
+                               Font gcFont = gc.getFont();
+                               gc.setFont(item.font == null ? parent.getFont() : item.font);
+
+                               if (item.shortenedText == null || item.shortenedTextWidth != textWidth) {
+                                       item.shortenedText = shortenText(gc, item.getText(), textWidth);
+                                       item.shortenedTextWidth = textWidth;
+                               }
+                               Point extent = gc.textExtent(item.shortenedText, FLAGS);
+                               int textY = y + (height - extent.y) / 2;
+                               textY += parent.onBottom ? -1 : 1;
+
+                               gc.setForeground(parent.selectionForeground);
+                               gc.drawText(item.shortenedText, xDraw, textY, FLAGS);
+                               gc.setFont(gcFont);
+
+                               // draw a Focus rectangle
+                               if (parent.isFocusControl()) {
+                                       Display display = parent.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(BUTTON_BORDER));
+                                               gc.drawLine(xDraw, textY+extent.y+1, xDraw+extent.x+1, textY+extent.y+1);
+                                       }
+                               }
+                       }
+                       if (parent.showClose || item.showClose) drawClose(gc, item.closeRect, item.closeImageState);
+               }
+       }
+
+       void drawTabArea(GC gc, Rectangle bounds, int state) {
+               Point size = parent.getSize();
+               int[] shape = null;
+               Color borderColor = parent.getDisplay().getSystemColor(BORDER1_COLOR);
+               int tabHeight = parent.tabHeight;
+               int style = parent.getStyle();
+
+               int borderLeft = parent.borderVisible ? 1 : 0;
+               int borderRight = borderLeft;
+               int borderTop = parent.onBottom ? borderLeft : 0;
+               int borderBottom = parent.onBottom ? 0 : borderLeft;
+
+               int selectedIndex = parent.selectedIndex;
+               int highlight_header = (style & SWT.FLAT) != 0 ? 1 : 3;
+               if (tabHeight == 0) {
+                       if ((style & SWT.FLAT) != 0 && (style & SWT.BORDER) == 0) return;
+                       int x1 = borderLeft - 1;
+                       int x2 = size.x - borderRight;
+                       int y1 = parent.onBottom ? size.y - borderBottom - highlight_header - 1 : borderTop + highlight_header;
+                       int y2 = parent.onBottom ? size.y - borderBottom : borderTop;
+                       if (borderLeft > 0 && parent.onBottom) y2 -= 1;
+
+                       shape = new int[] {x1, y1, x1,y2, x2,y2, x2,y1};
+
+                       // If horizontal gradient, show gradient across the whole area
+                       if (selectedIndex != -1 && parent.selectionGradientColors != null && parent.selectionGradientColors.length > 1 && !parent.selectionGradientVertical) {
+                               drawBackground(gc, shape, true);
+                       } else if (selectedIndex == -1 && parent.gradientColors != null && parent.gradientColors.length > 1 && !parent.gradientVertical) {
+                               drawBackground(gc, shape, false);
+                       } else {
+                               gc.setBackground(selectedIndex == -1 ? parent.getBackground() : parent.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 = parent.onBottom ? size.y - borderBottom - tabHeight : borderTop;
+               int width = size.x - borderLeft - borderRight + 1;
+               int height = tabHeight - 1;
+               boolean simple = parent.simple;
+               // Draw Tab Header
+               if (parent.onBottom) {
+                       int[] left, right;
+                       if ((style & SWT.BORDER) != 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 == 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 == 0) shape[index-1] += 1;
+                       }
+                       shape[index++] = x+width;
+                       shape[index++] = y-highlight_header;
+               } else {
+                       int[] left, right;
+                       if ((style & SWT.BORDER) != 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
+               boolean single = parent.single;
+               boolean bkSelected = single && selectedIndex != -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(parent.getParent().getBackground());
+               fillRegion(gc, r);
+               r.dispose();
+
+               // Draw selected tab
+               if (selectedIndex == -1) {
+                       // if no selected tab - draw line across bottom of all tabs
+                       int x1 = borderLeft;
+                       int y1 = (parent.onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight;
+                       int x2 = size.x - borderRight;
+                       gc.setForeground(borderColor);
+                       gc.drawLine(x1, y1, x2, y1);
+               }
+
+               // Draw border line
+               if (borderLeft > 0) {
+                       if (! borderColor.equals(lastBorderColor)) createAntialiasColors();
+                       antialias(shape, null, tabAreaColor, gc);
+                       gc.setForeground(borderColor);
+                       gc.drawPolyline(shape);
+               }
+       }
+
+       void drawUnselected(int index, GC gc, Rectangle bounds, int state) {
+               CTabItem item = parent.items[index];
+               int x = bounds.x;
+               int y = bounds.y;
+               int height = bounds.height;
+               int width = bounds.width;
+
+               // Do not draw partial items
+               if (!item.showing) return;
+
+               Rectangle clipping = gc.getClipping();
+               if (!clipping.intersects(bounds)) return;
+
+               if ((state & SWT.BACKGROUND) != 0) {
+                       if (index > 0 && index < parent.selectedIndex)
+                               drawLeftUnselectedBorder(gc, bounds, state);
+                       // If it is the last one then draw a line
+                       if (index > parent.selectedIndex)
+                               drawRightUnselectedBorder(gc, bounds, state);
+               }
+
+               if ((state & SWT.FOREGROUND) != 0) {
+                       // draw Image
+                       Rectangle trim = computeTrim(index, SWT.NONE, 0, 0, 0, 0);
+                       int xDraw = x - trim.x;
+                       Image image = item.getImage();
+                       if (image != null && !image.isDisposed() && parent.showUnselectedImage) {
+                               Rectangle imageBounds = image.getBounds();
+                               // only draw image if it won't overlap with close button
+                               int maxImageWidth = x + width - xDraw - (trim.width + trim.x);
+                               if (parent.showUnselectedClose && (parent.showClose || item.showClose)) {
+                                       maxImageWidth -= item.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 - (trim.width + trim.x);
+                       if (parent.showUnselectedClose && (parent.showClose || item.showClose)) {
+                               textWidth -= item.closeRect.width + INTERNAL_SPACING;
+                       }
+                       if (textWidth > 0) {
+                               Font gcFont = gc.getFont();
+                               gc.setFont(item.font == null ? parent.getFont() : item.font);
+                               if (item.shortenedText == null || item.shortenedTextWidth != textWidth) {
+                                       item.shortenedText = shortenText(gc, item.getText(), textWidth);
+                                       item.shortenedTextWidth = textWidth;
+                               }
+                               Point extent = gc.textExtent(item.shortenedText, FLAGS);
+                               int textY = y + (height - extent.y) / 2;
+                               textY += parent.onBottom ? -1 : 1;
+                               gc.setForeground(parent.getForeground());
+                               gc.drawText(item.shortenedText, xDraw, textY, FLAGS);
+                               gc.setFont(gcFont);
+                       }
+                       // draw close
+                       if (parent.showUnselectedClose && (parent.showClose || item.showClose)) drawClose(gc, item.closeRect, item.closeImageState);
+               }
+       }
+
+       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();
+       }
+
+       Color getFillColor() {
+               if (fillColor == null) {
+                       fillColor = new Color(parent.getDisplay(), CLOSE_FILL);
+               }
+               return fillColor;
+       }
+
+       private Font getChevronFont(Display display) {
+               if (chevronFont == null) {
+                       Point dpi = display.getDPI();
+                       int fontHeight = 72 * CHEVRON_FONT_HEIGHT / dpi.y;
+                       FontData fd = parent.getFont().getFontData()[0];
+                       fd.setHeight(fontHeight);
+                       chevronFont = new Font(display, fd);
+               }
+               return chevronFont;
+       }
+
+       /*
+        * Return true if given start color, the cache of highlight colors we have
+        * would match the highlight colors we'd compute.
+        */
+       boolean isSelectionHighlightColorsCacheHit(Color start) {
+
+               if(selectionHighlightGradientColorsCache == 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.equals(start))
+                       return false;
+
+               //Compare number of colours we have vs. we'd compute
+               if(selectionHighlightGradientColorsCache.length != parent.tabHeight)
+                       return false;
+
+               //Compare existing highlight end to what it would be (selectionBackground)
+               if(! highlightEnd.equals(parent.selectionBackground))
+                       return false;
+
+               return true;
+       }
+
+       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 == null)
+                       return;
+
+               //don't bother on low colour
+               if (parent.getDisplay().getDepth() < 15)
+                       return;
+
+               //don't bother if we don't have a background gradient
+               if(parent.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
+       }
+
+       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(parent.getDisplay());
+               layout.setText(text);
+               int end = layout.getPreviousOffset(length, SWT.MOVEMENT_CLUSTER);
+               while (end > 0) {
+                       text = text.substring(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 == 0 ? text.substring(0, 1) : text + ellipses;
+       }
+
+       void updateCurves () {
+               //Temp fix for Bug 384743
+               if (this.getClass().getName().equals("org.eclipse.e4.ui.workbench.renderers.swt.CTabRendering")) return;
+               int tabHeight = parent.tabHeight;
+               if (tabHeight == lastTabHeight) return;
+               if (parent.onBottom) {
+                       int d = tabHeight - 12;
+                       curve = new int[]{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 = new int[]{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 = new int[] {
+                                       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 = new int[] {
+                                       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 };
+               }
+       }
+
+       /*
+        * Return whether to use ellipses or just truncate labels
+        */
+       boolean useEllipses() {
+               return parent.simple;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CTabItem.java
new file mode 100644 (file)
index 0000000..eee6a7a
--- /dev/null
@@ -0,0 +1,450 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class CTabItem extends 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 = new Rectangle(0, 0, 0, 0);
+       int closeImageState = SWT.BACKGROUND;
+       int state = SWT.NONE;
+       boolean showClose = false;
+       boolean showing = false;
+
+/**
+ * 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 CTabItem (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 CTabItem (CTabFolder parent, int style, int index) {
+       super (parent, style);
+       showClose = (style & SWT.CLOSE) != 0;
+       parent.createItem (this, index);
+}
+
+
+@Override
+public 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;
+}
+
+/**
+ * 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 () {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       parent.runUpdate();
+       return new Rectangle(x, y, width, 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
+ */
+@Deprecated
+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 != 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 () {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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 boolean 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 == null && shortenedText != null) {
+               String text = getText();
+               if (!shortenedText.equals(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 boolean isShowing () {
+       checkWidget();
+       return showing;
+}
+
+/**
+ * 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 != null) {
+               if (control.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+               if (control.getParent() != parent) SWT.error (SWT.ERROR_INVALID_PARENT);
+       }
+       if (this.control != null && !this.control.isDisposed()) {
+               this.control.setVisible(false);
+       }
+       this.control = control;
+       if (this.control != null) {
+               int index = parent.indexOf (this);
+               if (index == parent.getSelectionIndex ()){
+                       this.control.setBounds(parent.getClientArea ());
+                       this.control.setVisible(true);
+               } else {
+                       int selectedIndex = parent.getSelectionIndex();
+                       Control selectedControl = null;
+                       if (selectedIndex != -1) {
+                               selectedControl = parent.getItem(selectedIndex).control;
+                       }
+                       if (this.control != selectedControl) {
+                               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
+ */
+@Deprecated
+public void setDisabledImage (Image image) {
+       checkWidget();
+       if (image != null && image.isDisposed ()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       this.disabledImage = image;
+}
+boolean setFocus () {
+       return control != null && !control.isDisposed() && control.setFocus ();
+}
+/**
+ * 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 != null && font.isDisposed ()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (font == null && this.font == null) return;
+       if (font != null && font.equals(this.font)) return;
+       this.font = font;
+       parent.updateFolder(CTabFolder.UPDATE_TAB_HEIGHT | CTabFolder.REDRAW_TABS);
+}
+@Override
+public void setImage (Image image) {
+       checkWidget();
+       if (image != null && image.isDisposed ()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       Image oldImage = getImage();
+       if (image == null && oldImage == null) return;
+       if (image != null && image.equals(oldImage)) return;
+       super.setImage(image);
+       parent.updateFolder(CTabFolder.UPDATE_TAB_HEIGHT | CTabFolder.REDRAW_TABS);
+}
+/**
+ * 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(boolean close) {
+       checkWidget();
+       if (showClose == close) return;
+       showClose = close;
+       parent.updateFolder(CTabFolder.REDRAW_TABS);
+}
+/**
+ * Sets the text to display on the tab.
+ * A carriage return '\n' allows to display multi line text.
+ *
+ * @param string the tab name
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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();
+       if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (string.equals(getText())) return;
+       super.setText(string);
+       shortenedText = null;
+       shortenedTextWidth = 0;
+       parent.updateFolder(CTabFolder.UPDATE_TAB_HEIGHT | CTabFolder.REDRAW_TABS);
+}
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ *
+ * @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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CaretEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CaretEvent.java
new file mode 100644 (file)
index 0000000..41bb86a
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.events.*;
+
+/**
+ * This event is sent when the caret offset changes.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.5
+ */
+public class CaretEvent extends TypedEvent {
+
+       /**
+        * caret offset
+        */
+       public int caretOffset;
+
+       static final long serialVersionUID = 3257846571587545489L;
+
+CaretEvent(StyledTextEvent e) {
+       super(e);
+       caretOffset = e.end;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CaretListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/CaretListener.java
new file mode 100644 (file)
index 0000000..a26605f
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * CaretEvents.
+ *
+ * @see CaretEvent
+ *
+ * @since 3.5
+ */
+@FunctionalInterface
+public interface CaretListener extends SWTEventListener {
+
+/**
+ * This method is called after the caret offset is changed.
+ *
+ * The following event fields are used:<ul>
+ * <li>event.caretOffset the new caret offset (input)</li>
+ * </ul>
+ *
+ * @param event the given event
+ *
+ * @see CaretEvent
+ */
+public void caretMoved(CaretEvent event);
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ControlEditor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ControlEditor.java
new file mode 100644 (file)
index 0000000..7ac70ed
--- /dev/null
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+*
+* 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:</p>
+*
+* <pre><code>
+* 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 != null) {
+*                      if (color != 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);
+* </code></pre>
+*
+* @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 boolean 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 boolean 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 boolean 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 ControlEditor (Composite parent) {
+       this.parent = parent;
+
+       controlListener = e -> layout ();
+       for (int i=0; i<EVENTS.length; i++) {
+               parent.addListener (EVENTS [i], controlListener);
+       }
+
+       scrollbarListener = e -> scroll (e);
+       ScrollBar hBar = parent.getHorizontalBar ();
+       if (hBar != null) hBar.addListener (SWT.Selection, scrollbarListener);
+       ScrollBar vBar = parent.getVerticalBar ();
+       if (vBar != 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 != null && !parent.isDisposed()) {
+               for (int i=0; i<EVENTS.length; i++) {
+                       parent.removeListener (EVENTS [i], controlListener);
+               }
+               ScrollBar hBar = parent.getHorizontalBar ();
+               if (hBar != null) hBar.removeListener (SWT.Selection, scrollbarListener);
+               ScrollBar vBar = parent.getVerticalBar ();
+               if (vBar != 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 == 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 == null || editor.isDisposed()) return;
+               editor.setFocus ();
+       }
+}
+void scroll (Event e) {
+       if (editor == 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 == 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 == null || this.editor.isDisposed()) return;
+       editor.setVisible(true);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/DefaultContent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/DefaultContent.java
new file mode 100644 (file)
index 0000000..bd3d013
--- /dev/null
@@ -0,0 +1,897 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.widgets.*;
+
+class DefaultContent implements StyledTextContent {
+       private final static String LineDelimiter = System.getProperty("line.separator");
+
+       List<StyledTextListener> textListeners = new ArrayList<>(); // stores text listeners for event sending
+       char[] textStore = new char[0]; // 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 = new int[50][2]; // 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</code> will always have
+ * at least one empty line.
+ */
+DefaultContent() {
+       super();
+       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 == 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 = new int[] {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 == size) {
+               newLines = new int[size+Compatibility.pow2(replaceExpandExp)][2];
+               replaceExpandExp++;
+               System.arraycopy(linesArray, 0, newLines, 0, size);
+       }
+       int[] range = new int[] {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>
+ */
+@Override
+public void addTextChangeListener(TextChangeListener listener) {
+       if (listener == null) error(SWT.ERROR_NULL_ARGUMENT);
+       StyledTextListener typedListener = new StyledTextListener(listener);
+       textListeners.add(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 == gapStart) {
+               // text is being inserted at the gap position
+               int size = (gapEnd - gapStart) - sizeHint;
+               if (lowWatermark <= size && size <= highWatermark)
+                       return;
+       } else if ((position + sizeHint == 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 == SWT.CR) {
+                       // see if the next character is a LF
+                       if (i + 1 < textLength) {
+                               ch = textStore[i+1];
+                               if (ch == SWT.LF) {
+                                       i++;
+                               }
+                       }
+                       addLineIndex(start, i - start + 1);
+                       start = i + 1;
+               } else if (ch == 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
+ */
+boolean isDelimiter(char ch) {
+       if (ch == SWT.CR) return true;
+       if (ch == 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 boolean specifying whether or not the replace operation is valid
+ */
+protected boolean isValidReplace(int start, int replaceLength, String newText){
+       if (replaceLength == 0) {
+               // inserting text, see if the \r\n line delimiter is being split
+               if (start == 0) return true;
+               if (start == getCharCount()) return true;
+               char before = getTextRange(start - 1, 1).charAt(0);
+               if (before == '\r') {
+                       char after = getTextRange(start, 1).charAt(0);
+                       if (after == '\n') return false;
+               }
+       } else {
+               // deleting text, see if part of a \r\n line delimiter is being deleted
+               char startChar = getTextRange(start, 1).charAt(0);
+               if (startChar == '\n') {
+                       // see if char before delete position is \r
+                       if (start != 0) {
+                               char before = getTextRange(start - 1, 1).charAt(0);
+                               if (before == '\r') return false;
+                       }
+               }
+               char endChar = getTextRange(start + replaceLength - 1, 1).charAt(0);
+               if (endChar == '\r') {
+                       // see if char after delete position is \n
+                       if (start + replaceLength != getCharCount()) {
+                               char after = getTextRange(start + replaceLength, 1).charAt(0);
+                               if (after == '\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 == SWT.CR) {
+                               // see if the next character is a LF
+                               if (location+1 < textStore.length) {
+                                       ch = textStore[location+1];
+                                       if (ch == SWT.LF) {
+                                               i++;
+                                       }
+                               }
+                               indexedLines = addLineIndex(start, i - start + 1, indexedLines, lineCount);
+                               lineCount++;
+                               start = i + 1;
+                       } else if (ch == 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 = new int[] {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() == 0) return;
+
+       int startLine = getLineAtOffset(position);
+       int change = text.length();
+       boolean endInsert = position == 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.charAt(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] == 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 == 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 == 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 == SWT.CR) {
+                               // see if the next character is a LF
+                               if (i + 1 < textStore.length) {
+                                       ch = textStore[i+1];
+                                       if (ch == SWT.LF) {
+                                               i++;
+                                               count++;
+                                       }
+                               }
+                               lineCount++;
+                       } else if (ch == 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.charAt(i);
+               if (ch == SWT.CR) {
+                       if (i + 1 < length && text.charAt(i + 1) == SWT.LF) {
+                               i++;
+                       }
+                       lineCount++;
+               } else if (ch == SWT.LF) {
+                       lineCount++;
+               }
+       }
+       return lineCount;
+}
+/**
+ * @return the logical length of the text store
+ */
+@Override
+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>
+ */
+@Override
+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 new String(textStore, start, length);
+       } else {
+               // gap is in the specified range, strip out the gap
+               StringBuilder buf = new StringBuilder();
+               int gapLength = gapEnd - gapStart;
+               buf.append(textStore, start, gapStart - start);
+               buf.append(textStore, gapEnd, length - gapLength - (gapStart - start));
+               length = buf.length();
+               while ((length - 1 >=0) && isDelimiter(buf.charAt(length - 1))) {
+                       length--;
+               }
+               return buf.toString().substring(0, length);
+       }
+}
+/**
+ * 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.
+ */
+@Override
+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 new String(textStore, start, length);
+       } else {
+               // gap is in the specified range, strip out the gap
+               StringBuilder buffer = new StringBuilder();
+               int gapLength = gapEnd - gapStart;
+               buffer.append(textStore, start, gapStart - start);
+               buffer.append(textStore, gapEnd, length - gapLength - (gapStart - start));
+               return buffer.toString();
+       }
+}
+/**
+ * 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
+ */
+@Override
+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>
+ */
+@Override
+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 == 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>
+ */
+@Override
+public int getOffsetAtLine(int lineIndex) {
+       if (lineIndex == 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
+ */
+boolean gapExists() {
+       return gapStart != 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 new String(textStore, start, length);
+}
+/**
+ * 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
+ */
+@Override
+public String getTextRange(int start, int length) {
+       if (textStore == null)
+               return "";
+       if (length == 0)
+               return "";
+       int end= start + length;
+       if (!gapExists() || (end < gapStart))
+               return new String(textStore, start, length);
+       if (gapStart < start) {
+               int gapLength= gapEnd - gapStart;
+               return new String(textStore, start + gapLength , length);
+       }
+       StringBuilder buf = new StringBuilder();
+       buf.append(textStore, start, gapStart - start);
+       buf.append(textStore, gapEnd, end - gapStart);
+       return buf.toString();
+}
+/**
+ * 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>
+ */
+@Override
+public void removeTextChangeListener(TextChangeListener listener){
+       if (listener == null) error(SWT.ERROR_NULL_ARGUMENT);
+       for (int i = 0; i < textListeners.size(); i++) {
+               TypedListener typedListener = textListeners.get(i);
+               if (typedListener.getEventListener () == listener) {
+                       textListeners.remove(i);
+                       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:
+ * </p>
+ * <ul>
+ * <li>(replaceText,newText) ==&gt; (replaceLineCount,newLineCount)
+ * <li>("","\n") ==&gt; (0,1)
+ * <li>("\n\n","a") ==&gt; (2,0)
+ * </ul>
+ *
+ * @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>
+ */
+@Override
+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 = ST.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 = ST.TextChanged;
+       sendTextEvent(event);
+}
+/**
+ * Sends the text listeners the TextChanged event.
+ */
+void sendTextEvent(StyledTextEvent event) {
+       for (int i = 0; i < textListeners.size(); i++) {
+               textListeners.get(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
+ */
+@Override
+public void setText (String text){
+       textStore = text.toCharArray();
+       gapStart = -1;
+       gapEnd = -1;
+       expandExp = 1;
+       indexLines();
+       StyledTextEvent event = new StyledTextEvent(this);
+       event.type = ST.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 == 0) return;
+
+       int startLine = getLineAtOffset(position);
+       int startLineOffset = getOffsetAtLine(startLine);
+       int endLine = getLineAtOffset(position + length);
+
+       String endText = "";
+       boolean splittingDelimiter = false;
+       if (position + length < getCharCount()) {
+               endText = getTextRange(position + length - 1, 2);
+               if ((endText.charAt(0) == SWT.CR) && (endText.charAt(1) == 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 == 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;
+       boolean 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 == SWT.CR && (textStore[j+1] == 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);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ExtendedModifyEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ExtendedModifyEvent.java
new file mode 100644 (file)
index 0000000..1b7c1ab
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+
+/**
+ * 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 extends 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 ExtendedModifyEvent(StyledTextEvent e) {
+       super(e);
+       start = e.start;
+       length = e.end - e.start;
+       replacedText = e.text;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ExtendedModifyListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ExtendedModifyListener.java
new file mode 100644 (file)
index 0000000..3652482
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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>
+ */
+@FunctionalInterface
+public interface ExtendedModifyListener extends 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);
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineBackgroundEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineBackgroundEvent.java
new file mode 100644 (file)
index 0000000..b87e237
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 extends 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 LineBackgroundEvent(StyledTextEvent e) {
+       super(e);
+       lineOffset = e.detail;
+       lineText = e.text;
+       lineBackground = e.lineBackground;
+}
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineBackgroundListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineBackgroundListener.java
new file mode 100644 (file)
index 0000000..41f8bb2
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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>
+ */
+@FunctionalInterface
+public interface LineBackgroundListener extends 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineStyleEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineStyleEvent.java
new file mode 100644 (file)
index 0000000..65ffa3d
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+
+/**
+ * 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 extends 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 vertical indent (input, output)
+        *
+        * @since 3.109
+        */
+       int verticalIndent;
+
+       /**
+        * line wrap indent (input, output)
+        *
+        * @since 3.6
+        */
+       public int wrapIndent;
+
+       /**
+        * line justification (input, output)
+        *
+        * @since 3.2
+        */
+       public boolean justify;
+
+       /**
+        * line bullet (output)
+        * @since 3.2
+        */
+       public Bullet bullet;
+
+       /**
+        * line bullet index (output)
+        * @since 3.2
+        */
+       public int bulletIndex;
+
+       /**
+        * line tab stops (output)
+        * @since 3.6
+        */
+       public int[] tabStops;
+
+
+       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 LineStyleEvent(StyledTextEvent e) {
+       super(e);
+       styles = e.styles;
+       ranges = e.ranges;
+       lineOffset = e.detail;
+       lineText = e.text;
+       alignment = e.alignment;
+       justify = e.justify;
+       indent = e.indent;
+       verticalIndent = e.verticalIndent;
+       wrapIndent = e.wrapIndent;
+       bullet = e.bullet;
+       bulletIndex = e.bulletIndex;
+       tabStops = e.tabStops;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineStyleListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/LineStyleListener.java
new file mode 100644 (file)
index 0000000..8e27979
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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>
+ */
+@FunctionalInterface
+public interface LineStyleListener extends 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MouseNavigator.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MouseNavigator.java
new file mode 100644 (file)
index 0000000..764ae80
--- /dev/null
@@ -0,0 +1,296 @@
+/**
+ * Copyright (c) 2019 Laurent CARON.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation (bug 542777)
+ */
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class add the following behaviour to <code>StyledText</code> widgets:
+ * <p>
+ * When the user clicks on the wheel, a circle with arrows appears. When the user moves the mouse,
+ * the StyledText content is scrolled (on the right or on the left for horizontal movements, up or down for vertical movements).
+ * </p>
+ *
+ * @since 3.110
+ */
+class MouseNavigator {
+       private final StyledText parent;
+       boolean navigationActivated = false;
+       private GC gc;
+       private static final int CIRCLE_RADIUS = 15;
+       private static final int CENTRAL_POINT_RADIUS = 2;
+       private Point originalMouseLocation;
+       private final Listener mouseDownListener, mouseUpListener, paintListener, mouseMoveListener, focusOutListener;
+       private boolean hasHBar, hasVBar;
+       private Cursor previousCursor;
+
+       MouseNavigator(final StyledText styledText) {
+               if (styledText == null) {
+                       SWT.error(SWT.ERROR_NULL_ARGUMENT);
+               }
+               if (styledText.isDisposed()) {
+                       SWT.error(SWT.ERROR_WIDGET_DISPOSED);
+               }
+               parent = styledText;
+
+               mouseDownListener = (event) -> {
+                       onMouseDown(event);
+               };
+               parent.addListener(SWT.MouseDown, mouseDownListener);
+
+               mouseUpListener = (event) -> {
+                       onMouseUp(event);
+               };
+               parent.addListener(SWT.MouseUp, mouseUpListener);
+
+               paintListener = (event) -> {
+                       onPaint(event);
+               };
+               parent.addListener(SWT.Paint, paintListener);
+
+               mouseMoveListener = (event) -> {
+                       onMouseMove(event);
+               };
+               parent.addListener(SWT.MouseMove, mouseMoveListener);
+
+               focusOutListener = (event) -> {
+                       onFocusOut(event);
+               };
+               parent.addListener(SWT.FocusOut, focusOutListener);
+       }
+
+       void onMouseDown(Event e) {
+               if ((e.button != 2) || navigationActivated) {
+                       return;
+               }
+
+               if (!parent.isVisible() || !parent.getEnabled() || parent.middleClickPressed) {
+                       return;
+               }
+
+               // Widget has no bar or bars are not enabled
+               initBarState();
+
+               if (!hasHBar && !hasVBar) {
+                       return;
+               }
+
+               navigationActivated = true;
+               previousCursor = parent.getCursor();
+               parent.setCursor(parent.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+               originalMouseLocation = getMouseLocation();
+               parent.redraw();
+       }
+
+       private void initBarState() {
+               hasHBar = computeHasHorizontalBar();
+               hasVBar = computeHasVerticalBar();
+       }
+
+       private boolean computeHasHorizontalBar() {
+               final ScrollBar horizontalBar = parent.getHorizontalBar();
+               final boolean hasHorizontalBar = horizontalBar != null && horizontalBar.isVisible();
+               final boolean exceedHorizontalSpace = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT).x > parent.getSize().x;
+               return hasHorizontalBar && exceedHorizontalSpace;
+       }
+
+       private boolean computeHasVerticalBar() {
+               final ScrollBar verticalBar = parent.getVerticalBar();
+               final boolean hasVerticalBar = verticalBar != null && verticalBar.isEnabled();
+               final boolean exceedVerticalSpace = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT).y > parent.getSize().y;
+               return hasVerticalBar && exceedVerticalSpace;
+       }
+
+       private void onMouseUp(Event e) {
+               if ((computeDist() < CIRCLE_RADIUS) && (computeDist() >= 0)) {
+                       return;
+               }
+               deactivate();
+       }
+
+       public int computeDist() {
+               if (originalMouseLocation == null) {
+                       return -1;
+               }
+               final Point mouseLocation = getMouseLocation();
+               final int deltaX = originalMouseLocation.x - mouseLocation.x;
+               final int deltaY = originalMouseLocation.y - mouseLocation.y;
+               final int dist = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+               return dist;
+       }
+
+       private void deactivate() {
+               parent.setCursor(previousCursor);
+               navigationActivated = false;
+               originalMouseLocation = null;
+               parent.redraw();
+       }
+
+       private void onFocusOut(Event e) {
+               deactivate();
+       }
+
+       private void onMouseMove(Event e) {
+               if (!navigationActivated) {
+                       return;
+               }
+
+               final Point mouseLocation = getMouseLocation();
+               final int deltaX = originalMouseLocation.x - mouseLocation.x;
+               final int deltaY = originalMouseLocation.y - mouseLocation.y;
+               final int dist = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+               if (dist < CIRCLE_RADIUS) {
+                       return;
+               }
+
+               parent.setRedraw(false);
+               if (hasHBar) {
+                       final ScrollBar bar = parent.getHorizontalBar();
+                       bar.setSelection((int) (bar.getSelection() - deltaX * .1));
+                       fireSelectionEvent(e, bar);
+               }
+
+               if (hasVBar) {
+                       final ScrollBar bar = parent.getVerticalBar();
+                       bar.setSelection((int) (bar.getSelection() - deltaY * .1));
+                       fireSelectionEvent(e, bar);
+               }
+               parent.setRedraw(true);
+               parent.redraw();
+       }
+
+       private void fireSelectionEvent(final Event e, final ScrollBar bar) {
+               final Event event = new Event();
+               event.widget = bar;
+               event.display = parent.getDisplay();
+               event.type = SWT.Selection;
+               event.time = e.time;
+
+               for (final Listener selectionListener : bar.getListeners(SWT.Selection)) {
+                       selectionListener.handleEvent(event);
+               }
+       }
+
+       private Point getMouseLocation() {
+               final Point cursorLocation = Display.getCurrent().getCursorLocation();
+               final Point relativeCursorLocation = parent.toControl(cursorLocation);
+               return relativeCursorLocation;
+       }
+
+       private void onPaint(final Event e) {
+               if (!navigationActivated) {
+                       return;
+               }
+
+               final Rectangle rect = parent.getClientArea();
+               if (rect.width == 0 || rect.height == 0) {
+                       return;
+               }
+               gc = e.gc;
+               gc.setAntialias(SWT.ON);
+               gc.setAdvanced(true);
+
+               final Color oldForegroundColor = gc.getForeground();
+               final Color oldBackgroundColor = gc.getBackground();
+               gc.setBackground(parent.getForeground());
+
+               drawCircle();
+               drawCentralPoint();
+
+               drawArrows();
+
+               gc.setForeground(oldForegroundColor);
+               gc.setBackground(oldBackgroundColor);
+       }
+
+       private void drawCircle() {
+               gc.setBackground(parent.getBackground());
+               gc.setForeground(parent.getForeground());
+               gc.setAlpha(200);
+               gc.fillOval(originalMouseLocation.x - CIRCLE_RADIUS, originalMouseLocation.y - CIRCLE_RADIUS, CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2);
+               gc.setBackground(parent.getForeground());
+               gc.setAlpha(255);
+               gc.drawOval(originalMouseLocation.x - CIRCLE_RADIUS, originalMouseLocation.y - CIRCLE_RADIUS, CIRCLE_RADIUS * 2, CIRCLE_RADIUS * 2);
+       }
+
+       private void drawCentralPoint() {
+               gc.fillOval(originalMouseLocation.x - CENTRAL_POINT_RADIUS, originalMouseLocation.y - CENTRAL_POINT_RADIUS, CENTRAL_POINT_RADIUS * 2, CENTRAL_POINT_RADIUS * 2);
+       }
+
+       private void drawArrows() {
+               gc.setLineWidth(2);
+               if (hasHBar) {
+                       drawHorizontalArrows();
+               }
+               if (hasVBar) {
+                       drawVerticalArrows();
+               }
+       }
+
+       private void drawHorizontalArrows() {
+               final int[] points = new int[6];
+               // Left
+               points[0] = originalMouseLocation.x - 6;
+               points[1] = originalMouseLocation.y + 3;
+               points[2] = originalMouseLocation.x - 9;
+               points[3] = originalMouseLocation.y;
+               points[4] = originalMouseLocation.x - 6;
+               points[5] = originalMouseLocation.y - 3;
+               gc.drawPolyline(points);
+
+               // Right
+               points[0] = originalMouseLocation.x + 7;
+               points[1] = originalMouseLocation.y + 3;
+               points[2] = originalMouseLocation.x + 10;
+               points[3] = originalMouseLocation.y;
+               points[4] = originalMouseLocation.x + 7;
+               points[5] = originalMouseLocation.y - 3;
+               gc.drawPolyline(points);
+       }
+
+       private void drawVerticalArrows() {
+               final int[] points = new int[6];
+               // Upper
+               points[0] = originalMouseLocation.x - 3;
+               points[1] = originalMouseLocation.y - 6;
+               points[2] = originalMouseLocation.x;
+               points[3] = originalMouseLocation.y - 10;
+               points[4] = originalMouseLocation.x + 3;
+               points[5] = originalMouseLocation.y - 6;
+               gc.drawPolyline(points);
+
+               // Lower
+               points[0] = originalMouseLocation.x - 3;
+               points[1] = originalMouseLocation.y + 7;
+               points[2] = originalMouseLocation.x;
+               points[3] = originalMouseLocation.y + 11;
+               points[4] = originalMouseLocation.x + 3;
+               points[5] = originalMouseLocation.y + 7;
+               gc.drawPolyline(points);
+
+       }
+
+       void dispose() {
+               if (parent.isDisposed()) {
+                       return;
+               }
+               parent.removeListener(SWT.MouseDown, mouseDownListener);
+               parent.removeListener(SWT.MouseUp, mouseUpListener);
+               parent.removeListener(SWT.Paint, paintListener);
+               parent.removeListener(SWT.MouseMove, mouseMoveListener);
+               parent.removeListener(SWT.MouseExit, focusOutListener);
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MovementEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MovementEvent.java
new file mode 100644 (file)
index 0000000..ccc0daf
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+
+/**
+ * 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 extends 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 MovementEvent(StyledTextEvent e) {
+       super(e);
+       lineOffset = e.detail;
+       lineText = e.text;
+       movement = e.count;
+       offset = e.start;
+       newOffset = e.end;
+}
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MovementListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/MovementListener.java
new file mode 100644 (file)
index 0000000..6fcb0f7
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * 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 extends 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);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PaintObjectEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PaintObjectEvent.java
new file mode 100644 (file)
index 0000000..889d252
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 extends 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 PaintObjectEvent(StyledTextEvent e) {
+       super(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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PaintObjectListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PaintObjectListener.java
new file mode 100644 (file)
index 0000000..f4384ad
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.internal.*;
+/**
+ * This listener is invoked when an object needs to be drawn.
+ *
+ * @since 3.2
+ */
+@FunctionalInterface
+public interface PaintObjectListener extends 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PopupList.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/PopupList.java
new file mode 100644 (file)
index 0000000..65d0895
--- /dev/null
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+* 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 PopupList(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 PopupList(Shell parent, int style) {
+       int listStyle = SWT.SINGLE | SWT.V_SCROLL;
+       if ((style & SWT.H_SCROLL) != 0) listStyle |= SWT.H_SCROLL;
+
+       shell = new Shell(parent, checkStyle(style));
+
+       list = new List(shell, listStyle);
+
+       // close dialog if user selects outside of the shell
+       shell.addListener(SWT.Deactivate, e -> shell.setVisible (false));
+
+       // resize shell when list resizes
+       shell.addControlListener(ControlListener.controlResizedAdapter(e -> {
+               Rectangle shellSize = shell.getClientArea();
+               list.setSize(shellSize.width, shellSize.height);
+       }));
+
+       // return list selection on Mouse Up or Carriage Return
+       list.addMouseListener(new MouseListener() {
+               @Override
+               public void mouseDoubleClick(MouseEvent e){}
+               @Override
+               public void mouseDown(MouseEvent e){}
+               @Override
+               public void mouseUp(MouseEvent e){
+                       shell.setVisible (false);
+               }
+       });
+       list.addKeyListener(new KeyListener() {
+               @Override
+               public void keyReleased(KeyEvent e){}
+               @Override
+               public void keyPressed(KeyEvent e){
+                       if (e.character == '\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 != 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 != null){
+               for (int i = 0; i < items.length; i++) {
+                       if (items[i].startsWith(string)){
+                               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_NULL_ARGUMENT - if the items array is null</li>
+*    <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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ST.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ST.java
new file mode 100644 (file)
index 0000000..8d0d214
--- /dev/null
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+/**
+ * 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 final int LINE_UP = 16777217;                     // binding = SWT.ARROW_UP
+       public static final int LINE_DOWN = 16777218;           // binding = SWT.ARROW_DOWN
+       public static final int LINE_START = 16777223;          // binding = SWT.HOME
+       public static final int LINE_END = 16777224;            // binding = SWT.END
+       public static final int COLUMN_PREVIOUS = 16777219;     // binding = SWT.ARROW_LEFT
+       public static final int COLUMN_NEXT = 16777220;                 // binding = SWT.ARROW_RIGHT
+       public static final int PAGE_UP = 16777221;                     // binding = SWT.PAGE_UP
+       public static final int PAGE_DOWN = 16777222;           // binding = SWT.PAGE_DOWN
+       public static final int WORD_PREVIOUS = 17039363;       // binding = SWT.MOD1 + SWT.ARROW_LEFT
+       public static final int WORD_NEXT = 17039364;           // binding = SWT.MOD1 + SWT.ARROW_RIGHT
+       public static final int TEXT_START = 17039367;          // binding = SWT.MOD1 + SWT.HOME
+       public static final int TEXT_END = 17039368;            // binding = SWT.MOD1 + SWT.END
+       public static final int WINDOW_START = 17039365;        // binding = SWT.MOD1 + SWT.PAGE_UP
+       public static final int WINDOW_END = 17039366;          // binding = SWT.MOD1 + SWT.PAGE_DOWN
+
+       /*
+        * Selection Key Actions
+        */
+       public static final int SELECT_ALL = 262209;                            // binding = SWT.MOD1 + 'A'
+       public static final int SELECT_LINE_UP = 16908289;                      // binding = SWT.MOD2 + SWT.ARROW_UP
+       public static final int SELECT_LINE_DOWN = 16908290;            // binding = SWT.MOD2 + SWT.ARROW_DOWN
+       public static final int SELECT_LINE_START = 16908295;           // binding = SWT.MOD2 + SWT.HOME
+       public static final int SELECT_LINE_END = 16908296;                     // binding = SWT.MOD2 + SWT.END
+       public static final int SELECT_COLUMN_PREVIOUS = 16908291;      // binding = SWT.MOD2 + SWT.ARROW_LEFT
+       public static final int SELECT_COLUMN_NEXT = 16908292;          // binding = SWT.MOD2 + SWT.ARROW_RIGHT
+       public static final int SELECT_PAGE_UP = 16908293;                      // binding = SWT.MOD2 + SWT.PAGE_UP
+       public static final int SELECT_PAGE_DOWN = 16908294;            // binding = SWT.MOD2 + SWT.PAGE_DOWN
+       public static final int SELECT_WORD_PREVIOUS = 17170435;                // binding = SWT.MOD1 + SWT.MOD2 + SWT.ARROW_LEFT
+       public static final int SELECT_WORD_NEXT = 17170436;            // binding = SWT.MOD1 + SWT.MOD2 + SWT.ARROW_RIGHT
+       public static final int SELECT_TEXT_START = 17170439;           // binding = SWT.MOD1 + SWT.MOD2 + SWT.HOME
+       public static final int SELECT_TEXT_END = 17170440;                     // binding = SWT.MOD1 + SWT.MOD2 + SWT.END
+       public static final int SELECT_WINDOW_START = 17170437;                 // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_UP
+       public static final int SELECT_WINDOW_END = 17170438;           // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_DOWN
+
+       /*
+        *  Modification Key Actions
+        */
+       public static final int CUT = 131199;                   // binding = SWT.MOD2 + SWT.DEL
+       public static final int COPY = 17039369;                // binding = SWT.MOD1 + SWT.INSERT;
+       public static final int PASTE = 16908297;               // binding = SWT.MOD2 + SWT.INSERT ;
+       public static final int DELETE_PREVIOUS = '\b';         // binding = SWT.BS;
+       public static final int DELETE_NEXT = 0x7F;             // binding = SWT.DEL;
+       public static final int DELETE_WORD_PREVIOUS = 262152;  // binding = SWT.BS | SWT.MOD1;
+       public static final int DELETE_WORD_NEXT = 262271;      // binding = SWT.DEL | SWT.MOD1;
+
+       /*
+        * Miscellaneous Key Actions
+        */
+       public static final int TOGGLE_OVERWRITE = 16777225; // binding = SWT.INSERT;
+
+       /**
+        * TEMPORARY CODE - API SUBJECT TO CHANGE
+        *
+        * Toggle block selection mode
+        *
+        * @since 3.5
+        */
+       public static final int TOGGLE_BLOCKSELECTION = 16777226;
+
+       /**
+        *  Bullet style dot.
+        *
+        *  @see Bullet
+        *
+        *  @since 3.2
+        */
+       public static final int BULLET_DOT = 1 << 0;
+
+       /**
+        *  Bullet style number.
+        *
+        *  @see Bullet
+        *
+        *  @since 3.2
+        */
+       public static final int BULLET_NUMBER = 1 << 1;
+
+       /**
+        *  Bullet style lower case letter.
+        *
+        *  @see Bullet
+        *
+        *  @since 3.2
+        */
+       public static final int BULLET_LETTER_LOWER = 1 << 2;
+
+       /**
+        *  Bullet style upper case letter.
+        *
+        *  @see Bullet
+        *
+        *  @since 3.2
+        */
+       public static final int BULLET_LETTER_UPPER = 1 << 3;
+
+       /**
+        *  Bullet style text.
+        *
+        *  @see Bullet
+        *
+        *  @since 3.2
+        */
+       public static final int BULLET_TEXT = 1 << 4;
+
+       /**
+        *  Bullet style custom draw.
+        *
+        *  @see StyledText#addPaintObjectListener(PaintObjectListener)
+        *  @see StyledText#removePaintObjectListener(PaintObjectListener)
+        *  @see Bullet
+        *
+        *  @since 3.2
+        */
+       public static final int BULLET_CUSTOM = 1 << 5;
+
+       /**
+        *  The ExtendedModify event type (value is 3000).
+        *
+        *  @since 3.8
+        */
+       public static final int ExtendedModify = 3000;
+
+       /**
+        *  The LineGetBackground event type (value is 3001).
+        *
+        *  @since 3.8
+        */
+       public static final int LineGetBackground = 3001;
+
+       /**
+        *  The LineGetStyle event type (value is 3002).
+        *
+        *  @since 3.8
+        */
+       public static final int LineGetStyle = 3002;
+
+       /**
+        *  The TextChanging event type (value is 3003).
+        *
+        *  @since 3.8
+        */
+       public static final int TextChanging = 3003;
+
+       /**
+        *  The TextSet event type (value is 3004).
+        *
+        *  @since 3.8
+        */
+       public static final int TextSet = 3004;
+
+       /**
+        *  The VerifyKey event type (value is 3005).
+        *
+        *  @since 3.8
+        */
+       public static final int VerifyKey = 3005;
+
+       /**
+        *  The TextChanged event type (value is 3006).
+        *
+        *  @since 3.8
+        */
+       public static final int TextChanged = 3006;
+
+       /**
+        *  The LineGetSegments event type (value is 3007).
+        *
+        *  @since 3.8
+        */
+       public static final int LineGetSegments = 3007;
+
+       /**
+        *  The PaintObject event type (value is 3008).
+        *
+        *  @since 3.8
+        */
+       public static final int PaintObject = 3008;
+
+       /**
+        *  The WordNext event type (value is 3009).
+        *
+        *  @since 3.8
+        */
+       public static final int WordNext = 3009;
+
+       /**
+        *  The WordPrevious event type (value is 3010).
+        *
+        *  @since 3.8
+        */
+       public static final int WordPrevious = 3010;
+
+       /**
+        *  The CaretMoved event type (value is 3011).
+        *
+        *  @since 3.8
+        */
+       public static final int CaretMoved = 3011;
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashForm.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashForm.java
new file mode 100644 (file)
index 0000000..90b067c
--- /dev/null
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL, SMOOTH</dd>
+ * </dl>
+ *
+ * @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 extends Composite {
+
+       /**
+       * The width of all sashes in the form.
+       */
+       public int SASH_WIDTH = 3;
+
+       int sashStyle;
+       Sash[] sashes = new Sash[0];
+       // 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 = new Control[0];
+       Control maxControl = null;
+       Listener sashListener;
+       static final 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 SashForm(Composite parent, int style) {
+       super(parent, checkStyle(style));
+       super.setLayout(new SashFormLayout());
+       sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
+       if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
+       if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
+       sashListener = e -> onDragSash(e);
+}
+static int checkStyle (int style) {
+       int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+       return style & mask;
+}
+Sash createSash() {
+       Sash sash = new Sash(this, sashStyle);
+       sash.setBackground(background);
+       sash.setForeground(foreground);
+       sash.setToolTipText(getToolTipText());
+       sash.addListener(SWT.Selection, sashListener);
+       return sash;
+}
+/**
+ * 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.
+ *
+ * <p>
+ * To retrieve the bidi orientation of the SashForm use <code>{@link #getStyle()}</code>
+ * and test if the SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT bits are set.
+ * </p>
+ *
+ * @return SWT.HORIZONTAL or SWT.VERTICAL
+ */
+@Override
+public int getOrientation() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return (sashStyle & SWT.VERTICAL) != 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;
+}
+@Override
+public int getStyle() {
+       int style = super.getStyle();
+       style |= getOrientation() == SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
+       if ((sashStyle & SWT.SMOOTH) != 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(){
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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 (data != null && data instanceof SashFormData) {
+                       ratios[i] = (int)(((SashFormData)data).weight * 1000 >> 16);
+               } else {
+                       ratios[i] = 200;
+               }
+       }
+       return ratios;
+}
+Control[] getControls(boolean onlyVisible) {
+       Control[] children = getChildren();
+       Control[] result = new Control[0];
+       for (int i = 0; i < children.length; i++) {
+               if (children[i] instanceof Sash) 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 = (Sash)event.widget;
+       int sashIndex = -1;
+       for (int i= 0; i < sashes.length; i++) {
+               if (sashes[i] == sash) {
+                       sashIndex = i;
+                       break;
+               }
+       }
+       if (sashIndex == -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();
+       boolean correction = false;
+       if (getOrientation() == 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 == null || !(data1 instanceof SashFormData)) {
+                       data1 = new SashFormData();
+                       c1.setLayoutData(data1);
+               }
+               Object data2 = c2.getLayoutData();
+               if (data2 == null || !(data2 instanceof SashFormData)) {
+                       data2 = new SashFormData();
+                       c2.setLayoutData(data2);
+               }
+               ((SashFormData)data1).weight = (((long)b1.width << 16) + area.width - 1) / area.width;
+               ((SashFormData)data2).weight = (((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 == null || !(data1 instanceof SashFormData)) {
+                       data1 = new SashFormData();
+                       c1.setLayoutData(data1);
+               }
+               Object data2 = c2.getLayoutData();
+               if (data2 == null || !(data2 instanceof SashFormData)) {
+                       data2 = new SashFormData();
+                       c2.setLayoutData(data2);
+               }
+               ((SashFormData)data1).weight = (((long)b1.height << 16) + area.height - 1) / area.height;
+               ((SashFormData)data2).weight = (((long)b2.height << 16) + area.height - 1) / area.height;
+       }
+       if (correction || (event.doit && event.detail != 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.
+ *
+ * <p>
+ * Since 3.7, this method can also be called with SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
+ * to change the bidi orientation of the SashForm.
+ * </p>
+ *
+ * @param orientation SWT.HORIZONTAL or SWT.VERTICAL, SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
+ *
+ * @see Control#setOrientation(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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the value of orientation is not SWT.HORIZONTAL or SWT.VERTICAL, SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
+ * </ul>
+ */
+@Override
+public void setOrientation(int orientation) {
+       checkWidget();
+       if (orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT) {
+               super.setOrientation(orientation);
+               return;
+       }
+       if (getOrientation() == orientation) return;
+       if (orientation != SWT.HORIZONTAL && orientation != SWT.VERTICAL) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       sashStyle &= ~(SWT.HORIZONTAL | SWT.VERTICAL);
+       sashStyle |= orientation == SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
+       for (int i = 0; i < sashes.length; i++) {
+               sashes[i].dispose();
+               sashes[i] = createSash();
+       }
+       layout(false);
+}
+@Override
+public void setBackground (Color color) {
+       super.setBackground(color);
+       background = color;
+       for (int i = 0; i < sashes.length; i++) {
+               sashes[i].setBackground(background);
+       }
+}
+@Override
+public 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>
+ */
+@Override
+public 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 == null) {
+               if (maxControl != 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 == width) return;
+       SASH_WIDTH = width;
+       layout(false);
+}
+@Override
+public void setToolTipText(String string) {
+       super.setToolTipText(string);
+       for (int i = 0; i < sashes.length; i++) {
+               sashes[i].setToolTipText(string);
+       }
+}
+/**
+ * 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 == null || weights.length != 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 == 0) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       for (int i = 0; i < cArray.length; i++) {
+               Object data = cArray[i].getLayoutData();
+               if (data == null || !(data instanceof SashFormData)) {
+                       data = new SashFormData();
+                       cArray[i].setLayoutData(data);
+               }
+               ((SashFormData)data).weight = (((long)weights[i] << 16) + total - 1) / total;
+       }
+
+       layout(false);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashFormData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashFormData.java
new file mode 100644 (file)
index 0000000..8091308
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+class SashFormData {
+
+       long weight;
+
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (index + 1, string.length ());
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString () {
+       return getName()+" {weight="+weight+"}"; //$NON-NLS-2$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashFormLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/SashFormLayout.java
new file mode 100644 (file)
index 0000000..5fe4264
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class provides the layout for SashForm
+ *
+ * @see SashForm
+ */
+class SashFormLayout extends Layout {
+@Override
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+       SashForm sashForm = (SashForm)composite;
+       Control[] cArray = sashForm.getControls(true);
+       int width = 0;
+       int height = 0;
+       if (cArray.length == 0) {
+               if (wHint != SWT.DEFAULT) width = wHint;
+               if (hHint != SWT.DEFAULT) height = hHint;
+               return new Point(width, height);
+       }
+       // determine control sizes
+       boolean vertical = sashForm.getOrientation() == 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 (data != null && data instanceof SashFormData) {
+                       ratios[i] = ((SashFormData)data).weight;
+               } else {
+                       data = new SashFormData();
+                       cArray[i].setLayoutData(data);
+                       ((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 += (int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
+               } else {
+                       width += (int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
+               }
+       }
+       width += sashForm.getBorderWidth()*2;
+       height += sashForm.getBorderWidth()*2;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       return new Point(width, height);
+}
+
+@Override
+protected boolean flushCache(Control control) {
+       return true;
+}
+
+@Override
+protected void layout(Composite composite, boolean flushCache) {
+       SashForm sashForm = (SashForm)composite;
+       Rectangle area = sashForm.getClientArea();
+       if (area.width <= 1 || area.height <= 1) return;
+
+       Control[] newControls = sashForm.getControls(true);
+       if (sashForm.controls.length == 0 && newControls.length == 0) return;
+       sashForm.controls = newControls;
+
+       Control[] controls = sashForm.controls;
+
+       if (sashForm.maxControl != null && !sashForm.maxControl.isDisposed()) {
+               for (int i= 0; i < controls.length; i++){
+                       if (controls[i] != 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] = sashForm.createSash();
+               }
+               sashForm.sashes = newSashes;
+       }
+       if (sashForm.sashes.length > controls.length - 1) {
+               if (controls.length == 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 == 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 (data != null && data instanceof SashFormData) {
+                       ratios[i] = ((SashFormData)data).weight;
+               } else {
+                       data = new SashFormData();
+                       controls[i].setLayoutData(data);
+                       ((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() == SWT.HORIZONTAL) {
+               int width = (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 = (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 = (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 = (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);
+               }
+
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ScrolledComposite.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ScrolledComposite.java
new file mode 100644 (file)
index 0000000..86f1980
--- /dev/null
@@ -0,0 +1,712 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <ol>
+ * <li> 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.</li>
+ *
+ * <li>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().</li>
+ * </ol>
+ *
+ * <pre><code>
+ * 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 ();
+ * }
+ * </code></pre>
+ *
+ * <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 extends Composite {
+
+       Control content;
+       Listener contentListener;
+       Listener filter;
+
+       int minHeight = 0;
+       int minWidth = 0;
+       boolean expandHorizontal = false;
+       boolean expandVertical = false;
+       boolean alwaysShowScroll = false;
+       boolean showFocusedControl = false;
+       boolean showNextFocusedControl = 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 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 ScrolledComposite(Composite parent, int style) {
+       super(parent, checkStyle(style));
+       super.setLayout(new ScrolledCompositeLayout());
+       ScrollBar hBar = getHorizontalBar ();
+       if (hBar != null) {
+               hBar.setVisible(false);
+               hBar.addListener (SWT.Selection, e -> hScroll());
+       }
+
+       ScrollBar vBar = getVerticalBar ();
+       if (vBar != null) {
+               vBar.setVisible(false);
+               vBar.addListener (SWT.Selection, e -> vScroll());
+       }
+
+       contentListener = e -> {
+               if (e.type != SWT.Resize) return;
+               layout(false);
+       };
+
+       filter = event -> {
+               if (event.type == SWT.FocusIn) {
+                       if (!showNextFocusedControl) {
+                               showNextFocusedControl = true;
+                       } else if (event.widget instanceof Control) {
+                               Control control = (Control) event.widget;
+                               if (contains(control)) showControl(control);
+                       }
+               } else {
+                       Widget w = event.widget;
+                       if (w instanceof Control) {
+                               showNextFocusedControl = w.getDisplay().getActiveShell() == ((Control) w).getShell();
+                       }
+               }
+       };
+
+       addDisposeListener(e -> {
+               getDisplay().removeFilter(SWT.FocusIn, filter);
+               getDisplay().removeFilter(SWT.FocusOut, 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;
+}
+
+boolean contains(Control control) {
+       if (control == null || control.isDisposed()) return false;
+
+       Composite parent = control.getParent();
+       while (parent != null && !(parent instanceof Shell)) {
+               if (this == 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 boolean getAlwaysShowScrollBars() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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 boolean 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 boolean 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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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 boolean 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 boolean getShowFocusedControl() {
+       checkWidget();
+       return showFocusedControl;
+}
+
+void hScroll() {
+       if (content == null) return;
+       Point location = content.getLocation ();
+       ScrollBar hBar = getHorizontalBar ();
+       int hSelection = hBar.getSelection ();
+       content.setLocation (-hSelection, location.y);
+}
+boolean needHScroll(Rectangle contentRect, boolean vVisible) {
+       ScrollBar hBar = getHorizontalBar();
+       if (hBar == null) return false;
+
+       Rectangle hostRect = getBounds();
+       int border = getBorderWidth();
+       hostRect.width -= 2*border;
+       ScrollBar vBar = getVerticalBar();
+       if (vVisible && vBar != null) hostRect.width -= vBar.getSize().x;
+
+       if (!expandHorizontal && contentRect.width > hostRect.width) return true;
+       if (expandHorizontal && minWidth > hostRect.width) return true;
+       return false;
+}
+
+boolean needVScroll(Rectangle contentRect, boolean hVisible) {
+       ScrollBar vBar = getVerticalBar();
+       if (vBar == null) return false;
+
+       Rectangle hostRect = getBounds();
+       int border = getBorderWidth();
+       hostRect.height -= 2*border;
+       ScrollBar hBar = getHorizontalBar();
+       if (hVisible && hBar != 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 == 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 == null) return;
+       ScrollBar hBar = getHorizontalBar ();
+       if (hBar != null) {
+               hBar.setSelection(x);
+               x = -hBar.getSelection ();
+       } else {
+               x = 0;
+       }
+       ScrollBar vBar = getVerticalBar ();
+       if (vBar != 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(boolean show) {
+       checkWidget();
+       if (show == alwaysShowScroll) return;
+       alwaysShowScroll = show;
+       ScrollBar hBar = getHorizontalBar ();
+       if (hBar != null && alwaysShowScroll) hBar.setVisible(true);
+       ScrollBar vBar = getVerticalBar ();
+       if (vBar != 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 != 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 != null) {
+               if (vBar != null) {
+                       vBar.setMaximum (0);
+                       vBar.setThumb (0);
+                       vBar.setSelection(0);
+               }
+               if (hBar != 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 != null) hBar.setVisible(alwaysShowScroll);
+               if (vBar != 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(boolean expand) {
+       checkWidget();
+       if (expand == 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(boolean expand) {
+       checkWidget();
+       if (expand == 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>
+ */
+@Override
+public 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 == 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 == minWidth && height == 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(boolean show) {
+       checkWidget();
+       if (showFocusedControl == show) return;
+       Display display = getDisplay();
+       display.removeFilter(SWT.FocusIn, filter);
+       display.removeFilter(SWT.FocusOut, filter);
+       showFocusedControl = show;
+       if (!showFocusedControl) return;
+       display.addFilter(SWT.FocusIn, filter);
+       display.addFilter(SWT.FocusOut, 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 == 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);
+       } else {
+               if (area.width < itemRect.x + itemRect.width) origin.x = Math.max(0, origin.x + itemRect.x + Math.min(itemRect.width, area.width) - area.width);
+       }
+       if (itemRect.y < 0) {
+               origin.y = Math.max(0, origin.y + itemRect.y);
+       } else {
+               if (area.height < itemRect.y + itemRect.height) origin.y = Math.max(0, origin.y + itemRect.y + Math.min(itemRect.height, area.height) - area.height);
+       }
+       setOrigin(origin);
+}
+
+void vScroll() {
+       if (content == null) return;
+       Point location = content.getLocation ();
+       ScrollBar vBar = getVerticalBar ();
+       int vSelection = vBar.getSelection ();
+       content.setLocation (location.x, -vSelection);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ScrolledCompositeLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ScrolledCompositeLayout.java
new file mode 100644 (file)
index 0000000..435e7a5
--- /dev/null
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class provides the layout for ScrolledComposite
+ *
+ * @see ScrolledComposite
+ */
+class ScrolledCompositeLayout extends Layout {
+
+       boolean inLayout = false;
+       static final int DEFAULT_WIDTH  = 64;
+       static final int DEFAULT_HEIGHT = 64;
+
+@Override
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+       ScrolledComposite sc = (ScrolledComposite)composite;
+       Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+       if (sc.content != 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 != SWT.DEFAULT) size.x = wHint;
+       if (hHint != SWT.DEFAULT) size.y = hHint;
+       return size;
+}
+
+@Override
+protected boolean flushCache(Control control) {
+       return true;
+}
+
+@Override
+protected void layout(Composite composite, boolean flushCache) {
+       if (inLayout) return;
+       ScrolledComposite sc = (ScrolledComposite)composite;
+       if (sc.content == null) return;
+       ScrollBar hBar = sc.getHorizontalBar();
+       ScrollBar vBar = sc.getVerticalBar();
+       if (hBar != null) {
+               if (hBar.getSize().y >= sc.getSize().y) {
+                       return;
+               }
+       }
+       if (vBar != null) {
+               if (vBar.getSize().x >= sc.getSize().x) {
+                       return;
+               }
+       }
+       inLayout = true;
+       Rectangle contentRect = sc.content.getBounds();
+       if (!sc.alwaysShowScroll) {
+               boolean hVisible = sc.needHScroll(contentRect, false);
+               boolean vVisible = sc.needVScroll(contentRect, hVisible);
+               if (!hVisible && vVisible) hVisible = sc.needHScroll(contentRect, vVisible);
+               if (hBar != null) hBar.setVisible(hVisible);
+               if (vBar != 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);
+       }
+
+       GC gc = new GC (sc);
+       if (hBar != null) {
+               hBar.setMaximum (contentRect.width);
+               hBar.setThumb (Math.min (contentRect.width, hostRect.width));
+               hBar.setIncrement ((int) gc.getFontMetrics ().getAverageCharacterWidth ());
+               hBar.setPageIncrement (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 != null) {
+               vBar.setMaximum (contentRect.height);
+               vBar.setThumb (Math.min (contentRect.height, hostRect.height));
+               vBar.setIncrement (gc.getFontMetrics ().getHeight ());
+               vBar.setPageIncrement (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;
+               }
+       }
+       gc.dispose ();
+
+       sc.content.setBounds (contentRect);
+       inLayout = false;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StackLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StackLayout.java
new file mode 100644 (file)
index 0000000..cf3c5f2
--- /dev/null
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 != null &amp;&amp; !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 extends Layout {
+
+       /**
+        * marginWidth specifies the number of points 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 points 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;
+
+@Override
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean 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 != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       return new Point(width, height);
+}
+
+@Override
+protected boolean flushCache(Control control) {
+       return true;
+}
+
+@Override
+protected void layout(Composite composite, boolean 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] == topControl);
+       }
+}
+
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (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 (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
+       if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
+       if (topControl != null) string += "topControl="+topControl+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyleRange.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyleRange.java
new file mode 100644 (file)
index 0000000..0f8ca21
--- /dev/null
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * <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 extends TextStyle implements Cloneable {
+
+       /**
+        * 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 StyleRange() {
+}
+
+/**
+ * Create a new style range from an existing text style.
+ *
+ * @param style the text style to copy
+ *
+ * @since 3.4
+ */
+public StyleRange(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 StyleRange(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 StyleRange(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()
+ */
+@Override
+public boolean equals(Object object) {
+       if (object == this) return true;
+       if (object instanceof StyleRange) {
+               StyleRange style = (StyleRange)object;
+               if (start != style.start) return false;
+               if (length != 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)
+ */
+@Override
+public int hashCode() {
+       return super.hashCode() ^ fontStyle;
+}
+boolean isVariableHeight() {
+       return font != null || (metrics != null && (metrics.ascent != 0 || metrics.descent != 0)) || rise != 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 boolean isUnstyled() {
+       if (font != null) return false;
+       if (rise != 0) return false;
+       if (metrics != null) return false;
+       if (foreground != null) return false;
+       if (background != null) return false;
+       if (fontStyle != SWT.NORMAL) return false;
+       if (underline) return false;
+       if (strikeout) return false;
+       if (borderStyle != 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 boolean similarTo(StyleRange style) {
+       if (!super.equals(style)) return false;
+       if (fontStyle != style.fontStyle) return false;
+       return true;
+}
+
+/**
+ * Returns a new StyleRange with the same values as this StyleRange.
+ *
+ * @return a shallow copy of this StyleRange
+ */
+@Override
+public Object clone() {
+       try {
+               return super.clone();
+       } catch (CloneNotSupportedException e) {
+               return null;
+       }
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the StyleRange
+ */
+@Override
+public String toString() {
+       StringBuilder buffer = new StringBuilder();
+       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 = str.indexOf('{');
+       str = str.substring(index + 1);
+       if (str.length() > 1) buffer.append(", ");
+       buffer.append(str);
+       return buffer.toString();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledText.java
new file mode 100644 (file)
index 0000000..61453a5
--- /dev/null
@@ -0,0 +1,10923 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Andrey Loskutov <loskutov@gmx.de> - bug 488172
+ *     Stefan Xenos (Google) - bug 487254 - StyledText.getTopIndex() can return negative values
+ *     Angelo Zerr <angelo.zerr@gmail.com> - Customize different line spacing of StyledText - Bug 522020
+ *     Karsten Thoms <thoms@itemis.de> - bug 528746 add getOffsetAtPoint(Point)
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.printing.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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:</p>
+ * <ul>
+ * <li>getStyleRangeAtOffset(int)
+ * <li>getStyleRanges()
+ * <li>replaceStyleRanges(int,int,StyleRange[])
+ * <li>setStyleRange(StyleRange)
+ * <li>setStyleRanges(StyleRange[])
+ * </ul>
+ * <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:</p>
+ * <ul>
+ * <li>getLineBackground(int)
+ * <li>setLineBackground(int,int,Color)
+ * </ul>
+ * <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>
+ * <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, OrientationChange
+ * </dl>
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class StyledText extends Canvas {
+       static final char TAB = '\t';
+       static final String PlatformLineDelimiter = System.getProperty("line.separator");
+       static final int BIDI_CARET_WIDTH = 3;
+       static final int DEFAULT_WIDTH  = 64;
+       static final int DEFAULT_HEIGHT = 64;
+       static final int V_SCROLL_RATE = 50;
+       static final int H_SCROLL_RATE = 10;
+       static final int PREVIOUS_OFFSET_TRAILING = 0;
+       static final int OFFSET_LEADING = 1;
+
+       static final String STYLEDTEXT_KEY = "org.eclipse.swt.internal.cocoa.styledtext"; //$NON-NLS-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
+       boolean alwaysShowScroll = true;
+       int ignoreResize = 0;
+       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 [] tabs;
+       int leftMargin;
+       int topMargin;
+       int rightMargin;
+       int bottomMargin;
+       Color marginColor;
+       int columnX;                                            // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
+       int caretOffset;
+       int caretAlignment;
+       Point selection = new Point(0, 0);      // x and y are start and end caret offsets of selection (x <= y)
+       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
+       boolean editable = true;
+       boolean wordWrap = false;                       // text is wrapped automatically
+       boolean visualWrap = false;             // process line breaks inside logical lines (inserted by BidiSegmentEvent)
+       boolean hasStyleWithVariableHeight = false;
+       boolean hasVerticalIndent = false;
+       boolean doubleClickEnabled = true;      // see getDoubleClickEnabled
+       boolean overwrite = false;                      // insert/overwrite edit mode
+       int textLimit = -1;                                     // limits the number of characters the user can type in the widget. Unlimited by default.
+       Map<Integer, Integer> keyActionMap = new HashMap<>();
+       Color background = null;                        // workaround for bug 4791
+       Color foreground = null;                        //
+       /** True if a non-default background color is set */
+       boolean customBackground;
+       /** True if a non-default foreground color is set */
+       boolean customForeground;
+       /** False iff the widget is disabled */
+       boolean enabled = true;
+       /** True iff the widget is in the midst of being enabled or disabled */
+       boolean insideSetEnableCall;
+       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 lastCharCount = 0;
+       int lastLineBottom;                                     // the bottom pixel of the last line been replaced
+       boolean 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;
+       boolean updateCaretDirection = true;
+       boolean dragDetect = true;
+       IME ime;
+       Cursor cursor;
+       int alignment;
+       boolean justify;
+       int indent, wrapIndent;
+       int lineSpacing;
+       int alignmentMargin;
+       int newOrientation = SWT.NONE;
+       int accCaretOffset;
+       Accessible acc;
+       AccessibleControlAdapter accControlAdapter;
+       AccessibleAttributeAdapter accAttributeAdapter;
+       AccessibleEditableTextListener accEditableTextListener;
+       AccessibleTextExtendedAdapter accTextExtendedAdapter;
+       AccessibleAdapter accAdapter;
+       MouseNavigator mouseNavigator;
+       boolean middleClickPressed;
+
+       //block selection
+       boolean blockSelection;
+       int blockXAnchor = -1, blockYAnchor = -1;
+       int blockXLocation = -1, blockYLocation = -1;
+
+       final static boolean IS_MAC, IS_GTK;
+       static {
+               String platform = SWT.getPlatform();
+               IS_MAC = "cocoa".equals(platform);
+               IS_GTK = "gtk".equals(platform);
+       }
+
+       /**
+        * The Printing class implements 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 implements Runnable {
+               final static int LEFT = 0;                                              // left aligned header/footer segment
+               final static int CENTER = 1;                                    // centered header/footer segment
+               final static int RIGHT = 2;                                             // right aligned header/footer segment
+
+               Printer printer;
+               StyledTextRenderer printerRenderer;
+               StyledTextPrintOptions printOptions;
+               Rectangle clientArea;
+               FontData fontData;
+               Font printerFont;
+               Map<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 scope;                                                                              // scope of print job
+               int startLine;                                                                  // first (wrapped) line to print
+               int endLine;                                                                    // last (wrapped) line to print
+               boolean singleLine;                                                             // widget single line mode
+               Point selection = null;                                 // selected text
+               boolean 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.
+        *
+        * @param parent StyledText widget to print.
+        * @param printer printer device to print on.
+        * @param printOptions print options
+        */
+       Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
+               this.printer = printer;
+               this.printOptions = printOptions;
+               this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0;
+               singleLine = styledText.isSingleLine();
+               startPage = 1;
+               endPage = Integer.MAX_VALUE;
+               PrinterData data = printer.getPrinterData();
+               scope = data.scope;
+               if (scope == PrinterData.PAGE_RANGE) {
+                       startPage = data.startPage;
+                       endPage = data.endPage;
+                       if (endPage < startPage) {
+                               int temp = endPage;
+                               endPage = startPage;
+                               startPage = temp;
+                       }
+               } else if (scope == 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.
+        *
+        * @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(ST.LineGetBackground) || (styledText.isListening(ST.LineGetSegments)) || styledText.isListening(ST.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 != null && event.lineBackground != null) {
+                                       printerRenderer.setLineBackground(i, 1, event.lineBackground);
+                               }
+                               event = styledText.getBidiSegments(lineOffset, line);
+                               if (event != null) {
+                                       printerRenderer.setLineSegments(i, 1, event.segments);
+                                       printerRenderer.setLineSegmentChars(i, 1, event.segmentsChars);
+                               }
+                               event = styledText.getLineStyleData(lineOffset, line);
+                               if (event != 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 != null && styles.length > 0) {
+                                               printerRenderer.setStyleRanges(event.ranges, styles);
+                                       }
+                               }
+                       }
+               }
+               Point screenDPI = styledText.getDisplay().getDPI();
+               Point printerDPI = printer.getDPI();
+               resources = new HashMap<> ();
+               for (int i = 0; i < lineCount; i++) {
+                       Color color = printerRenderer.getLineBackground(i, null);
+                       if (color != null) {
+                               if (printOptions.printLineBackground) {
+                                       Color printerColor = (Color)resources.get(color);
+                                       if (printerColor == null) {
+                                               printerColor = new Color (printer, color.getRGB());
+                                               resources.put(color, printerColor);
+                                       }
+                                       printerRenderer.setLineBackground(i, 1, printerColor);
+                               } else {
+                                       printerRenderer.setLineBackground(i, 1, null);
+                               }
+                       }
+                       int indent = printerRenderer.getLineIndent(i, 0);
+                       if (indent != 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 != null) {
+                               Font printerFont = (Font)resources.get(font);
+                               if (printerFont == null) {
+                                       printerFont = new Font (printer, font.getFontData());
+                                       resources.put(font, printerFont);
+                               }
+                               style.font = printerFont;
+                       }
+                       Color color = style.foreground;
+                       if (color != null) {
+                               Color printerColor = (Color)resources.get(color);
+                               if (printOptions.printTextForeground) {
+                                       if (printerColor == null) {
+                                               printerColor = new Color (printer, color.getRGB());
+                                               resources.put(color, printerColor);
+                                       }
+                                       style.foreground = printerColor;
+                               } else {
+                                       style.foreground = null;
+                               }
+                       }
+                       color = style.background;
+                       if (color != null) {
+                               Color printerColor = (Color)resources.get(color);
+                               if (printOptions.printTextBackground) {
+                                       if (printerColor == null) {
+                                               printerColor = new Color (printer, color.getRGB());
+                                               resources.put(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 != 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>.
+        *
+        * @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 != null) {
+                       gc.dispose();
+                       gc = null;
+               }
+               if (resources != null) {
+                       for (Resource resource : resources.values()) {
+                               resource.dispose();
+                       }
+                       resources = null;
+               }
+               if (printerFont != null) {
+                       printerFont.dispose();
+                       printerFont = null;
+               }
+               if (printerRenderer != null) {
+                       printerRenderer.dispose();
+                       printerRenderer = null;
+               }
+       }
+       void init() {
+               Rectangle trim = printer.computeTrim(0, 0, 0, 0);
+               Point dpi = printer.getDPI();
+
+               printerFont = new Font(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 != null) {
+                       clientArea.y += lineHeight * 2;
+                       clientArea.height -= lineHeight * 2;
+               }
+               if (printOptions.footer != null) {
+                       clientArea.height -= lineHeight * 2;
+               }
+
+               // TODO not wrapped
+               StyledTextContent content = printerRenderer.content;
+               startLine = 0;
+               endLine = singleLine ? 0 : content.getLineCount() - 1;
+               if (scope == PrinterData.PAGE_RANGE) {
+                       int pageSize = clientArea.height / lineHeight;//WRONG
+                       startLine = (startPage - 1) * pageSize;
+               } else if (scope == 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 != null || printOptions.footer != 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 != null) {
+                               for (int i = startLine; i < Math.min(count, lineLabels.length); i++) {
+                                       if (lineLabels[i] != null) {
+                                               printLayout.setText(lineLabels[i]);
+                                               int lineWidth = printLayout.getBounds().width;
+                                               numberingWidth = Math.max(numberingWidth, lineWidth);
+                                       }
+                               }
+                       } else {
+                               StringBuilder buffer = new StringBuilder("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 == 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 == 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((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((Rectangle)null);
+                                               paintY += layoutHeight;
+                                       }
+                               }
+                       }
+                       printerRenderer.disposeTextLayout(layout);
+               }
+               if (page <= endPage && paintY > clientArea.y) {
+                       // close partial page
+                       printDecoration(page, false, printLayout);
+                       printer.endPage();
+               }
+               if (printLayout != 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, boolean header, TextLayout layout) {
+               String text = header ? printOptions.header : printOptions.footer;
+               if (text == null) return;
+               int lastSegmentIndex = 0;
+               for (int i = 0; i < 3; i++) {
+                       int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
+                       String segment;
+                       if (segmentIndex == -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, boolean header, TextLayout layout) {
+               int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
+               if (pageIndex != -1) {
+                       int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length();
+                       StringBuilder buffer = new StringBuilder(segment.substring (0, pageIndex));
+                       buffer.append (page);
+                       buffer.append (segment.substring(pageIndex + pageTagLength));
+                       segment = buffer.toString();
+               }
+               if (segment.length() > 0) {
+                       layout.setText(segment);
+                       int segmentWidth = layout.getBounds().width;
+                       int segmentHeight = printerRenderer.getLineHeight();
+                       int drawX = 0, drawY;
+                       if (alignment == LEFT) {
+                               drawX = clientArea.x;
+                       } else if (alignment == CENTER) {
+                               drawX = (pageWidth - segmentWidth) / 2;
+                       } else if (alignment == 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 != 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 != null) {
+                               if (0 <= index && index < lineLabels.length && lineLabels[index] != null) {
+                                       printLayout.setText(lineLabels[index]);
+                               } else {
+                                       printLayout.setText("");
+                               }
+                       } else {
+                               printLayout.setText(String.valueOf(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.
+        */
+       @Override
+       public void run() {
+               String jobName = printOptions.jobName;
+               if (jobName == 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 extends TextWriter {
+               static final int DEFAULT_FOREGROUND = 0;
+               static final int DEFAULT_BACKGROUND = 1;
+               List<Color> colorTable;
+               List<Font> fontTable;
+
+       /**
+        * 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 RTFWriter(int start, int length) {
+               super(start, length);
+               colorTable = new ArrayList<>();
+               fontTable = new ArrayList<>();
+               colorTable.add(getForeground());
+               colorTable.add(getBackground());
+               fontTable.add(getFont());
+       }
+       /**
+        * 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.
+        */
+       @Override
+       public 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 == null) return defaultIndex;
+               int index = colorTable.indexOf(color);
+               if (index == -1) {
+                       index = colorTable.size();
+                       colorTable.add(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 = fontTable.indexOf(font);
+               if (index == -1) {
+                       index = fontTable.size();
+                       fontTable.add(font);
+               }
+               return index;
+       }
+       /**
+        * 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) {
+               for (int index = start; index < end; index++) {
+                       char ch = string.charAt(index);
+                       if (ch > 0x7F) {
+                               // write the sub string from the last escaped character
+                               // to the current one. Fixes bug 21698.
+                               if (index > start) {
+                                       write(string.substring(start, index));
+                               }
+                               write("\\u");
+                               write(Integer.toString((short) ch));
+                               write('?');                                             // ANSI representation (1 byte long, \\uc1)
+                               start = index + 1;
+                       } else if (ch == '}' || ch == '{' || ch == '\\') {
+                               // write the sub string from the last escaped character
+                               // to the current one. Fixes bug 21698.
+                               if (index > start) {
+                                       write(string.substring(start, index));
+                               }
+                               write('\\');
+                               write(ch);
+                               start = index + 1;
+                       }
+               }
+               // write from the last escaped character to the end.
+               // Fixes bug 21698.
+               if (start < end) {
+                       write(string.substring(start, end));
+               }
+       }
+       /**
+        * Writes the RTF header including font table and color table.
+        */
+       void writeHeader() {
+               StringBuilder header = new StringBuilder();
+               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.
+               String cpg = System.getProperty("file.encoding").toLowerCase();
+               if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
+                       cpg = cpg.substring(2, cpg.length());
+                       header.append("\\ansicpg");
+                       header.append(cpg);
+               }
+               header.append("\\uc1\\deff0{\\fonttbl{\\f0\\fnil ");
+               header.append(fontData.getName());
+               header.append(";");
+               for (int i = 1; i < fontTable.size(); i++) {
+                       header.append("\\f");
+                       header.append(i);
+                       header.append(" ");
+                       FontData fd = fontTable.get(i).getFontData()[0];
+                       header.append(fd.getName());
+                       header.append(";");
+               }
+               header.append("}}\n{\\colortbl");
+               for (int i = 0; i < colorTable.size(); i++) {
+                       Color color = colorTable.get(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>
+        */
+       @Override
+       public void writeLine(String line, int lineOffset) {
+               if (isClosed()) {
+                       SWT.error(SWT.ERROR_IO);
+               }
+               int lineIndex = content.getLineAtOffset(lineOffset);
+               int lineAlignment, lineIndent;
+               boolean lineJustify;
+               int[] ranges;
+               StyleRange[] styles;
+               StyledTextEvent event = getLineStyleData(lineOffset, line);
+               if (event != 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 == null) styles = new StyleRange[0];
+               Color lineBackground = renderer.getLineBackground(lineIndex, null);
+               event = getLineBackgroundData(lineOffset, line);
+               if (event != null && event.lineBackground != 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>
+        */
+       @Override
+       public 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 \chshdng0\chcbpat 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, boolean 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;
+               }
+               if (justify) write("\\qj");
+               write(" ");
+
+               if (lineBackground != null) {
+                       write("{\\chshdng0\\chcbpat");
+                       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 != 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 != DEFAULT_BACKGROUND) {
+                               write("\\chshdng0\\chcbpat");
+                               write(colorIndex);
+                       }
+                       int fontStyle = style.fontStyle;
+                       Font font = style.font;
+                       if (font != null) {
+                               int fontIndex = getFontIndex(font);
+                               write("\\f");
+                               write(fontIndex);
+                               FontData fontData = font.getFontData()[0];
+                               write("\\fs");
+                               write(fontData.getHeight() * 2);
+                               fontStyle = fontData.getStyle();
+                       }
+                       if ((fontStyle & SWT.BOLD) != 0) {
+                               write("\\b");
+                       }
+                       if ((fontStyle & SWT.ITALIC) != 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 ((fontStyle & SWT.BOLD) != 0) {
+                               write("\\b0");
+                       }
+                       if ((style.fontStyle & SWT.ITALIC) != 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 != 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 StringBuilder 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 boolean 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 TextWriter(int start, int length) {
+               buffer = new StringBuilder(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 boolean specifying whether or not the writer is closed
+        */
+       public boolean 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
+        */
+       @Override
+       public 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 &lt; 0 or &gt; 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.insert(offset, 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 StyledText(Composite parent, int style) {
+       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();
+       if ((style & SWT.READ_ONLY) != 0) {
+               setEditable(false);
+       }
+       leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0;
+       if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) {
+               leftMargin = topMargin = rightMargin = bottomMargin = 2;
+       }
+       alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+       if (alignment == 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) != 0) {
+               setWordWrap(true);
+       }
+       if (isBidiCaret()) {
+               createCaretBitmaps();
+               Runnable runnable = () -> {
+                       int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT;
+                       if (direction == caretDirection) return;
+                       if (getCaret() != defaultCaret) return;
+                       Point newCaretPos = getPointAtOffset(caretOffset);
+                       setCaretLocation(newCaretPos, direction);
+               };
+               BidiUtil.addLanguageListener(this, runnable);
+       }
+       setCaret(defaultCaret);
+       calculateScrollBars();
+       createKeyBindings();
+       super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
+       installListeners();
+       initializeAccessible();
+       setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this));
+       if (IS_MAC) setData(STYLEDTEXT_KEY);
+}
+/**
+ * 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       StyledTextListener typedListener = new StyledTextListener(extendedModifyListener);
+       addListener(ST.ExtendedModify, typedListener);
+}
+/**
+ * Adds a bidirectional segment listener.
+ * <p>
+ * A BidiSegmentEvent is sent
+ * whenever a line of text is measured or rendered. You 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       addListener(ST.LineGetSegments, new StyledTextListener(listener));
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       super.redraw();
+}
+/**
+ * Adds a caret listener. CaretEvent is sent when the caret offset changes.
+ *
+ * @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.5
+ */
+public void addCaretListener(CaretListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       addListener(ST.CaretMoved, 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (!isListening(ST.LineGetBackground)) {
+               renderer.clearLineBackground(0, content.getLineCount());
+       }
+       addListener(ST.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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (!isListening(ST.LineGetStyle)) {
+               setStyleRanges(0, 0, null, null, true);
+               renderer.clearLineStyle(0, content.getLineCount());
+       }
+       addListener(ST.LineGetStyle, new StyledTextListener(listener));
+       setCaretLocation();
+}
+/**
+ * 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 == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       addListener(ST.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. The selection values returned are visual
+ * (i.e., x will always always be &lt;= y).
+ * No event is sent when the caret is moved while the selection length is 0.
+ * </p><p>
+ * <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 == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       addListener(ST.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 == 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 (movementListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       addListener(ST.WordNext, new StyledTextListener(movementListener));
+       addListener(ST.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>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void append(String string) {
+       checkWidget();
+       if (string == 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 != null) {
+               verticalBar.setIncrement(getVerticalIncrement());
+       }
+       if (horizontalBar != 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 oldDelta = delta;
+       int oldTopIndex = topIndex;
+       int oldTopIndexY = topIndexY;
+       if (isFixedLineHeight()) {
+               int verticalIncrement = getVerticalIncrement();
+               if (verticalIncrement == 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 = getVerticalScrollOffset() / verticalIncrement;
+                               }
+                       } 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 == 0 || -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+                               topIndex = lineIndex;
+                               topIndexY = - delta;
+                       } else {
+                               topIndex = lineIndex - 1;
+                               topIndexY = - renderer.getLineHeight(topIndex) - delta;
+                       }
+               }
+       }
+       if (topIndex < 0) {
+               // TODO: This logging is in place to determine why topIndex is getting set to negative values.
+               // It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
+               System.err.println("StyledText: topIndex was " + topIndex
+                               + ", isFixedLineHeight() = " + isFixedLineHeight()
+                               + ", delta = " + delta
+                               + ", content.getLineCount() = " + content.getLineCount()
+                               + ", clientAreaHeight = " + clientAreaHeight
+                               + ", oldTopIndex = " + oldTopIndex
+                               + ", oldTopIndexY = " + oldTopIndexY
+                               + ", getVerticalScrollOffset = " + getVerticalScrollOffset()
+                               + ", oldDelta = " + oldDelta
+                               + ", getVerticalIncrement() = " + getVerticalIncrement());
+               topIndex = 0;
+       }
+       if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) {
+               int width = renderer.getWidth();
+               renderer.calculateClientArea();
+               if (width != renderer.getWidth()) {
+                       setScrollBars(false);
+               }
+       }
+}
+/**
+ * Hides the scroll bars if widget is created in single line mode.
+ */
+static int checkStyle(int style) {
+       if ((style & SWT.SINGLE) != 0) {
+               style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI);
+       } else {
+               style |= SWT.MULTI;
+               if ((style & SWT.WRAP) != 0) {
+                       style &= ~SWT.H_SCROLL;
+               }
+       }
+       style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND;
+       /* Clear SWT.CENTER to avoid the conflict with SWT.EMBEDDED */
+       return style & ~SWT.CENTER;
+}
+/**
+ * Scrolls down the text to use new space made available by a resize or by
+ * deleted lines.
+ */
+void claimBottomFreeSpace() {
+       if (ime.getCompositionOffset() != -1) return;
+       if (isFixedLineHeight()) {
+               int newVerticalOffset = Math.max(0, renderer.getHeight() - 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);
+       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);
+       }
+}
+void clearBlockSelection(boolean reset, boolean sendEvent) {
+       if (reset) resetSelection();
+       blockXAnchor = blockYAnchor = -1;
+       blockXLocation = blockYLocation = -1;
+       caretDirection = SWT.NULL;
+       updateCaretVisibility();
+       super.redraw();
+       if (sendEvent) sendSelectionEvent();
+}
+/**
+ * Removes the widget selection.
+ *
+ * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset.
+ */
+void clearSelection(boolean 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();
+               }
+       }
+}
+@Override
+public Point computeSize (int wHint, int hHint, boolean changed) {
+       checkWidget();
+       int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount();
+       int width = 0;
+       int height = 0;
+       if (wHint == SWT.DEFAULT || hHint == 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 == 0 ? 1 : wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(1, wHint - leftMargin - rightMargin));
+                       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 == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int wTrim = getLeftMargin() + 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();
+       copySelection(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();
+       copySelection(clipboardType);
+}
+boolean copySelection(int type) {
+       if (type != DND.CLIPBOARD && type != DND.SELECTION_CLIPBOARD) return false;
+       try {
+               if (blockSelection && blockXLocation != -1) {
+                       String text = getBlockSelectionText(PlatformLineDelimiter);
+                       if (text.length() > 0) {
+                               //TODO RTF support
+                               TextTransfer plainTextTransfer = TextTransfer.getInstance();
+                               Object[] data = new Object[]{text};
+                               Transfer[] types = new Transfer[]{plainTextTransfer};
+                               clipboard.setContents(data, types, type);
+                               return true;
+                       }
+               } else {
+                       int length = selection.y - selection.x;
+                       if (length > 0) {
+                               setClipboardContent(selection.x, length, type);
+                               return true;
+                       }
+               }
+       } catch (SWTError error) {
+               // Copy to clipboard failed. This happens when another application
+               // is accessing the clipboard while we copy. Ignore the error.
+               // Rethrow all other errors. Fixes bug 17578.
+               if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
+                       throw error;
+               }
+       }
+       return false;
+}
+/**
+ * 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;
+}
+/**
+ * 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 content 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
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.8
+ */
+public boolean getAlwaysShowScrollBars() {
+       checkWidget();
+       return alwaysShowScroll;
+}
+int getAvailableHeightAbove(int height) {
+       int maxHeight = verticalScrollOffset;
+       if (maxHeight == -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 the color of the margins.
+ *
+ * @return the color of the margins.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public Color getMarginColor() {
+       checkWidget();
+       return marginColor != null ? marginColor : getBackground();
+}
+/**
+ * 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 == 0) {
+               return text;
+       }
+       int crIndex = 0;
+       int lfIndex = 0;
+       int i = 0;
+       StringBuilder convertedText = new StringBuilder(length);
+       String delimiter = getLineDelimiter();
+       while (i < length) {
+               if (crIndex != -1) {
+                       crIndex = text.indexOf(SWT.CR, i);
+               }
+               if (lfIndex != -1) {
+                       lfIndex = text.indexOf(SWT.LF, i);
+               }
+               if (lfIndex == -1 && crIndex == -1) {   // no more line breaks?
+                       break;
+               } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) {
+                       convertedText.append(text.substring(i, crIndex));
+                       if (lfIndex == 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() == 0)) {
+               convertedText.append(text.substring(i));
+       }
+       return convertedText.toString();
+}
+boolean checkDragDetect(Event event) {
+       if (!isListening(SWT.DragDetect)) return false;
+       if (event.button != 1) return false;
+       if (blockSelection && blockXLocation != -1) {
+               Rectangle rect = getBlockSelectionRectangle();
+               if (rect.contains(event.x, event.y)) {
+                       return dragDetect(event);
+               }
+       } else {
+               if (selection.x == 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_MAC) {
+               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_MAC) {
+               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_MAC) {
+               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 != null) {
+               if (defaultCaret != null && leftCaretBitmap.equals(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 != null) {
+               if (defaultCaret != null && rightCaretBitmap.equals(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();
+       // Abort cut operation if copy to clipboard fails.
+       // Fixes bug 21030.
+       if (copySelection(DND.CLIPBOARD)) {
+               if (blockSelection && blockXLocation != -1) {
+                       insertBlockSelectionText((char)0, SWT.NULL);
+               } else {
+                       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) {
+       int caretLine = getCaretLine();
+       if (event.y > clientAreaHeight - bottomMargin && caretLine != content.getLineCount() - 1) {
+               doAutoScroll(SWT.DOWN, event.y - (clientAreaHeight - bottomMargin));
+       } else if (event.y < topMargin && caretLine != 0) {
+               doAutoScroll(SWT.UP, topMargin - event.y);
+       } else if (event.x < leftMargin && !wordWrap) {
+               doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x);
+       } else if (event.x > clientAreaWidth - rightMargin && !wordWrap) {
+               doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - 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 == direction) {
+               return;
+       }
+
+       Runnable timer = null;
+       final Display display = getDisplay();
+       // Set a timer that will simulate the user pressing and holding
+       // down a cursor key (i.e., arrowUp, arrowDown).
+       if (direction == SWT.UP) {
+               timer = new Runnable() {
+                       @Override
+                       public void run() {
+                               /* Bug 437357 - NPE in StyledText.getCaretLine
+                                * StyledText.content is null at times, probably because the
+                                * widget itself has been disposed.
+                                */
+                               if (isDisposed()) return;
+                               if (autoScrollDirection == SWT.UP) {
+                                       if (blockSelection) {
+                                               int verticalScrollOffset = getVerticalScrollOffset();
+                                               int y = blockYLocation - verticalScrollOffset;
+                                               int pixels = Math.max(-autoScrollDistance, -verticalScrollOffset);
+                                               if (pixels != 0) {
+                                                       setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
+                                                       scrollVertical(pixels, true);
+                                               }
+                                       } else {
+                                               doSelectionPageUp(autoScrollDistance);
+                                       }
+                                       display.timerExec(V_SCROLL_RATE, this);
+                               }
+                       }
+               };
+               autoScrollDirection = direction;
+               display.timerExec(V_SCROLL_RATE, timer);
+       } else if (direction == SWT.DOWN) {
+               timer = new Runnable() {
+                       @Override
+                       public void run() {
+                               /* Bug 437357 - NPE in StyledText.getCaretLine
+                                * StyledText.content is null at times, probably because the
+                                * widget itself has been disposed.
+                                */
+                               if (isDisposed()) return;
+                               if (autoScrollDirection == SWT.DOWN) {
+                                       if (blockSelection) {
+                                               int verticalScrollOffset = getVerticalScrollOffset();
+                                               int y = blockYLocation - verticalScrollOffset;
+                                               int max = renderer.getHeight() - verticalScrollOffset - clientAreaHeight;
+                                               int pixels = Math.min(autoScrollDistance, Math.max(0,max));
+                                               if (pixels != 0) {
+                                                       setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
+                                                       scrollVertical(pixels, true);
+                                               }
+                                       } else {
+                                               doSelectionPageDown(autoScrollDistance);
+                                       }
+                                       display.timerExec(V_SCROLL_RATE, this);
+                               }
+                       }
+               };
+               autoScrollDirection = direction;
+               display.timerExec(V_SCROLL_RATE, timer);
+       } else if (direction == ST.COLUMN_NEXT) {
+               timer = new Runnable() {
+                       @Override
+                       public void run() {
+                               /* Bug 437357 - NPE in StyledText.getCaretLine
+                                * StyledText.content is null at times, probably because the
+                                * widget itself has been disposed.
+                                */
+                               if (isDisposed()) return;
+                               if (autoScrollDirection == ST.COLUMN_NEXT) {
+                                       if (blockSelection) {
+                                               int x = blockXLocation - horizontalScrollOffset;
+                                               int max = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth;
+                                               int pixels = Math.min(autoScrollDistance, Math.max(0,max));
+                                               if (pixels != 0) {
+                                                       setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
+                                                       scrollHorizontal(pixels, true);
+                                               }
+                                       } else {
+                                               doVisualNext();
+                                               setMouseWordSelectionAnchor();
+                                               doMouseSelection();
+                                       }
+                                       display.timerExec(H_SCROLL_RATE, this);
+                               }
+                       }
+               };
+               autoScrollDirection = direction;
+               display.timerExec(H_SCROLL_RATE, timer);
+       } else if (direction == ST.COLUMN_PREVIOUS) {
+               timer = new Runnable() {
+                       @Override
+                       public void run() {
+                               /* Bug 437357 - NPE in StyledText.getCaretLine
+                                * StyledText.content is null at times, probably because the
+                                * widget itself has been disposed.
+                                */
+                               if (isDisposed()) return;
+                               if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
+                                       if (blockSelection) {
+                                               int x = blockXLocation - horizontalScrollOffset;
+                                               int pixels = Math.max(-autoScrollDistance, -horizontalScrollOffset);
+                                               if (pixels != 0) {
+                                                       setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
+                                                       scrollHorizontal(pixels, true);
+                                               }
+                                       } else {
+                                               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 != 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 == lineOffset) {
+                       lineOffset = content.getOffsetAtLine(lineIndex - 1);
+                       event.start = lineOffset + content.getLine(lineIndex - 1).length();
+                       event.end = caretOffset;
+               } else {
+                       boolean isSurrogate = false;
+                       String lineText = content.getLine(lineIndex);
+                       char ch = lineText.charAt(caretOffset - lineOffset - 1);
+                       if (0xDC00 <= ch && ch <= 0xDFFF) {
+                               if (caretOffset - lineOffset - 2 >= 0) {
+                                       ch = lineText.charAt(caretOffset - lineOffset - 2);
+                                       isSurrogate = 0xD800 <= ch && ch <= 0xDBFF;
+                               }
+                       }
+                       TextLayout layout = renderer.getTextLayout(lineIndex);
+                       int start = layout.getPreviousOffset(caretOffset - lineOffset, isSurrogate ? SWT.MOVEMENT_CLUSTER : SWT.MOVEMENT_CHAR);
+                       renderer.disposeTextLayout(layout);
+                       event.start = start + lineOffset;
+                       event.end = caretOffset;
+               }
+               sendKeyEvent(event);
+       }
+}
+void doBlockColumn(boolean next) {
+       if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
+       int x = blockXLocation - horizontalScrollOffset;
+       int y = blockYLocation - getVerticalScrollOffset();
+       int[] trailing = new int[1];
+       int offset = getOffsetAtPoint(x, y, trailing, true);
+       if (offset != -1) {
+               offset += trailing[0];
+               int lineIndex = content.getLineAtOffset(offset);
+               int newOffset;
+               if (next) {
+                       newOffset = getClusterNext(offset, lineIndex);
+               } else {
+                       newOffset = getClusterPrevious(offset, lineIndex);
+               }
+               offset = newOffset != offset ? newOffset : -1;
+       }
+       if (offset != -1) {
+               setBlockSelectionOffset(offset, true);
+               showCaret();
+       } else {
+               int width = next ? renderer.averageCharWidth : -renderer.averageCharWidth;
+               int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
+               x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
+               setBlockSelectionLocation(x, y, true);
+               Rectangle rect = new Rectangle(x, y, 0, 0);
+               showLocation(rect, true);
+       }
+}
+void doBlockContentStartEnd(boolean end) {
+       if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
+       int offset = end ? content.getCharCount() : 0;
+       setBlockSelectionOffset(offset, true);
+       showCaret();
+}
+void doBlockWord(boolean next) {
+       if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
+       int x = blockXLocation - horizontalScrollOffset;
+       int y = blockYLocation - getVerticalScrollOffset();
+       int[] trailing = new int[1];
+       int offset = getOffsetAtPoint(x, y, trailing, true);
+       if (offset != -1) {
+               offset += trailing[0];
+               int lineIndex = content.getLineAtOffset(offset);
+               int lineOffset = content.getOffsetAtLine(lineIndex);
+               String lineText = content.getLine(lineIndex);
+               int lineLength = lineText.length();
+               int newOffset = offset;
+               if (next) {
+                       if (offset < lineOffset + lineLength) {
+                               newOffset = getWordNext(offset, SWT.MOVEMENT_WORD);
+                       }
+               } else {
+                       if (offset > lineOffset) {
+                               newOffset = getWordPrevious(offset, SWT.MOVEMENT_WORD);
+                       }
+               }
+               offset = newOffset != offset ? newOffset : -1;
+       }
+       if (offset != -1) {
+               setBlockSelectionOffset(offset, true);
+               showCaret();
+       } else {
+               int width = (next ? renderer.averageCharWidth : -renderer.averageCharWidth) * 6;
+               int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
+               x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
+               setBlockSelectionLocation(x, y, true);
+               Rectangle rect = new Rectangle(x, y, 0, 0);
+               showLocation(rect, true);
+       }
+}
+void doBlockLineVertical(boolean up) {
+       if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
+       int y = blockYLocation - getVerticalScrollOffset();
+       int lineIndex = getLineIndex(y);
+       if (up) {
+               if (lineIndex > 0) {
+                       y = getLinePixel(lineIndex - 1);
+                       setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
+                       if (y < topMargin) {
+                               scrollVertical(y - topMargin, true);
+                       }
+               }
+       } else {
+               int lineCount = content.getLineCount();
+               if (lineIndex + 1 < lineCount) {
+                       y = getLinePixel(lineIndex + 2) - 1;
+                       setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
+                       int bottom = clientAreaHeight - bottomMargin;
+                       if (y > bottom) {
+                               scrollVertical(y - bottom, true);
+                       }
+               }
+       }
+}
+void doBlockLineHorizontal(boolean end) {
+       if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
+       int x = blockXLocation - horizontalScrollOffset;
+       int y = blockYLocation - getVerticalScrollOffset();
+       int lineIndex = getLineIndex(y);
+       int lineOffset = content.getOffsetAtLine(lineIndex);
+       String lineText = content.getLine(lineIndex);
+       int lineLength = lineText.length();
+       int[] trailing = new int[1];
+       int offset = getOffsetAtPoint(x, y, trailing, true);
+       if (offset != -1) {
+               offset += trailing[0];
+               int newOffset = offset;
+               if (end) {
+                       if (offset < lineOffset + lineLength) {
+                               newOffset = lineOffset + lineLength;
+                       }
+               } else {
+                       if (offset > lineOffset) {
+                               newOffset = lineOffset;
+                       }
+               }
+               offset = newOffset != offset ? newOffset : -1;
+       } else {
+               if (!end) offset = lineOffset + lineLength;
+       }
+       if (offset != -1) {
+               setBlockSelectionOffset(offset, true);
+               showCaret();
+       } else {
+               int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
+               x = (end ? maxWidth : 0) - horizontalScrollOffset;
+               setBlockSelectionLocation(x, y, true);
+               Rectangle rect = new Rectangle(x, y, 0, 0);
+               showLocation(rect, true);
+       }
+}
+void doBlockSelection(boolean sendEvent) {
+       if (caretOffset > selectionAnchor) {
+               selection.x = selectionAnchor;
+               selection.y = caretOffset;
+       } else {
+               selection.x = caretOffset;
+               selection.y = selectionAnchor;
+       }
+       updateCaretVisibility();
+       setCaretLocation();
+       super.redraw();
+       if (sendEvent) {
+               sendSelectionEvent();
+       }
+       sendAccessibleTextCaretMoved();
+}
+/**
+ * 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(char key) {
+       if (blockSelection && blockXLocation != -1) {
+               insertBlockSelectionText(key, SWT.NULL);
+               return;
+       }
+
+       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 == SWT.CR || key == SWT.LF) {
+               if (!isSingleLine()) {
+                       event.text = getLineDelimiter();
+               }
+       } else if (selection.x == selection.y && overwrite && key != 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++;
+               }
+               event.text = new String(new char[] {key});
+       } else {
+               event.text = new String(new char[] {key});
+       }
+       if (event.text != 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();
+               setCaretOffset(length, SWT.DEFAULT);
+               showCaret();
+       }
+}
+/**
+ * Moves the caret in front of the first character of the widget content.
+ */
+void doContentStart() {
+       setCaretOffset(0, SWT.DEFAULT);
+       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) {
+               setCaretOffset(selection.x, 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) {
+               setCaretOffset(selection.y, 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 != 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 == 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 != 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 != 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. Moves the caret to
+ * the end of the text if the caret already is on the last line.
+ */
+void doLineDown(boolean select) {
+       int caretLine = getCaretLine();
+       int lineCount = content.getLineCount();
+       int y = 0;
+       boolean lastLine = false;
+       if (isWordWrap()) {
+               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 == layoutLineCount - 1) {
+                       lastLine = caretLine == lineCount - 1;
+                       caretLine++;
+               } else {
+                       y = layout.getLineBounds(lineIndex + 1).y;
+                       y++; // bug 485722: workaround for fractional line heights
+               }
+               renderer.disposeTextLayout(layout);
+       } else {
+               lastLine = caretLine == lineCount - 1;
+               caretLine++;
+       }
+       if (lastLine) {
+               setCaretOffset(content.getCharCount(), SWT.DEFAULT);
+       } else {
+               int[] alignment = new int[1];
+               int offset = getOffsetAtPoint(columnX, y, caretLine, alignment);
+               setCaretOffset(offset, alignment[0]);
+       }
+       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 (isWordWrap()) {
+               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;
+       }
+       setCaretOffset(lineEndOffset, PREVIOUS_OFFSET_TRAILING);
+       showCaret();
+}
+/**
+ * Moves the caret to the beginning of the line.
+ */
+void doLineStart() {
+       int caretLine = getCaretLine();
+       int lineOffset = content.getOffsetAtLine(caretLine);
+       if (isWordWrap()) {
+               TextLayout layout = renderer.getTextLayout(caretLine);
+               int offsetInLine = caretOffset - lineOffset;
+               int lineIndex = getVisualLineIndex(layout, offsetInLine);
+               int[] offsets = layout.getLineOffsets();
+               lineOffset += offsets[lineIndex];
+               renderer.disposeTextLayout(layout);
+       }
+       setCaretOffset(lineOffset, 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. Moves the caret to
+ * the beginning of the document if it is already on the first line.
+ */
+void doLineUp(boolean select) {
+       int caretLine = getCaretLine(), y = 0;
+       boolean firstLine = false;
+       if (isWordWrap()) {
+               int lineOffset = content.getOffsetAtLine(caretLine);
+               int offsetInLine = caretOffset - lineOffset;
+               TextLayout layout = renderer.getTextLayout(caretLine);
+               int lineIndex = getVisualLineIndex(layout, offsetInLine);
+               if (lineIndex == 0) {
+                       firstLine = caretLine == 0;
+                       if (!firstLine) {
+                               caretLine--;
+                               y = renderer.getLineHeight(caretLine) - 1;
+                               y--; // bug 485722: workaround for fractional line heights
+                       }
+               } else {
+                       y = layout.getLineBounds(lineIndex - 1).y;
+                       y++; // bug 485722: workaround for fractional line heights
+               }
+               renderer.disposeTextLayout(layout);
+       } else {
+               firstLine = caretLine == 0;
+               caretLine--;
+       }
+       if (firstLine) {
+               setCaretOffset(0, SWT.DEFAULT);
+       } else {
+               int[] alignment = new int[1];
+               int offset = getOffsetAtPoint(columnX, y, caretLine, alignment);
+               setCaretOffset(offset, alignment[0]);
+       }
+       int oldColumnX = columnX;
+       int oldHScrollOffset = horizontalScrollOffset;
+       if (select) setMouseWordSelectionAnchor();
+       showCaret();
+       if (select) doSelection(ST.COLUMN_PREVIOUS);
+       int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+       columnX = oldColumnX + hScrollChange;
+}
+void doMouseLinkCursor() {
+       Display display = getDisplay();
+       Point point = display.getCursorLocation();
+       point = display.map(null, this, point);
+       doMouseLinkCursor(point.x, point.y);
+}
+void doMouseLinkCursor(int x, int y) {
+       int offset = getOffsetAtPoint(x, y, null, true);
+       Display display = getDisplay();
+       Cursor newCursor = cursor;
+       if (renderer.hasLink(offset)) {
+               newCursor = display.getSystemCursor(SWT.CURSOR_HAND);
+       } else {
+               if (cursor == null) {
+                       int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
+                       newCursor = display.getSystemCursor(type);
+               }
+       }
+       if (newCursor != getCursor()) super.setCursor(newCursor);
+}
+/**
+ * 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, boolean select) {
+       int line = getLineIndex(y);
+
+       updateCaretDirection = true;
+
+       if (blockSelection) {
+               x = Math.max(leftMargin, Math.min(x, clientAreaWidth - rightMargin));
+               y = Math.max(topMargin, Math.min(y, clientAreaHeight - bottomMargin));
+               if (doubleClickEnabled && clickCount > 1) {
+                       boolean wordSelect = (clickCount & 1) == 0;
+                       if (wordSelect) {
+                               Point left = getPointAtOffset(doubleClickSelection.x);
+                               int[] trailing = new int[1];
+                               int offset = getOffsetAtPoint(x, y, trailing, true);
+                               if (offset != -1) {
+                                       if (x > left.x) {
+                                               offset = getWordNext(offset + trailing[0], SWT.MOVEMENT_WORD_END);
+                                               setBlockSelectionOffset(doubleClickSelection.x, offset, true);
+                                       } else {
+                                               offset = getWordPrevious(offset + trailing[0], SWT.MOVEMENT_WORD_START);
+                                               setBlockSelectionOffset(doubleClickSelection.y, offset, true);
+                                       }
+                               } else {
+                                       if (x > left.x) {
+                                               setBlockSelectionLocation(left.x, left.y, x, y, true);
+                                       } else {
+                                               Point right = getPointAtOffset(doubleClickSelection.y);
+                                               setBlockSelectionLocation(right.x, right.y, x, y, true);
+                                       }
+                               }
+                       } else {
+                               setBlockSelectionLocation(blockXLocation, y, true);
+                       }
+                       return;
+               } else {
+                       if (select) {
+                               if (blockXLocation == -1) {
+                                       setBlockSelectionOffset(caretOffset, false);
+                               }
+                       } else {
+                               clearBlockSelection(true, false);
+                       }
+                       int[] trailing = new int[1];
+                       int offset = getOffsetAtPoint(x, y, trailing, true);
+                       if (offset != -1) {
+                               if (select) {
+                                       setBlockSelectionOffset(offset + trailing[0], true);
+                                       return;
+                               }
+                       } else {
+                               if (isFixedLineHeight() && renderer.fixedPitch) {
+                                       int avg = renderer.averageCharWidth;
+                                       x = ((x + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
+                               }
+                               setBlockSelectionLocation(x, y, true);
+                               return;
+                       }
+               }
+       }
+
+       // 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[] alignment = new int[1];
+       int newCaretOffset = getOffsetAtPoint(x, y, alignment);
+       int newCaretAlignemnt = alignment[0];
+
+       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
+       boolean vchange = 0 <= y && y < clientAreaHeight || newCaretLine == 0 || newCaretLine == content.getLineCount() - 1;
+       boolean hchange = 0 <= x && x < clientAreaWidth || wordWrap || newCaretLine != content.getLineAtOffset(caretOffset);
+       if (vchange && hchange && (newCaretOffset != caretOffset || newCaretAlignemnt != caretAlignment)) {
+               setCaretOffset(newCaretOffset, newCaretAlignemnt);
+               if (select) doMouseSelection();
+               showCaret();
+       }
+       if (!select) {
+               setCaretOffset(newCaretOffset, newCaretAlignemnt);
+               clearSelection(true);
+       }
+}
+/**
+ * Updates the selection based on the caret position
+ */
+void doMouseSelection() {
+       if (caretOffset <= selection.x ||
+               (caretOffset > selection.x &&
+                caretOffset < selection.y && selectionAnchor == 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 == selection.x) {
+               selectionAnchor = doubleClickSelection.y;
+       } else if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) {
+               selectionAnchor = doubleClickSelection.x;
+       }
+       if (0 <= x && x < clientAreaWidth) {
+               boolean wordSelect = (clickCount & 1) == 0;
+               if (caretOffset == 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(boolean 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 == -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);
+                       int[] alignment = new int[1];
+                       int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines), alignment);
+                       setCaretOffset(offset, alignment[0]);
+                       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 == -1) {
+                       lineIndex = getPartialBottomIndex();
+                       int topY = getLinePixel(lineIndex);
+                       lineHeight = renderer.getLineHeight(lineIndex);
+                       height = topY;
+                       if (topY + lineHeight <= clientAreaHeight) {
+                               height += lineHeight;
+                       } else {
+                               if (isWordWrap()) {
+                                       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 (isWordWrap()) {
+                               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 (isWordWrap()) {
+                       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);
+               }
+               int[] alignment = new int[1];
+               int offset = getOffsetAtPoint(columnX, caretHeight, lineIndex, alignment);
+               setCaretOffset(offset, alignment[0]);
+               if (select) doSelection(ST.COLUMN_NEXT);
+               height = getAvailableHeightBellow(height);
+               scrollVertical(height, true);
+               if (height == 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 (isWordWrap()) {
+                       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 == -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) {
+                       setCaretOffset(bottomOffset, OFFSET_LEADING);
+                       showCaret();
+               }
+       }
+}
+/**
+ * Moves the cursor to the beginning of the first fully visible line.
+ */
+void doPageStart() {
+       int topOffset;
+       if (isWordWrap()) {
+               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 == 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) {
+               setCaretOffset(topOffset, 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(boolean 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 == -1 ? clientAreaHeight : height) / lineHeight;
+                       int scrollLines = Math.max(1, Math.min(caretLine, lines));
+                       caretLine -= scrollLines;
+                       int[] alignment = new int[1];
+                       int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine), alignment);
+                       setCaretOffset(offset, alignment[0]);
+                       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 == -1) {
+                       if (topIndexY == 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 (isWordWrap()) {
+                                       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 (isWordWrap()) {
+                               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 (isWordWrap()) {
+                       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);
+               int[] alignment = new int[1];
+               int offset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex, alignment);
+               setCaretOffset(offset, alignment[0]);
+               if (select) doSelection(ST.COLUMN_PREVIOUS);
+               height = getAvailableHeightAbove(height);
+               scrollVertical(-height, true);
+               if (height == 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 == -1) {
+               selectionAnchor = selection.x;
+       }
+       if (direction == 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 != selectionAnchor) {
+                               redrawEnd = selection.y;
+                               selection.y = selectionAnchor;
+                       }
+               // test whether selection actually changed. Fixes 1G71EO1
+               } else if (selectionAnchor == 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 != selectionAnchor) {
+                               redrawStart = selection.x;
+                               selection.x = selectionAnchor;
+                       }
+               // test whether selection actually changed. Fixes 1G71EO1
+               } else if (selectionAnchor == 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 != -1 && redrawEnd != -1) {
+               internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+               sendSelectionEvent();
+       }
+       sendAccessibleTextCaretMoved();
+}
+/**
+ * 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;
+       int offset, alignment;
+       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);
+               offset = offsetInLine + lineOffset;
+               alignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING;
+               setCaretOffset(offset, alignment);
+               showCaret();
+       } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) {
+               caretLine++;
+               offset = content.getOffsetAtLine(caretLine);
+               alignment = PREVIOUS_OFFSET_TRAILING;
+               setCaretOffset(offset, alignment);
+               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;
+       if (offsetInLine > 0) {
+               int offset = getClusterPrevious(caretOffset, caretLine);
+               setCaretOffset(offset, OFFSET_LEADING);
+               showCaret();
+       } else if (caretLine > 0) {
+               caretLine--;
+               lineOffset = content.getOffsetAtLine(caretLine);
+               int offset = lineOffset + content.getLine(caretLine).length();
+               setCaretOffset(offset, OFFSET_LEADING);
+               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 offset = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
+       // 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) == content.getLineAtOffset(offset)) {
+               // Force symmetrical movement for word next and previous. Fixes 14536
+               setCaretOffset(offset, OFFSET_LEADING);
+               showCaret();
+       }
+}
+/**
+ * Moves the caret to the start of the previous word.
+ */
+void doSelectionWordPrevious() {
+       int offset = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
+       setCaretOffset(offset, OFFSET_LEADING);
+       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() {
+       int offset = getClusterPrevious(caretOffset, getCaretLine());
+       setCaretOffset(offset, SWT.DEFAULT);
+       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() {
+       int offset = getClusterNext(caretOffset, getCaretLine());
+       setCaretOffset(offset, SWT.DEFAULT);
+       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) {
+               setCaretOffset(selection.y, SWT.DEFAULT);
+               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) {
+               setCaretOffset(selection.x, SWT.DEFAULT);
+               showCaret();
+       } else {
+               doSelectionWordPrevious();
+       }
+}
+/**
+ * Ends the autoscroll process.
+ */
+void endAutoScroll() {
+       autoScrollDirection = SWT.NULL;
+}
+@Override
+public Color getBackground() {
+       checkWidget();
+       if (background == null) {
+               return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+       }
+       return background;
+}
+/**
+ * Returns the baseline, in points.
+ *
+ * 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 points.
+ *
+ * @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 (&lt; 0 or &gt; 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.
+ */
+@Deprecated
+public boolean getBidiColoring() {
+       checkWidget();
+       return bidiColoring;
+}
+/**
+ * Returns whether the widget is in block selection mode.
+ *
+ * @return true if widget is in block selection mode, 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.5
+ */
+public boolean getBlockSelection() {
+       checkWidget();
+       return blockSelection;
+}
+Rectangle getBlockSelectionPosition() {
+       int firstLine = getLineIndex(blockYAnchor - getVerticalScrollOffset());
+       int lastLine = getLineIndex(blockYLocation - getVerticalScrollOffset());
+       if (firstLine > lastLine) {
+               int temp = firstLine;
+               firstLine = lastLine;
+               lastLine = temp;
+       }
+       int left = blockXAnchor;
+       int right = blockXLocation;
+       if (left > right) {
+               left = blockXLocation;
+               right = blockXAnchor;
+       }
+       return new Rectangle (left - horizontalScrollOffset, firstLine, right - horizontalScrollOffset, lastLine);
+}
+/**
+ * Returns the block selection bounds. The bounds is
+ * relative to the upper left corner of the document.
+ *
+ * @return the block selection bounds
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public Rectangle getBlockSelectionBounds() {
+       Rectangle rect;
+       if (blockSelection && blockXLocation != -1) {
+               rect = getBlockSelectionRectangle();
+       } else {
+               Point startPoint = getPointAtOffset(selection.x);
+               Point endPoint = getPointAtOffset(selection.y);
+               int height = getLineHeight(selection.y);
+               rect = new Rectangle(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y + height - startPoint.y);
+               if (selection.x == selection.y) {
+                       rect.width = getCaretWidth();
+               }
+       }
+       rect.x += horizontalScrollOffset;
+       rect.y += getVerticalScrollOffset();
+       return rect;
+}
+Rectangle getBlockSelectionRectangle() {
+       Rectangle rect = getBlockSelectionPosition();
+       rect.y = getLinePixel(rect.y);
+       rect.width = rect.width - rect.x;
+       rect.height =  getLinePixel(rect.height + 1) - rect.y;
+       return rect;
+}
+String getBlockSelectionText(String delimiter) {
+       Rectangle rect = getBlockSelectionPosition();
+       int firstLine = rect.y;
+       int lastLine = rect.height;
+       int left = rect.x;
+       int right = rect.width;
+       StringBuilder buffer = new StringBuilder();
+       for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
+               int start = getOffsetAtPoint(left, 0, lineIndex, null);
+               int end = getOffsetAtPoint(right, 0, lineIndex, null);
+               if (start > end) {
+                       int temp = start;
+                       start = end;
+                       end = temp;
+               }
+               String text = content.getTextRange(start, end - start);
+               buffer.append(text);
+               if (lineIndex < lastLine) buffer.append(delimiter);
+       }
+       return buffer.toString();
+}
+/**
+ * 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 != 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;
+}
+/**
+ * Returns the bottom margin.
+ *
+ * @return the bottom margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public int getBottomMargin() {
+       checkWidget();
+       return bottomMargin;
+}
+Rectangle getBoundsAtOffset(int offset) {
+       int lineIndex = content.getLineAtOffset(offset);
+       int lineOffset = content.getOffsetAtLine(lineIndex);
+       String line = content.getLine(lineIndex);
+       Rectangle bounds;
+       if (line.length() != 0) {
+               TextLayout layout = renderer.getTextLayout(lineIndex);
+               int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset));
+               bounds = layout.getBounds(offsetInLine, offsetInLine);
+               if (getListeners(ST.LineGetSegments).length > 0 && caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) {
+                       offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+                       Point point = layout.getLocation(offsetInLine, true);
+                       bounds = new Rectangle (point.x, point.y, 0, bounds.height);
+               }
+               renderer.disposeTextLayout(layout);
+       } else {
+               bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
+       }
+       if (offset == caretOffset && !isWordWrap()) {
+               int lineEnd = lineOffset + line.length();
+               if (offset == lineEnd) {
+                       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 == 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;
+}
+@Override
+public boolean 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 boolean 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 boolean getEditable() {
+       checkWidget();
+       return editable;
+}
+@Override
+public Color getForeground() {
+       checkWidget();
+       if (foreground == 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 &gt; 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 SWT logical point starting at 0, if &gt; 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 boolean 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();
+       Integer action = keyActionMap.get(key);
+       return action == null ? SWT.NULL : action.intValue();
+}
+/**
+ * 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 (&lt; 0 or &gt;= 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 &lt;= offset &lt;= 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 (&lt; 0 or &gt; 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(ST.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(ST.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(ST.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 != 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 points.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 points
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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 (&lt; 0 or &gt; 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(ST.LineGetStyle) ? 0 : renderer.getLineIndent(index, indent);
+}
+/**
+ * Returns the vertical indentation of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line vertical 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>
+ *
+ * @since 3.109
+ */
+public int getLineVerticalIndent(int index) {
+       checkWidget();
+       if (index < 0 || index >= content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       return isListening(ST.LineGetStyle) ? 0 : renderer.getLineVerticalIndent(index);
+}
+/**
+ * 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 boolean getLineJustify(int index) {
+       checkWidget();
+       if (index < 0 || index > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       return isListening(ST.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(ST.LineGetStyle, lineOffset, line);
+}
+/**
+ * Returns the top SWT logical point, 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 == lineCount it returns the bottom SWT logical point of the last line.
+ * It means this function can be used to retrieve the bottom SWT logical point of any line.
+ *
+ * @return the top SWT logical point 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 == 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 point
+ *
+ * @return the line index for a given y-coordinate point
+ *
+ * @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 == 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 tab stops of the line at the given <code>index</code>.
+ *
+ * @param index the index of the line
+ *
+ * @return the tab stops for 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>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT when the index is invalid</li>
+ * </ul>
+ *
+ * @see #getTabStops()
+ *
+ * @since 3.6
+ */
+public int[] getLineTabStops(int index) {
+       checkWidget();
+       if (index < 0 || index > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (isListening(ST.LineGetStyle)) return null;
+       int[] tabs = renderer.getLineTabStops(index, null);
+       if (tabs == null) tabs = this.tabs;
+       if (tabs == null) return new int [] {renderer.tabWidth};
+       int[] result = new int[tabs.length];
+       System.arraycopy(tabs, 0, result, 0, tabs.length);
+       return result;
+}
+/**
+ * Returns the wrap indentation of the line at the given <code>index</code>.
+ *
+ * @param index the index of the line
+ *
+ * @return the wrap 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 #getWrapIndent()
+ *
+ * @since 3.6
+ */
+public int getLineWrapIndent(int index) {
+       checkWidget();
+       if (index < 0 || index > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       return isListening(ST.LineGetStyle) ? 0 : renderer.getLineWrapIndent(index, wrapIndent);
+}
+/**
+ * Returns the left margin.
+ *
+ * @return the left margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public int getLeftMargin() {
+       checkWidget();
+       return leftMargin - alignmentMargin;
+}
+/**
+ * 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 &lt;= offset &lt;= 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 (&lt; 0 or &gt; getCharCount())</li>
+ * </ul>
+ */
+public Point getLocationAtOffset(int offset) {
+       checkWidget();
+       if (offset < 0 || offset > getCharCount()) {
+               SWT.error(SWT.ERROR_INVALID_RANGE);
+       }
+       return getPointAtOffset(offset);
+}
+/**
+ * Returns <code>true</code> if the mouse navigator is enabled.
+ * When mouse navigator is enabled, the user can navigate through the widget by pressing the middle button and moving the cursor
+ *
+ * @return the mouse navigator'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
+ * @since 3.110
+ */
+public boolean getMouseNavigatorEnabled () {
+       checkWidget ();
+       return mouseNavigator != null;
+}
+/**
+ * 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 &lt;= lineIndex &lt; 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 (&lt; 0 or &gt;= 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>
+ *
+ * @deprecated Use {@link #getOffsetAtPoint(Point)} instead for better performance
+ */
+@Deprecated
+public int getOffsetAtLocation(Point point) {
+       checkWidget();
+       if (point == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       int[] trailing = new int[1];
+       int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
+       if (offset == -1) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       return offset + trailing[0];
+}
+
+/**
+ * Returns the offset of the character at the given point 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 point.
+ * If the x coordinate of the point is beyond the center of a character
+ * the returned offset will be behind the character.
+ * </p>
+ * Note: This method is functionally similar to {@link #getOffsetAtLocation(Point)} except that
+ * it does not throw an exception when no character is found and thus performs faster.
+ *
+ * @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 point relative
+ *  to the first character in the document.
+ * -1 when there is no character at the specified 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>
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_NULL_ARGUMENT when point is <code>null</code></li>
+ * </ul>
+ *
+ * @since 3.107
+ */
+public int getOffsetAtPoint(Point point) {
+       checkWidget();
+       if (point == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       int[] trailing = new int[1];
+       int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
+       return offset != -1 ? offset + trailing[0] : -1;
+}
+
+int getOffsetAtPoint(int x, int y, int[] alignment) {
+       int lineIndex = getLineIndex(y);
+       y -= getLinePixel(lineIndex);
+       return getOffsetAtPoint(x, y, lineIndex, alignment);
+}
+int getOffsetAtPoint(int x, int y, int lineIndex, int[] alignment) {
+       TextLayout layout = renderer.getTextLayout(lineIndex);
+       x += horizontalScrollOffset - leftMargin;
+       int[] trailing = new int[1];
+       int offsetInLine = layout.getOffset(x, y, trailing);
+       if (alignment != null) alignment[0] = OFFSET_LEADING;
+       if (trailing[0] != 0) {
+               int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
+               int lineStart = layout.getLineOffsets()[lineInParagraph];
+               if (offsetInLine + trailing[0] == lineStart) {
+                       offsetInLine += trailing[0];
+                       if (alignment != null) alignment[0] = PREVIOUS_OFFSET_TRAILING;
+               } else {
+                       String line = content.getLine(lineIndex);
+                       int level = 0;
+                       if (alignment != null) {
+                               int offset = offsetInLine;
+                               while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
+                               if (offset == 0 && Character.isDigit(line.charAt(offset))) {
+                                       level = isMirrored() ? 1 : 0;
+                               } else {
+                                       level = layout.getLevel(offset) & 0x1;
+                               }
+                       }
+                       offsetInLine += trailing[0];
+                       if (alignment != null) {
+                               int trailingLevel = layout.getLevel(offsetInLine) & 0x1;
+                               if (level != trailingLevel) {
+                                       alignment[0] = PREVIOUS_OFFSET_TRAILING;
+                               } else {
+                                       alignment[0] = OFFSET_LEADING;
+                               }
+                       }
+               }
+       }
+       renderer.disposeTextLayout(layout);
+       return offsetInLine + content.getOffsetAtLine(lineIndex);
+}
+int getOffsetAtPoint(int x, int y, int[] trailing, boolean 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
+ */
+@Override
+public int getOrientation () {
+       return super.getOrientation ();
+}
+/**
+ * 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, boolean)</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(boolean)
+ */
+public int[] getRanges() {
+       checkWidget();
+       if (!isListening(ST.LineGetStyle)) {
+               int[] ranges = renderer.getRanges(0, content.getCharCount());
+               if (ranges != 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, boolean)</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, boolean)
+ */
+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(ST.LineGetStyle)) {
+               int[] ranges = renderer.getRanges(start, length);
+               if (ranges != null) return ranges;
+       }
+       return new int[0];
+}
+/**
+ * Returns the right margin.
+ *
+ * @return the right margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public int getRightMargin() {
+       checkWidget();
+       return rightMargin;
+}
+/**
+ * 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
+ *  &lt;= 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 == 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 == 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 ranges of text that are inside the block selection rectangle.
+ * <p>
+ * The ranges array contains start and length pairs. When the receiver is not
+ * in block selection mode the return arrays contains the start and length of
+ * the regular selection.
+ *
+ * @return the ranges 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>
+ * </ul>
+ *
+ * @since 3.5
+ */
+public int[] getSelectionRanges() {
+       checkWidget();
+       if (blockSelection && blockXLocation != -1) {
+               Rectangle rect = getBlockSelectionPosition();
+               int firstLine = rect.y;
+               int lastLine = rect.height;
+               int left = rect.x;
+               int right = rect.width;
+               int[] ranges = new int[(lastLine - firstLine + 1) * 2];
+               int index = 0;
+               for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
+                       int start = getOffsetAtPoint(left, 0, lineIndex, null);
+                       int end = getOffsetAtPoint(right, 0, lineIndex, null);
+                       if (start > end) {
+                               int temp = start;
+                               start = end;
+                               end = temp;
+                       }
+                       ranges[index++] = start;
+                       ranges[index++] = end - start;
+               }
+               return ranges;
+       }
+       return new int[] {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 == 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();
+       if (blockSelection && blockXLocation != -1) {
+               return getBlockSelectionText(content.getLineDelimiter()).length();
+       }
+       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 == 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();
+       if (blockSelection && blockXLocation != -1) {
+               return getBlockSelectionText(content.getLineDelimiter());
+       }
+       return content.getTextRange(selection.x, selection.y - selection.x);
+}
+StyledTextEvent getBidiSegments(int lineOffset, String line) {
+       if (!isListening(ST.LineGetSegments)) {
+               if (!bidiColoring) return null;
+               StyledTextEvent event = new StyledTextEvent(content);
+               event.segments = getBidiSegmentsCompatibility(line, lineOffset);
+               return event;
+       }
+       StyledTextEvent event = sendLineEvent(ST.LineGetSegments, lineOffset, line);
+       if (event == null || event.segments == null || event.segments.length == 0) return null;
+       int lineLength = line.length();
+       int[] segments = event.segments;
+       if (segments[0] > lineLength) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       char[] segmentsChars = event.segmentsChars;
+       boolean hasSegmentsChars = segmentsChars != null;
+       for (int i = 1; i < segments.length; i++) {
+               if ((hasSegmentsChars ? segments[i] < segments[i - 1] : segments[i] <= segments[i - 1]) || segments[i] > lineLength) {
+                       SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       if (hasSegmentsChars && !visualWrap) {
+               for (int i= 0; i < segmentsChars.length; i++) {
+                       if (segmentsChars[i] == '\n' || segmentsChars[i] == '\r') {
+                               visualWrap = true;
+                               break;
+                       }
+               }
+       }
+       return event;
+}
+/**
+ * @see #getBidiSegments
+ * Supports deprecated setBidiColoring API. Remove when API is removed.
+ */
+int [] getBidiSegmentsCompatibility(String line, int lineOffset) {
+       int lineLength = line.length();
+       StyleRange [] styles = null;
+       StyledTextEvent event = getLineStyleData(lineOffset, line);
+       if (event != null) {
+               styles = event.styles;
+       } else {
+               styles = renderer.getStyleRanges(lineOffset, lineLength, true);
+       }
+       if (styles == null || styles.length == 0) {
+               return new int[] {0, lineLength};
+       }
+       int k=0, count = 1;
+       while (k < styles.length && styles[k].start == 0 && styles[k].length == 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 == 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 &lt;= offset &lt; getCharCount() must be true.
+ * @return a StyleRange with start == offset and length == 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(ST.LineGetStyle)) {
+               StyleRange[] ranges = renderer.getStyleRanges(offset, 1, true);
+               if (ranges != 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(boolean)</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(boolean)
+ */
+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(boolean 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, boolean)</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 &gt;= start
+ *  and the last returned <code>StyleRange</code> will have an ending
+ *  offset &lt;= 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, boolean)
+ *
+ * @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 &gt;= start
+ *  and the last returned <code>StyleRange</code> will have an ending
+ *  offset &gt;= 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, boolean includeRanges) {
+       checkWidget();
+       int contentLength = getCharCount();
+       int end = start + length;
+       if (start > end || start < 0 || end > contentLength) {
+               SWT.error(SWT.ERROR_INVALID_RANGE);
+       }
+       if (!isListening(ST.LineGetStyle)) {
+               StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges);
+               if (ranges != 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>
+ *
+ * @see #getTabStops()
+ */
+public int getTabs() {
+       checkWidget();
+       return tabLength;
+}
+
+/**
+ * Returns the tab list of the receiver.
+ *
+ * @return the tab 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>
+ *
+ * @since 3.6
+ */
+public int[] getTabStops() {
+       checkWidget();
+       if (tabs == null) return new int [] {renderer.tabWidth};
+       int[] result = new int[tabs.length];
+       System.arraycopy(tabs, 0, result, 0, tabs.length);
+       return result;
+}
+
+/**
+ * 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 == lineStart) {
+                               if (i == lineEnd) {
+                                       rect = layout.getBounds(start - lineOffset, end - lineOffset);
+                               } else {
+                                       rect = layout.getBounds(start - lineOffset, length);
+                               }
+                               y += rect.y;
+                       } else if (i == 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;
+}
+/**
+ * Returns the top margin.
+ *
+ * @return the top margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public int getTopMargin() {
+       checkWidget();
+       return topMargin;
+}
+/**
+ * Gets the top SWT logical point.
+ * <p>
+ * The top point is the SWT logical point position of the line that is
+ * currently at the top of the widget. The text widget can be scrolled by points
+ * by dragging the scroll thumb so that a partial line may be displayed at the top
+ * the widget.  The top point changes when the widget is scrolled.  The top point
+ * does not include the widget trimming.
+ * </p>
+ *
+ * @return SWT logical point 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 == -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();
+       Caret caret = getCaret();
+       if (caret != null && lineIndex != 0 && offsetInLine == offsets[lineIndex]) {
+               int lineY = layout.getLineBounds(lineIndex).y;
+               int caretY = caret.getLocation().y - getLinePixel(getCaretLine());
+               if (lineY > caretY) lineIndex--;
+               caretAlignment = OFFSET_LEADING;
+       }
+       return lineIndex;
+}
+int getCaretDirection() {
+       if (!isBidiCaret()) return SWT.DEFAULT;
+       if (ime.getCompositionOffset() != -1) return SWT.DEFAULT;
+       if (!updateCaretDirection && caretDirection != 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 == 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT;
+       if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offset > 0) offset--;
+       if (offset == lineLength && offset > 0) offset--;
+       while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
+       if (offset == 0 && Character.isDigit(line.charAt(offset))) {
+               return isMirrored() ? SWT.RIGHT : SWT.LEFT;
+       }
+       TextLayout layout = renderer.getTextLayout(caretLine);
+       int level = layout.getLevel(offset);
+       renderer.disposeTextLayout(layout);
+       return ((level & 1) != 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;
+               return width > 0 ? width : 1;
+       }
+       return -1;
+}
+int getWordNext (int offset, int movement) {
+       return getWordNext(offset, movement, false);
+}
+int getWordNext (int offset, int movement, boolean ignoreListener) {
+       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 >= lineOffset + lineLength) {
+                       newOffset = content.getOffsetAtLine(lineIndex + 1);
+               } else {
+                       TextLayout layout = renderer.getTextLayout(lineIndex);
+                       newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement);
+                       renderer.disposeTextLayout(layout);
+               }
+       }
+       if (ignoreListener) return newOffset;
+       return sendWordBoundaryEvent(ST.WordNext, movement, offset, newOffset, lineText, lineOffset);
+}
+int getWordPrevious(int offset, int movement) {
+       return getWordPrevious(offset, movement, false);
+}
+int getWordPrevious(int offset, int movement, boolean ignoreListener) {
+       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 == lineOffset) {
+                       String nextLineText = content.getLine(lineIndex - 1);
+                       int nextLineOffset = content.getOffsetAtLine(lineIndex - 1);
+                       newOffset = nextLineOffset + nextLineText.length();
+               } else {
+                       int layoutOffset = Math.min(offset - lineOffset, lineText.length());
+                       TextLayout layout = renderer.getTextLayout(lineIndex);
+                       newOffset = lineOffset + layout.getPreviousOffset(layoutOffset, movement);
+                       renderer.disposeTextLayout(layout);
+               }
+       }
+       if (ignoreListener) return newOffset;
+       return sendWordBoundaryEvent(ST.WordPrevious, movement, offset, newOffset, lineText, lineOffset);
+}
+/**
+ * Returns whether the widget wraps lines.
+ *
+ * @return true if widget wraps lines, false otherwise
+ * @since 2.0
+ */
+public boolean getWordWrap() {
+       checkWidget();
+       return wordWrap;
+}
+/**
+ * Returns the wrap indentation of the widget.
+ *
+ * @return the wrap 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 #getLineWrapIndent(int)
+ *
+ * @since 3.6
+ */
+public int getWrapIndent() {
+       checkWidget();
+       return wrapIndent;
+}
+/**
+ * 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 = Math.max (0, 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 != 0  && offsetInLine <= lineLength) {
+               if (offsetInLine == lineLength) {
+                       offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+                       point = layout.getLocation(offsetInLine, true);
+               } else {
+                       switch (caretAlignment) {
+                               case OFFSET_LEADING:
+                                       point = layout.getLocation(offsetInLine, false);
+                                       break;
+                               case PREVIOUS_OFFSET_TRAILING:
+                               default:
+                                       boolean lineBegin = offsetInLine == 0;
+                                       // If word wrap is enabled, we should also consider offsets
+                                       // of wrapped line parts as line begin and do NOT go back.
+                                       // This prevents clients to jump one line higher than
+                                       // expected, see bug 488172.
+                                       // Respect caretAlignment at the caretOffset, unless there's
+                                       // a non-empty selection, see bug 488172 comment 6.
+                                       if (wordWrap && !lineBegin && (offset != caretOffset || selection.x != selection.y)) {
+                                               int[] offsets = layout.getLineOffsets();
+                                               for (int i : offsets) {
+                                                       if (i == offsetInLine) {
+                                                               lineBegin = true;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if (lineBegin) {
+                                               point = layout.getLocation(offsetInLine, false);
+                                       } else {
+                                               offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+                                               point = layout.getLocation(offsetInLine, true);
+                                       }
+                                       break;
+                       }
+               }
+       } else {
+               point = new Point(layout.getIndent(), layout.getVerticalIndent());
+       }
+       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>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when string is null</li>
+ * </ul>
+ */
+public void insert(String string) {
+       checkWidget();
+       if (string == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       if (blockSelection) {
+               insertBlockSelectionText(string, false);
+       } else {
+               Point sel = getSelectionRange();
+               replaceTextRange(sel.x, sel.y, string);
+       }
+}
+int insertBlockSelectionText(String text, boolean fillWithSpaces) {
+       int lineCount = 1;
+       for (int i = 0; i < text.length(); i++) {
+               char ch = text.charAt(i);
+               if (ch == '\n' || ch == '\r') {
+                       lineCount++;
+                       if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
+                               i++;
+                       }
+               }
+       }
+       String[] lines = new String[lineCount];
+       int start = 0;
+       lineCount = 0;
+       for (int i = 0; i < text.length(); i++) {
+               char ch = text.charAt(i);
+               if (ch == '\n' || ch == '\r') {
+                       lines[lineCount++] = text.substring(start, i);
+                       if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
+                               i++;
+                       }
+                       start = i + 1;
+               }
+       }
+       lines[lineCount++] = text.substring(start);
+       if (fillWithSpaces) {
+               int maxLength = 0;
+               for (int i = 0; i < lines.length; i++) {
+                       int length = lines[i].length();
+                       maxLength = Math.max(maxLength, length);
+               }
+               for (int i = 0; i < lines.length; i++) {
+                       String line = lines[i];
+                       int length = line.length();
+                       if (length < maxLength) {
+                               int numSpaces = maxLength - length;
+                               StringBuilder buffer = new StringBuilder(length + numSpaces);
+                               buffer.append(line);
+                               for (int j = 0; j < numSpaces; j++) buffer.append(' ');
+                               lines[i] = buffer.toString();
+                       }
+               }
+       }
+       int firstLine, lastLine, left, right;
+       if (blockXLocation != -1) {
+               Rectangle rect = getBlockSelectionPosition();
+               firstLine = rect.y;
+               lastLine = rect.height;
+               left = rect.x;
+               right = rect.width;
+       } else {
+               firstLine = lastLine = getCaretLine();
+               left = right = getPointAtOffset(caretOffset).x;
+       }
+       start = caretOffset;
+       int caretLine = getCaretLine();
+       int index = 0, lineIndex = firstLine;
+       while (lineIndex <= lastLine) {
+               String string = index < lineCount ? lines[index++] : "";
+               int lineStart = sendTextEvent(left, right, lineIndex, string, fillWithSpaces);
+               if (lineIndex == caretLine) start = lineStart;
+               lineIndex++;
+       }
+       while (index < lineCount) {
+               int lineStart = sendTextEvent(left, left, lineIndex, lines[index++], fillWithSpaces);
+               if (lineIndex == caretLine) start = lineStart;
+               lineIndex++;
+       }
+       return start;
+}
+void insertBlockSelectionText(char key, int action) {
+       if (key == SWT.CR || key == SWT.LF) return;
+       Rectangle rect = getBlockSelectionPosition();
+       int firstLine = rect.y;
+       int lastLine = rect.height;
+       int left = rect.x;
+       int right = rect.width;
+       int[] trailing = new int[1];
+       int offset = 0, delta = 0;
+       String text = key != 0 ? new String(new char[] {key}) : "";
+       int length = text.length();
+       for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
+               String line = content.getLine(lineIndex);
+               int lineOffset = content.getOffsetAtLine(lineIndex);
+               int lineEndOffset = lineOffset + line.length();
+               int linePixel = getLinePixel(lineIndex);
+               int start = getOffsetAtPoint(left, linePixel, trailing, true);
+               boolean outOfLine = start == -1;
+               if (outOfLine) {
+                       start = left < leftMargin ? lineOffset : lineEndOffset;
+               } else {
+                       start += trailing[0];
+               }
+               int end = getOffsetAtPoint(right, linePixel, trailing, true);
+               if (end == -1) {
+                       end = right < leftMargin ? lineOffset : lineEndOffset;
+               } else {
+                       end += trailing[0];
+               }
+               if (start > end) {
+                       int temp = start;
+                       start = end;
+                       end = temp;
+               }
+               if (start == end && !outOfLine) {
+                       switch (action) {
+                               case ST.DELETE_PREVIOUS:
+                                       if (start > lineOffset) start = getClusterPrevious(start, lineIndex);
+                                       break;
+                               case ST.DELETE_NEXT:
+                                       if (end < lineEndOffset) end = getClusterNext(end, lineIndex);
+                                       break;
+                       }
+               }
+               if (outOfLine) {
+                       if (line.length() >= delta) {
+                               delta = line.length();
+                               offset = lineEndOffset + length;
+                       }
+               } else {
+                       offset = start + length;
+                       delta = content.getCharCount();
+               }
+               Event event = new Event();
+               event.text = text;
+               event.start = start;
+               event.end = end;
+               sendKeyEvent(event);
+       }
+       int x = getPointAtOffset(offset).x;
+       int verticalScrollOffset = getVerticalScrollOffset();
+       setBlockSelectionLocation(x, blockYAnchor - verticalScrollOffset, x, blockYLocation - verticalScrollOffset, false);
+}
+/**
+ * Creates content change listeners and set the default content model.
+ */
+void installDefaultContent() {
+       textChangeListener = new TextChangeListener() {
+               @Override
+               public void textChanging(TextChangingEvent event) {
+                       handleTextChanging(event);
+               }
+               @Override
+               public void textChanged(TextChangedEvent event) {
+                       handleTextChanged(event);
+               }
+               @Override
+               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 = event -> {
+               switch (event.type) {
+                       case SWT.Dispose: handleDispose(event); break;
+                       case SWT.KeyDown: handleKeyDown(event); break;
+                       case SWT.KeyUp: handleKeyUp(event); break;
+                       case SWT.MenuDetect: handleMenuDetect(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;
+               }
+       };
+       addListener(SWT.Dispose, listener);
+       addListener(SWT.KeyDown, listener);
+       addListener(SWT.KeyUp, listener);
+       addListener(SWT.MenuDetect, 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, event -> {
+               if (!editable) {
+                       event.doit = false;
+                       event.start = 0;
+                       event.end = 0;
+                       event.text = "";
+                       return;
+               }
+
+               switch (event.detail) {
+                       case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break;
+                       case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break;
+                       case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break;
+               }
+       });
+       if (verticalBar != null) {
+               verticalBar.addListener(SWT.Selection, event -> handleVerticalScroll(event));
+       }
+       if (horizontalBar != null) {
+               horizontalBar.addListener(SWT.Selection, 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 (isWordWrap() && startIndex > 0 && offsets[startIndex] == 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 == endLine) {
+               int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
+               if (startIndex == 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 == 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 != 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 == 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) {
+       if (event.start != event.end) {
+               int charCount = getCharCount();
+               event.start = Math.max(0, Math.min(event.start, charCount));
+               event.end = Math.max(0, Math.min(event.end, charCount));
+               if (event.text != null) {
+                       setSelection(event.start, event.end);
+               } else {
+                       event.text = getTextRange(event.start, event.end - event.start);
+               }
+       } else {
+               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 charCount = content.getCharCount();
+       start = Math.min(start, charCount);
+       end = Math.min(end, charCount);
+       int length = text.length();
+       if (length == ime.getCommitCount()) {
+               content.replaceTextRange(start, end - start, "");
+               setCaretOffset(ime.getCompositionOffset(), SWT.DEFAULT);
+               caretWidth = 0;
+               caretDirection = SWT.NULL;
+       } else {
+               content.replaceTextRange(start, end - start, text);
+               int alignment = SWT.DEFAULT;
+               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);
+                       alignment = OFFSET_LEADING;
+               }
+               setCaretOffset(ime.getCaretOffset(), alignment);
+       }
+       resetSelection();
+       showCaret();
+}
+/**
+ * Frees resources.
+ */
+void handleDispose(Event event) {
+       removeListener(SWT.Dispose, listener);
+       notifyListeners(SWT.Dispose, event);
+       event.type = SWT.None;
+
+       clipboard.dispose();
+       if (renderer != null) {
+               renderer.dispose();
+               renderer = null;
+       }
+       if (content != null) {
+               content.removeTextChangeListener(textChangeListener);
+               content = null;
+       }
+       if (defaultCaret != null) {
+               defaultCaret.dispose();
+               defaultCaret = null;
+       }
+       if (leftCaretBitmap != null) {
+               leftCaretBitmap.dispose();
+               leftCaretBitmap = null;
+       }
+       if (rightCaretBitmap != null) {
+               rightCaretBitmap.dispose();
+               rightCaretBitmap = null;
+       }
+       if (isBidiCaret()) {
+               BidiUtil.removeLanguageListener(this);
+       }
+       selectionBackground = null;
+       selectionForeground = null;
+       marginColor = null;
+       textChangeListener = null;
+       selection = null;
+       doubleClickSelection = null;
+       keyActionMap = null;
+       background = null;
+       foreground = null;
+       clipboard = null;
+       tabs = 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 != 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 == SWT.NULL) {
+                       // see if we have a control character
+                       if ((event.stateMask & SWT.CTRL) != 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 == SWT.NULL) {
+               boolean ignore = false;
+
+               if (IS_MAC) {
+                       // Ignore accelerator key combinations (we do not want to
+                       // insert a character in the text in this instance).
+                       ignore = (event.stateMask & (SWT.COMMAND | SWT.CTRL)) != 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 ||
+                                       event.stateMask == SWT.CTRL ||
+                                       event.stateMask == (SWT.ALT | SWT.SHIFT) ||
+                                       event.stateMask == (SWT.CTRL | SWT.SHIFT);
+               }
+               // -ignore anything below SPACE except for line delimiter keys and tab.
+               // -ignore DEL
+               if (!ignore && event.character > 31 && event.character != SWT.DEL ||
+                       event.character == SWT.CR || event.character == SWT.LF ||
+                       event.character == 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 == null) {
+               clipboardSelection = new Point(selection.x, selection.y);
+       }
+       newOrientation = SWT.NONE;
+       event.stateMask &= SWT.MODIFIER_MASK;
+
+       Event verifyEvent = new Event();
+       verifyEvent.character = event.character;
+       verifyEvent.keyCode = event.keyCode;
+       verifyEvent.keyLocation = event.keyLocation;
+       verifyEvent.stateMask = event.stateMask;
+       verifyEvent.doit = event.doit;
+       notifyListeners(ST.VerifyKey, verifyEvent);
+       if (verifyEvent.doit) {
+               if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL && event.keyCode == SWT.SHIFT && isBidiCaret()) {
+                       newOrientation = event.keyLocation == SWT.LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
+               }
+               handleKey(event);
+       }
+}
+/**
+ * Update the Selection Clipboard.
+ *
+ * @param event keyboard event
+ */
+void handleKeyUp(Event event) {
+       if (clipboardSelection != null) {
+               if (clipboardSelection.x != selection.x || clipboardSelection.y != selection.y) {
+                       copySelection(DND.SELECTION_CLIPBOARD);
+               }
+       }
+       clipboardSelection = null;
+
+       if (newOrientation != SWT.NONE) {
+               if (newOrientation != getOrientation()) {
+                       Event e = new Event();
+                       e.doit = true;
+                       notifyListeners(SWT.OrientationChange, e);
+                       if (e.doit) {
+                               setOrientation(newOrientation);
+                       }
+               }
+               newOrientation = SWT.NONE;
+       }
+}
+/**
+ * Update the event location for focus-based context menu triggers.
+ *
+ * @param event menu detect event
+ */
+void handleMenuDetect(Event event) {
+       if (event.detail == SWT.MENU_KEYBOARD) {
+               Point point = getDisplay().map(this, null, getPointAtOffset(caretOffset));
+               event.x = point.x;
+               event.y = point.y + getLineHeight(caretOffset);
+       }
+}
+/**
+ * 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 == 2) {
+               // On GTK, if mouseNavigator is enabled we have to distinguish a short middle-click (to paste content) from
+               // a long middle-click (mouse navigation started)
+               if (IS_GTK && mouseNavigator != null) {
+                       middleClickPressed = true;
+                       getDisplay().timerExec(200, ()->{
+                               boolean click = middleClickPressed;
+                               middleClickPressed = false;
+                               if (click && mouseNavigator !=null) {
+                                       mouseNavigator.onMouseDown(event);
+                               } else {
+                                       pasteOnMiddleClick(event);
+                               }
+                       });
+                       return;
+               } else {
+                       pasteOnMiddleClick(event);
+               }
+       }
+
+       //set selection
+       if ((event.button != 1) || (IS_MAC && (event.stateMask & SWT.MOD4) != 0)) {
+               return;
+       }
+       clickCount = event.count;
+       if (clickCount == 1) {
+               boolean select = (event.stateMask & SWT.MOD2) != 0;
+               doMouseLocationChange(event.x, event.y, select);
+       } else {
+               if (doubleClickEnabled) {
+                       boolean wordSelect = (clickCount & 1) == 0;
+                       int offset = getOffsetAtPoint(event.x, event.y, null);
+                       int lineIndex = content.getLineAtOffset(offset);
+                       int lineOffset = content.getOffsetAtLine(lineIndex);
+                       if (wordSelect) {
+                               int min = blockSelection ? lineOffset : 0;
+                               int max = blockSelection ? lineOffset + content.getLine(lineIndex).length() : content.getCharCount();
+                               int start = Math.max(min, getWordPrevious(offset, SWT.MOVEMENT_WORD_START));
+                               int end = Math.min(max, getWordNext(start, SWT.MOVEMENT_WORD_END));
+                               setSelection(start, end - start, false, true);
+                               sendSelectionEvent();
+                       } else {
+                               if (blockSelection) {
+                                       setBlockSelectionLocation(leftMargin, event.y, clientAreaWidth - rightMargin, event.y, true);
+                               } else {
+                                       int lineEnd = content.getCharCount();
+                                       if (lineIndex + 1 < content.getLineCount()) {
+                                               lineEnd = content.getOffsetAtLine(lineIndex + 1);
+                                       }
+                                       setSelection(lineOffset, lineEnd - lineOffset, false, false);
+                                       sendSelectionEvent();
+                               }
+                       }
+                       doubleClickSelection = new Point(selection.x, selection.y);
+                       showCaret();
+               }
+       }
+}
+/**
+ * Updates the caret location and selection if mouse button 1 is pressed
+ * during the mouse move.
+ */
+void handleMouseMove(Event event) {
+       if (clickCount > 0) {
+               update();
+               doAutoScroll(event);
+               doMouseLocationChange(event.x, event.y, true);
+       }
+       if (renderer.hasLinks) {
+               doMouseLinkCursor(event.x, event.y);
+       }
+}
+/**
+ * Autoscrolling ends when the mouse button is released.
+ */
+void handleMouseUp(Event event) {
+       middleClickPressed = false;
+       clickCount = 0;
+       endAutoScroll();
+       if (event.button == 1) {
+               copySelection(DND.SELECTION_CLIPBOARD);
+       }
+}
+/**
+ * Renders the invalidated area specified in the paint event.
+ *
+ * @param event paint event
+ */
+void handlePaint(Event event) {
+       if (event.width == 0 || event.height == 0) return;
+       if (clientAreaWidth == 0 || clientAreaHeight == 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);
+               }
+       }
+       if (blockSelection && blockXLocation != -1) {
+               gc.setBackground(getSelectionBackground());
+               Rectangle rect = getBlockSelectionRectangle();
+               gc.drawRectangle(rect.x, rect.y, Math.max(1, rect.width - 1), Math.max(1, rect.height - 1));
+               gc.setAdvanced(true);
+               if (gc.getAdvanced()) {
+                       gc.setAlpha(100);
+                       gc.fillRectangle(rect);
+                       gc.setAdvanced(false);
+               }
+       }
+
+       // fill the margin background
+       gc.setBackground(marginColor != null ? marginColor : background);
+       if (topMargin > 0) {
+               drawBackground(gc, 0, 0, clientAreaWidth, topMargin);
+       }
+       if (bottomMargin > 0) {
+               drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin);
+       }
+       if (leftMargin - alignmentMargin > 0) {
+               drawBackground(gc, 0, 0, leftMargin - alignmentMargin, 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;
+       if (!alwaysShowScroll && ignoreResize != 0) return;
+
+       redrawMargins(oldHeight, oldWidth);
+       if (wordWrap) {
+               if (oldWidth != clientAreaWidth) {
+                       renderer.reset(0, content.getLineCount());
+                       verticalScrollOffset = -1;
+                       renderer.calculateIdle();
+                       super.redraw();
+               }
+               if (oldHeight != clientAreaHeight) {
+                       if (oldHeight == 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 != 0) {
+                       ScrollBar horizontalBar = getHorizontalBar();
+                       if (horizontalBar != null && horizontalBar.getVisible()) {
+                               if (horizontalScrollOffset != horizontalBar.getSelection()) {
+                                       horizontalBar.setSelection(horizontalScrollOffset);
+                                       horizontalScrollOffset = horizontalBar.getSelection();
+                               }
+                       }
+               }
+       }
+       updateCaretVisibility();
+       claimBottomFreeSpace();
+       setAlignment();
+       //TODO FIX TOP INDEX DURING RESIZE
+//     if (oldHeight != 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 != -1 && lastTextChangeStart < offset) {
+               ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount);
+       }
+       int firstLine = content.getLineAtOffset(lastTextChangeStart);
+       resetCache(firstLine, 0);
+       if (!isFixedLineHeight() && topIndex > firstLine) {
+               topIndex = firstLine;
+               if (topIndex < 0) {
+                       // TODO: This logging is in place to determine why topIndex is getting set to negative values.
+                       // It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
+                       System.err.println("StyledText: topIndex was " + topIndex
+                                       + ", lastTextChangeStart = " + lastTextChangeStart
+                                       + ", content.getClass() = " + content.getClass()
+                                       );
+                       topIndex = 0;
+               }
+               topIndexY = 0;
+               super.redraw();
+       } else {
+               int lastLine = firstLine + lastTextChangeNewLineCount;
+               int firstLineTop = getLinePixel(firstLine);
+               int newLastLineBottom = getLinePixel(lastLine + 1);
+               if (lastLineBottom != 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.
+       if (!(blockSelection && blockXLocation != -1)) {
+               updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount);
+       }
+       if (lastTextChangeReplaceLineCount > 0 || wordWrap || visualWrap) {
+               claimBottomFreeSpace();
+       }
+       if (lastTextChangeReplaceCharCount > 0) {
+               claimRightFreeSpace();
+       }
+
+       sendAccessibleTextChanged(lastTextChangeStart, lastTextChangeNewCharCount, 0);
+       lastCharCount += lastTextChangeNewCharCount;
+       lastCharCount -= lastTextChangeReplaceCharCount;
+       setAlignment();
+}
+/**
+ * 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);
+       }
+       sendAccessibleTextChanged(lastTextChangeStart, 0, lastTextChangeReplaceCharCount);
+       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) setCaretOffset(newEndOfText, SWT.DEFAULT);
+}
+/**
+ * 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();
+       int newCharCount = getCharCount();
+       sendAccessibleTextChanged(0, newCharCount, lastCharCount);
+       lastCharCount = newCharCount;
+       setAlignment();
+}
+/**
+ * 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) != 0) {
+                               event.doit = true;
+                       } else {
+                               if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) {
+                                       event.doit = true;
+                               }
+                       }
+                       break;
+       }
+}
+/**
+ * Scrolls the widget vertically.
+ */
+void handleVerticalScroll(Event event) {
+       int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset();
+       scrollVertical(scrollPixel, false);
+}
+/**
+ * Add accessibility support for the widget.
+ */
+void initializeAccessible() {
+       acc = getAccessible();
+
+       accAdapter = new AccessibleAdapter() {
+               @Override
+               public void getName (AccessibleEvent e) {
+                       String name = null;
+                       String text = getAssociatedLabel ();
+                       if (text != null) {
+                               name = stripMnemonic (text);
+                       }
+                       e.result = name;
+               }
+               @Override
+               public void getHelp(AccessibleEvent e) {
+                       e.result = getToolTipText();
+               }
+               @Override
+               public void getKeyboardShortcut(AccessibleEvent e) {
+                       String shortcut = null;
+                       String text = getAssociatedLabel ();
+                       if (text != null) {
+                               char mnemonic = _findMnemonic (text);
+                               if (mnemonic != '\0') {
+                                       shortcut = "Alt+"+mnemonic; //$NON-NLS-1$
+                               }
+                       }
+                       e.result = shortcut;
+               }
+       };
+       acc.addAccessibleListener(accAdapter);
+
+       accTextExtendedAdapter = new AccessibleTextExtendedAdapter() {
+               @Override
+               public void getCaretOffset(AccessibleTextEvent e) {
+                       e.offset = StyledText.this.getCaretOffset();
+               }
+               @Override
+               public void setCaretOffset(AccessibleTextEvent e) {
+                       StyledText.this.setCaretOffset(e.offset);
+                       e.result = ACC.OK;
+               }
+               @Override
+               public void getSelectionRange(AccessibleTextEvent e) {
+                       Point selection = StyledText.this.getSelectionRange();
+                       e.offset = selection.x;
+                       e.length = selection.y;
+               }
+               @Override
+               public void addSelection(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       Point point = st.getSelection();
+                       if (point.x == point.y) {
+                               int end = e.end;
+                               if (end == -1) end = st.getCharCount();
+                               st.setSelection(e.start, end);
+                               e.result = ACC.OK;
+                       }
+               }
+               @Override
+               public void getSelection(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       if (st.blockSelection && st.blockXLocation != -1) {
+                               Rectangle rect = st.getBlockSelectionPosition();
+                               int lineIndex = rect.y + e.index;
+                               int linePixel = st.getLinePixel(lineIndex);
+                               e.ranges = getRanges(rect.x, linePixel, rect.width, linePixel);
+                               if (e.ranges.length > 0) {
+                                       e.start = e.ranges[0];
+                                       e.end = e.ranges[e.ranges.length - 1];
+                               }
+                       } else {
+                               if (e.index == 0) {
+                                       Point point = st.getSelection();
+                                       e.start = point.x;
+                                       e.end = point.y;
+                                       if (e.start > e.end) {
+                                               int temp = e.start;
+                                               e.start = e.end;
+                                               e.end = temp;
+                                       }
+                               }
+                       }
+               }
+               @Override
+               public void getSelectionCount(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       if (st.blockSelection && st.blockXLocation != -1) {
+                               Rectangle rect = st.getBlockSelectionPosition();
+                               e.count = rect.height - rect.y + 1;
+                       } else {
+                               Point point = st.getSelection();
+                               e.count = point.x == point.y ? 0 : 1;
+                       }
+               }
+               @Override
+               public void removeSelection(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       if (e.index == 0) {
+                               if (st.blockSelection) {
+                                       st.clearBlockSelection(true, false);
+                               } else {
+                                       st.clearSelection(false);
+                               }
+                               e.result = ACC.OK;
+                       }
+               }
+               @Override
+               public void setSelection(AccessibleTextEvent e) {
+                       if (e.index != 0) return;
+                       StyledText st = StyledText.this;
+                       Point point = st.getSelection();
+                       if (point.x == point.y) return;
+                       int end = e.end;
+                       if (end == -1) end = st.getCharCount();
+                       st.setSelection(e.start, end);
+                       e.result = ACC.OK;
+               }
+               @Override
+               public void getCharacterCount(AccessibleTextEvent e) {
+                       e.count = StyledText.this.getCharCount();
+               }
+               @Override
+               public void getOffsetAtPoint(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       Point point = new Point (e.x, e.y);
+                       Display display = st.getDisplay();
+                       point = display.map(null, st, point);
+                       e.offset = st.getOffsetAtPoint(point.x, point.y, null, true);
+               }
+               @Override
+               public void getTextBounds(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       int start = e.start;
+                       int end = e.end;
+                       int contentLength = st.getCharCount();
+                       start = Math.max(0, Math.min(start, contentLength));
+                       end = Math.max(0, Math.min(end, contentLength));
+                       if (start > end) {
+                               int temp = start;
+                               start = end;
+                               end = temp;
+                       }
+                       int startLine = st.getLineAtOffset(start);
+                       int endLine = st.getLineAtOffset(end);
+                       Rectangle[] rects = new Rectangle[endLine - startLine + 1];
+                       Rectangle bounds = null;
+                       int index = 0;
+                       Display display = st.getDisplay();
+                       for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
+                               Rectangle rect = new Rectangle(0, 0, 0, 0);
+                               rect.y = st.getLinePixel(lineIndex);
+                               rect.height = st.renderer.getLineHeight(lineIndex);
+                               if (lineIndex == startLine) {
+                                       rect.x = st.getPointAtOffset(start).x;
+                               } else {
+                                       rect.x = st.leftMargin - st.horizontalScrollOffset;
+                               }
+                               if (lineIndex == endLine) {
+                                       rect.width = st.getPointAtOffset(end).x - rect.x;
+                               } else {
+                                       TextLayout layout = st.renderer.getTextLayout(lineIndex);
+                                       rect.width = layout.getBounds().width - rect.x;
+                                       st.renderer.disposeTextLayout(layout);
+                               }
+                               rects [index++] = rect = display.map(st, null, rect);
+                               if (bounds == null) {
+                                       bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height);
+                               } else {
+                                       bounds.add(rect);
+                               }
+                       }
+                       e.rectangles = rects;
+                       if (bounds != null) {
+                               e.x = bounds.x;
+                               e.y = bounds.y;
+                               e.width = bounds.width;
+                               e.height = bounds.height;
+                       }
+               }
+               int[] getRanges(int left, int top, int right, int bottom) {
+                       StyledText st = StyledText.this;
+                       int lineStart = st.getLineIndex(top);
+                       int lineEnd = st.getLineIndex(bottom);
+                       int count = lineEnd - lineStart + 1;
+                       int[] ranges = new int [count * 2];
+                       int index = 0;
+                       for (int lineIndex = lineStart; lineIndex <= lineEnd; lineIndex++) {
+                               String line = st.content.getLine(lineIndex);
+                               int lineOffset = st.content.getOffsetAtLine(lineIndex);
+                               int lineEndOffset = lineOffset + line.length();
+                               int linePixel = st.getLinePixel(lineIndex);
+                               int start = st.getOffsetAtPoint(left, linePixel, null, true);
+                               if (start == -1) {
+                                       start = left < st.leftMargin ? lineOffset : lineEndOffset;
+                               }
+                               int[] trailing = new int[1];
+                               int end = st.getOffsetAtPoint(right, linePixel, trailing, true);
+                               if (end == -1) {
+                                       end = right < st.leftMargin ? lineOffset : lineEndOffset;
+                               } else {
+                                       end += trailing[0];
+                               }
+                               if (start > end) {
+                                       int temp = start;
+                                       start = end;
+                                       end = temp;
+                               }
+                               ranges[index++] = start;
+                               ranges[index++] = end;
+                       }
+                       return ranges;
+               }
+               @Override
+               public void getRanges(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       Point point = new Point (e.x, e.y);
+                       Display display = st.getDisplay();
+                       point = display.map(null, st, point);
+                       e.ranges = getRanges(point.x, point.y, point.x + e.width, point.y + e.height);
+                       if (e.ranges.length > 0) {
+                               e.start = e.ranges[0];
+                               e.end = e.ranges[e.ranges.length - 1];
+                       }
+               }
+               @Override
+               public void getText(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       int start = e.start;
+                       int end = e.end;
+                       int contentLength = st.getCharCount();
+                       if (end == -1) end = contentLength;
+                       start = Math.max(0, Math.min(start, contentLength));
+                       end = Math.max(0, Math.min(end, contentLength));
+                       if (start > end) {
+                               int temp = start;
+                               start = end;
+                               end = temp;
+                       }
+                       int count = e.count;
+                       switch (e.type) {
+                               case ACC.TEXT_BOUNDARY_ALL:
+                                       //nothing to do
+                                       break;
+                               case ACC.TEXT_BOUNDARY_CHAR: {
+                                       int newCount = 0;
+                                       if (count > 0) {
+                                               while (count-- > 0) {
+                                                       int newEnd = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
+                                                       if (newEnd == contentLength) break;
+                                                       if (newEnd == end) break;
+                                                       end = newEnd;
+                                                       newCount++;
+                                               }
+                                               start = end;
+                                               end = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
+                                       } else {
+                                               while (count++ < 0) {
+                                                       int newStart = st.getWordPrevious(start, SWT.MOVEMENT_CLUSTER);
+                                                       if (newStart == start) break;
+                                                       start = newStart;
+                                                       newCount--;
+                                               }
+                                               end = st.getWordNext(start, SWT.MOVEMENT_CLUSTER);
+                                       }
+                                       count = newCount;
+                                       break;
+                               }
+                               case ACC.TEXT_BOUNDARY_WORD: {
+                                       int newCount = 0;
+                                       if (count > 0) {
+                                               while (count-- > 0) {
+                                                       int newEnd = st.getWordNext(end, SWT.MOVEMENT_WORD_START, true);
+                                                       if (newEnd == end) break;
+                                                       newCount++;
+                                                       end = newEnd;
+                                               }
+                                               start = end;
+                                               end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
+                                       } else {
+                                               if (st.getWordPrevious(Math.min(start + 1, contentLength), SWT.MOVEMENT_WORD_START, true) == start) {
+                                                       //start is a word start already
+                                                       count++;
+                                               }
+                                               while (count <= 0) {
+                                                       int newStart = st.getWordPrevious(start, SWT.MOVEMENT_WORD_START, true);
+                                                       if (newStart == start) break;
+                                                       count++;
+                                                       start = newStart;
+                                                       if (count != 0) newCount--;
+                                               }
+                                               if (count <= 0 && start == 0) {
+                                                       end = start;
+                                               } else {
+                                                       end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
+                                               }
+                                       }
+                                       count = newCount;
+                                       break;
+                               }
+                               case ACC.TEXT_BOUNDARY_LINE:
+                                       //TODO implement line
+                               case ACC.TEXT_BOUNDARY_PARAGRAPH:
+                               case ACC.TEXT_BOUNDARY_SENTENCE: {
+                                       int offset = count > 0 ? end : start;
+                                       int lineIndex = st.getLineAtOffset(offset) + count;
+                                       lineIndex = Math.max(0, Math.min(lineIndex, st.getLineCount() - 1));
+                                       start = st.getOffsetAtLine(lineIndex);
+                                       String line = st.getLine(lineIndex);
+                                       end = start + line.length();
+                                       count = lineIndex - st.getLineAtOffset(offset);
+                                       break;
+                               }
+                       }
+                       e.start = start;
+                       e.end = end;
+                       e.count = count;
+                       e.result = st.content.getTextRange(start, end - start);
+               }
+               @Override
+               public void getVisibleRanges(AccessibleTextEvent e) {
+                       e.ranges = getRanges(leftMargin, topMargin, clientAreaWidth - rightMargin, clientAreaHeight - bottomMargin);
+                       if (e.ranges.length > 0) {
+                               e.start = e.ranges[0];
+                               e.end = e.ranges[e.ranges.length - 1];
+                       }
+               }
+               @Override
+               public void scrollText(AccessibleTextEvent e) {
+                       StyledText st = StyledText.this;
+                       int topPixel = getTopPixel(), horizontalPixel = st.getHorizontalPixel();
+                       switch (e.type) {
+                               case ACC.SCROLL_TYPE_ANYWHERE:
+                               case ACC.SCROLL_TYPE_TOP_LEFT:
+                               case ACC.SCROLL_TYPE_LEFT_EDGE:
+                               case ACC.SCROLL_TYPE_TOP_EDGE: {
+                                       Rectangle rect = st.getBoundsAtOffset(e.start);
+                                       if (e.type != ACC.SCROLL_TYPE_TOP_EDGE) {
+                                               horizontalPixel = horizontalPixel + rect.x - st.leftMargin;
+                                       }
+                                       if (e.type != ACC.SCROLL_TYPE_LEFT_EDGE) {
+                                               topPixel = topPixel + rect.y - st.topMargin;
+                                       }
+                                       break;
+                               }
+                               case ACC.SCROLL_TYPE_BOTTOM_RIGHT:
+                               case ACC.SCROLL_TYPE_BOTTOM_EDGE:
+                               case ACC.SCROLL_TYPE_RIGHT_EDGE: {
+                                       Rectangle rect = st.getBoundsAtOffset(e.end - 1);
+                                       if (e.type != ACC.SCROLL_TYPE_BOTTOM_EDGE) {
+                                               horizontalPixel = horizontalPixel - st.clientAreaWidth + rect.x + rect.width + st.rightMargin;
+                                       }
+                                       if (e.type != ACC.SCROLL_TYPE_RIGHT_EDGE) {
+                                               topPixel = topPixel - st.clientAreaHeight + rect.y +rect.height + st.bottomMargin;
+                                       }
+                                       break;
+                               }
+                               case ACC.SCROLL_TYPE_POINT: {
+                                       Point point = new Point(e.x, e.y);
+                                       Display display = st.getDisplay();
+                                       point = display.map(null, st, point);
+                                       Rectangle rect = st.getBoundsAtOffset(e.start);
+                                       topPixel = topPixel - point.y + rect.y;
+                                       horizontalPixel = horizontalPixel - point.x + rect.x;
+                                       break;
+                               }
+                       }
+                       st.setTopPixel(topPixel);
+                       st.setHorizontalPixel(horizontalPixel);
+                       e.result = ACC.OK;
+               }
+       };
+       acc.addAccessibleTextListener(accTextExtendedAdapter);
+
+       accEditableTextListener = new AccessibleEditableTextListener() {
+               @Override
+               public void setTextAttributes(AccessibleTextAttributeEvent e) {
+                       // This method must be implemented by the application
+                       e.result = ACC.OK;
+               }
+               @Override
+               public void replaceText(AccessibleEditableTextEvent e) {
+                       StyledText st = StyledText.this;
+                       st.replaceTextRange(e.start, e.end - e.start, e.string);
+                       e.result = ACC.OK;
+               }
+               @Override
+               public void pasteText(AccessibleEditableTextEvent e) {
+                       StyledText st = StyledText.this;
+                       st.setSelection(e.start);
+                       st.paste();
+                       e.result = ACC.OK;
+               }
+               @Override
+               public void cutText(AccessibleEditableTextEvent e) {
+                       StyledText st = StyledText.this;
+                       st.setSelection(e.start, e.end);
+                       st.cut();
+                       e.result = ACC.OK;
+               }
+               @Override
+               public void copyText(AccessibleEditableTextEvent e) {
+                       StyledText st = StyledText.this;
+                       st.setSelection(e.start, e.end);
+                       st.copy();
+                       e.result = ACC.OK;
+               }
+       };
+       acc.addAccessibleEditableTextListener(accEditableTextListener);
+
+       accAttributeAdapter = new AccessibleAttributeAdapter() {
+               @Override
+               public void getAttributes(AccessibleAttributeEvent e) {
+                       StyledText st = StyledText.this;
+                       e.leftMargin = st.getLeftMargin();
+                       e.topMargin = st.getTopMargin();
+                       e.rightMargin = st.getRightMargin();
+                       e.bottomMargin = st.getBottomMargin();
+                       e.tabStops = st.getTabStops();
+                       e.justify = st.getJustify();
+                       e.alignment = st.getAlignment();
+                       e.indent = st.getIndent();
+               }
+               @Override
+               public void getTextAttributes(AccessibleTextAttributeEvent e) {
+                       StyledText st = StyledText.this;
+                       int contentLength = st.getCharCount();
+                       if (!isListening(ST.LineGetStyle) && st.renderer.styleCount == 0) {
+                               e.start = 0;
+                               e.end = contentLength;
+                               e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
+                               return;
+                       }
+                       int offset = Math.max(0, Math.min(e.offset, contentLength - 1));
+                       int lineIndex = st.getLineAtOffset(offset);
+                       int lineOffset = st.getOffsetAtLine(lineIndex);
+                       int lineCount = st.getLineCount();
+                       offset = offset - lineOffset;
+
+                       TextLayout layout = st.renderer.getTextLayout(lineIndex);
+                       int lineLength = layout.getText().length();
+                       if (lineLength > 0) {
+                               e.textStyle = layout.getStyle(Math.max(0, Math.min(offset, lineLength - 1)));
+                       }
+
+                       // If no override info available, use defaults. Don't supply default colors, though.
+                       if (e.textStyle == null) {
+                               e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
+                       } else {
+                               if (e.textStyle.foreground == null || e.textStyle.background == null || e.textStyle.font == null) {
+                                       TextStyle textStyle = new TextStyle(e.textStyle);
+                                       if (textStyle.foreground == null) textStyle.foreground = st.foreground;
+                                       if (textStyle.background == null) textStyle.background = st.background;
+                                       if (textStyle.font == null) textStyle.font = st.getFont();
+                                       e.textStyle = textStyle;
+                               }
+                       }
+
+                       //offset at line delimiter case
+                       if (offset >= lineLength) {
+                               e.start = lineOffset + lineLength;
+                               if (lineIndex + 1 < lineCount) {
+                                       e.end = st.getOffsetAtLine(lineIndex + 1);
+                               } else  {
+                                       e.end = contentLength;
+                               }
+                               return;
+                       }
+
+                       int[] ranges = layout.getRanges();
+                       st.renderer.disposeTextLayout(layout);
+                       int index = 0;
+                       int end = 0;
+                       while (index < ranges.length) {
+                               int styleStart = ranges[index++];
+                               int styleEnd = ranges[index++];
+                               if (styleStart <= offset && offset <= styleEnd) {
+                                       e.start = lineOffset + styleStart;
+                                       e.end = lineOffset + styleEnd + 1;
+                                       return;
+                               }
+                               if (styleStart > offset) {
+                                       e.start = lineOffset + end;
+                                       e.end = lineOffset + styleStart;
+                                       return;
+                               }
+                               end = styleEnd + 1;
+                       }
+                       if (index == ranges.length) {
+                               e.start = lineOffset + end;
+                               if (lineIndex + 1 < lineCount) {
+                                       e.end = st.getOffsetAtLine(lineIndex + 1);
+                               } else  {
+                                       e.end = contentLength;
+                               }
+                       }
+               }
+       };
+       acc.addAccessibleAttributeListener(accAttributeAdapter);
+
+       accControlAdapter = new AccessibleControlAdapter() {
+               @Override
+               public void getRole(AccessibleControlEvent e) {
+                       e.detail = ACC.ROLE_TEXT;
+               }
+               @Override
+               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;
+                       if (isSingleLine()) state |= ACC.STATE_SINGLELINE;
+                       else state |= ACC.STATE_MULTILINE;
+                       e.detail = state;
+               }
+               @Override
+               public void getValue(AccessibleControlEvent e) {
+                       e.result = StyledText.this.getText();
+               }
+       };
+       acc.addAccessibleControlListener(accControlAdapter);
+
+       addListener(SWT.FocusIn, event -> acc.setFocus(ACC.CHILDID_SELF));
+}
+
+@Override
+public void dispose() {
+       /*
+        * Note: It is valid to attempt to dispose a widget more than once.
+        * Added check for this.
+        */
+       if (!isDisposed()) {
+               acc.removeAccessibleControlListener(accControlAdapter);
+               acc.removeAccessibleAttributeListener(accAttributeAdapter);
+               acc.removeAccessibleEditableTextListener(accEditableTextListener);
+               acc.removeAccessibleTextListener(accTextExtendedAdapter);
+               acc.removeAccessibleListener(accAdapter);
+       }
+       super.dispose();
+}
+
+/*
+ * Return the Label immediately preceding the receiver in the z-order,
+ * or null if none.
+ */
+String getAssociatedLabel () {
+       Control[] siblings = getParent ().getChildren ();
+       for (int i = 0; i < siblings.length; i++) {
+               if (siblings [i] == StyledText.this) {
+                       if (i > 0) {
+                               Control sibling = siblings [i-1];
+                               if (sibling instanceof Label) return ((Label) sibling).getText();
+                               if (sibling instanceof CLabel) return ((CLabel) sibling).getText();
+                       }
+                       break;
+               }
+       }
+       return null;
+}
+String stripMnemonic (String string) {
+       int index = 0;
+       int length = string.length ();
+       do {
+               while ((index < length) && (string.charAt (index) != '&')) index++;
+               if (++index >= length) return string;
+               if (string.charAt (index) != '&') {
+                       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'.
+ */
+char _findMnemonic (String string) {
+       if (string == null) return '\0';
+       int index = 0;
+       int length = string.length ();
+       do {
+               while (index < length && string.charAt (index) != '&') index++;
+               if (++index >= length) return '\0';
+               if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (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();
+       if (blockSelection && invokeBlockAction(action)) return;
+       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;
+               case ST.TOGGLE_BLOCKSELECTION:
+                       setBlockSelection(!blockSelection);
+                       break;
+       }
+}
+/**
+* Returns true if an action should not be performed when block
+* selection in active
+*/
+boolean invokeBlockAction(int action) {
+       switch (action) {
+               // Navigation
+               case ST.LINE_UP:
+               case ST.LINE_DOWN:
+               case ST.LINE_START:
+               case ST.LINE_END:
+               case ST.COLUMN_PREVIOUS:
+               case ST.COLUMN_NEXT:
+               case ST.PAGE_UP:
+               case ST.PAGE_DOWN:
+               case ST.WORD_PREVIOUS:
+               case ST.WORD_NEXT:
+               case ST.TEXT_START:
+               case ST.TEXT_END:
+               case ST.WINDOW_START:
+               case ST.WINDOW_END:
+                       clearBlockSelection(false, false);
+                       return false;
+               // Selection
+               case ST.SELECT_LINE_UP:
+                       doBlockLineVertical(true);
+                       return true;
+               case ST.SELECT_LINE_DOWN:
+                       doBlockLineVertical(false);
+                       return true;
+               case ST.SELECT_LINE_START:
+                       doBlockLineHorizontal(false);
+                       return true;
+               case ST.SELECT_LINE_END:
+                       doBlockLineHorizontal(true);
+                       return false;
+               case ST.SELECT_COLUMN_PREVIOUS:
+                       doBlockColumn(false);
+                       return true;
+               case ST.SELECT_COLUMN_NEXT:
+                       doBlockColumn(true);
+                       return true;
+               case ST.SELECT_WORD_PREVIOUS:
+                       doBlockWord(false);
+                       return true;
+               case ST.SELECT_WORD_NEXT:
+                       doBlockWord(true);
+                       return true;
+               case ST.SELECT_ALL:
+                       return false;
+               case ST.SELECT_TEXT_START:
+                       doBlockContentStartEnd(false);
+                       break;
+               case ST.SELECT_TEXT_END:
+                       doBlockContentStartEnd(true);
+                       break;
+               case ST.SELECT_PAGE_UP:
+               case ST.SELECT_PAGE_DOWN:
+               case ST.SELECT_WINDOW_START:
+               case ST.SELECT_WINDOW_END:
+                       //blocked actions
+                       return true;
+               // Modification
+               case ST.CUT:
+               case ST.COPY:
+               case ST.PASTE:
+                       return false;
+               case ST.DELETE_PREVIOUS:
+               case ST.DELETE_NEXT:
+                       if (blockXLocation != -1) {
+                               insertBlockSelectionText((char)0, action);
+                               return true;
+                       }
+                       return false;
+               case ST.DELETE_WORD_PREVIOUS:
+               case ST.DELETE_WORD_NEXT:
+                       //blocked actions
+                       return blockXLocation != -1;
+       }
+       return false;
+}
+boolean isBidiCaret() {
+       return BidiUtil.isBidiPlatform();
+}
+boolean isFixedLineHeight() {
+       return !isWordWrap() && lineSpacing == 0 && renderer.lineSpacingProvider == null && !hasStyleWithVariableHeight && !hasVerticalIndent;
+}
+/**
+ * Returns whether the given offset is inside a multi byte line delimiter.
+ * Example:
+ * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == 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.
+ */
+boolean 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
+ */
+boolean isMirrored() {
+       return (getStyle() & SWT.MIRRORED) != 0;
+}
+/**
+ * Returns <code>true</code> if any text in the widget is selected,
+ * and <code>false</code> otherwise.
+ *
+ * @return the text 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>
+ *
+ * @since 3.103
+ */
+public boolean isTextSelected() {
+       checkWidget();
+       if (blockSelection && blockXLocation != -1) {
+               Rectangle rect = getBlockSelectionPosition();
+               return !rect.isEmpty();
+       }
+       return selection.y != selection.x;
+}
+/**
+ * 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
+ */
+boolean isSingleLine() {
+       return (getStyle() & SWT.SINGLE) != 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, boolean updateCaret) {
+       event.doit = true;
+       notifyListeners(SWT.Verify, event);
+       if (event.doit) {
+               StyledTextEvent styledTextEvent = null;
+               int replacedLength = event.end - event.start;
+               if (isListening(ST.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() == 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 != lineIndexEnd) {
+                                       renderer.disposeTextLayout(layout);
+                                       lineOffset = content.getOffsetAtLine(lineIndexEnd);
+                                       layout = renderer.getTextLayout(lineIndexEnd);
+                               }
+                               int levelEnd = layout.getLevel(event.end - lineOffset);
+                               renderer.disposeTextLayout(layout);
+                               if (levelStart != 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 && !(blockSelection && blockXLocation != -1)) {
+                       // always update the caret location. fixes 1G8FODP
+                       setSelection(event.start + event.text.length(), 0, true, false);
+                       showCaret();
+               }
+               notifyListeners(SWT.Modify, event);
+               if (isListening(ST.ExtendedModify)) {
+                       notifyListeners(ST.ExtendedModify, styledTextEvent);
+               }
+       }
+}
+void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) {
+       if (isListening(ST.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(ST.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 = (String) getClipboardContent(DND.CLIPBOARD);
+       if (text != null && text.length() > 0) {
+               if (blockSelection) {
+                       boolean fillWithSpaces = isFixedLineHeight() && renderer.fixedPitch;
+                       int offset = insertBlockSelectionText(text, fillWithSpaces);
+                       setCaretOffset(offset, SWT.DEFAULT);
+                       clearBlockSelection(true, true);
+                       setCaretLocation();
+                       return;
+               }
+               Event event = new Event();
+               event.start = selection.x;
+               event.end = selection.y;
+               String delimitedText = getModelDelimitedText(text);
+               if (textLimit > 0) {
+                       int uneditedTextLength = getCharCount() - (selection.y - selection.x);
+                       if ((uneditedTextLength + delimitedText.length()) > textLimit) {
+                               int endIndex = textLimit - uneditedTextLength;
+                               delimitedText = delimitedText.substring(0, Math.max(endIndex, 0));
+                       }
+               }
+               event.text = delimitedText;
+               sendKeyEvent(event);
+       }
+}
+private void pasteOnMiddleClick(Event event) {
+       String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD);
+       if (text != 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);
+       }
+}
+/**
+ * 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 == 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 == null || options == 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()
+ */
+@Override
+public void redraw() {
+       super.redraw();
+       int itemCount = getPartialBottomIndex() - topIndex + 1;
+       renderer.reset(topIndex, itemCount);
+       renderer.calculate(topIndex, itemCount);
+       setScrollBars(false);
+       doMouseLinkCursor();
+}
+/**
+ * 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()
+ */
+@Override
+public void redraw(int x, int y, int width, int height, boolean 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);
+               doMouseLinkCursor();
+       }
+}
+void redrawLines(int startLine, int lineCount, boolean bottomChanged) {
+       // do nothing if redraw range is completely invisible
+       int endLine = startLine + lineCount - 1;
+       int partialBottomIndex = getPartialBottomIndex();
+       int partialTopIndex = getPartialTopIndex();
+       if (startLine > partialBottomIndex || endLine < partialTopIndex) {
+               return;
+       }
+       // only redraw visible lines
+       if (startLine < partialTopIndex) {
+               startLine = partialTopIndex;
+       }
+       if (endLine > partialBottomIndex) {
+               endLine = partialBottomIndex;
+       }
+       int redrawTop = getLinePixel(startLine);
+       int redrawBottom = getLinePixel(endLine + 1);
+       if (bottomChanged) redrawBottom = clientAreaHeight - bottomMargin;
+       int redrawWidth = clientAreaWidth - leftMargin - rightMargin;
+       super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true);
+}
+void redrawLinesBullet (int[] redrawLines) {
+       if (redrawLines == 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 != null) {
+                       StyleRange style = bullet.style;
+                       GlyphMetrics metrics = style.metrics;
+                       width = metrics.width;
+               }
+               if (width == -1) width = getClientArea().width;
+               int height = renderer.getLineHeight(lineIndex);
+               int y = getLinePixel(lineIndex);
+               super.redraw(0, y, width, height, false);
+       }
+}
+void redrawMargins(int oldHeight, int oldWidth) {
+       /* Redraw the old or new right/bottom margin if needed */
+       if (oldWidth != clientAreaWidth) {
+               if (rightMargin > 0) {
+                       int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin;
+                       super.redraw(x, 0, rightMargin, oldHeight, false);
+               }
+       }
+       if (oldHeight != clientAreaHeight) {
+               if (bottomMargin > 0) {
+                       int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin;
+                       super.redraw(0, y, oldWidth, bottomMargin, 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, boolean 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);
+       doMouseLinkCursor();
+}
+/**
+ * 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.LineGetSegments, listener);
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       super.redraw();
+}
+/**
+ * Removes the specified caret 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.5
+ */
+public void removeCaretListener(CaretListener listener) {
+       checkWidget();
+       if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.CaretMoved, 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.LineGetStyle, listener);
+       setCaretLocation();
+}
+/**
+ * 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 == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.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 == 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 == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(ST.WordNext, listener);
+       removeListener(ST.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 &lt;= offset &lt;= getCharCount())</li>
+ *   <li>ERROR_NULL_ARGUMENT when ranges is null</li>
+ * </ul>
+ *
+ * @since 2.0
+ *
+ * @see #setStyleRanges(int, int, int[], StyleRange[])
+ */
+public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
+       checkWidget();
+       if (isListening(ST.LineGetStyle)) return;
+       if (ranges == 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:
+ * </p>
+ * <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>
+ *
+ * @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 &lt;= offset &lt;= 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>
+ *   <li>ERROR_NULL_ARGUMENT when string is null</li>
+ * </ul>
+ */
+public void replaceTextRange(int start, int length, String text) {
+       checkWidget();
+       if (text == 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();
+       setCaretOffset(0, SWT.DEFAULT);
+       topIndex = 0;
+       topIndexY = 0;
+       verticalScrollOffset = 0;
+       horizontalScrollOffset = 0;
+       resetSelection();
+       renderer.setContent(content);
+       if (verticalBar != null) {
+               verticalBar.setSelection(0);
+       }
+       if (horizontalBar != null) {
+               horizontalBar.setSelection(0);
+       }
+       resetCache(0, 0);
+       setCaretLocation();
+       super.redraw();
+}
+void resetBidiData() {
+       caretDirection = SWT.NULL;
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       keyActionMap.clear();
+       createKeyBindings();
+       super.redraw();
+}
+void resetCache(SortedSet<Integer> lines) {
+       if (lines == null || lines.isEmpty()) return;
+       int maxLineIndex = renderer.maxWidthLineIndex;
+       renderer.reset(lines);
+       renderer.calculateClientArea();
+       if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
+               renderer.calculate(maxLineIndex, 1);
+       }
+       setScrollBars(true);
+       if (!isFixedLineHeight()) {
+               if (topIndex > lines.iterator().next()) {
+                       verticalScrollOffset = -1;
+               }
+               renderer.calculateIdle();
+       }
+}
+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;
+       sendAccessibleTextCaretMoved();
+}
+
+@Override
+public void scroll(int destX, int destY, int x, int y, int width, int height, boolean 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 SWT logical points to scroll, &gt; 0 = scroll left,
+ *     &lt; 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.
+ */
+boolean scrollHorizontal(int pixels, boolean adjustScrollBar) {
+       if (pixels == 0) return false;
+       if (wordWrap) return false;
+       ScrollBar horizontalBar = getHorizontalBar();
+       if (horizontalBar != 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
+ */
+boolean scrollVertical(int pixels, boolean adjustScrollBar) {
+       if (pixels == 0) {
+               return false;
+       }
+       if (verticalScrollOffset != -1) {
+               ScrollBar verticalBar = getVerticalBar();
+               if (verticalBar != null && adjustScrollBar) {
+                       verticalBar.setSelection(verticalScrollOffset + pixels);
+               }
+               int deltaY = 0;
+               if (pixels > 0) {
+                       int sourceY = topMargin + pixels;
+                       int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
+                       if (scrollHeight > 0) {
+                               deltaY = -pixels;
+                       }
+               } else {
+                       int destinationY = topMargin - pixels;
+                       int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
+                       if (scrollHeight > 0) {
+                               deltaY = -pixels;
+                       }
+               }
+               Control[] children = getChildren();
+               for (int i=0; i<children.length; i++) {
+                       Control child = children[i];
+                       Rectangle rect = child.getBounds();
+                       child.setLocation(rect.x, rect.y + deltaY);
+               }
+               verticalScrollOffset += pixels;
+               calculateTopIndex(pixels);
+               super.redraw();
+       } else {
+               calculateTopIndex(pixels);
+               super.redraw();
+       }
+       setCaretLocation();
+       return true;
+}
+void scrollText(int srcY, int destY) {
+       if (srcY == 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);
+       }
+}
+void sendAccessibleTextCaretMoved() {
+       if (caretOffset != accCaretOffset) {
+               accCaretOffset = caretOffset;
+               getAccessible().textCaretMoved(caretOffset);
+       }
+}
+void sendAccessibleTextChanged(int start, int newCharCount, int replaceCharCount) {
+       Accessible accessible = getAccessible();
+       if (replaceCharCount != 0) {
+               accessible.textChanged(ACC.TEXT_DELETE, start, replaceCharCount);
+       }
+       if (newCharCount != 0) {
+               accessible.textChanged(ACC.TEXT_INSERT, start, newCharCount);
+       }
+}
+/**
+ * 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();
+       if (blockSelection) {
+               renderer.calculate(0, content.getLineCount());
+               setScrollBars(false);
+               int verticalScrollOffset = getVerticalScrollOffset();
+               int left = leftMargin - horizontalScrollOffset;
+               int top = topMargin - verticalScrollOffset;
+               int right = renderer.getWidth() - rightMargin - horizontalScrollOffset;
+               int bottom = renderer.getHeight() - bottomMargin - verticalScrollOffset;
+               setBlockSelectionLocation(left, top, right, bottom, false);
+               return;
+       }
+       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.wrapIndent = wrapIndent;
+               event.justify = justify;
+               notifyListeners(eventType, event);
+       }
+       return 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 sendTextEvent(int left, int right, int lineIndex, String text, boolean fillWithSpaces) {
+       int lineWidth = 0, start, end;
+       StringBuilder buffer = new StringBuilder();
+       if (lineIndex < content.getLineCount()) {
+               int[] trailing = new int[1];
+               start = getOffsetAtPoint(left, getLinePixel(lineIndex), trailing, true);
+               if (start == -1) {
+                       int lineOffset = content.getOffsetAtLine(lineIndex);
+                       int lineLegth = content.getLine(lineIndex).length();
+                       start = end = lineOffset + lineLegth;
+                       if (fillWithSpaces) {
+                               TextLayout layout = renderer.getTextLayout(lineIndex);
+                               lineWidth = layout.getBounds().width;
+                               renderer.disposeTextLayout(layout);
+                       }
+               } else {
+                       start += trailing[0];
+                       end = left == right ? start : getOffsetAtPoint(right, 0, lineIndex, null);
+                       fillWithSpaces = false;
+               }
+       } else {
+               start = end = content.getCharCount();
+               buffer.append(content.getLineDelimiter());
+       }
+       if (start > end) {
+               int temp = start;
+               start = end;
+               end = temp;
+       }
+       if (fillWithSpaces) {
+               int spacesWidth = left - lineWidth + horizontalScrollOffset - leftMargin;
+               int spacesCount = spacesWidth / renderer.averageCharWidth;
+               for (int i = 0; i < spacesCount; i++) {
+                       buffer.append(' ');
+               }
+       }
+       buffer.append(text);
+       Event event = new Event();
+       event.start = start;
+       event.end = end;
+       event.text = buffer.toString();
+       sendKeyEvent(event);
+       return event.start + event.text.length();
+}
+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 != 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;
+}
+void setAlignment() {
+       if ((getStyle() & SWT.SINGLE) == 0) return;
+       int alignment = renderer.getLineAlignment(0, this.alignment);
+       int newAlignmentMargin = 0;
+       if (alignment != SWT.LEFT) {
+               renderer.calculate(0, 1);
+               int width = renderer.getWidth() - alignmentMargin;
+               newAlignmentMargin = clientAreaWidth - width;
+               if (newAlignmentMargin < 0) newAlignmentMargin = 0;
+               if (alignment == SWT.CENTER) newAlignmentMargin /= 2;
+       }
+       if (alignmentMargin != newAlignmentMargin) {
+               leftMargin -= alignmentMargin;
+               leftMargin += newAlignmentMargin;
+               alignmentMargin = newAlignmentMargin;
+               resetCache(0, 1);
+               setCaretLocation();
+               super.redraw();
+       }
+}
+/**
+ * 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>
+ * 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 == 0 || this.alignment == alignment) return;
+       this.alignment = alignment;
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       setAlignment();
+       super.redraw();
+}
+/**
+ * Set the Always Show Scrollbars flag.  True if the scrollbars are
+ * always shown even if they are not required (default value).  False if the scrollbars are only
+ * visible when some part of the content 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>
+ *
+ * @since 3.8
+ */
+public void setAlwaysShowScrollBars(boolean show) {
+       checkWidget();
+       if (show == alwaysShowScroll) return;
+       alwaysShowScroll = show;
+       setScrollBars(true);
+}
+/**
+ * @see Control#setBackground(Color)
+ */
+@Override
+public void setBackground(Color color) {
+       checkWidget();
+       boolean backgroundDisabled = false;
+       if (!this.enabled && color == null) {
+               if (background != null) {
+                       Color disabledBg = getDisplay().getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND);
+                       if (background.equals(disabledBg)) {
+                               return;
+                       } else {
+                               color = new Color (getDisplay(), disabledBg.getRGBA());
+                               backgroundDisabled = true;
+                       }
+               }
+       }
+       customBackground = color != null && !this.insideSetEnableCall && !backgroundDisabled;
+       background = color;
+       super.setBackground(color);
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       super.redraw();
+}
+/**
+ * Sets the block selection mode.
+ *
+ * @param blockSelection true=enable block selection, false=disable block selection
+ *
+ * @since 3.5
+ */
+public void setBlockSelection(boolean blockSelection) {
+       checkWidget();
+       if ((getStyle() & SWT.SINGLE) != 0) return;
+       if (blockSelection == this.blockSelection) return;
+       if (wordWrap) return;
+       this.blockSelection = blockSelection;
+       if (cursor == null) {
+               Display display = getDisplay();
+               int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
+               super.setCursor(display.getSystemCursor(type));
+       }
+       if (blockSelection) {
+               int start = selection.x;
+               int end = selection.y;
+               if (start != end) {
+                       setBlockSelectionOffset(start, end, false);
+               }
+       } else {
+               clearBlockSelection(false, false);
+       }
+}
+/**
+ * Sets the block selection bounds. The bounds is
+ * relative to the upper left corner of the document.
+ *
+ * @param rect the new bounds for the block selection
+ *
+ * @see #setBlockSelectionBounds(int, int, 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>
+ * </ul>
+ *
+ * @since 3.5
+ */
+public void setBlockSelectionBounds(Rectangle rect) {
+       checkWidget();
+       if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       setBlockSelectionBounds(rect.x, rect.y, rect.width, rect.height);
+}
+/**
+ * Sets the block selection bounds. The bounds is
+ * relative to the upper left corner of the document.
+ *
+ * @param x the new x coordinate for the block selection
+ * @param y the new y coordinate for the block selection
+ * @param width the new width for the block selection
+ * @param height the new height for the block 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>
+ *
+ * @since 3.5
+ */
+public void setBlockSelectionBounds(int x, int y, int width, int height) {
+       checkWidget();
+       int verticalScrollOffset = getVerticalScrollOffset();
+       if (!blockSelection) {
+               x -= horizontalScrollOffset;
+               y -= verticalScrollOffset;
+               int start = getOffsetAtPoint(x, y, null);
+               int end = getOffsetAtPoint(x+width-1, y+height-1, null);
+               setSelection(start, end - start, false, false);
+               setCaretLocation();
+               return;
+       }
+       int minY = topMargin;
+       int minX = leftMargin;
+       int maxY = renderer.getHeight() - bottomMargin;
+       int maxX = Math.max(clientAreaWidth, renderer.getWidth()) - rightMargin;
+       int anchorX = Math.max(minX, Math.min(maxX, x)) - horizontalScrollOffset;
+       int anchorY = Math.max(minY, Math.min(maxY, y)) - verticalScrollOffset;
+       int locationX = Math.max(minX, Math.min(maxX, x + width)) - horizontalScrollOffset;
+       int locationY = Math.max(minY, Math.min(maxY, y + height - 1)) - verticalScrollOffset;
+       if (isFixedLineHeight() && renderer.fixedPitch) {
+               int avg = renderer.averageCharWidth;
+               anchorX = ((anchorX - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
+               locationX = ((locationX + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
+       }
+       setBlockSelectionLocation(anchorX, anchorY, locationX, locationY, false);
+}
+void setBlockSelectionLocation (int x, int y, boolean sendEvent) {
+       int verticalScrollOffset = getVerticalScrollOffset();
+       blockXLocation = x + horizontalScrollOffset;
+       blockYLocation = y + verticalScrollOffset;
+       int[] alignment = new int[1];
+       int offset = getOffsetAtPoint(x, y, alignment);
+       setCaretOffset(offset, alignment[0]);
+       if (blockXAnchor == -1) {
+               blockXAnchor = blockXLocation;
+               blockYAnchor = blockYLocation;
+               selectionAnchor = caretOffset;
+       }
+       doBlockSelection(sendEvent);
+}
+void setBlockSelectionLocation (int anchorX, int anchorY, int x, int y, boolean sendEvent) {
+       int verticalScrollOffset = getVerticalScrollOffset();
+       blockXAnchor = anchorX + horizontalScrollOffset;
+       blockYAnchor = anchorY + verticalScrollOffset;
+       selectionAnchor = getOffsetAtPoint(anchorX, anchorY, null);
+       setBlockSelectionLocation(x, y, sendEvent);
+}
+void setBlockSelectionOffset (int offset, boolean sendEvent) {
+       Point point = getPointAtOffset(offset);
+       int verticalScrollOffset = getVerticalScrollOffset();
+       blockXLocation = point.x + horizontalScrollOffset;
+       blockYLocation = point.y + verticalScrollOffset;
+       setCaretOffset(offset, SWT.DEFAULT);
+       if (blockXAnchor == -1) {
+               blockXAnchor = blockXLocation;
+               blockYAnchor = blockYLocation;
+               selectionAnchor = caretOffset;
+       }
+       doBlockSelection(sendEvent);
+}
+void setBlockSelectionOffset (int anchorOffset, int offset, boolean sendEvent) {
+       int verticalScrollOffset = getVerticalScrollOffset();
+       Point anchorPoint = getPointAtOffset(anchorOffset);
+       blockXAnchor = anchorPoint.x + horizontalScrollOffset;
+       blockYAnchor = anchorPoint.y + verticalScrollOffset;
+       selectionAnchor = anchorOffset;
+       setBlockSelectionOffset(offset, sendEvent);
+}
+/**
+ * Sets the receiver's caret.  Set the caret's height and location.
+ *
+ * @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>
+ */
+@Override
+public void setCaret(Caret caret) {
+       checkWidget ();
+       super.setCaret(caret);
+       caretDirection = SWT.NULL;
+       if (caret != 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.
+ */
+@Deprecated
+public void setBidiColoring(boolean mode) {
+       checkWidget();
+       bidiColoring = mode;
+}
+/**
+ * Sets the bottom margin.
+ *
+ * @param bottomMargin the bottom margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public void setBottomMargin (int bottomMargin) {
+       checkWidget();
+       setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
+}
+/**
+ * Moves the Caret to the current caret offset.
+ */
+void setCaretLocation() {
+       Point newCaretPos = getPointAtOffset(caretOffset);
+       setCaretLocation(newCaretPos, getCaretDirection());
+}
+void setCaretLocation(final Point location, int direction) {
+       Caret caret = getCaret();
+       if (caret != null) {
+               final boolean isDefaultCaret = caret == defaultCaret;
+               final StyleRange styleAtOffset = content.getCharCount() > 0 ?
+                       (caretOffset < content.getCharCount() ?
+                               getStyleRangeAtOffset(caretOffset) :
+                               getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style
+                       null;
+               final int caretLine = getCaretLine();
+
+               int graphicalLineHeight = getLineHeight();
+               final int lineStartOffset = getOffsetAtLine(caretLine);
+               int graphicalLineFirstOffset = lineStartOffset;
+               final int lineEndOffset = lineStartOffset + getLine(caretLine).length();
+               int graphicalLineLastOffset = lineEndOffset;
+               if (caretLine < getLineCount() && renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles...
+                       graphicalLineHeight = getLineHeight(caretOffset);
+                       final Rectangle characterBounds = getBoundsAtOffset(caretOffset);
+                       graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y));
+                       graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1;
+                       if (graphicalLineLastOffset < graphicalLineFirstOffset) {
+                               graphicalLineLastOffset = getCharCount();
+                       }
+               }
+
+               int caretHeight = getLineHeight();
+               boolean isTextAlignedAtBottom = true;
+               if (graphicalLineFirstOffset >= 0) {
+                       for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) {
+                               isTextAlignedAtBottom &= (
+                                       (style.font == null || Objects.equals(style.font, getFont())) &&
+                                       style.rise >= 0 &&
+                                       (style.metrics == null || style.metrics.descent <= 0)
+                               );
+                       }
+               }
+               if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) {
+                       if (isDefaultCaret) {
+                               direction = SWT.DEFAULT;
+                               caretHeight = graphicalLineHeight;
+                       } else {
+                               caretHeight = caret.getSize().y;
+                       }
+               }
+               if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) {
+                       location.y += (graphicalLineHeight - caretHeight);
+               }
+
+               int imageDirection = direction;
+               if (isMirrored()) {
+                       if (imageDirection == SWT.LEFT) {
+                               imageDirection = SWT.RIGHT;
+                       } else if (imageDirection == SWT.RIGHT) {
+                               imageDirection = SWT.LEFT;
+                       }
+               }
+               if (isDefaultCaret && imageDirection == SWT.RIGHT) {
+                       location.x -= (caret.getSize().x - 1);
+               }
+               if (isDefaultCaret) {
+                       caret.setBounds(location.x, location.y, caretWidth, caretHeight);
+               } else {
+                       caret.setLocation(location);
+               }
+               if (direction != caretDirection) {
+                       caretDirection = direction;
+                       if (isDefaultCaret) {
+                               if (imageDirection == SWT.DEFAULT) {
+                                       defaultCaret.setImage(null);
+                               } else if (imageDirection == SWT.LEFT) {
+                                       defaultCaret.setImage(leftCaretBitmap);
+                               } else if (imageDirection == SWT.RIGHT) {
+                                       defaultCaret.setImage(rightCaretBitmap);
+                               }
+                       }
+                       if (caretDirection == SWT.LEFT) {
+                               BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI);
+                       } else if (caretDirection == SWT.RIGHT) {
+                               BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
+                       }
+               }
+               updateCaretVisibility();
+       }
+       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 the offset 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 != caretOffset) {
+               if (offset < 0) {
+                       offset = 0;
+               } else if (offset > length) {
+                       offset = 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);
+                       }
+               }
+               setCaretOffset(offset, PREVIOUS_OFFSET_TRAILING);
+               // clear the selection if the caret is moved.
+               // don't notify listeners about the selection change.
+               if (blockSelection) {
+                       clearBlockSelection(true, false);
+               } else {
+                       clearSelection(false);
+               }
+       }
+       setCaretLocation();
+}
+void setCaretOffset(int offset, int alignment) {
+       if (caretOffset != offset) {
+               caretOffset = offset;
+               if (isListening(ST.CaretMoved)) {
+                       StyledTextEvent event = new StyledTextEvent(content);
+                       event.end = caretOffset;
+                       notifyListeners(ST.CaretMoved, event);
+               }
+       }
+       if (alignment != SWT.DEFAULT) {
+               caretAlignment = alignment;
+       }
+}
+/**
+ * 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 org.eclipse.swt.dnd.Clipboard#setContents
+ */
+void setClipboardContent(int start, int length, int clipboardType) throws SWTError {
+       if (clipboardType == DND.SELECTION_CLIPBOARD && !IS_GTK) return;
+       TextTransfer plainTextTransfer = TextTransfer.getInstance();
+       TextWriter plainTextWriter = new TextWriter(start, length);
+       String plainText = getPlatformDelimitedText(plainTextWriter);
+       Object[] data;
+       Transfer[] types;
+       if (clipboardType == DND.SELECTION_CLIPBOARD) {
+               data = new Object[]{plainText};
+               types = new Transfer[]{plainTextTransfer};
+       } else {
+               RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+               RTFWriter rtfWriter = new RTFWriter(start, length);
+               String rtfText = getPlatformDelimitedText(rtfWriter);
+               data = new Object[]{rtfText, plainText};
+               types = new 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 == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       if (content != 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)
+ */
+@Override
+public void setCursor (Cursor cursor) {
+       checkWidget();
+       if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       this.cursor = cursor;
+       if (cursor == null) {
+               Display display = getDisplay();
+               int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
+               super.setCursor(display.getSystemCursor(type));
+       } else {
+               super.setCursor(cursor);
+       }
+}
+/**
+ * Sets whether the widget implements double click mouse behavior.
+ *
+ * @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(boolean enable) {
+       checkWidget();
+       doubleClickEnabled = enable;
+}
+@Override
+public void setDragDetect (boolean dragDetect) {
+       checkWidget ();
+       this.dragDetect = dragDetect;
+}
+/**
+ * Sets whether the widget content can be edited.
+ *
+ * @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(boolean editable) {
+       checkWidget();
+       this.editable = editable;
+}
+@Override
+public void setEnabled(boolean enabled) {
+       super.setEnabled(enabled);
+       Display display = getDisplay();
+       this.enabled = enabled;
+       this.insideSetEnableCall = true;
+       try {
+               if (enabled) {
+                       if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+                       if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+               } else {
+                       if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND));
+                       if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND));
+               }
+       }
+       finally {
+               this.insideSetEnableCall = false;
+       }
+}
+/**
+ * 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>
+ */
+@Override
+public 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 != 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();
+}
+@Override
+public void setForeground(Color color) {
+       checkWidget();
+       boolean foregroundDisabled = false;
+       if (!this.enabled && color == null) {
+               if (foreground != null) {
+                       Color disabledFg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND);
+                       if (foreground.equals(disabledFg)) {
+                               return;
+                       } else {
+                               color = new Color (getDisplay(), disabledFg.getRGBA());
+                               foregroundDisabled = true;
+                       }
+               }
+       }
+       customForeground = color != null && !this.insideSetEnableCall && !foregroundDisabled;
+       foreground = color;
+       super.setForeground(color);
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       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 &gt; 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() == 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 SWT logical point offset relative to the start of the line.
+ * Do nothing if there is no text set.
+ * <p>
+ * <b>NOTE:</b> The horizontal SWT logical point offset is reset to 0 when new text
+ * is set in the widget.
+ * </p>
+ *
+ * @param pixel horizontal SWT logical point 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() == 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 points, 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 == 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, boolean)
+ *
+ * @since 3.2
+ */
+public void setJustify(boolean justify) {
+       checkWidget();
+       if (this.justify == 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;
+       int keyInt = key & SWT.KEY_MASK;
+       char keyChar = (char)keyInt;
+       /**
+        * Bug 440535: Make sure the key getting mapped to letter is in defiened
+        * character range and filter out incorrect int to char typecasting. For
+        * Example: SWT.KEYPAD_CR int gets wrongly type-cast to char letter 'p'
+        */
+       if (Character.isDefined(keyInt) && Character.isLetter(keyChar)) {
+               // make the keybinding case insensitive by adding it
+               // in its upper and lower case form
+               char ch = Character.toUpperCase(keyChar);
+               int newKey = ch | modifierValue;
+               if (action == SWT.NULL) {
+                       keyActionMap.remove(newKey);
+               } else {
+                       keyActionMap.put(newKey, action);
+               }
+               ch = Character.toLowerCase(keyChar);
+               newKey = ch | modifierValue;
+               if (action == SWT.NULL) {
+                       keyActionMap.remove(newKey);
+               } else {
+                       keyActionMap.put(newKey, action);
+               }
+       } else {
+               if (action == SWT.NULL) {
+                       keyActionMap.remove(key);
+               } else {
+                       keyActionMap.put(key, action);
+               }
+       }
+}
+/**
+ * Sets the left margin.
+ *
+ * @param leftMargin the left margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public void setLeftMargin (int leftMargin) {
+       checkWidget();
+       setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
+}
+/**
+ * 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>
+ * 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><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>
+ * 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(ST.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, false);
+       int caretLine = getCaretLine();
+       if (startLine <= caretLine && caretLine < startLine + lineCount) {
+               setCaretLocation();
+       }
+       setAlignment();
+}
+/**
+ * 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(ST.LineGetBackground)) return;
+       if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (background != null) {
+               renderer.setLineBackground(startLine, lineCount, background);
+       } else {
+               renderer.clearLineBackground(startLine, lineCount);
+       }
+       redrawLines(startLine, lineCount, false);
+}
+/**
+ * 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(ST.LineGetStyle)) return;
+       if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int oldBottom = getLinePixel(startLine + lineCount);
+       renderer.setLineBullet(startLine, lineCount, bullet);
+       resetCache(startLine, lineCount);
+       int newBottom = getLinePixel(startLine + lineCount);
+       redrawLines(startLine, lineCount, oldBottom != newBottom);
+       int caretLine = getCaretLine();
+       if (startLine <= caretLine && caretLine < startLine + lineCount) {
+               setCaretLocation();
+       }
+}
+/**
+ * Returns true if StyledText is in word wrap mode and false otherwise.
+ *
+ * @return true if StyledText is in word wrap mode and false otherwise.
+ */
+boolean isWordWrap() {
+       return wordWrap || visualWrap;
+}
+/**
+ * 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(ST.LineGetStyle)) return;
+       if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int oldBottom = getLinePixel(startLine + lineCount);
+       renderer.setLineIndent(startLine, lineCount, indent);
+       resetCache(startLine, lineCount);
+       int newBottom = getLinePixel(startLine + lineCount);
+       redrawLines(startLine, lineCount, oldBottom != newBottom);
+       int caretLine = getCaretLine();
+       if (startLine <= caretLine && caretLine < startLine + lineCount) {
+               setCaretLocation();
+       }
+}
+
+/**
+ * Sets the vertical 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><p>
+ * Setting both line spacing and vertical indent on a line would result in the
+ * spacing and indent add up for the line.
+ * </p>
+ *
+ * @param lineIndex line index the vertical indent is applied to, 0 based
+ * @param verticalLineIndent vertical 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 index is invalid</li>
+ * </ul>
+ * @since 3.109
+ */
+public void setLineVerticalIndent(int lineIndex, int verticalLineIndent) {
+       checkWidget();
+       if (isListening(ST.LineGetStyle)) return;
+       if (lineIndex < 0 || lineIndex >= content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (verticalLineIndent == renderer.getLineVerticalIndent(lineIndex)) {
+                       return;
+       }
+       int oldBottom = getLinePixel(lineIndex + 1);
+       if (oldBottom <= getClientArea().height) {
+               verticalScrollOffset = -1;
+       }
+       renderer.setLineVerticalIndent(lineIndex, verticalLineIndent);
+       hasVerticalIndent = verticalLineIndent != 0 || renderer.hasVerticalIndent();
+       resetCache(lineIndex, 1);
+       int newBottom = getLinePixel(lineIndex + 1);
+       redrawLines(lineIndex, 1, oldBottom != newBottom);
+       int caretLine = getCaretLine();
+       if (lineIndex <= caretLine && caretLine < lineIndex + 1) {
+               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(boolean)
+ * @since 3.2
+ */
+public void setLineJustify(int startLine, int lineCount, boolean justify) {
+       checkWidget();
+       if (isListening(ST.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, false);
+       int caretLine = getCaretLine();
+       if (startLine <= caretLine && caretLine < startLine + lineCount) {
+               setCaretLocation();
+       }
+}
+/**
+ * Sets the line spacing of the widget. The line spacing applies for all lines.
+ * In the case of #setLineSpacingProvider(StyledTextLineSpacingProvider) is customized,
+ * the line spacing are applied only for the lines which are not managed by {@link StyledTextLineSpacingProvider}.
+ *
+ * @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>
+ * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
+ * @since 3.2
+ */
+public void setLineSpacing(int lineSpacing) {
+       checkWidget();
+       if (this.lineSpacing == lineSpacing || lineSpacing < 0) return;
+       this.lineSpacing = lineSpacing;
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       super.redraw();
+}
+/**
+ * Sets the line spacing provider of the widget. The line spacing applies for some lines with customized spacing
+ * or reset the customized spacing if the argument is null.
+ *
+ * @param lineSpacingProvider the line spacing provider (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 #setLineSpacingProvider(StyledTextLineSpacingProvider)
+ * @since 3.107
+ */
+public void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
+       checkWidget();
+       boolean wasFixedLineHeight = isFixedLineHeight();
+       if (renderer.getLineSpacingProvider() == null && lineSpacingProvider == null
+                       || (renderer.getLineSpacingProvider() != null
+                                       && renderer.getLineSpacingProvider().equals(lineSpacingProvider)))
+               return;
+       renderer.setLineSpacingProvider(lineSpacingProvider);
+       // reset lines cache if needed
+       if (lineSpacingProvider == null) {
+               if (!wasFixedLineHeight) {
+                       resetCache(0, content.getLineCount());
+               }
+       } else {
+               if (wasFixedLineHeight) {
+                       int firstLine = -1;
+                       for (int i = 0; i < content.getLineCount(); i++) {
+                               Integer lineSpacing = lineSpacingProvider.getLineSpacing(i);
+                               if (lineSpacing != null && lineSpacing > 0) {
+                                       // there is a custom line spacing, set StyledText as variable line height mode
+                                       // reset only the line size
+                                       renderer.reset(i, 1);
+                                       if (firstLine == -1) {
+                                               firstLine = i;
+                                       }
+                               }
+                       }
+                       if (firstLine != -1) {
+                               // call reset cache for the first line which have changed to recompute scrollbars
+                               resetCache(firstLine, 0);
+                       }
+               }
+       }
+       setCaretLocation();
+       super.redraw();
+}
+/**
+ * Sets the tab stops of the specified lines.
+ * <p>
+ * Should not be called if a <code>LineStyleListener</code> 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 tabStops tab stops
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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 #setTabStops(int[])
+ * @since 3.6
+ */
+public void setLineTabStops(int startLine, int lineCount, int[] tabStops) {
+       checkWidget();
+       if (isListening(ST.LineGetStyle)) return;
+       if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (tabStops != null) {
+               int pos = 0;
+               int[] newTabs = new int[tabStops.length];
+               for (int i = 0; i < tabStops.length; i++) {
+                       if (tabStops[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+                       newTabs[i] = pos = tabStops[i];
+               }
+               renderer.setLineTabStops(startLine, lineCount, newTabs);
+       } else {
+               renderer.setLineTabStops(startLine, lineCount, null);
+       }
+       resetCache(startLine, lineCount);
+       redrawLines(startLine, lineCount, false);
+       int caretLine = getCaretLine();
+       if (startLine <= caretLine && caretLine < startLine + lineCount) {
+               setCaretLocation();
+       }
+}
+/**
+ * Sets the wrap indent of the specified lines.
+ * <p>
+ * Should not be called if a <code>LineStyleListener</code> 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 wrap indent is applied to, 0 based
+ * @param lineCount number of lines the wrap indent applies to.
+ * @param wrapIndent line wrap 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 #setWrapIndent(int)
+ * @since 3.6
+ */
+public void setLineWrapIndent(int startLine, int lineCount, int wrapIndent) {
+       checkWidget();
+       if (isListening(ST.LineGetStyle)) return;
+       if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int oldBottom = getLinePixel(startLine + lineCount);
+       renderer.setLineWrapIndent(startLine, lineCount, wrapIndent);
+       resetCache(startLine, lineCount);
+       int newBottom = getLinePixel(startLine + lineCount);
+       redrawLines(startLine, lineCount, oldBottom != newBottom);
+       int caretLine = getCaretLine();
+       if (startLine <= caretLine && caretLine < startLine + lineCount) {
+               setCaretLocation();
+       }
+}
+
+/**
+ * Sets the color of the margins.
+ *
+ * @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.5
+ */
+public void setMarginColor(Color color) {
+       checkWidget();
+       if (color != null && color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       marginColor = color;
+       super.redraw();
+}
+/**
+ * Sets the margins.
+ *
+ * @param leftMargin the left margin.
+ * @param topMargin the top margin.
+ * @param rightMargin the right margin.
+ * @param bottomMargin the bottom margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
+       checkWidget();
+       this.leftMargin = Math.max(0, leftMargin) + alignmentMargin;
+       this.topMargin = Math.max(0, topMargin);
+       this.rightMargin = Math.max(0, rightMargin);
+       this.bottomMargin = Math.max(0, bottomMargin);
+       resetCache(0, content.getLineCount());
+       setScrollBars(true);
+       setCaretLocation();
+       setAlignment();
+       super.redraw();
+}
+/**
+ * Sets the enabled state of the mouse navigator. When the mouse navigator is enabled, the user can navigate through the widget
+ * by pressing the middle button and moving the cursor.
+ *
+ * @param enabled if true, the mouse navigator is enabled, if false the mouse navigator is deactivated
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.110
+ */
+public void setMouseNavigatorEnabled(boolean enabled) {
+       checkWidget();
+       if ((enabled && mouseNavigator != null) || (!enabled && mouseNavigator == null)) {
+               return;
+       }
+       if (enabled) {
+               mouseNavigator = new MouseNavigator(this);
+       } else {
+               mouseNavigator.dispose();
+               mouseNavigator = null;
+       }
+}
+/**
+ * Flips selection anchor based on word selection direction.
+ */
+void setMouseWordSelectionAnchor() {
+       if (doubleClickEnabled && 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
+ */
+@Override
+public void setOrientation(int orientation) {
+       int oldOrientation = getOrientation();
+       super.setOrientation(orientation);
+       int newOrientation = getOrientation();
+       if (oldOrientation != newOrientation) {
+               resetBidiData();
+       }
+}
+/**
+ * Sets the right margin.
+ *
+ * @param rightMargin the right margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public void setRightMargin (int rightMargin) {
+       checkWidget();
+       setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
+}
+void setScrollBar(ScrollBar bar, int clientArea, int maximum, int margin) {
+       int inactive = 1;
+       if (clientArea < maximum) {
+               bar.setMaximum(maximum - margin);
+               bar.setThumb(clientArea - margin);
+               bar.setPageIncrement(clientArea - margin);
+               if (!alwaysShowScroll) bar.setVisible(true);
+       } else if (bar.getThumb() != inactive || bar.getMaximum() != inactive) {
+               bar.setValues(bar.getSelection(), bar.getMinimum(), inactive, inactive, bar.getIncrement(), inactive);
+       }
+}
+/**
+ * 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(boolean vertical) {
+       ignoreResize++;
+       if (!isFixedLineHeight() || !alwaysShowScroll) vertical = true;
+       ScrollBar verticalBar = vertical ? getVerticalBar() : null;
+       ScrollBar horizontalBar = getHorizontalBar();
+       int oldHeight = clientAreaHeight;
+       int oldWidth = clientAreaWidth;
+       if (!alwaysShowScroll) {
+               if (verticalBar != null) verticalBar.setVisible(false);
+               if (horizontalBar != null) horizontalBar.setVisible(false);
+       }
+       if (verticalBar != null) {
+               setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
+       }
+       if (horizontalBar != null && !wordWrap) {
+               setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
+               if (!alwaysShowScroll && horizontalBar.getVisible() && verticalBar != null) {
+                       setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
+                       if (verticalBar.getVisible()) {
+                               setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
+                       }
+               }
+       }
+       if (!alwaysShowScroll) {
+               redrawMargins(oldHeight, oldWidth);
+       }
+       ignoreResize--;
+}
+/**
+ * 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 &gt; 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 == 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 != null) {
+               if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       selectionBackground = color;
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       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 != null) {
+               if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       selectionForeground = color;
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       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 &gt; 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 &gt;= 0 must be true.
+ * @param length number of characters to select, 0 &lt;= start + length
+ *     &lt;= 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, boolean sendEvent, boolean doBlock) {
+       int end = start + length;
+       if (start > end) {
+               int temp = end;
+               end = start;
+               start = temp;
+       }
+       // is the selection range different or is the selection direction
+       // different?
+       if (selection.x != start || selection.y != end ||
+               (length > 0 && selectionAnchor != selection.x) ||
+               (length < 0 && selectionAnchor != selection.y)) {
+               if (blockSelection && doBlock) {
+                       if (length < 0) {
+                               setBlockSelectionOffset(end, start, sendEvent);
+                       } else {
+                               setBlockSelectionOffset(start, end, sendEvent);
+                       }
+               } else {
+                       int oldStart = selection.x;
+                       int oldLength = selection.y - selection.x;
+                       int charCount = content.getCharCount();
+                       // called internally to remove selection after text is removed
+                       // therefore make sure redraw range is valid.
+                       int redrawX = Math.min(selection.x, charCount);
+                       int redrawY = Math.min(selection.y, charCount);
+                       if (length < 0) {
+                               selectionAnchor = selection.y = end;
+                               selection.x = start;
+                               setCaretOffset(start, PREVIOUS_OFFSET_TRAILING);
+                       } else {
+                               selectionAnchor = selection.x = start;
+                               selection.y = end;
+                               setCaretOffset(end, PREVIOUS_OFFSET_TRAILING);
+                       }
+                       redrawX = Math.min(redrawX, selection.x);
+                       redrawY = Math.max(redrawY, selection.y);
+                       if (redrawY - redrawX > 0) {
+                               internalRedrawRange(redrawX, redrawY - redrawX);
+                       }
+                       if (sendEvent && (oldLength != end - start || (oldLength != 0 && oldStart != start))) {
+                               sendSelectionEvent();
+                       }
+                       sendAccessibleTextCaretMoved();
+               }
+       }
+}
+/**
+ * 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, true);
+       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 (&gt; getCharCount())</li>
+ * </ul>
+ */
+public void setStyleRange(StyleRange range) {
+       checkWidget();
+       if (isListening(ST.LineGetStyle)) return;
+       if (range != null) {
+               if (range.isUnstyled()) {
+                       setStyleRanges(range.start, range.length, null, null, false);
+               } else {
+                       setStyleRanges(range.start, 0, null, new StyleRange[]{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 == styles.length)</li>
+ *    <li>ERROR_INVALID_RANGE when a range is outside the valid range (&gt; 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(ST.LineGetStyle)) return;
+       if (ranges == null || styles == 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 == styles.length)</li>
+ *    <li>ERROR_INVALID_RANGE when a range is outside the valid range (&gt; 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(ST.LineGetStyle)) return;
+       if (ranges == null || styles == null) {
+               setStyleRanges(0, 0, null, null, true);
+       } else {
+               setStyleRanges(0, 0, ranges, styles, true);
+       }
+}
+void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) {
+       int charCount = content.getCharCount();
+       if (reset) {
+               start = 0;
+               length = charCount;
+       }
+       int[] formerRanges = getRanges(start, length);
+       StyleRange[] formerStyles = getStyleRanges(start, length);
+       int end = start + length;
+       final boolean wasFixedLineHeight = isFixedLineHeight();
+       if (start > end || start < 0) {
+               SWT.error(SWT.ERROR_INVALID_RANGE);
+       }
+       if (styles != null) {
+               if (end > charCount) {
+                       SWT.error(SWT.ERROR_INVALID_RANGE);
+               }
+               if (ranges != null) {
+                       if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+               int lastOffset = 0;
+               for (int i = 0; i < styles.length; i ++) {
+                       if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+                       int rangeStart, rangeLength;
+                       if (ranges != 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);
+                       hasStyleWithVariableHeight |= styles[i].isVariableHeight();
+                       lastOffset = rangeStart + rangeLength;
+               }
+       }
+       int rangeStart = start, rangeEnd = end;
+       if (styles != null && styles.length > 0) {
+               if (ranges != 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;
+               }
+       }
+
+       // This needs to happen before new styles are applied
+       int expectedBottom = 0;
+       if (!isFixedLineHeight() && !reset) {
+               int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+               int partialTopIndex = getPartialTopIndex();
+               int partialBottomIndex = getPartialBottomIndex();
+               if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+                       expectedBottom = getLinePixel(lineEnd + 1);
+               }
+       }
+       if (reset) {
+               renderer.setStyleRanges(null, null);
+       } else {
+               renderer.updateRanges(start, length, length);
+       }
+       if (styles != null && styles.length > 0) {
+               renderer.setStyleRanges(ranges, styles);
+       }
+
+       // re-evaluate variable height with all styles (including new ones)
+       hasStyleWithVariableHeight = false;
+       for (StyleRange style : getStyleRanges(false)) {
+               hasStyleWithVariableHeight = style.isVariableHeight();
+               if (hasStyleWithVariableHeight) break;
+       }
+
+       SortedSet<Integer> modifiedLines = computeModifiedLines(formerRanges, formerStyles, ranges, styles);
+       resetCache(modifiedLines);
+       if (reset) {
+               super.redraw();
+       } else {
+               int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
+               int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+               int partialTopIndex = getPartialTopIndex();
+               int partialBottomIndex = getPartialBottomIndex();
+               if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) {
+                       int top = 0;
+                       int bottom = clientAreaHeight;
+                       if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) {
+                               top = Math.max(0, getLinePixel(lineStart));
+                       }
+                       if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+                               bottom = getLinePixel(lineEnd + 1);
+                       }
+                       if (!(wasFixedLineHeight && isFixedLineHeight()) && bottom != expectedBottom) {
+                               bottom = clientAreaHeight;
+                       }
+                       super.redraw(0, top, clientAreaWidth, bottom - top, false);
+               }
+       }
+       int oldColumnX = columnX;
+       setCaretLocation();
+       columnX = oldColumnX;
+       doMouseLinkCursor();
+}
+
+/**
+ *
+ * @param referenceRanges former ranges, sorted by order and without overlapping, typically returned {@link #getRanges(int, int)}
+ * @param referenceStyles
+ * @param newRanges former ranges, sorted by order and without overlapping
+ * @param newStyles
+ * @return
+ */
+private SortedSet<Integer> computeModifiedLines(int[] referenceRanges, StyleRange[] referenceStyles, int[] newRanges, StyleRange[] newStyles) {
+       if (referenceStyles == null) {
+               referenceStyles = new StyleRange[0];
+       }
+       if (referenceRanges == null) {
+               referenceRanges = createRanges(referenceStyles);
+       }
+       if (newStyles == null) {
+               newStyles = new StyleRange[0];
+       }
+       if (newRanges == null) {
+               newRanges = createRanges(newStyles);
+       }
+       if (referenceRanges.length != 2 * referenceStyles.length) {
+               throw new IllegalArgumentException();
+       }
+       if (newRanges.length != 2 * newStyles.length) {
+               throw new IllegalArgumentException();
+       }
+       SortedSet<Integer> res = new TreeSet<>();
+       int referenceRangeIndex = 0;
+       int newRangeIndex = 0;
+       StyleRange defaultStyle = new StyleRange();
+       defaultStyle.foreground = this.foreground;
+       defaultStyle.background = this.background;
+       defaultStyle.font = getFont();
+       int currentOffset = referenceRanges.length > 0 ? referenceRanges[0] : Integer.MAX_VALUE;
+       if (newRanges.length > 0) {
+               currentOffset = Math.min(currentOffset, newRanges[0]);
+       }
+       while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) {
+               int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset
+
+               while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) {
+                       referenceRangeIndex++;
+               }
+               StyleRange referenceStyleAtCurrentOffset = defaultStyle;
+               if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling
+                       referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex];
+                       nextMilestoneOffset =  endRangeOffset(referenceRanges, referenceRangeIndex);
+               } else if (referenceRangeIndex < referenceStyles.length) { // no range, default styling
+                       nextMilestoneOffset = referenceRanges[2 * referenceRangeIndex]; // beginning of next range
+               }
+
+               while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) {
+                       newRangeIndex++;
+               }
+               StyleRange newStyleAtCurrentOffset = defaultStyle;
+               if (isInRange(newRanges, newRangeIndex, currentOffset)) {
+                       newStyleAtCurrentOffset = newStyles[newRangeIndex];
+                       nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex));
+               } else if (newRangeIndex < newStyles.length) {
+                       nextMilestoneOffset = Math.min(nextMilestoneOffset, newRanges[2 * newRangeIndex]);
+               }
+
+               if (!referenceStyleAtCurrentOffset.similarTo(newStyleAtCurrentOffset)) {
+                       int fromLine = getLineAtOffset(currentOffset);
+                       int toLine = getLineAtOffset(nextMilestoneOffset - 1);
+                       for (int line = fromLine; line <= toLine; line++) {
+                               res.add(line);
+                       }
+                       currentOffset = toLine + 1 < getLineCount() ? getOffsetAtLine(toLine + 1) : content.getCharCount();
+               } else {
+                       currentOffset = nextMilestoneOffset;
+               }
+       }
+       return res;
+}
+private int[] createRanges(StyleRange[] referenceStyles) {
+       int[] referenceRanges;
+       referenceRanges = new int[2 * referenceStyles.length];
+       for (int i = 0; i < referenceStyles.length; i++) {
+               referenceRanges[2 * i] = referenceStyles[i].start;
+               referenceRanges[2 * i + 1] = referenceStyles[i].length;
+       }
+       return referenceRanges;
+}
+
+private boolean isInRange(int[] ranges, int styleIndex, int offset) {
+       if (ranges == null || ranges.length == 0 || styleIndex < 0 || 2 * styleIndex + 1 > ranges.length) {
+               return false;
+       }
+       int start = ranges[2 * styleIndex];
+       int length = ranges[2 * styleIndex + 1];
+       return offset >= start && offset < start + length;
+}
+
+/**
+ * The offset on which the range ends (excluded)
+ * @param ranges
+ * @param styleIndex
+ * @return
+ */
+private int endRangeOffset(int[] ranges, int styleIndex) {
+       if (styleIndex < 0 || 2 * styleIndex > ranges.length) {
+               throw new IllegalArgumentException();
+       }
+       int start = ranges[2 * styleIndex];
+       int length = ranges[2 * styleIndex + 1];
+       return start + length;
+}
+
+/**
+ * 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_NULL_ARGUMENT when the list of ranges is null</li>
+ *    <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (&gt; getCharCount())</li>
+ * </ul>
+ *
+ * @see #setStyleRanges(int[], StyleRange[])
+ */
+public void setStyleRanges(StyleRange[] ranges) {
+       checkWidget();
+       if (isListening(ST.LineGetStyle)) return;
+       if (ranges == 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>
+ *
+ * @see #setTabStops(int[])
+ */
+public void setTabs(int tabs) {
+       checkWidget();
+       tabLength = tabs;
+       renderer.setFont(null, tabs);
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       super.redraw();
+}
+
+/**
+ * Sets the receiver's tab list. Each value in the tab list specifies
+ * the space in points from the origin of the document to the respective
+ * tab stop.  The last tab stop width is repeated continuously.
+ *
+ * @param tabs the new tab list (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>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if a tab stop is negative or less than the previous stop in the list</li>
+ * </ul>
+ *
+ * @see StyledText#getTabStops()
+ *
+ * @since 3.6
+ */
+public void setTabStops(int [] tabs) {
+       checkWidget();
+       if (tabs != null) {
+               int pos = 0;
+               int[] newTabs = new int[tabs.length];
+               for (int i = 0; i < tabs.length; i++) {
+                       if (tabs[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+                       newTabs[i] = pos = tabs[i];
+               }
+               this.tabs = newTabs;
+       } else {
+               this.tabs = null;
+       }
+       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>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when string is null</li>
+ * </ul>
+ */
+public void setText(String text) {
+       checkWidget();
+       if (text == 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(ST.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);
+               notifyListeners(SWT.Modify, event);
+               if (styledTextEvent != null) {
+                       notifyListeners(ST.ExtendedModify, styledTextEvent);
+               }
+       }
+}
+
+/**
+ * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
+ * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code> or
+ * <code>SWT.RIGHT_TO_LEFT</code>.
+ * <p>
+ * <code>setOrientation</code> would override this value with the text direction
+ * that is consistent with the new orientation.
+ * </p>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows.
+ * It doesn't set the base text direction on GTK and Cocoa.
+ * </p>
+ *
+ * @param textDirection the base text direction 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>
+ *
+ * @see SWT#FLIP_TEXT_DIRECTION
+ */
+@Override
+public void setTextDirection(int textDirection) {
+       checkWidget();
+       int oldStyle = getStyle();
+       super.setTextDirection(textDirection);
+       if (isAutoDirection () || oldStyle != getStyle()) {
+               resetBidiData();
+       }
+}
+
+/**
+ * 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 == 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() == 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 margin.
+ *
+ * @param topMargin the top margin.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.5
+ */
+public void setTopMargin (int topMargin) {
+       checkWidget();
+       setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
+}
+/**
+ * Sets the top SWT logical point offset. Do nothing if there is no text set.
+ * <p>
+ * The top point offset is the vertical SWT logical point offset of the widget. The
+ * widget is scrolled so that the given SWT logical point position is at the top.
+ * The top index is adjusted to the corresponding top line.
+ * Note: The top point is reset to 0 when new text is set in the widget.
+ * </p>
+ *
+ * @param pixel new top point 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() == 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(boolean wrap) {
+       checkWidget();
+       if ((getStyle() & SWT.SINGLE) != 0) return;
+       if (wordWrap == wrap) return;
+       if (wordWrap && blockSelection) setBlockSelection(false);
+       wordWrap = wrap;
+       resetCache(0, content.getLineCount());
+       horizontalScrollOffset = 0;
+       ScrollBar horizontalBar = getHorizontalBar();
+       if (horizontalBar != null) {
+               horizontalBar.setVisible(!wordWrap);
+       }
+       setScrollBars(true);
+       setCaretLocation();
+       super.redraw();
+}
+/**
+ * Sets the wrap line indentation of the widget.
+ * <p>
+ * It is the amount of blank space, in points, at the beginning of each wrapped line.
+ * When a line wraps in several lines all the lines but the first one is indented
+ * by this amount.
+ * </p>
+ *
+ * @param wrapIndent the new wrap 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 #setLineWrapIndent(int, int, int)
+ *
+ * @since 3.6
+ */
+public void setWrapIndent(int wrapIndent) {
+       checkWidget();
+       if (this.wrapIndent == wrapIndent || wrapIndent < 0) return;
+       this.wrapIndent = wrapIndent;
+       resetCache(0, content.getLineCount());
+       setCaretLocation();
+       super.redraw();
+}
+boolean showLocation(Rectangle rect, boolean scrollPage) {
+       boolean scrolled = false;
+       if (rect.y < topMargin) {
+               scrolled = scrollVertical(rect.y - topMargin, true);
+       } else if (rect.y + rect.height > clientAreaHeight - bottomMargin) {
+               if (clientAreaHeight - topMargin - bottomMargin <= 0) {
+                       scrolled = scrollVertical(rect.y - topMargin, true);
+               } else {
+                       scrolled = scrollVertical(rect.y + rect.height - (clientAreaHeight - bottomMargin), true);
+               }
+       }
+       int width = clientAreaWidth - rightMargin - leftMargin;
+       if (width > 0) {
+               int minScroll = scrollPage ? width / 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 - rightMargin)) {
+                       int scrollWidth =  Math.max(rect.x + rect.width - (clientAreaWidth - rightMargin), minScroll);
+                       int maxScroll = renderer.getWidth() - horizontalScrollOffset - 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?
+       boolean rightToLeft = caretOffset == 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;
+       boolean 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 = endOffset == caretOffset ? getCaretWidth() : 0;
+               showLocation(endBounds, false);
+       } else {
+               // just show the end of the selection since the selection start
+               // will not be visible
+               showLocation(endBounds, true);
+       }
+}
+void updateCaretVisibility() {
+       Caret caret = getCaret();
+       if (caret != null) {
+               if (blockSelection && blockXLocation != -1) {
+                       caret.setVisible(false);
+               } else {
+                       Point location = caret.getLocation();
+                       Point size = caret.getSize();
+                       boolean visible =
+                               topMargin <= location.y + size.y && location.y <= clientAreaHeight - bottomMargin &&
+                               leftMargin <= location.x + size.x && location.x <= clientAreaWidth - rightMargin;
+                       caret.setVisible(visible);
+               }
+       }
+}
+/**
+ * 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 (isWordWrap()) 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, false);
+       } else {
+               // move selection to keep same text selected
+               setSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true, false);
+       }
+       setCaretLocation();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextContent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextContent.java
new file mode 100644 (file)
index 0000000..72a12b0
--- /dev/null
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+/**
+ * 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
+ *     For example, if text = "\r\n\r\n", and delimiter = "\r\n", then:
+ * <ul>
+ * <li>getLine(0) == ""
+ * <li>getLine(1) == ""
+ * <li>getLine(2) == ""
+ * </ul>
+ *     or if text = "A\nBC\nD", and delimiter = "\n", then:
+ * <ul>
+ * <li>getLine(0) == "A"
+ * <li>getLine(1) == "BC"
+ * <li>getLine(2) == "D"
+ * </ul>
+ */
+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 {@link #getCharCount()} is valid
+ *     and should answer the line index of the last line.
+ * @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) == 0
+ * <li>getLineAtOffset(1) == 0
+ * <li>getLineAtOffset(2) == 1
+ * <li>getLineAtOffset(3) == 1
+ * <li>getLineAtOffset(4) == 2
+ * </ul>
+ *     or if text = "A\nBC\nD", and delimiter = "\n", then:
+ * <ul>
+ * <li>getLineAtOffset(0) == 0
+ * <li>getLineAtOffset(1) == 0
+ * <li>getLineAtOffset(2) == 1
+ * <li>getLineAtOffset(3) == 1
+ * <li>getLineAtOffset(4) == 1
+ * <li>getLineAtOffset(5) == 2
+ * <li>getLineAtOffset(6) == 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 ==&gt; getLineCount
+ * <li>        null ==&gt; 1
+ * <li>        "" ==&gt; 1
+ * <li>        "a\n" ==&gt; 2
+ * <li>        "\n\n" ==&gt; 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) == 0
+ * <li>getOffsetAtLine(1) == 2
+ * <li>getOffsetAtLine(2) == 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:
+ * </p>
+ * <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) ==&gt; (replaceLineCount, newLineCount)
+ * <li>("", "\n") ==&gt; (0, 1)
+ * <li>("\n\n", "a") ==&gt; (2, 0)
+ * <li>("a", "\n\n") ==&gt; (0, 2)
+ * <li>("\n", "") ==&gt; (1, 0)
+ * </ul>
+ *
+ * @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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.java
new file mode 100644 (file)
index 0000000..675cad9
--- /dev/null
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
+ * </dl>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class StyledTextDropTargetEffect extends 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 StyledTextDropTargetEffect(StyledText styledText) {
+               super(styledText);
+               paintListener = event -> {
+                       if (currentOffset != -1) {
+                               StyledText text = (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
+        */
+       @Override
+       public 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
+        */
+       @Override
+       public void dragLeave(DropTargetEvent event) {
+               StyledText text = (StyledText) getControl();
+               if (currentOffset != -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
+        */
+       @Override
+       public void dragOver(DropTargetEvent event) {
+               int effect = event.feedback;
+               StyledText text = (StyledText) getControl();
+
+               Point pt = text.getDisplay().map(null, text, event.x, event.y);
+               if ((effect & DND.FEEDBACK_SCROLL) == 0) {
+                       scrollBeginTime = 0;
+                       scrollX = scrollY = -1;
+               } else {
+                       if (text.getCharCount() == 0) {
+                               scrollBeginTime = 0;
+                               scrollX = scrollY = -1;
+                       } else {
+                               if (scrollX != -1 && scrollY != -1 && scrollBeginTime != 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();
+                                               double charWidth = fm.getAverageCharacterWidth();
+                                               int scrollAmount = (int) (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) != 0) {
+                       int[] trailing = new int [1];
+                       int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false);
+                       newOffset += trailing [0];
+                       if (newOffset != currentOffset) {
+                               refreshCaret(text, currentOffset, newOffset);
+                               currentOffset = newOffset;
+                       }
+               }
+       }
+
+       void refreshCaret(StyledText text, int oldOffset, int newOffset) {
+               if (oldOffset != newOffset) {
+                       if (oldOffset != -1) {
+                               Point oldPos = text.getLocationAtOffset(oldOffset);
+                               int oldHeight = text.getLineHeight(oldOffset);
+                               text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false);
+                       }
+                       if (newOffset != -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
+        */
+       @Override
+       public void dropAccept(DropTargetEvent event) {
+               if (currentOffset != -1) {
+                       StyledText text = (StyledText) getControl();
+                       text.setSelection(currentOffset);
+                       currentOffset = -1;
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextEvent.java
new file mode 100644 (file)
index 0000000..7004d37
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ *
+ */
+class StyledTextEvent extends Event {
+       // used by LineStyleEvent
+       int[] ranges;
+       StyleRange[] styles;
+       int alignment;
+       int indent;
+       int verticalIndent;
+       int wrapIndent;
+       boolean justify;
+       Bullet bullet;
+       int bulletIndex;
+       int[] tabStops;
+       // used by LineBackgroundEvent
+       Color lineBackground;
+       // used by TextChangedEvent
+       int replaceCharCount;
+       int newCharCount;
+       int replaceLineCount;
+       int newLineCount;
+       // used by PaintObjectEvent
+       int x;
+       int y;
+       int ascent;
+       int descent;
+       StyleRange style;
+
+StyledTextEvent (StyledTextContent content) {
+       super();
+       data = content;
+}
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextLineSpacingProvider.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextLineSpacingProvider.java
new file mode 100644 (file)
index 0000000..430a77d
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ *  Copyright (c) 2017 Angelo ZERR.
+ *
+ *  This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License 2.0
+ *  which accompanies this distribution, and is available at
+ *  https://www.eclipse.org/legal/epl-2.0/
+ *
+ *  SPDX-License-Identifier: EPL-2.0
+ *
+ *  Contributors:
+ *  Angelo Zerr <angelo.zerr@gmail.com> - Customize different line spacing of StyledText - Bug 522020
+ */
+package org.eclipse.swt.custom;
+
+/**
+ * Line spacing provider used to customize different line spacing for some lines
+ * of {@link StyledText}
+ *
+ * @since 3.107
+ */
+@FunctionalInterface
+public interface StyledTextLineSpacingProvider {
+
+       /**
+        * Returns the line spacing of the given line index and null otherwise. In this
+        * case, it will use the {@link StyledText#getLineSpacing()}.
+        *
+        * @param lineIndex
+        *            line index.
+        * @return the line spacing of the given line index and null otherwise. In this
+        *         case, it will use the {@link StyledText#getLineSpacing()}.
+        * @since 3.107
+        */
+       Integer getLineSpacing(int lineIndex);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextListener.java
new file mode 100644 (file)
index 0000000..d27682f
--- /dev/null
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.widgets.*;
+
+class StyledTextListener extends TypedListener {
+/**
+ */
+StyledTextListener(SWTEventListener listener) {
+       super(listener);
+}
+/**
+ * Process StyledText events by invoking the event's handler.
+ *
+ * @param e the event to handle
+ */
+@Override
+public void handleEvent(Event e) {
+
+       switch (e.type) {
+               case ST.ExtendedModify:
+                       ExtendedModifyEvent extendedModifyEvent = new ExtendedModifyEvent((StyledTextEvent) e);
+                       ((ExtendedModifyListener) eventListener).modifyText(extendedModifyEvent);
+                       break;
+               case ST.LineGetBackground:
+                       LineBackgroundEvent lineBgEvent = new LineBackgroundEvent((StyledTextEvent) e);
+                       ((LineBackgroundListener) eventListener).lineGetBackground(lineBgEvent);
+                       ((StyledTextEvent) e).lineBackground = lineBgEvent.lineBackground;
+                       break;
+               case ST.LineGetSegments:
+                       BidiSegmentEvent segmentEvent = new BidiSegmentEvent((StyledTextEvent) e);
+                       ((BidiSegmentListener) eventListener).lineGetSegments(segmentEvent);
+                       ((StyledTextEvent) e).segments = segmentEvent.segments;
+                       ((StyledTextEvent) e).segmentsChars = segmentEvent.segmentsChars;
+                       break;
+               case ST.LineGetStyle:
+                       LineStyleEvent lineStyleEvent = new LineStyleEvent((StyledTextEvent) e);
+                       ((LineStyleListener) eventListener).lineGetStyle(lineStyleEvent);
+                       ((StyledTextEvent) e).ranges = lineStyleEvent.ranges;
+                       ((StyledTextEvent) e).styles = lineStyleEvent.styles;
+                       ((StyledTextEvent) e).alignment = lineStyleEvent.alignment;
+                       ((StyledTextEvent) e).indent = lineStyleEvent.indent;
+                       ((StyledTextEvent) e).verticalIndent = lineStyleEvent.verticalIndent;
+                       ((StyledTextEvent) e).wrapIndent = lineStyleEvent.wrapIndent;
+                       ((StyledTextEvent) e).justify = lineStyleEvent.justify;
+                       ((StyledTextEvent) e).bullet = lineStyleEvent.bullet;
+                       ((StyledTextEvent) e).bulletIndex = lineStyleEvent.bulletIndex;
+                       ((StyledTextEvent) e).tabStops = lineStyleEvent.tabStops;
+                       break;
+               case ST.PaintObject:
+                       PaintObjectEvent paintObjectEvent = new PaintObjectEvent((StyledTextEvent) e);
+                       ((PaintObjectListener) eventListener).paintObject(paintObjectEvent);
+                       break;
+               case ST.VerifyKey:
+                       VerifyEvent verifyEvent = new VerifyEvent(e);
+                       ((VerifyKeyListener) eventListener).verifyKey(verifyEvent);
+                       e.doit = verifyEvent.doit;
+                       break;
+               case ST.TextChanged: {
+                       TextChangedEvent textChangedEvent = new TextChangedEvent((StyledTextContent) e.data);
+                       ((TextChangeListener) eventListener).textChanged(textChangedEvent);
+                       break;
+               }
+               case ST.TextChanging:
+                       TextChangingEvent textChangingEvent = new TextChangingEvent((StyledTextContent) e.data, (StyledTextEvent) e);
+                       ((TextChangeListener) eventListener).textChanging(textChangingEvent);
+                       break;
+               case ST.TextSet: {
+                       TextChangedEvent textChangedEvent = new TextChangedEvent((StyledTextContent) e.data);
+                       ((TextChangeListener) eventListener).textSet(textChangedEvent);
+                       break;
+               }
+               case ST.WordNext: {
+                       MovementEvent wordBoundaryEvent = new MovementEvent((StyledTextEvent) e);
+                       ((MovementListener) eventListener).getNextOffset(wordBoundaryEvent);
+                       ((StyledTextEvent) e).end = wordBoundaryEvent.newOffset;
+                       break;
+               }
+               case ST.WordPrevious: {
+                       MovementEvent wordBoundaryEvent = new MovementEvent((StyledTextEvent) e);
+                       ((MovementListener) eventListener).getPreviousOffset(wordBoundaryEvent);
+                       ((StyledTextEvent) e).end = wordBoundaryEvent.newOffset;
+                       break;
+               }
+               case ST.CaretMoved: {
+                       CaretEvent caretEvent = new CaretEvent((StyledTextEvent) e);
+                       ((CaretListener) eventListener).caretMoved(caretEvent);
+                       ((StyledTextEvent) e).end = caretEvent.caretOffset;
+                       break;
+               }
+       }
+}
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextPrintOptions.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextPrintOptions.java
new file mode 100644 (file)
index 0000000..9cf2879
--- /dev/null
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+/**
+ * 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 boolean printTextForeground = false;
+       /**
+        * Print the text background color. Default value is <code>false</code>.
+        */
+       public boolean printTextBackground = false;
+       /**
+        * Print the font styles. Default value is <code>false</code>.
+        */
+       public boolean printTextFontStyle = false;
+       /**
+        * Print the line background color. Default value is <code>false</code>.
+        */
+       public boolean printLineBackground = false;
+
+       /**
+        * Print line numbers. Default value is <code>false</code>.
+        *
+        * @since 3.3
+        */
+       public boolean printLineNumbers = false;
+
+       /**
+        * Labels used for printing line numbers.
+        *
+        * @since 3.4
+        */
+       public String[] lineLabels = null;
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/StyledTextRenderer.java
new file mode 100644 (file)
index 0000000..d972777
--- /dev/null
@@ -0,0 +1,1938 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Anton Leherbauer (Wind River Systems) - Bug 439419
+ *     Angelo Zerr <angelo.zerr@gmail.com> - Customize different line spacing of StyledText - Bug 522020
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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;
+
+       /* Custom line spacing */
+       StyledTextLineSpacingProvider lineSpacingProvider;
+       boolean lineSpacingComputing;
+
+       /* Font info */
+       Font regularFont, boldFont, italicFont, boldItalicFont;
+       int tabWidth;
+       int ascent, descent;
+       int averageCharWidth;
+       int tabLength;  //tab length in spaces
+
+       /* Line data */
+       int topIndex = -1;
+       TextLayout[] layouts;
+       int lineCount;
+       LineSizeInfo[] lineSizes;
+       LineInfo[] lines;
+       int maxWidth;
+       int maxWidthLineIndex;
+       boolean idleRunning;
+
+       /* Bullet */
+       Bullet[] bullets;
+       int[] bulletsIndices;
+       int[] redrawLines;
+
+       /* Style data */
+       int[] ranges;
+       int styleCount;
+       StyleRange[] styles;
+       StyleRange[] stylesSet;
+       int stylesSetCount = 0;
+       boolean hasLinks, fixedPitch;
+       final static int BULLET_MARGIN = 8;
+
+       final static boolean COMPACT_STYLES = true;
+       final static boolean MERGE_STYLES = true;
+
+       final static int GROW = 32;
+       final static int IDLE_TIME = 50;
+       final static int CACHE_SIZE = 300;
+
+       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;
+       final static int TABSTOPS = 1 << 6;
+       final static int WRAP_INDENT = 1 << 7;
+       final static int SEGMENT_CHARS = 1 << 8;
+       final static int VERTICAL_INDENT = 1 << 9;
+
+       static class LineSizeInfo {
+
+               private static final int RESETED_SIZE = -1;
+
+               /* Line size */
+               int height;
+               int width;
+
+               public LineSizeInfo() {
+                       resetSize();
+               }
+
+               /**
+                * Reset the line size.
+                */
+               void resetSize() {
+                       height = RESETED_SIZE;
+                       width = RESETED_SIZE;
+               }
+
+               /**
+                * Returns true if the TextLayout get from the layout pool can be directly used
+                * or must be refreshed with styles.
+                *
+                * @return true if the TextLayout get from the layout pool can be directly used
+                *         or must be refreshed with styles.
+                */
+               boolean canLayout() {
+                       return !needsRecalculateWidth();
+               }
+
+               /**
+                * Returns true if it needs to recalculate the line size and false
+                * otherwise.
+                *
+                * @return true if it needs to recalculate the line size and false
+                *         otherwise.
+                */
+               boolean needsRecalculateSize() {
+                       return needsRecalculateWidth() || needsRecalculateHeight();
+               }
+
+               /**
+                * Returns true if it needs to recalculate the line width and false
+                * otherwise.
+                *
+                * @return true if it needs to recalculate the line width and false
+                *         otherwise.
+                */
+               boolean needsRecalculateWidth() {
+                       return width == RESETED_SIZE;
+               }
+
+               /**
+                * Returns true if it needs to recalculate the line height and false
+                * otherwise.
+                *
+                * @return true if it needs to recalculate the line height and false
+                *         otherwise.
+                */
+               boolean needsRecalculateHeight() {
+                       return height == RESETED_SIZE;
+               }
+       }
+
+       static class LineInfo {
+               int flags;
+               Color background;
+               int alignment;
+               int indent;
+               int wrapIndent;
+               boolean justify;
+               int[] segments;
+               char[] segmentsChars;
+               int[] tabStops;
+               int verticalIndent;
+
+               public LineInfo() {
+               }
+               public LineInfo(LineInfo info) {
+                       if (info != null) {
+                               flags = info.flags;
+                               background = info.background;
+                               alignment = info.alignment;
+                               indent = info.indent;
+                               wrapIndent = info.wrapIndent;
+                               justify = info.justify;
+                               segments = info.segments;
+                               segmentsChars = info.segmentsChars;
+                               tabStops = info.tabStops;
+                               verticalIndent = info.verticalIndent;
+                       }
+               }
+       }
+       static int cap (TextLayout layout, int offset) {
+               if (layout == null) return offset;
+               return Math.min (layout.getText().length() -1, Math.max (0, offset));
+       }
+
+StyledTextRenderer(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] == 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 != null && ranges[j - 2] + ranges[j - 1] == 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 == newStyle.start && newStyle.similarTo(style)) {
+                               style.length += newStyle.length;
+                       } else {
+                               styles[j++] = newStyle;
+                       }
+               }
+               StyleRange style = styles[j - 1];
+               if (endStyle != null && style.start + style.length == 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 > lineSizes.length) {
+               return;
+       }
+       int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth();
+       for (int i = startLine; i < endLine; i++) {
+               LineSizeInfo line = getLineSize(i);
+               if (line.needsRecalculateSize()) {
+                       TextLayout layout = getTextLayout(i);
+                       Rectangle rect = layout.getBounds();
+                       line.width = rect.width + hTrim;
+                       line.height = rect.height;
+                       disposeTextLayout(layout);
+               }
+               if (line.width > maxWidth) {
+                       maxWidth = line.width;
+                       maxWidthLineIndex = i;
+               }
+       }
+}
+LineSizeInfo getLineSize(int i) {
+       if (lineSizes[i] == null) {
+               lineSizes[i] = new LineSizeInfo();
+       }
+       return lineSizes[i];
+}
+void calculateClientArea () {
+       int index = Math.max (0, styledText.getTopIndex());
+       int lineCount = content.getLineCount();
+       int height = styledText.getClientArea().height;
+       int y = 0;
+       /*
+        * There exists a possibility of ArrayIndexOutOfBounds Exception in
+        * below code, exact scenario not known. To avoid this exception added
+        * check for 'index' value, refer Bug 471192.
+        */
+       while (height > y && lineCount > index && lineSizes.length > index) {
+               calculate(index, 1);
+               y += lineSizes[index++].height;
+       }
+}
+void calculateIdle () {
+       if (idleRunning) return;
+       Runnable runnable = new Runnable() {
+               @Override
+               public void run() {
+                       if (styledText == null) return;
+                       int i;
+                       long start = System.currentTimeMillis();
+                       for (i = 0; i < lineCount; i++) {
+                               LineSizeInfo line = getLineSize(i);
+                               if (line.needsRecalculateSize()) {
+                                       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 != null) {
+                                       bar.setSelection(styledText.getVerticalScrollOffset());
+                               }
+                       }
+               }
+       };
+       Display display = styledText.getDisplay();
+       display.asyncExec(runnable);
+       idleRunning = true;
+}
+void clearLineBackground(int startLine, int count) {
+       if (lines == null) return;
+       for (int i = startLine; i < startLine + count; i++) {
+               LineInfo info = lines[i];
+               if (info != null) {
+                       info.flags &= ~BACKGROUND;
+                       info.background = null;
+                       if (info.flags == 0) lines[i] = null;
+               }
+       }
+}
+void clearLineStyle(int startLine, int count) {
+       if (lines == null) return;
+       for (int i = startLine; i < startLine + count; i++) {
+               LineInfo info = lines[i];
+               if (info != null) {
+                       info.flags &= ~(ALIGNMENT | INDENT | VERTICAL_INDENT | WRAP_INDENT | JUSTIFY | TABSTOPS);
+                       if (info.flags == 0) lines[i] = null;
+               }
+       }
+}
+void copyInto(StyledTextRenderer renderer) {
+       if (ranges != null) {
+               int[] newRanges = renderer.ranges = new int[styleCount << 1];
+               System.arraycopy(ranges, 0, newRanges, 0, newRanges.length);
+       }
+       if (styles != null) {
+               StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount];
+               for (int i = 0; i < newStyles.length; i++) {
+                       newStyles[i] = (StyleRange)styles[i].clone();
+               }
+               renderer.styleCount = styleCount;
+       }
+       if (lines != 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 != null) boldFont.dispose();
+       if (italicFont != null) italicFont.dispose();
+       if (boldItalicFont != null) boldItalicFont.dispose();
+       boldFont = italicFont = boldItalicFont = null;
+       reset();
+       content = null;
+       device = null;
+       styledText = null;
+}
+void disposeTextLayout (TextLayout layout) {
+       if (layouts != null) {
+               for (int i = 0; i < layouts.length; i++) {
+                       if (layouts[i] == 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 != null) gc.setForeground(color);
+       Font font = style.font;
+       if (font != 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 = String.valueOf(index + 1); break;
+               case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break;
+               case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break;
+       }
+       if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text;
+       Display display = styledText.getDisplay();
+       TextLayout layout = new TextLayout(display);
+       layout.setText(string);
+       layout.setAscent(lineAscent);
+       layout.setDescent(lineDescent);
+       style = (StyleRange)style.clone();
+       style.metrics = null;
+       if (style.font == 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;
+       if (styledText.getBlockSelection()) {
+               selectionStart = selectionEnd = 0;
+       }
+       Rectangle client = styledText.getClientArea();
+       Color lineBackground = getLineBackground(lineIndex, null);
+       StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
+       if (event != null && event.lineBackground != null) lineBackground = event.lineBackground;
+       int height = layout.getBounds().height;
+       int verticalIndent = layout.getVerticalIndent();
+       if (lineBackground != null) {
+               if (verticalIndent > 0) {
+                       gc.setBackground(widgetBackground);
+                       gc.fillRectangle(client.x, paintY, client.width, verticalIndent);
+               }
+               gc.setBackground(lineBackground);
+               gc.fillRectangle(client.x, paintY + verticalIndent, client.width, height - verticalIndent);
+       } else {
+               gc.setBackground(widgetBackground);
+               styledText.drawBackground(gc, client.x, paintY, client.width, height);
+       }
+       gc.setForeground(widgetForeground);
+       if (selectionStart == 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) != 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 != null) {
+               if (bulletsIndices != 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 != -1) break;
+                       }
+               }
+       }
+       if (bulletIndex != -1 && bullet != null) {
+               FontMetrics metrics = layout.getLineMetrics(0);
+               int lineAscent = metrics.getAscent() + metrics.getLeading();
+               if (bullet.type == 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 != null) {
+                       if (ranges == null) ranges = layout.getRanges();
+                       int start = ranges[i << 1];
+                       int length = ranges[(i << 1) + 1] - start + 1;
+                       Point point = layout.getLocation(start, false);
+                       FontMetrics metrics = layout.getLineMetrics(layout.getLineIndex(start));
+                       StyleRange style = (StyleRange)((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 != null) return boldFont;
+                       return boldFont = new Font(device, getFontData(style));
+               case SWT.ITALIC:
+                       if (italicFont != null) return italicFont;
+                       return italicFont = new Font(device, getFontData(style));
+               case SWT.BOLD | SWT.ITALIC:
+                       if (boldItalicFont != 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 + styledText.topMargin + styledText.bottomMargin;
+       }
+       int totalHeight = 0;
+       int width = styledText.getWrapWidth();
+       for (int i = 0; i < lineCount; i++) {
+               LineSizeInfo line = getLineSize(i);
+               int height = line.height;
+               if (line.needsRecalculateHeight()) {
+                       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;
+}
+boolean hasLink(int offset) {
+       if (offset == -1) return false;
+       int lineIndex = content.getLineAtOffset(offset);
+       int lineOffset = content.getOffsetAtLine(lineIndex);
+       String line = content.getLine(lineIndex);
+       StyledTextEvent event = styledText.getLineStyleData(lineOffset, line);
+       if (event != null) {
+               StyleRange[] styles = event.styles;
+               if (styles != null) {
+                       int[] ranges = event.ranges;
+                       if (ranges != null) {
+                               for (int i = 0; i < ranges.length; i+=2) {
+                                       if (ranges[i] <= offset && offset < ranges[i] + ranges[i+1] && styles[i >> 1].underline && styles[i >> 1].underlineStyle == SWT.UNDERLINE_LINK) {
+                                               return true;
+                                       }
+                               }
+                       } else {
+                               for (int i = 0; i < styles.length; i++) {
+                                       StyleRange style = styles[i];
+                                       if (style.start <= offset && offset < style.start + style.length && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+       }  else {
+               if (ranges != null) {
+                       int rangeCount = styleCount << 1;
+                       int index = getRangeIndex(offset, -1, rangeCount);
+                       if (index >= rangeCount) return false;
+                       int rangeStart = ranges[index];
+                       int rangeLength = ranges[index + 1];
+                       StyleRange rangeStyle = styles[index >> 1];
+                       if (rangeStart <= offset && offset < rangeStart + rangeLength && rangeStyle.underline && rangeStyle.underlineStyle == SWT.UNDERLINE_LINK) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+int getLineAlignment(int index, int defaultAlignment) {
+       if (lines == null) return defaultAlignment;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & ALIGNMENT) != 0) {
+               return info.alignment;
+       }
+       return defaultAlignment;
+}
+Color getLineBackground(int index, Color defaultBackground) {
+       if (lines == null) return defaultBackground;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & BACKGROUND) != 0) {
+               return info.background;
+       }
+       return defaultBackground;
+}
+Bullet getLineBullet (int index, Bullet defaultBullet) {
+       if (bullets == null) return defaultBullet;
+       if (bulletsIndices != null) return defaultBullet;
+       for (int i = 0; i < bullets.length; i++) {
+               Bullet bullet = bullets[i];
+               if (bullet.indexOf(index) != -1) return bullet;
+       }
+       return defaultBullet;
+}
+int getLineHeight() {
+       return ascent + descent;
+}
+int getLineHeight(int lineIndex) {
+       LineSizeInfo line = getLineSize(lineIndex);
+       if (line.needsRecalculateHeight()) {
+               // here we are in "variable line height", the call of calculate which uses TextLayout can be very slow
+               // check if line can use the default line height.
+               if (isVariableHeight(lineIndex)) {
+                       calculate(lineIndex, 1);
+               } else {
+                       line.height = getLineHeight() + getLineSpacing(lineIndex);
+               }
+       }
+       return line.height;
+}
+/**
+ * Returns true if the given line can use the default line height and false
+ * otherwise.
+ *
+ * @param lineIndex
+ *            line index
+ * @return true if the given line can use the default line height and false
+ *         otherwise.
+ */
+private boolean isVariableHeight(int lineIndex) {
+       if (styledText.isWordWrap()) {
+               // In word wrap mode, the line height must be recomputed with TextLayout
+               return true;
+       }
+       StyleRange[] styles = getStylesForLine(lineIndex);
+       if (styles != null) {
+               for (StyleRange style : styles) {
+                       if (style.isVariableHeight()) {
+                               // style is variable height
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+/**
+ * returns true if the given line index defines custom line spacing and false
+ * otherwise.
+ *
+ * @param lineIndex
+ *            the line index.
+ * @return true if the given line index defines custom line spacing and false
+ *         otherwise.
+ */
+private int getLineSpacing(int lineIndex) {
+       if (styledText.lineSpacing > 0) {
+               return styledText.lineSpacing;
+       } else if (lineSpacingProvider != null) {
+               Integer lineSpacing = lineSpacingProvider.getLineSpacing(lineIndex);
+               if (lineSpacing != null) {
+                       return lineSpacing;
+               }
+       }
+       return 0;
+}
+/**
+ * Returns styles range for the given line index and null otherwise.
+ *
+ * @param lineIndex
+ *            the line index.
+ * @return styles range for the given line index and null otherwise.
+ */
+private StyleRange[] getStylesForLine(int lineIndex) {
+       int start = styledText.getOffsetAtLine(lineIndex);
+       int length = styledText.getLine(lineIndex).length();
+       return getStyleRanges(start, length, false);
+}
+int getLineIndent(int index, int defaultIndent) {
+       if (lines == null) return defaultIndent;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & INDENT) != 0) {
+               return info.indent;
+       }
+       return defaultIndent;
+}
+int getLineVerticalIndent(int index) {
+       if (lines == null) return 0;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & VERTICAL_INDENT) != 0) {
+               return info.verticalIndent;
+       }
+       return 0;
+}
+int getLineWrapIndent(int index, int defaultWrapIndent) {
+       if (lines == null) return defaultWrapIndent;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & WRAP_INDENT) != 0) {
+               return info.wrapIndent;
+       }
+       return defaultWrapIndent;
+}
+boolean getLineJustify(int index, boolean defaultJustify) {
+       if (lines == null) return defaultJustify;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & JUSTIFY) != 0) {
+               return info.justify;
+       }
+       return defaultJustify;
+}
+int[] getLineTabStops(int index, int[] defaultTabStops) {
+       if (lines == null) return defaultTabStops;
+       LineInfo info = lines[index];
+       if (info != null && (info.flags & TABSTOPS) != 0) {
+               return info.tabStops;
+       }
+       return defaultTabStops;
+}
+StyledTextLineSpacingProvider getLineSpacingProvider() {
+       return lineSpacingProvider;
+}
+int getRangeIndex(int offset, int low, int high) {
+       if (styleCount == 0) return 0;
+       if (ranges != 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) {
+       if (length == 0) return null;
+       int[] newRanges;
+       int end = start + length - 1;
+       if (ranges != 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));
+               if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2);
+               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));
+               if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1);
+               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, boolean includeRanges) {
+       if (length == 0) return null;
+       StyleRange[] newStyles;
+       int end = start + length - 1;
+       if (ranges != 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));
+               if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2);
+               newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1];
+               if (includeRanges) {
+                       for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) {
+                               newStyles[j] = (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));
+               if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1);
+               newStyles = new StyleRange[rangeEnd - rangeStart + 1];
+               System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length);
+       }
+       if (includeRanges || ranges == null) {
+               StyleRange style = newStyles[0];
+               if (start > style.start) {
+                       newStyles[0] = style = (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) {
+                       newStyles[newStyles.length - 1] = style = (StyleRange)style.clone();
+                       style.length = end - style.start + 1;
+               }
+       }
+       return newStyles;
+}
+StyleRange getStyleRange(StyleRange style) {
+       if (style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) hasLinks = true;
+       if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style;
+       StyleRange clone = (StyleRange)style.clone();
+       clone.start = clone.length = 0;
+       clone.fontStyle = SWT.NORMAL;
+       if (clone.font == null) clone.font = getFont(style.fontStyle);
+       return clone;
+}
+TextLayout getTextLayout(int lineIndex) {
+       if (lineSpacingProvider == null) {
+               return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing);
+       }
+       // Compute line spacing for the given line index.
+       int newLineSpacing = styledText.lineSpacing;
+       Integer spacing = lineSpacingProvider.getLineSpacing(lineIndex);
+       if (spacing != null && spacing.intValue() >= 0) {
+               newLineSpacing = spacing;
+       }
+       // Check if line spacing has not changed
+       if (isSameLineSpacing(lineIndex, newLineSpacing)) {
+               return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), newLineSpacing);
+       }
+       // Get text layout with original StyledText line spacing.
+       TextLayout layout = getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(),
+                       styledText.lineSpacing);
+       if (layout.getSpacing() != newLineSpacing) {
+               layout.setSpacing(newLineSpacing);
+               if (lineSpacingComputing) {
+                       return layout;
+               }
+               try {
+                       /* Call of resetCache, setCaretLocation, redraw call getTextLayout method
+                        * To avoid having stack overflow, lineSpacingComputing flag is used to call
+                        * resetCache, setCaretLocation, redraw methods only at the end of the compute of all lines spacing.
+                        */
+                       lineSpacingComputing = true;
+                       styledText.resetCache(lineIndex, 1);
+                       styledText.setCaretLocation();
+                       styledText.redraw();
+               } finally {
+                       lineSpacingComputing = false;
+               }
+       }
+       return layout;
+}
+boolean isSameLineSpacing(int lineIndex, int newLineSpacing) {
+       if (layouts == null) {
+               return false;
+       }
+       int layoutIndex = lineIndex - topIndex;
+       if (0 <= layoutIndex && layoutIndex < layouts.length) {
+               TextLayout layout = layouts[layoutIndex];
+               return layout != null && !layout.isDisposed() && layout.getSpacing() == newLineSpacing;
+       }
+       return false;
+}
+
+private static final class StyleEntry {
+       public final int start;
+       public final int end;
+       public final TextStyle style;
+
+       public StyleEntry(TextStyle style, int start, int end) {
+               this.style = style;
+               this.start = start;
+               this.end = end;
+       }
+}
+
+TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) {
+       TextLayout layout = null;
+       if (styledText != null) {
+               int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0;
+               if (layouts == null || topIndex != this.topIndex) {
+                       TextLayout[] newLayouts = new TextLayout[CACHE_SIZE];
+                       if (layouts != null) {
+                               for (int i = 0; i < layouts.length; i++) {
+                                       if (layouts[i] != null) {
+                                               int layoutIndex = (i + this.topIndex) - topIndex;
+                                               if (0 <= layoutIndex && layoutIndex < newLayouts.length) {
+                                                       newLayouts[layoutIndex] = layouts[i];
+                                               } else {
+                                                       layouts[i].dispose();
+                                               }
+                                       }
+                               }
+                       }
+                       if (bullets != null && bulletsIndices != null && topIndex != 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 != null) {
+                       int layoutIndex = lineIndex - topIndex;
+                       if (0 <= layoutIndex && layoutIndex < layouts.length) {
+                               layout = layouts[layoutIndex];
+                               if (layout != null) {
+                                       // Bug 520374: lineIndex can be >= linesSize.length
+                                       if(lineIndex < lineSizes.length && getLineSize(lineIndex).canLayout()) {
+                                               return layout;
+                                       }
+                               } else {
+                                       layout = layouts[layoutIndex] = new TextLayout(device);
+                               }
+                       }
+               }
+       }
+       if (layout == null) layout = new TextLayout(device);
+       String line = content.getLine(lineIndex);
+       int lineOffset = content.getOffsetAtLine(lineIndex);
+       int[] segments = null;
+       char[] segmentChars = null;
+       int indent = 0;
+       int wrapIndent = 0;
+       int verticalIndent = 0;
+       int alignment = SWT.LEFT;
+       int textDirection = orientation;
+       boolean justify = false;
+       int[] tabs = {tabWidth};
+       Bullet bullet = null;
+       int[] ranges = null;
+       StyleRange[] styles = null;
+       int rangeStart = 0, styleCount = 0;
+       StyledTextEvent event = null;
+       if (styledText != null) {
+               event = styledText.getBidiSegments(lineOffset, line);
+               if (event != null) {
+                       segments = event.segments;
+                       segmentChars = event.segmentsChars;
+               }
+               event = styledText.getLineStyleData(lineOffset, line);
+               indent = styledText.indent;
+               wrapIndent = styledText.wrapIndent;
+               alignment = styledText.alignment;
+               if (styledText.isAutoDirection()) {
+                       textDirection = SWT.AUTO_TEXT_DIRECTION;
+               } else if ((styledText.getStyle() & SWT.FLIP_TEXT_DIRECTION) != 0) {
+                       textDirection = orientation == SWT.RIGHT_TO_LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
+               }
+               justify = styledText.justify;
+               if (styledText.tabs != null) tabs = styledText.tabs;
+       }
+       if (event != null) {
+               indent = event.indent;
+               verticalIndent = event.verticalIndent;
+               wrapIndent = event.wrapIndent;
+               alignment = event.alignment;
+               justify = event.justify;
+               bullet = event.bullet;
+               ranges = event.ranges;
+               styles = event.styles;
+               if (event.tabStops != null) tabs = event.tabStops;
+               if (styles != null) {
+                       styleCount = styles.length;
+                       if (styledText.isFixedLineHeight()) {
+                               for (int i = 0; i < styleCount; i++) {
+                                       if (styles[i].isVariableHeight()) {
+                                               styledText.hasStyleWithVariableHeight = true;
+                                               styledText.verticalScrollOffset = -1;
+                                               styledText.redraw();
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               if (bullets == null || bulletsIndices == 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 != null) {
+                       LineInfo info = lines[lineIndex];
+                       if (info != null) {
+                               if ((info.flags & INDENT) != 0) indent = info.indent;
+                               if ((info.flags & VERTICAL_INDENT) != 0) verticalIndent = info.verticalIndent;
+                               if ((info.flags & WRAP_INDENT) != 0) wrapIndent = info.wrapIndent;
+                               if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment;
+                               if ((info.flags & JUSTIFY) != 0) justify = info.justify;
+                               if ((info.flags & SEGMENTS) != 0) segments = info.segments;
+                               if ((info.flags & SEGMENT_CHARS) != 0) segmentChars = info.segmentsChars;
+                               if ((info.flags & TABSTOPS) != 0) tabs = info.tabStops;
+                       }
+               }
+               if (bulletsIndices != null) {
+                       bullets = null;
+                       bulletsIndices = null;
+               }
+               if (bullets != null) {
+                       for (int i = 0; i < bullets.length; i++) {
+                               if (bullets[i].indexOf(lineIndex) != -1) {
+                                       bullet = bullets[i];
+                                       break;
+                               }
+                       }
+               }
+               ranges = this.ranges;
+               styles = this.styles;
+               styleCount = this.styleCount;
+               if (ranges != null) {
+                       rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1);
+               } else {
+                       rangeStart = getRangeIndex(lineOffset, -1, styleCount);
+               }
+       }
+       if (bullet != null) {
+               StyleRange style = bullet.style;
+               GlyphMetrics metrics = style.metrics;
+               indent += metrics.width;
+       }
+
+       // prepare styles, as it may change the line content, do it before calling layout.setText()
+       // This needs to happen early to handle the case of GlyphMetrics on \t.
+       // The root cause is that TextLayout doesn't return the right value for the bounds when
+       // GlyphMetrics are applied on \t. A better fix could be implemented directly in (all 3)
+       // TextLayout classes.
+       List<StyleEntry> styleEntries = new ArrayList<>();
+       int lastOffset = 0;
+       int length = line.length();
+       if (styles != null) {
+               if (ranges != 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) {
+                                       styleEntries.add(new StyleEntry(null, lastOffset, start - 1));
+                               }
+                               TextStyle style = getStyleRange(styles[i >> 1]);
+                               int endIndex = Math.max(start, Math.min(length, end + 1));
+                               if (style.metrics != null && line.substring(start, endIndex).contains("\t")) {
+                                       line =
+                                               line.substring(0, start) +
+                                               line.substring(start, endIndex).replace('\t', ' ') +
+                                               (end < line.length() ? line.substring(end + 1, line.length()) : "");
+                               }
+                               styleEntries.add(new StyleEntry(style, 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) {
+                                       styleEntries.add(new StyleEntry(null, lastOffset, start - 1));
+                               }
+                               TextStyle style = getStyleRange(styles[i]);
+                               int endIndex = Math.max(start, Math.min(length, end + 1));
+                               if (style.metrics != null && line.substring(start, endIndex).contains("\t")) {
+                                       line =
+                                               line.substring(0, start) +
+                                               line.substring(start, endIndex).replace('\t', ' ') +
+                                               (end < line.length() ? line.substring(end + 1, line.length()) : "");
+                               }
+                               styleEntries.add(new StyleEntry(style, start, end));
+                               lastOffset = Math.max(lastOffset, end);
+                       }
+               }
+       }
+       if (lastOffset < length) styleEntries.add(new StyleEntry(null, lastOffset, length));
+
+       layout.setFont(regularFont);
+       layout.setAscent(ascent);
+       layout.setDescent(descent);
+       layout.setText(line);
+       layout.setOrientation(orientation);
+       layout.setSegments(segments);
+       layout.setSegmentsChars(segmentChars);
+       layout.setWidth(width);
+       layout.setSpacing(lineSpacing);
+       layout.setTabs(tabs);
+       layout.setDefaultTabWidth(tabLength);
+       layout.setIndent(indent);
+       layout.setVerticalIndent(verticalIndent);
+       layout.setWrapIndent(wrapIndent);
+       layout.setAlignment(alignment);
+       layout.setJustify(justify);
+       layout.setTextDirection(textDirection);
+       // apply styles, must be done after layout.setText()
+       for (StyleEntry styleEntry : styleEntries) {
+               layout.setStyle(styleEntry.style, styleEntry.start, styleEntry.end);
+       }
+
+       if (styledText != null && styledText.ime != null) {
+               IME ime = styledText.ime;
+               int compositionOffset = ime.getCompositionOffset();
+               if (compositionOffset != -1) {
+                       int commitCount = ime.getCommitCount();
+                       int compositionLength = ime.getText().length();
+                       if (compositionLength != commitCount) {
+                               int compositionLine = content.getLineAtOffset(compositionOffset);
+                               if (compositionLine == 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++) {
+                                                               if (!(0 <= j && j < length)) break;
+                                                               userStyle = layout.getStyle(cap(layout, j));
+                                                               if (userStyle == null && j > 0) userStyle = layout.getStyle(cap(layout, j - 1));
+                                                               if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(cap(layout, j + 1));
+                                                               if (userStyle == null) {
+                                                                       layout.setStyle(imeStyle, j, j);
+                                                               } else {
+                                                                       TextStyle newStyle = new TextStyle(imeStyle);
+                                                                       if (newStyle.font == null) newStyle.font = userStyle.font;
+                                                                       if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground;
+                                                                       if (newStyle.background == null) newStyle.background = userStyle.background;
+                                                                       layout.setStyle(newStyle, j, j);
+                                                               }
+                                                       }
+                                               }
+                                       } else {
+                                               int start = compositionOffset - lineOffset;
+                                               int end = start + compositionLength - 1;
+                                               TextStyle userStyle = layout.getStyle(cap(layout, start));
+                                               if (userStyle == null) {
+                                                       if (start > 0) userStyle = layout.getStyle(cap(layout, start - 1));
+                                                       if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(cap(layout, end + 1));
+                                                       if (userStyle != null) {
+                                                               TextStyle newStyle = new TextStyle();
+                                                               newStyle.font = userStyle.font;
+                                                               newStyle.foreground = userStyle.foreground;
+                                                               newStyle.background = userStyle.background;
+                                                               layout.setStyle(newStyle, start, end);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (styledText != 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 != -1) {
+                       FontMetrics metrics = layout.getLineMetrics(index);
+                       ascent = metrics.getAscent() + metrics.getLeading();
+                       descent = metrics.getDescent();
+                       if (layouts != null) {
+                               for (int i = 0; i < layouts.length; i++) {
+                                       if (layouts[i] != null && layouts[i] != layout) {
+                                               layouts[i].setAscent(ascent);
+                                               layouts[i].setDescent(descent);
+                                       }
+                               }
+                       }
+                       styledText.calculateScrollBars();
+                       if (styledText.verticalScrollOffset != 0) {
+                               int topIndex = styledText.topIndex;
+                               int topIndexY = styledText.topIndexY;
+                               int lineHeight = getLineHeight();
+                               int newVerticalScrollOffset;
+                               if (topIndexY >= 0) {
+                                       newVerticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY;
+                               } else {
+                                       newVerticalScrollOffset = topIndex * lineHeight - topIndexY;
+                               }
+                               styledText.scrollVertical(newVerticalScrollOffset - styledText.verticalScrollOffset, true);
+                       }
+                       if (styledText.isBidiCaret()) styledText.createCaretBitmaps();
+                       styledText.caretDirection = SWT.NULL;
+                       styledText.setCaretLocation();
+                       styledText.redraw();
+               }
+       }
+       return layout;
+}
+int getWidth() {
+       return maxWidth;
+}
+void reset() {
+       if (layouts != null) {
+               for (int i = 0; i < layouts.length; i++) {
+                       TextLayout layout = layouts[i];
+                       if (layout != null) layout.dispose();
+               }
+               layouts = null;
+       }
+       topIndex = -1;
+       stylesSetCount = styleCount = lineCount = 0;
+       ranges = null;
+       styles = null;
+       stylesSet = null;
+       lines = null;
+       lineSizes = null;
+       bullets = null;
+       bulletsIndices = null;
+       redrawLines = null;
+       hasLinks = false;
+}
+void reset(int startLine, int lineCount) {
+       int endLine = startLine + lineCount;
+       if (startLine < 0 || endLine > lineSizes.length) return;
+       SortedSet<Integer> lines = new TreeSet<>();
+       for (int i = startLine; i < endLine; i++) {
+               lines.add(Integer.valueOf(i));
+       }
+       reset(lines);
+}
+void reset(Set<Integer> lines) {
+       if (lines == null || lines.isEmpty()) return;
+       int resetLineCount = 0;
+       for (Integer line : lines) {
+               if (line >= 0 || line < lineCount) {
+                       resetLineCount++;
+                       getLineSize(line.intValue()).resetSize();
+               }
+       }
+       if (lines.contains(Integer.valueOf(maxWidthLineIndex))) {
+               maxWidth = 0;
+               maxWidthLineIndex = -1;
+               if (resetLineCount != this.lineCount) {
+                       for (int i = 0; i < this.lineCount; i++) {
+                               LineSizeInfo lineSize = getLineSize(i);
+                               if (lineSize.width > maxWidth) {
+                                       maxWidth = lineSize.width;
+                                       maxWidthLineIndex = i;
+                               }
+                       }
+               }
+       }
+}
+void setContent(StyledTextContent content) {
+       reset();
+       this.content = content;
+       lineCount = content.getLineCount();
+       lineSizes = new LineSizeInfo[lineCount];
+       maxWidth = 0;
+       maxWidthLineIndex = -1;
+       reset(0, lineCount);
+}
+void setFont(Font font, int tabs) {
+       TextLayout layout = new TextLayout(device);
+       layout.setFont(regularFont);
+       tabLength = tabs;
+       if (font != null) {
+               if (boldFont != null) boldFont.dispose();
+               if (italicFont != null) italicFont.dispose();
+               if (boldItalicFont != 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);
+       StringBuilder tabBuffer = new StringBuilder(tabs);
+       for (int i = 0; i < tabs; i++) {
+               tabBuffer.append(' ');
+       }
+       layout.setText(tabBuffer.toString());
+       tabWidth = layout.getBounds().width;
+       layout.dispose();
+       if (styledText != null) {
+               GC gc = new GC(styledText);
+               averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth();
+               fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$
+               gc.dispose();
+       }
+}
+void setLineAlignment(int startLine, int count, int alignment) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= ALIGNMENT;
+               lines[i].alignment = alignment;
+       }
+}
+void setLineBackground(int startLine, int count, Color background) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= BACKGROUND;
+               lines[i].background = background;
+       }
+}
+void setLineBullet(int startLine, int count, Bullet bullet) {
+       if (bulletsIndices != null) {
+               bulletsIndices = null;
+               bullets = null;
+       }
+       if (bullets == null) {
+               if (bullet == null) return;
+               bullets = new Bullet[1];
+               bullets[0] = bullet;
+       }
+       int index = 0;
+       while (index < bullets.length) {
+               if (bullet == bullets[index]) break;
+               index++;
+       }
+       if (bullet != null) {
+               if (index == 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 == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= INDENT;
+               lines[i].indent = indent;
+       }
+}
+void setLineVerticalIndent(int lineIndex, int verticalLineIndent) {
+       if (lines == null)
+               lines = new LineInfo[lineCount];
+       if (lines[lineIndex] == null) {
+               lines[lineIndex] = new LineInfo();
+       }
+       lines[lineIndex].flags |= VERTICAL_INDENT;
+       lines[lineIndex].verticalIndent = verticalLineIndent;
+}
+void setLineWrapIndent(int startLine, int count, int wrapIndent) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= WRAP_INDENT;
+               lines[i].wrapIndent = wrapIndent;
+       }
+}
+void setLineJustify(int startLine, int count, boolean justify) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= JUSTIFY;
+               lines[i].justify = justify;
+       }
+}
+void setLineSegments(int startLine, int count, int[] segments) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= SEGMENTS;
+               lines[i].segments = segments;
+       }
+}
+void setLineSegmentChars(int startLine, int count, char[] segmentChars) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= SEGMENT_CHARS;
+               lines[i].segmentsChars = segmentChars;
+       }
+}
+void setLineTabStops(int startLine, int count, int[] tabStops) {
+       if (lines == null) lines = new LineInfo[lineCount];
+       for (int i = startLine; i < startLine + count; i++) {
+               if (lines[i] == null) {
+                       lines[i] = new LineInfo();
+               }
+               lines[i].flags |= TABSTOPS;
+               lines[i].tabStops = tabStops;
+       }
+}
+void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
+       this.lineSpacingProvider = lineSpacingProvider;
+}
+void setStyleRanges (int[] newRanges, StyleRange[] newStyles) {
+       if (newStyles == null) {
+               stylesSetCount = styleCount = 0;
+               ranges = null;
+               styles = null;
+               stylesSet = null;
+               hasLinks = false;
+               return;
+       }
+       if (newRanges == null && COMPACT_STYLES) {
+               newRanges = new int[newStyles.length << 1];
+               StyleRange[] tmpStyles = new StyleRange[newStyles.length];
+               if (stylesSet == 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 == stylesSetCount) {
+                               if (stylesSetCount == 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 == 0) {
+               if (newRanges != 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 != null && ranges == 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 == null && ranges != 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 != null) {
+               int rangeCount = styleCount << 1;
+               int start = newRanges[0];
+               int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd;
+               boolean insert = modifyStart == rangeCount;
+               if (!insert) {
+                       int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1];
+                       modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+                       insert = modifyStart == 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 == 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;
+               boolean insert = modifyStart == styleCount;
+               if (!insert) {
+                       int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length;
+                       modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+                       insert = modifyStart == 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 == 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++] = (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++] = (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 == content.getCharCount()) lines = null;
+       if (replaceLineCount == lineCount) {
+               lineCount = newLineCount;
+               lineSizes = new LineSizeInfo[lineCount];
+               reset(0, lineCount);
+       } else {
+               int startIndex = startLine + replaceLineCount + 1;
+               int endIndex = startLine + newLineCount + 1;
+               if(lineCount < startLine) {
+                       SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startLine: " + lineCount + ":" + startLine);
+               }
+               if(lineCount < startIndex) {
+                       SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startIndex: " + lineCount + ":" + startIndex);
+               }
+               int delta = newLineCount - replaceLineCount;
+               if (lineCount + delta > lineSizes.length) {
+                       LineSizeInfo[] newLineSizes = new LineSizeInfo[lineCount + delta + GROW];
+                       System.arraycopy(lineSizes, 0, newLineSizes, 0, lineCount);
+                       lineSizes = newLineSizes;
+               }
+               if (lines != null) {
+                       if (lineCount + delta > lines.length) {
+                               LineInfo[] newLines = new LineInfo[lineCount + delta + GROW];
+                               System.arraycopy(lines, 0, newLines, 0, lineCount);
+                               lines = newLines;
+                       }
+               }
+               System.arraycopy(lineSizes, startIndex, lineSizes, endIndex, lineCount - startIndex);
+               for (int i = startLine; i < endIndex; i++) {
+                       lineSizes[i] = null;
+               }
+               for (int i = lineCount + delta; i < lineCount; i++) {
+                       lineSizes[i] = null;
+               }
+               if (layouts != 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] != null) layouts[i].dispose();
+                                       layouts[i] = null;
+                                       if (bullets != null && bulletsIndices != 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 != null && bulletsIndices != null) {
+                                                               bullets[endIndex] = bullets[i];
+                                                               bulletsIndices[endIndex] = bulletsIndices[i];
+                                                               bullets[i] = null;
+                                                       }
+                                               } else {
+                                                       if (layouts[i] != null) layouts[i].dispose();
+                                                       layouts[i] = null;
+                                                       if (bullets != null && bulletsIndices != 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 != null && bulletsIndices != null) {
+                                                               bullets[endIndex] = bullets[i];
+                                                               bulletsIndices[endIndex] = bulletsIndices[i];
+                                                               bullets[i] = null;
+                                                       }
+                                               } else {
+                                                       if (layouts[i] != null) layouts[i].dispose();
+                                                       layouts[i] = null;
+                                                       if (bullets != null && bulletsIndices != null) bullets[i] = null;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               if (replaceLineCount != 0 || newLineCount != 0) {
+                       int startLineOffset = content.getOffsetAtLine(startLine);
+                       if (startLineOffset != start) startLine++;
+                       updateBullets(startLine, replaceLineCount, newLineCount, true);
+                       if (lines != 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 != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) {
+                       maxWidth = 0;
+                       maxWidthLineIndex = -1;
+                       for (int i = 0; i < lineCount; i++) {
+                               LineSizeInfo lineSize = getLineSize(i);
+                               if (lineSize.width > maxWidth) {
+                                       maxWidth = lineSize.width;
+                                       maxWidthLineIndex = i;
+                               }
+                       }
+               }
+       }
+}
+void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) {
+       if (bullets == null) return;
+       if (bulletsIndices != null) return;
+       for (int i = 0; i < bullets.length; i++) {
+               Bullet bullet = bullets[i];
+               int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update);
+               if (lines != null) {
+                       if (redrawLines == 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() == 0) removed++;
+       }
+       if (removed > 0) {
+               if (removed == 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 == 0 || (replaceCharCount == 0 && newCharCount == 0)) return;
+       if (ranges != null) {
+               int rangeCount = styleCount << 1;
+               int modifyStart = getRangeIndex(start, -1, rangeCount);
+               if (modifyStart == rangeCount) return;
+               int end = start + replaceCharCount;
+               int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+               int offset = newCharCount - replaceCharCount;
+               if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+                       if (newCharCount == 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 != 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 != 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 == styleCount) return;
+               int end = start + replaceCharCount;
+               int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+               int offset = newCharCount - replaceCharCount;
+               if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+                       if (newCharCount == 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] = (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 != 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 != 0) {
+                               for (int i = modifyEnd; i < styleCount; i++) {
+                                       styles[i].start += offset;
+                               }
+                       }
+                       System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd);
+                       styleCount -= modifyEnd - modifyStart;
+               }
+       }
+}
+
+public boolean hasVerticalIndent() {
+       return Arrays.stream(lines).filter(Objects::nonNull) //
+                       .mapToInt(line -> line.verticalIndent) //
+                       .anyMatch(n -> n != 0);
+}
+
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TableCursor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TableCursor.java
new file mode 100644 (file)
index 0000000..48dead7
--- /dev/null
@@ -0,0 +1,677 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * For a detailed example of using a TableCursor to navigate to a cell and then edit it see
+ * http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet96.java .
+ *
+ * <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 extends Canvas {
+       Table table;
+       TableItem row = null;
+       TableColumn column = null;
+       Listener 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 TableCursor(Table parent, int style) {
+       super(parent, style);
+       table = parent;
+       setBackground(null);
+       setForeground(null);
+
+       listener = event -> {
+               switch (event.type) {
+                       case SWT.Dispose :
+                               onDispose(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;
+                               }
+                               break;
+                       }
+               }
+       };
+       int[] events = new int[] {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 = event -> {
+               switch (event.type) {
+                       case SWT.MouseDown :
+                               tableMouseDown(event);
+                               break;
+                       case SWT.FocusIn :
+                               tableFocusIn(event);
+                               break;
+               }
+       };
+       table.addListener(SWT.FocusIn, tableListener);
+       table.addListener(SWT.MouseDown, tableListener);
+
+       disposeItemListener = event -> {
+               unhookRowColumnListeners();
+               row = null;
+               column = null;
+               _resize();
+       };
+       disposeColumnListener = event -> {
+               unhookRowColumnListeners();
+               row = null;
+               column = null;
+               _resize();
+       };
+       resizeListener = event -> _resize();
+       ScrollBar hBar = table.getHorizontalBar();
+       if (hBar != null) {
+               hBar.addListener(SWT.Selection, resizeListener);
+       }
+       ScrollBar vBar = table.getVerticalBar();
+       if (vBar != null) {
+               vBar.addListener(SWT.Selection, resizeListener);
+       }
+
+       getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
+               @Override
+               public void getRole(AccessibleControlEvent e) {
+                       e.detail = ACC.ROLE_TABLECELL;
+               }
+       });
+       getAccessible().addAccessibleListener(new AccessibleAdapter() {
+               @Override
+               public void getName(AccessibleEvent e) {
+                       if (row == null) return;
+                       int columnIndex = column == null ? 0 : table.indexOf(column);
+                       e.result = row.getText(columnIndex);
+               }
+       });
+}
+
+/**
+ * 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 == null)
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener(listener);
+       addListener(SWT.Selection, typedListener);
+       addListener(SWT.DefaultSelection, typedListener);
+}
+
+void onDispose(Event event) {
+       removeListener(SWT.Dispose, listener);
+       notifyListeners(SWT.Dispose, event);
+       event.type = SWT.None;
+
+       table.removeListener(SWT.FocusIn, tableListener);
+       table.removeListener(SWT.MouseDown, tableListener);
+       unhookRowColumnListeners();
+       ScrollBar hBar = table.getHorizontalBar();
+       if (hBar != null) {
+               hBar.removeListener(SWT.Selection, resizeListener);
+       }
+       ScrollBar vBar = table.getVerticalBar();
+       if (vBar != null) {
+               vBar.removeListener(SWT.Selection, resizeListener);
+       }
+}
+
+void keyDown(Event event) {
+       if (row == null) return;
+       switch (event.character) {
+               case SWT.CR :
+                       notifyListeners(SWT.DefaultSelection, new Event());
+                       return;
+       }
+       int rowIndex = table.indexOf(row);
+       int columnIndex = column == 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 == 0) break;
+                               int[] order = table.getColumnOrder();
+                               int index = 0;
+                               while (index < order.length) {
+                                       if (order[index] == columnIndex) break;
+                                       index++;
+                               }
+                               if (index == order.length) index = 0;
+                               int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+                               if (event.keyCode == 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 == 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 == rowIndex) {
+                                       index = Math.min(end, index + page - 1);
+                               }
+                               setRowColumn(index, columnIndex, true);
+                               break;
+                       }
+       }
+}
+
+void paint(Event event) {
+       if (row == null) return;
+       int columnIndex = column == null ? 0 : table.indexOf(column);
+       GC gc = event.gc;
+       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 != 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".equals(platform)) { //$NON-NLS-1$
+                       if (table.getColumnCount() == 0 || columnIndex == 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;
+                               }
+                       }
+               }  else {
+                       if (table.getColumnCount() == 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;
+                               }
+                       }
+               }
+               int textY = (size.y - extent.y) / 2;
+               gc.drawString(text, x, textY);
+       }
+       if (isFocusControl()) {
+               Display display = getDisplay();
+               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 == null && column == 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) != 0) {
+               if (item == null) return;
+       } else {
+               int start = item != 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 == null) return;
+       }
+       TableColumn newColumn = null;
+       int columnCount = table.getColumnCount();
+       if (columnCount == 0) {
+               if ((table.getStyle() & SWT.FULL_SELECTION) == 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 == null) {
+                       if ((table.getStyle() & SWT.FULL_SELECTION) == 0) return;
+                       newColumn = table.getColumn(0);
+               }
+       }
+       setRowColumn(item, newColumn, true);
+       setFocus();
+       return;
+}
+void setRowColumn(int row, int column, boolean notify) {
+       TableItem item = row == -1 ? null : table.getItem(row);
+       TableColumn col = column == -1 || table.getColumnCount() == 0 ? null : table.getColumn(column);
+       setRowColumn(item, col, notify);
+}
+void setRowColumn(TableItem row, TableColumn column, boolean notify) {
+       if (this.row == row && this.column == column) {
+               return;
+       }
+       if (this.row != null && this.row != row) {
+               this.row.removeListener(SWT.Dispose, disposeItemListener);
+               this.row = null;
+       }
+       if (this.column != null && this.column != column) {
+               this.column.removeListener(SWT.Dispose, disposeColumnListener);
+               this.column.removeListener(SWT.Move, resizeListener);
+               this.column.removeListener(SWT.Resize, resizeListener);
+               this.column = null;
+       }
+       if (row != null) {
+               if (this.row != row) {
+                       this.row = row;
+                       row.addListener(SWT.Dispose, disposeItemListener);
+                       table.showItem(row);
+               }
+               if (this.column != column && column != 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 == null ? 0 : table.indexOf(column);
+               setBounds(row.getBounds(columnIndex));
+               redraw();
+               if (notify) {
+                       notifyListeners(SWT.Selection, new Event());
+               }
+       }
+       getAccessible().setFocus(ACC.CHILDID_SELF);
+}
+
+@Override
+public void setVisible(boolean 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 == null) {
+               SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       }
+       removeListener(SWT.Selection, listener);
+       removeListener(SWT.DefaultSelection, listener);
+}
+
+void _resize() {
+       if (row == null) {
+               setBounds(-200, -200, 0, 0);
+       } else {
+               int columnIndex = column == null ? 0 : table.indexOf(column);
+               setBounds(row.getBounds(columnIndex));
+       }
+}
+/**
+ * Returns the index of the column over which the TableCursor is positioned.
+ *
+ * @return the column index 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 == null ? 0 : table.indexOf(column);
+}
+/**
+ * Returns the background color that the receiver will use to draw.
+ *
+ * @return the receiver's background color
+ */
+@Override
+public Color getBackground() {
+       checkWidget();
+       if (background == null) {
+               return getDisplay().getSystemColor(BACKGROUND);
+       }
+       return background;
+}
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ */
+@Override
+public Color getForeground() {
+       checkWidget();
+       if (foreground == null) {
+               return getDisplay().getSystemColor(FOREGROUND);
+       }
+       return foreground;
+}
+/**
+ * Returns the row over which the TableCursor is positioned.
+ *
+ * @return the item for the current position, or <code>null</code> if none
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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>
+ */
+@Override
+public 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>
+ */
+@Override
+public 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 == 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 == 0 ? 0 : columnCount - 1;
+       if (row == null
+               || row.isDisposed()
+               || column < 0
+               || column > maxColumnIndex)
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       setRowColumn(table.indexOf(row), column, false);
+}
+void unhookRowColumnListeners() {
+       if (column != null) {
+               column.removeListener(SWT.Dispose, disposeColumnListener);
+               column.removeListener(SWT.Move, resizeListener);
+               column.removeListener(SWT.Resize, resizeListener);
+               column = null;
+       }
+       if (row != null) {
+               row.removeListener(SWT.Dispose, disposeItemListener);
+               row = null;
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TableEditor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TableEditor.java
new file mode 100644 (file)
index 0000000..7692fbd
--- /dev/null
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+*
+* 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:</p>
+* <pre><code>
+*      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 != null) oldEditor.dispose();
+*
+*                      // Identify the selected row
+*                      TableItem item = (TableItem)e.item;
+*                      if (item == 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);
+*              }
+*      });
+* </code></pre>
+*
+* @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 extends 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 TableEditor (Table table) {
+       super(table);
+       this.table = table;
+
+       columnListener = new ControlListener() {
+               @Override
+               public void controlMoved(ControlEvent e){
+                       layout ();
+               }
+               @Override
+               public void controlResized(ControlEvent e){
+                       layout ();
+               }
+       };
+       timer = () -> layout ();
+
+       // To be consistent with older versions of SWT, grabVertical defaults to true
+       grabVertical = true;
+}
+@Override
+Rectangle computeBounds () {
+       if (item == null || column == -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0);
+       Rectangle cell = item.getBounds(column);
+       Rectangle rect = item.getImageBounds(column);
+       if (rect.width != 0) {
+               int imageGap = Math.max(rect.x - cell.x, 0);
+               cell.x = rect.x + rect.width;
+               cell.width -= (imageGap + 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 == SWT.RIGHT) {
+               editorRect.x += cell.width - editorRect.width;
+       } else if (horizontalAlignment == SWT.LEFT) {
+               // do nothing - cell.x is the right answer
+       } else { // default is CENTER
+               editorRect.x += (cell.width - editorRect.width)/2;
+       }
+
+       if (verticalAlignment == SWT.BOTTOM) {
+               editorRect.y += cell.height - editorRect.height;
+       } else if (verticalAlignment == 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.
+ */
+@Override
+public void dispose () {
+       if (table != 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 != 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 == 0) {
+               this.column = (column == 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();
+}
+@Override
+public 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);
+}
+@Override
+public void layout () {
+       if (table == null || table.isDisposed()) return;
+       if (item == null || item.isDisposed()) return;
+       int columnCount = table.getColumnCount();
+       if (columnCount == 0 && column != 0) return;
+       if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+       super.layout();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangeListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangeListener.java
new file mode 100644 (file)
index 0000000..0585f6e
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * 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 extends 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);
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangedEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangedEvent.java
new file mode 100644 (file)
index 0000000..ba38bee
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+
+/**
+ * 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 extends TypedEvent {
+
+       static final long serialVersionUID = 3258696524257835065L;
+
+/**
+ * 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 TextChangedEvent(StyledTextContent source) {
+       super(source);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangingEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TextChangingEvent.java
new file mode 100644 (file)
index 0000000..d5ddd64
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.events.*;
+
+/**
+ * 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 extends 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 TextChangingEvent(StyledTextContent source) {
+       super(source);
+}
+TextChangingEvent(StyledTextContent source, StyledTextEvent e) {
+       super(source);
+       start = e.start;
+       replaceCharCount = e.replaceCharCount;
+       newCharCount = e.newCharCount;
+       replaceLineCount = e.replaceLineCount;
+       newLineCount = e.newLineCount;
+       newText = e.text;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TreeCursor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TreeCursor.java
new file mode 100644 (file)
index 0000000..051dee6
--- /dev/null
@@ -0,0 +1,957 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A TreeCursor provides a way for the user to navigate around a Tree with columns using the
+ * keyboard. It also provides a mechanism for selecting an individual cell in a tree.
+ * <p>
+ * For a detailed example of using a TreeCursor to navigate to a cell and then edit it see
+ * http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet360.java .
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection</dd>
+ * </dl>
+ *
+ * @since 3.8
+ */
+public class TreeCursor extends Canvas {
+       Tree tree;
+       TreeItem row;
+       TreeColumn column;
+       Listener listener, treeListener, 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 tree 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 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#BORDER
+ * @see Widget#checkSubclass()
+ * @see Widget#getStyle()
+ */
+public TreeCursor(Tree parent, int style) {
+       super(parent, style);
+       tree = parent;
+       setBackground(null);
+       setForeground(null);
+
+       listener = event -> {
+               if (row != null) {
+                       /*
+                        * Detect cases where the cursor position has become invalid and fix it.
+                        * The typical cause of this is programmatic tree changes, such as
+                        * expanding/collapsing and item and creating/disposing items.
+                        */
+                       if (row.isDisposed()) {
+                               unhookRowColumnListeners();
+                               _resize();
+                               tree.setFocus();
+                               return;
+                       }
+                       TreeItem current = row;
+                       TreeItem parentItem = row.getParentItem();
+                       while (parentItem != null && !parentItem.getExpanded()) {
+                               current = parentItem;
+                               parentItem = current.getParentItem();
+                       }
+                       if (current != row) {
+                               setRowColumn(current, column, false);
+                       }
+               }
+               switch (event.type) {
+                       case SWT.Dispose:
+                               onDispose(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;
+                               }
+                               break;
+               }
+       };
+       int[] events = new int[] { SWT.Dispose, SWT.FocusIn, SWT.FocusOut, SWT.KeyDown, SWT.Paint, SWT.Traverse };
+       for (int i = 0; i < events.length; i++) {
+               addListener(events[i], listener);
+       }
+
+       treeListener = event -> {
+               switch (event.type) {
+                       case SWT.Collapse:
+                               treeCollapse(event);
+                               break;
+                       case SWT.Expand:
+                               treeExpand(event);
+                               break;
+                       case SWT.FocusIn:
+                               treeFocusIn(event);
+                               break;
+                       case SWT.MouseDown:
+                               treeMouseDown(event);
+                               break;
+               }
+       };
+       tree.addListener(SWT.Collapse, treeListener);
+       tree.addListener(SWT.Expand, treeListener);
+       tree.addListener(SWT.FocusIn, treeListener);
+       tree.addListener(SWT.MouseDown, treeListener);
+
+       disposeItemListener = event -> {
+               TreeItem currentItem = row;
+               while (currentItem != null) {
+                       currentItem.removeListener(SWT.Dispose, disposeItemListener);
+                       currentItem = currentItem.getParentItem();
+               }
+               TreeItem disposedItem = (TreeItem)event.widget;
+               TreeItem parentItem = disposedItem.getParentItem();
+               if (parentItem != null) {
+                       setRowColumn(parentItem, column, true);
+               } else {
+                       if (tree.getItemCount() == 1) {
+                               unhookRowColumnListeners();
+                       } else {
+                               TreeItem newFocus = null;
+                               int rowIndex = tree.indexOf(disposedItem);
+                               if (rowIndex != 0) {
+                                       TreeItem previousItem = tree.getItem(rowIndex - 1);
+                                       if (!previousItem.isDisposed()) {
+                                               newFocus = previousItem;
+                                       }
+                               }
+                               if (newFocus == null && rowIndex + 1 < tree.getItemCount()) {
+                                       TreeItem nextItem = tree.getItem(rowIndex + 1);
+                                       if (!nextItem.isDisposed()) {
+                                               newFocus = nextItem;
+                                       }
+                               }
+                               if (newFocus != null) {
+                                       setRowColumn(newFocus, column, true);
+                               } else {
+                                       unhookRowColumnListeners();
+                               }
+                       }
+               }
+               _resize();
+       };
+       disposeColumnListener = event -> {
+               if (column != null) {
+                       if (tree.getColumnCount() == 1) {
+                               column = null;
+                       } else {
+                               int columnIndex = tree.indexOf(column);
+                               int positionIndex = columnIndex;
+                               int[] columnOrder = tree.getColumnOrder();
+                               for (int i = 0; i < columnOrder.length; i++) {
+                                       if (columnOrder[i] == columnIndex) {
+                                               positionIndex = i;
+                                               break;
+                                       }
+                               }
+                               if (positionIndex == columnOrder.length - 1) {
+                                       setRowColumn(row, tree.getColumn(columnOrder[positionIndex - 1]), true);
+                               } else {
+                                       setRowColumn(row, tree.getColumn(columnOrder[positionIndex + 1]), true);
+                               }
+                       }
+               }
+               _resize();
+       };
+       resizeListener = event -> _resize();
+       ScrollBar hBar = tree.getHorizontalBar();
+       if (hBar != null) {
+               hBar.addListener(SWT.Selection, resizeListener);
+       }
+       ScrollBar vBar = tree.getVerticalBar();
+       if (vBar != null) {
+               vBar.addListener(SWT.Selection, resizeListener);
+       }
+
+       getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
+               @Override
+               public void getRole(AccessibleControlEvent e) {
+                       e.detail = ACC.ROLE_TABLECELL;
+               }
+       });
+       getAccessible().addAccessibleListener(new AccessibleAdapter() {
+               @Override
+               public void getName(AccessibleEvent e) {
+                       if (row == null) return;
+                       int columnIndex = column == null ? 0 : tree.indexOf(column);
+                       e.result = row.getText(columnIndex);
+               }
+       });
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be notified when the receiver's
+ * selection changes, 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
+ *
+ * @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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener(listener);
+       addListener(SWT.Selection, typedListener);
+       addListener(SWT.DefaultSelection, typedListener);
+}
+
+int countSubTreePages(TreeItem root) {
+       int pages = 1;
+       if (root == null) return 0;
+       if (root.getItemCount() == 0) return 1;
+       if (!root.getExpanded()) return 1;
+       TreeItem[] items = root.getItems();
+       for (int i = 0; i < items.length; i++) {
+               pages += countSubTreePages(items[i]);
+       }
+       return pages;
+}
+
+int findIndex(TreeItem[] items, TreeItem treeItem) {
+       if (items == null || treeItem == null) return -1;
+       Rectangle rect = treeItem.getBounds();
+       int index = 0;
+       for (int i = 0; i < items.length; i++) {
+               TreeItem previousItem = null;
+               TreeItem currentItem = items[i];
+               if (i > 0) previousItem = items[i - 1];
+               Rectangle rect1 = currentItem.getBounds();
+               if (rect.y == rect1.y) return index;
+               if (rect.y < rect1.y) {
+                       return index - 1 + findIndex(previousItem.getItems(), treeItem);
+               }
+               if (rect.y > rect1.y && i == items.length - 1) {
+                       return index + findIndex(currentItem.getItems(), treeItem);
+               }
+               if (rect.y >= rect1.y + (1 + currentItem.getItemCount()) * tree.getItemHeight() && currentItem.getExpanded()) {
+                       index += countSubTreePages(currentItem);
+                       continue;
+               }
+               index++;
+       }
+       return -1;
+}
+
+TreeItem findItem(TreeItem[] items, Point pt) {
+       int start = 0, end = items.length - 1;
+       int index = end / 2;
+       while (end - start > 1) {
+               TreeItem currentItem = items[index];
+               Rectangle bounds = currentItem.getBounds();
+               if (pt.y < bounds.y) {
+                       end = index;
+                       index = (end - start) / 2;
+               } else {
+                       start = index;
+                       index = start + ((end - start) / 2);
+               }
+       }
+
+       Rectangle endBounds = items[end].getBounds();
+       if (endBounds.y < pt.y) {
+               if (endBounds.y + endBounds.height < pt.y) {
+                       if (!items[end].getExpanded()) return null;
+                       return findItem(items[end].getItems(), pt);
+               }
+               int[] columnOrder = tree.getColumnOrder();
+               Rectangle bounds = null;
+               if (columnOrder.length > 0) {
+                       Rectangle rect1 = items[end].getBounds(columnOrder[0]);
+                       Rectangle rect2 = items[end].getBounds(columnOrder[columnOrder.length - 1]);
+                       bounds = rect1.union(rect2);
+                       bounds.height += tree.getLinesVisible() ? tree.getGridLineWidth() : 0;
+               } else {
+                       bounds = items[end].getBounds();
+               }
+               return bounds.contains(pt) ? items[end] : null;
+       }
+
+       Rectangle startBounds = items[start].getBounds();
+       if (startBounds.y + startBounds.height < pt.y) {
+               return findItem(items[start].getItems(), pt);
+       }
+       int[] columnOrder = tree.getColumnOrder();
+       Rectangle bounds = null;
+       if (columnOrder.length > 0) {
+               Rectangle rect1 = items[start].getBounds(columnOrder[0]);
+               Rectangle rect2 = items[start].getBounds(columnOrder[columnOrder.length - 1]);
+               bounds = rect1.union(rect2);
+               bounds.height += tree.getLinesVisible() ? tree.getGridLineWidth() : 0;
+       } else {
+               bounds = items[start].getBounds();
+       }
+       return bounds.contains(pt) ? items[start] : null;
+}
+
+/**
+ * Returns the background color that the receiver will use to draw.
+ *
+ * @return the receiver's background color
+ */
+@Override
+public Color getBackground() {
+       checkWidget();
+       if (background == null) {
+               return getDisplay().getSystemColor(BACKGROUND);
+       }
+       return background;
+}
+
+/**
+ * Returns the index of the column over which the TreeCursor is positioned.
+ *
+ * @return the column index 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 == null ? 0 : tree.indexOf(column);
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ */
+@Override
+public Color getForeground() {
+       checkWidget();
+       if (foreground == null) {
+               return getDisplay().getSystemColor(FOREGROUND);
+       }
+       return foreground;
+}
+
+TreeItem getLastVisibleItem(TreeItem[] items) {
+       if (items == null) return null;
+       TreeItem last = items[items.length - 1];
+       if (last.getExpanded() && last.getItemCount() > 0) {
+               return getLastVisibleItem(last.getItems());
+       }
+       return last;
+}
+
+TreeItem getNextItem(TreeItem item) {
+       if (item == null) return null;
+       if (item.getExpanded() && item.getItemCount() > 0) {
+               return item.getItem(0);
+       }
+
+       TreeItem parentItem = item.getParentItem();
+       while (parentItem != null) {
+               int index = parentItem.indexOf(item);
+               if (index == -1) return null;
+               if (index < parentItem.getItemCount() - 1) {
+                       return parentItem.getItem(index + 1);
+               }
+               item = parentItem;
+               parentItem = item.getParentItem();
+       }
+       int index = tree.indexOf(item);
+       if (index == -1) return null;
+       if (index == tree.getItemCount() - 1) return null;
+       return tree.getItem(index + 1);
+}
+
+TreeItem getPreviousItem(TreeItem item) {
+       if (item == null) return null;
+       TreeItem parentItem = item.getParentItem();
+       if (parentItem == null) {
+               int index = tree.indexOf(item);
+               if (index == -1 || index == 0) return null;
+               item = tree.getItem(index - 1);
+               if (item.getExpanded() && item.getItemCount() > 0) {
+                       return getLastVisibleItem(item.getItems());
+               }
+               return item;
+       }
+       int index = parentItem.indexOf(item);
+       if (index == -1) return null;
+       if (index == 0) return parentItem;
+       item = parentItem.getItem(index - 1);
+       if (item.getExpanded() && item.getItemCount() > 0) {
+               return getLastVisibleItem(item.getItems());
+       }
+       return item;
+}
+
+/**
+ * Returns the row over which the TreeCursor is positioned.
+ *
+ * @return the item for the current position, or <code>null</code> if none
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 getRow() {
+       checkWidget();
+       return row;
+}
+
+void keyDown(Event event) {
+       if (row == null) return;
+       switch (event.character) {
+               case SWT.CR:
+                       notifyListeners(SWT.DefaultSelection, new Event());
+                       return;
+       }
+       switch (event.keyCode) {
+               case SWT.ARROW_UP:
+                       TreeItem previousItem = getPreviousItem(row);
+                       if (previousItem != null) {
+                               setRowColumn(previousItem, column, true);
+                       }
+                       break;
+               case SWT.ARROW_DOWN:
+                       TreeItem nextItem = getNextItem(row);
+                       if (nextItem != null) {
+                               setRowColumn(nextItem, column, true);
+                       }
+                       break;
+               case SWT.ARROW_LEFT:
+               case SWT.ARROW_RIGHT: {
+                       if ((event.stateMask & SWT.MOD1) != 0) {
+                               row.setExpanded (event.keyCode == SWT.ARROW_RIGHT);
+                               break;
+                       }
+                       int columnCount = tree.getColumnCount();
+                       if (columnCount == 0) break;
+                       int columnIndex = column == null ? 0 : tree.indexOf(column);
+                       int[] columnOrder = tree.getColumnOrder();
+                       int index = 0;
+                       while (index < columnOrder.length) {
+                               if (columnOrder[index] == columnIndex) break;
+                               index++;
+                       }
+                       if (index == columnOrder.length) index = 0;
+                       int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+                       TreeItem parentRow = row.getParentItem();
+                       int rowIndex = tree.indexOf(row);
+                       if (event.keyCode == leadKey) {
+                               if (parentRow != null) {
+                                       setRowColumn(row, tree.getColumn(columnOrder[Math.max(0, index - 1)]), true);
+                               } else {
+                                       setRowColumn(rowIndex, columnOrder[Math.max(0, index - 1)], true);
+                               }
+                       } else {
+                               if (parentRow != null) {
+                                       setRowColumn(row, tree.getColumn(columnOrder[Math.min(columnCount - 1, index + 1)]), true);
+                               } else {
+                                       setRowColumn(rowIndex, columnOrder[Math.min(columnCount - 1, index + 1)], true);
+                               }
+                       }
+                       break;
+               }
+               case SWT.HOME:
+                       int columnIndex = column == null ? 0 : tree.indexOf(column);
+                       setRowColumn(0, columnIndex, true);
+                       break;
+               case SWT.END: {
+                       TreeItem[] items = tree.getItems();
+                       setRowColumn(getLastVisibleItem(items), column, true);
+                       break;
+               }
+               case SWT.PAGE_UP: {
+                       Rectangle rect = tree.getClientArea();
+                       Rectangle itemRect = tree.getTopItem().getBounds();
+                       TreeItem item = row;
+                       int index = findIndex(tree.getItems(), item);
+                       int itemHeight = tree.getItemHeight();
+                       rect.height -= itemRect.y;
+                       int page = Math.max(1, rect.height / itemHeight);
+                       if (index - page <= 0) {
+                               TreeItem first = tree.getItem(0);
+                               setRowColumn(first, column, true);
+                               break;
+                       }
+                       for (int i = 0; i < page; i++) {
+                               item = getPreviousItem(item);
+                       }
+                       setRowColumn(item, column, true);
+                       break;
+               }
+               case SWT.PAGE_DOWN: {
+                       Rectangle rect = tree.getClientArea();
+                       Rectangle itemRect = tree.getTopItem().getBounds();
+                       TreeItem item = row;
+                       int index = findIndex(tree.getItems(), item);
+                       int height = tree.getItemHeight();
+                       rect.height -= itemRect.y;
+                       TreeItem last = getLastVisibleItem(tree.getItems());
+                       int page = Math.max(1, rect.height / height);
+                       int end = findIndex(tree.getItems(), last);
+                       if (end <= index + page) {
+                               setRowColumn(last, column, true);
+                               break;
+                       }
+                       for (int i = 0; i < page; i++) {
+                               item = getNextItem(item);
+                       }
+                       setRowColumn(item, column, true);
+                       break;
+               }
+       }
+}
+
+void onDispose(Event event) {
+       removeListener(SWT.Dispose, listener);
+       notifyListeners(SWT.Dispose, event);
+       event.type = SWT.None;
+
+       tree.removeListener(SWT.Collapse, treeListener);
+       tree.removeListener(SWT.Expand, treeListener);
+       tree.removeListener(SWT.FocusIn, treeListener);
+       tree.removeListener(SWT.MouseDown, treeListener);
+       unhookRowColumnListeners();
+       ScrollBar hBar = tree.getHorizontalBar();
+       if (hBar != null) {
+               hBar.removeListener(SWT.Selection, resizeListener);
+       }
+       ScrollBar vBar = tree.getVerticalBar();
+       if (vBar != null) {
+               vBar.removeListener(SWT.Selection, resizeListener);
+       }
+}
+
+void paint(Event event) {
+       if (row == null) return;
+       int columnIndex = column == null ? 0 : tree.indexOf(column);
+       int orderedIndex = columnIndex;
+       int[] columnOrder = tree.getColumnOrder();
+       for (int i = 0; i < columnOrder.length; i++) {
+               if (columnOrder[i] == columnIndex) {
+                       orderedIndex = i;
+                       break;
+               }
+       }
+       GC gc = event.gc;
+       gc.setBackground(getBackground());
+       gc.setForeground(getForeground());
+       gc.fillRectangle(event.x, event.y, event.width, event.height);
+       Image image = row.getImage(columnIndex);
+       int x = 0;
+       // Temporary code - need a better way to determine trim
+       String platform = SWT.getPlatform();
+       if (image != null) {
+               if ("win32".equals(platform)) { //$NON-NLS-1$
+                       if (orderedIndex > 0) {
+                               x += 2;
+                       }
+               } else {
+                       x += 2;
+               }
+       }
+       Point size = getSize();
+       if (image != 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 trim
+               if ("win32".equals(platform)) { //$NON-NLS-1$
+                       if (tree.getColumnCount() == 0 || orderedIndex == 0) {
+                               x += image == null ? 2 : 5;
+                       } else {
+                               int alignmnent = column.getAlignment();
+                               switch (alignmnent) {
+                                       case SWT.LEFT:
+                                               x += image == null ? 5 : 3;
+                                               break;
+                                       case SWT.RIGHT:
+                                               x = bounds.width - extent.x - 2;
+                                               break;
+                                       case SWT.CENTER:
+                                               x += Math.ceil((bounds.width - x - extent.x) / 2.0);
+                                               break;
+                               }
+                       }
+               } else {
+                       if (tree.getColumnCount() == 0) {
+                               x += image == null ? 4 : 3;
+                       } else {
+                               int alignmnent = column.getAlignment();
+                               switch (alignmnent) {
+                                       case SWT.LEFT:
+                                               x += image == null ? 5 : 3;
+                                               break;
+                                       case SWT.RIGHT:
+                                               x = bounds.width - extent.x - 2;
+                                               break;
+                                       case SWT.CENTER:
+                                               x += (bounds.width - x - extent.x) / 2 + 2;
+                                               break;
+                               }
+                       }
+               }
+               int textY = (size.y - extent.y) / 2;
+               gc.drawString(text, x, textY);
+       }
+       if (isFocusControl()) {
+               Display display = getDisplay();
+               gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+               gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+               gc.drawFocus(0, 0, size.x, size.y);
+       }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will be notified when the
+ * receiver's selection changes.
+ *
+ * @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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(SWT.Selection, listener);
+       removeListener(SWT.DefaultSelection, listener);
+}
+
+void _resize() {
+       if (row == null) {
+               setBounds(-200, -200, 0, 0);
+       } else {
+               int columnIndex = column == null ? 0 : tree.indexOf(column);
+               setBounds(row.getBounds(columnIndex));
+       }
+}
+
+/**
+ * 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>
+ */
+@Override
+public 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>
+ */
+@Override
+public void setForeground (Color color) {
+       foreground = color;
+       super.setForeground(getForeground());
+       redraw();
+}
+
+void setRowColumn(int row, int column, boolean notify) {
+       TreeItem item = row == -1 ? null : tree.getItem(row);
+       TreeColumn col = column == -1 || tree.getColumnCount() == 0 ? null : tree.getColumn(column);
+       setRowColumn(item, col, notify);
+}
+
+void setRowColumn(TreeItem row, TreeColumn column, boolean notify) {
+       if (this.row != null && this.row != row) {
+               TreeItem currentItem = this.row;
+               while (currentItem != null) {
+                       currentItem.removeListener(SWT.Dispose, disposeItemListener);
+                       currentItem = currentItem.getParentItem();
+               }
+               this.row = null;
+       }
+       if (this.column != null && this.column != column) {
+               this.column.removeListener(SWT.Dispose, disposeColumnListener);
+               this.column.removeListener(SWT.Move, resizeListener);
+               this.column.removeListener(SWT.Resize, resizeListener);
+               this.column = null;
+       }
+       if (row != null) {
+               if (this.row != row) {
+                       this.row = row;
+                       TreeItem currentItem = row;
+                       while (currentItem != null) {
+                               currentItem.addListener(SWT.Dispose, disposeItemListener);
+                               currentItem = currentItem.getParentItem();
+                       }
+                       tree.showItem(row);
+               }
+               if (this.column != column && column != null) {
+                       this.column = column;
+                       column.addListener(SWT.Dispose, disposeColumnListener);
+                       column.addListener(SWT.Move, resizeListener);
+                       column.addListener(SWT.Resize, resizeListener);
+                       tree.showColumn(column);
+               }
+               int columnIndex = column == null ? 0 : tree.indexOf(column);
+               setBounds(row.getBounds(columnIndex));
+               redraw();
+               if (notify) notifyListeners(SWT.Selection, new Event());
+       }
+}
+
+/**
+ * Positions the TreeCursor over the root-level cell at the given row and column in the parent tree.
+ *
+ * @param row the index of the root-level 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 = tree.getColumnCount();
+       int maxColumnIndex = columnCount == 0 ? 0 : columnCount - 1;
+       if (row < 0 || row >= tree.getItemCount() || column < 0 || column > maxColumnIndex) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       setRowColumn(row, column, false);
+}
+
+/**
+ * Positions the TreeCursor over the cell at the given row and column in the parent tree.
+ *
+ * @param row the TreeItem 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(TreeItem row, int column) {
+       checkWidget();
+       int columnCount = tree.getColumnCount();
+       int maxColumnIndex = columnCount == 0 ? 0 : columnCount - 1;
+       if (row == null || row.isDisposed() || column < 0 || column > maxColumnIndex) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       TreeColumn col = tree.getColumnCount() == 0 ? null : tree.getColumn(column);
+       setRowColumn(row, col, false);
+}
+
+@Override
+public void setVisible(boolean visible) {
+       checkWidget();
+       if (visible) {
+               _resize();
+       }
+       super.setVisible(visible);
+}
+
+void treeCollapse(Event event) {
+       if (row == null) return;
+       TreeItem root = (TreeItem)event.item;
+       TreeItem parentItem = row.getParentItem();
+       while (parentItem != null) {
+               if (parentItem == root) {
+                       setRowColumn(root, column, true);
+                       return;
+               }
+               parentItem = parentItem.getParentItem();
+       }
+
+       getDisplay().asyncExec(() -> {
+               if (isDisposed()) return;
+               setRowColumn(row, column, true);
+       });
+}
+
+void treeExpand(Event event) {
+       getDisplay().asyncExec(() -> {
+               if (isDisposed()) return;
+               setRowColumn(row, column, true);
+       });
+}
+
+void treeFocusIn(Event event) {
+       if (isVisible()) {
+               if (row == null && column == null) return;
+               setFocus();
+       }
+}
+
+void treeMouseDown(Event event) {
+       if (tree.getItemCount() == 0) return;
+       Point pt = new Point(event.x, event.y);
+       TreeItem item = tree.getItem(pt);
+       if (item == null && (tree.getStyle() & SWT.FULL_SELECTION) == 0) {
+               TreeItem currentItem = tree.getTopItem();
+               TreeItem parentItem = currentItem.getParentItem();
+               while (parentItem != null) {
+                       currentItem = parentItem;
+                       parentItem = currentItem.getParentItem();
+               }
+               int start = tree.indexOf(currentItem);
+               int viewportItemCount = tree.getClientArea().height / tree.getItemHeight();
+               int end = Math.min(start + viewportItemCount, tree.getItemCount() - 1);
+               TreeItem[] allItems = tree.getItems();
+               TreeItem[] items = new TreeItem[end - start + 1];
+               System.arraycopy(allItems, start, items, 0, end - start + 1);
+               item = findItem(items, pt);
+       }
+       if (item == null) return;
+
+       TreeColumn newColumn = null;
+       int lineWidth = tree.getLinesVisible() ? tree.getGridLineWidth() : 0;
+       int columnCount = tree.getColumnCount();
+       if (columnCount > 0) {
+               for (int i = 0; i < columnCount; i++) {
+                       Rectangle rect = item.getBounds(i);
+                       rect.width += lineWidth;
+                       rect.height += lineWidth;
+                       if (rect.contains(pt)) {
+                               newColumn = tree.getColumn(i);
+                               break;
+                       }
+               }
+               if (newColumn == null) {
+                       newColumn = tree.getColumn(0);
+               }
+       }
+       setRowColumn(item, newColumn, true);
+       setFocus();
+}
+
+void unhookRowColumnListeners() {
+       if (column != null && !column.isDisposed()) {
+               column.removeListener(SWT.Dispose, disposeColumnListener);
+               column.removeListener(SWT.Move, resizeListener);
+               column.removeListener(SWT.Resize, resizeListener);
+       }
+       column = null;
+       if (row != null && !row.isDisposed()) {
+               TreeItem currentItem = row;
+               while (currentItem != null) {
+                       currentItem.removeListener(SWT.Dispose, disposeItemListener);
+                       currentItem = currentItem.getParentItem();
+               }
+       }
+       row = null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TreeEditor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/TreeEditor.java
new file mode 100644 (file)
index 0000000..5ec8f95
--- /dev/null
@@ -0,0 +1,324 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+*
+* 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:</p>
+* <pre><code>
+*      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 != null) oldEditor.dispose();
+*
+*                      // Identify the selected row
+*                      TreeItem item = (TreeItem)e.item;
+*                      if (item == 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);
+*              }
+*      });
+* </code></pre>
+*
+* @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 extends ControlEditor {
+       Tree tree;
+       TreeItem item;
+       int column = 0;
+       ControlListener columnListener;
+       TreeListener treeListener;
+       Runnable timer;
+       static final int TIMEOUT = 1500;
+
+/**
+* Creates a TreeEditor for the specified Tree.
+*
+* @param tree the Tree Control above which this editor will be displayed
+*
+*/
+public TreeEditor (Tree tree) {
+       super(tree);
+       this.tree = tree;
+
+       columnListener = new ControlListener() {
+               @Override
+               public void controlMoved(ControlEvent e){
+                       layout();
+               }
+               @Override
+               public void controlResized(ControlEvent e){
+                       layout();
+               }
+       };
+       timer = () -> layout ();
+       treeListener = new TreeListener () {
+               final Runnable runnable = () -> {
+                       if (editor == null || editor.isDisposed()) return;
+                       if (TreeEditor.this.tree.isDisposed()) return;
+                       layout();
+                       editor.setVisible(true);
+               };
+               @Override
+               public void treeCollapsed(TreeEvent e) {
+                       if (editor == null || editor.isDisposed ()) return;
+                       editor.setVisible(false);
+                       e.display.asyncExec(runnable);
+               }
+               @Override
+               public void treeExpanded(TreeEvent e) {
+                       if (editor == null || editor.isDisposed ()) return;
+                       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 == null || column == -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() == 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 == SWT.RIGHT) {
+               editorRect.x += cell.width - editorRect.width;
+       } else if (horizontalAlignment == 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 == SWT.BOTTOM) {
+               editorRect.y += cell.height - editorRect.height;
+       } else if (verticalAlignment == 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.
+ */
+@Override
+public void dispose () {
+       if (tree != null && !tree.isDisposed()) {
+               if (this.column > -1 && this.column < tree.getColumnCount()){
+                       TreeColumn treeColumn = tree.getColumn(this.column);
+                       treeColumn.removeControlListener(columnListener);
+               }
+               if (treeListener != 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 != 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 == 0) {
+               this.column = (column == 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);
+}
+@Override
+public 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);
+}
+
+@Override
+public void layout () {
+       if (tree == null || tree.isDisposed()) return;
+       if (item == null || item.isDisposed()) return;
+       int columnCount = tree.getColumnCount();
+       if (columnCount == 0 && column != 0) return;
+       if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+       super.layout();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/VerifyKeyListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/VerifyKeyListener.java
new file mode 100644 (file)
index 0000000..c285231
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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>
+ */
+@FunctionalInterface
+public interface VerifyKeyListener extends 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ViewForm.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ViewForm.java
new file mode 100644 (file)
index 0000000..af2dde8
--- /dev/null
@@ -0,0 +1,499 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+
+public class ViewForm extends Composite {
+
+       /**
+        * marginWidth specifies the number of points 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 points 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 points 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 points 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
+        */
+       @Deprecated
+       public static RGB borderInsideRGB  = new RGB (132, 130, 132);
+       /**
+        * 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
+        */
+       @Deprecated
+       public static RGB borderMiddleRGB  = new RGB (143, 141, 138);
+       /**
+        * 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
+        */
+       @Deprecated
+       public static RGB borderOutsideRGB = new RGB (171, 168, 165);
+
+       // SWT widgets
+       Control topLeft;
+       Control topCenter;
+       Control topRight;
+       Control content;
+
+       // Configuration and state info
+       boolean separateTopCenter = false;
+       boolean showBorder = false;
+
+       int separator = -1;
+       int borderTop = 0;
+       int borderBottom = 0;
+       int borderLeft = 0;
+       int borderRight = 0;
+       int highlight = 0;
+       Point oldSize;
+
+       Color selectionBackground;
+       Listener listener;
+
+       static final int OFFSCREEN = -200;
+       static final int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW;
+       static final int SELECTION_BACKGROUND = SWT.COLOR_LIST_BACKGROUND;
+/**
+ * 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 ViewForm(Composite parent, int style) {
+       super(parent, checkStyle(style));
+       super.setLayout(new ViewFormLayout());
+
+       setBorderVisible((style & SWT.BORDER) != 0);
+
+       listener = e -> {
+               switch (e.type) {
+                       case SWT.Dispose: onDispose(e); break;
+                       case SWT.Paint: onPaint(e.gc); break;
+                       case SWT.Resize: onResize(); break;
+               }
+       };
+
+       int[] events = new int[] {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);
+//     }
+//}
+
+@Override
+public 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);
+}
+@Override
+public 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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the parent.
+        */
+       //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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //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() {
+       /*
+        * This call is intentionally commented out, to allow this getter method to be
+        * called from a thread which is different from one that created the widget.
+        */
+       //checkWidget();
+       return topRight;
+}
+void onDispose(Event event) {
+       removeListener(SWT.Dispose, listener);
+       notifyListeners(SWT.Dispose, event);
+       event.type = SWT.None;
+
+       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 = new int[] {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 == null || oldSize.x == 0 || oldSize.y == 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 != null && content.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (this.content != 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>
+ */
+@Override
+public void setLayout (Layout layout) {
+       checkWidget();
+       return;
+}
+void setSelectionBackground (Color color) {
+       checkWidget();
+       if (selectionBackground == color) return;
+       if (color == 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 != null && topCenter.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (this.topCenter != 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 != null && c.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (this.topLeft != 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 != null && c.getParent() != this) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (this.topRight != 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(boolean show) {
+       checkWidget();
+       if (showBorder == show) return;
+
+       showBorder = show;
+       if (showBorder) {
+               borderLeft = borderTop = borderRight = borderBottom = 1;
+               if ((getStyle() & SWT.FLAT)== 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(boolean show) {
+       checkWidget();
+       separateTopCenter = show;
+       layout(false);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ViewFormLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/ViewFormLayout.java
new file mode 100644 (file)
index 0000000..c9245b4
--- /dev/null
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class provides the layout for ViewForm
+ *
+ * @see ViewForm
+ */
+class ViewFormLayout extends Layout {
+
+@Override
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+       ViewForm form = (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 != null) {
+               leftSize = computeChildSize(left, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+       }
+       Point centerSize = new Point(0, 0);
+       if (center != null) {
+               centerSize = computeChildSize(center, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+       }
+       Point rightSize = new Point(0, 0);
+       if (right != null) {
+               rightSize = computeChildSize(right, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+       }
+       Point size = new Point(0, 0);
+       // calculate width of title bar
+       if (form.separateTopCenter ||
+               (wHint != 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 != null){
+                       size.y += centerSize.y;
+                       if (left != null ||right != 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 != null) {
+               if (left != null || right != null || center != 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 != SWT.DEFAULT) size.x  = wHint;
+       if (hHint != SWT.DEFAULT) size.y = hHint;
+
+       return size;
+}
+
+Point computeChildSize(Control control, int wHint, int hHint, boolean flushCache) {
+       Object data = control.getLayoutData();
+       if (data == null || !(data instanceof CLayoutData)) {
+               data = new CLayoutData();
+               control.setLayoutData(data);
+       }
+       return ((CLayoutData)data).computeSize(control, wHint, hHint, flushCache);
+}
+
+int computeTrim(Control c) {
+       if (c instanceof Scrollable) {
+               Rectangle rect = ((Scrollable) c).computeTrim (0, 0, 0, 0);
+               return rect.width;
+       }
+       return c.getBorderWidth () * 2;
+}
+
+@Override
+protected boolean flushCache(Control control) {
+       Object data = control.getLayoutData();
+       if (data != null && data instanceof CLayoutData) ((CLayoutData)data).flushCache();
+       return true;
+}
+
+@Override
+protected void layout(Composite composite, boolean flushCache) {
+       ViewForm form = (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 != null && !left.isDisposed()) {
+               leftSize = computeChildSize(left, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+       }
+       Point centerSize = new Point(0, 0);
+       if (center != null && !center.isDisposed()) {
+               centerSize = computeChildSize(center, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+       }
+       Point rightSize = new Point(0, 0);
+       if (right != 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;
+
+       boolean top = false;
+       if (form.separateTopCenter || minTopWidth > rect.width) {
+               int topHeight = Math.max(rightSize.y, leftSize.y);
+               if (right != null && !right.isDisposed()) {
+                       top = true;
+                       x -= rightSize.x;
+                       right.setBounds(x, y, rightSize.x, topHeight);
+                       x -= form.horizontalSpacing;
+               }
+               if (left != 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 != null && !center.isDisposed()) {
+                       top = true;
+                       int trim = computeTrim(center);
+                       int w = rect.width - 2*form.marginWidth - 2*form.highlight - trim;
+                       Point size = computeChildSize(center, w, SWT.DEFAULT, false);
+                       if (size.x < centerSize.x) {
+                               centerSize = size;
+                       }
+                       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 != null && !right.isDisposed()) {
+                       top = true;
+                       x -= rightSize.x;
+                       right.setBounds(x, y, rightSize.x, topHeight);
+                       x -= form.horizontalSpacing;
+               }
+               if (center != null && !center.isDisposed()) {
+                       top = true;
+                       x -= centerSize.x;
+                       center.setBounds(x, y, centerSize.x, topHeight);
+                       x -= form.horizontalSpacing;
+               }
+               if (left != null && !left.isDisposed()) {
+                       top = true;
+                       Rectangle trim = left instanceof Composite ? ((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 != null && !content.isDisposed()) {
+               if (left != null || right!= null || center != 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 != form.separator) {
+               int t, b;
+               if (oldSeperator == -1) {
+                       t = form.separator;
+                       b = form.separator + 1;
+               } else if (form.separator == -1) {
+                       t = oldSeperator;
+                       b = oldSeperator + 1;
+               } else {
+                       t = Math.min(form.separator, oldSeperator);
+                       b = Math.max(form.separator, oldSeperator);
+               }
+               form.redraw(form.borderLeft, t, form.getSize().x - form.borderLeft - form.borderRight, b - t, false);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/custom/package.html
new file mode 100644 (file)
index 0000000..3011a3f
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Custom widgets.
+<h2>
+Package Specification</h2>
+This package contains the custom widgets which were written to provide the
+standard look and feel of the Eclipse platform.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ByteArrayTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ByteArrayTransfer.java
new file mode 100644 (file)
index 0000000..3dee95c
--- /dev/null
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 == 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 == null) return null;
+ *
+ *             MyType[] myData = new MyType[0];
+ *             try {
+ *                     ByteArrayInputStream in = new ByteArrayInputStream(buffer);
+ *                     DataInputStream readIn = new DataInputStream(in);
+ *                     while(readIn.available() &gt; 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 extends Transfer {
+
+@Override
+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;
+}
+
+@Override
+public boolean isSupportedType(TransferData transferData){
+       if (transferData == null) return false;
+       int[] types = getTypeIds();
+       for (int i = 0; i < types.length; i++) {
+               FORMATETC format = transferData.formatetc;
+               if (format.cfFormat == types[i] &&
+                       (format.dwAspect & COM.DVASPECT_CONTENT) == COM.DVASPECT_CONTENT &&
+                       (format.tymed & COM.TYMED_HGLOBAL) == 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
+ */
+@Override
+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 = (byte[])object;
+       int size = data.length;
+       long newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, size);
+       OS.MoveMemory(newPtr, data, size);
+       transferData.stgmedium = new STGMEDIUM();
+       transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+       transferData.stgmedium.unionField = newPtr;
+       transferData.stgmedium.pUnkForRelease = 0;
+       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
+ */
+@Override
+protected Object nativeToJava(TransferData transferData) {
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0)  return null;
+
+       IDataObject data = new IDataObject(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 != COM.S_OK) return null;
+       long hMem = stgmedium.unionField;
+       int size = OS.GlobalSize(hMem);
+       byte[] buffer = new byte[size];
+       long ptr = OS.GlobalLock(hMem);
+       OS.MoveMemory(buffer, ptr, size);
+       OS.GlobalUnlock(hMem);
+       OS.GlobalFree(hMem);
+       return buffer;
+}
+
+boolean checkByteArray(Object object) {
+       return (object != null && object instanceof byte[] && ((byte[])object).length > 0);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/Clipboard.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/Clipboard.java
new file mode 100644 (file)
index 0000000..67b9b4b
--- /dev/null
@@ -0,0 +1,808 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Clipboard {
+
+       private static final int RETRY_LIMIT = 10;
+       private Display display;
+
+       // ole interfaces
+       private COMObject iDataObject;
+       private int refCount;
+       private Transfer[] transferAgents = new Transfer[0];
+       private Object[] data = new Object[0];
+       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 Clipboard(Display display) {
+       checkSubclass ();
+       if (display == null) {
+               display = Display.getCurrent();
+               if (display == null) {
+                       display = Display.getDefault();
+               }
+       }
+       if (display.getThread() != Thread.currentThread()) {
+               DND.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+       }
+       this.display = display;
+       TCHAR chFormatName = new TCHAR(0, "Preferred DropEffect", true); //$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 = getClass().getName ();
+       String validName = Clipboard.class.getName();
+       if (!validName.equals(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 == null) DND.error (SWT.ERROR_WIDGET_DISPOSED);
+       if (display.getThread() != Thread.currentThread ()) 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) != 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.getAddress()) == 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(0);
+               }
+       }
+}
+
+/**
+ * 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() != Thread.currentThread()) 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.getAddress()) == 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>
+ *
+ *    <pre><code>
+ *    Clipboard clipboard = new Clipboard(display);
+ *    TextTransfer textTransfer = TextTransfer.getInstance();
+ *    String textData = (String)clipboard.getContents(textTransfer);
+ *    if (textData != null) System.out.println("Text is "+textData);
+ *    RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ *    String rtfData = (String)clipboard.getContents(rtfTransfer);
+ *    if (rtfData != 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>
+ *
+ *    <pre><code>
+ *    Clipboard clipboard = new Clipboard(display);
+ *    TextTransfer textTransfer = TextTransfer.getInstance();
+ *    String textData = (String)clipboard.getContents(textTransfer);
+ *    if (textData != null) System.out.println("Text is "+textData);
+ *    RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ *    String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD);
+ *    if (rtfData != 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 == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+       if ((clipboards & DND.CLIPBOARD) == 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.
+       */
+       long[] ppv = new long[1];
+       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(ppv);
+       while (result != COM.S_OK && retryCount++ < RETRY_LIMIT) {
+               try {Thread.sleep(50);} catch (Throwable t) {}
+               MSG msg = new MSG();
+               OS.PeekMessage(msg, 0, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+               result = COM.OleGetClipboard(ppv);
+       }
+       if (result != COM.S_OK) return null;
+       IDataObject dataObject = new IDataObject(ppv[0]);
+       try {
+               TransferData[] allowed = transfer.getSupportedTypes();
+               for (int i = 0; i < allowed.length; i++) {
+                       if (dataObject.QueryGetData(allowed[i].formatetc) == COM.S_OK) {
+                               TransferData data = allowed[i];
+                               data.pIDataObject = ppv[0];
+                               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 boolean isDisposed () {
+       return (display == 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>
+ *
+ * <pre><code>
+ *     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>
+ *
+ * <pre><code>
+ *     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 == null || dataTypes == null || data.length != dataTypes.length || data.length == 0) {
+               DND.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       for (int i = 0; i < data.length; i++) {
+               if (data[i] == null || dataTypes[i] == null || !dataTypes[i].validate(data[i])) {
+                       DND.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       if ((clipboards & DND.CLIPBOARD) == 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.getAddress());
+
+       /*
+       * 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 != COM.S_OK && retryCount++ < RETRY_LIMIT) {
+               try {Thread.sleep(50);} catch (Throwable t) {}
+               MSG msg = new MSG();
+               OS.PeekMessage(msg, 0, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+               result = COM.OleSetClipboard(iDataObject.getAddress());
+       }
+       if (result != 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 COMObject(new int[]{2, 0, 0, 2, 2, 1, 2, 3, 2, 4, 1, 1}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return GetData(args[0], args[1]);}
+               // method4 GetDataHere - not implemented
+               @Override
+               public long method5(long[] args) {return QueryGetData(args[0]);}
+               // method6 GetCanonicalFormatEtc - not implemented
+               // method7 SetData - not implemented
+               @Override
+               public long method8(long[] args) {return EnumFormatEtc((int)args[0], args[1]);}
+               // method9 DAdvise - not implemented
+               // method10 DUnadvise - not implemented
+               // method11 EnumDAdvise - not implemented
+       };
+}
+private void disposeCOMInterfaces() {
+       if (iDataObject != null)
+               iDataObject.dispose();
+       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.
+ */
+private int EnumFormatEtc(int dwDirection, long ppenumFormatetc) {
+       // only allow getting of data - SetData is not currently supported
+       if (dwDirection == 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);
+       OS.MoveMemory(ppenumFormatetc, new long[] {enumFORMATETC.getAddress()}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+private int GetData(long pFormatetc, long 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 == 0 || pmedium == 0) return COM.E_INVALIDARG;
+       if (QueryGetData(pFormatetc) != 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 == 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
+               OS.MoveMemory(stgmedium.unionField, new int[] {COM.DROPEFFECT_COPY}, 4);
+               stgmedium.pUnkForRelease = 0;
+               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 == -1) return COM.DV_E_FORMATETC;
+       transferAgents[transferIndex].javaToNative(data[transferIndex], transferData);
+       COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof);
+       return transferData.result;
+}
+
+private int QueryGetData(long pFormatetc) {
+       if (transferAgents == 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 == 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.
+ */
+private int QueryInterface(long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDataObject) ) {
+               OS.MoveMemory(ppvObject, new long[] {iDataObject.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+private int Release() {
+       refCount--;
+       if (refCount == 0) {
+               this.data = new Object[0];
+               this.transferAgents = new Transfer[0];
+               disposeCOMInterfaces();
+               if (COM.FreeUnusedLibraries) {
+                       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) == 0) return new TransferData[0];
+       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++){
+               char [] buffer = new char [maxSize];
+               int size = OS.GetClipboardFormatName(types[i].cfFormat, buffer, maxSize);
+               if (size != 0) {
+                       names[i] = new String (buffer, 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 = new FORMATETC[0];
+       long[] ppv = new long[1];
+       /* OleGetClipboard([out] ppDataObject).
+        * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+        */
+       if (COM.OleGetClipboard(ppv) != COM.S_OK) return types;
+       IDataObject dataObject = new IDataObject(ppv[0]);
+       long[] ppFormatetc = new long[1];
+       /* 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, ppFormatetc);
+       dataObject.Release();
+       if (rc != COM.S_OK)return types;
+       IEnumFORMATETC enumFormatetc = new IEnumFORMATETC(ppFormatetc[0]);
+       // Loop over enumerator and save any types that match what we are looking for
+       long rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+       int[] pceltFetched = new int[1];
+       enumFormatetc.Reset();
+       while (enumFormatetc.Next(1, rgelt, pceltFetched) == COM.S_OK && pceltFetched[0] == 1) {
+               FORMATETC formatetc = new FORMATETC();
+               COM.MoveMemory(formatetc, rgelt, FORMATETC.sizeof);
+               FORMATETC[] newTypes = new FORMATETC[types.length + 1];
+               System.arraycopy(types, 0, newTypes, 0, types.length);
+               newTypes[types.length] = formatetc;
+               types = newTypes;
+       }
+       OS.GlobalFree(rgelt);
+       enumFormatetc.Release();
+       return types;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DND.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DND.java
new file mode 100644 (file)
index 0000000..9363386
--- /dev/null
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 final static int CLIPBOARD = 1 << 0;
+
+       /**
+        * The transfer mechanism for clients that use the selection
+        * mechanism (value is 2).
+        *
+        * @see Clipboard
+        *
+        * @since 3.1
+        */
+       public final static int SELECTION_CLIPBOARD = 1 << 1;
+
+       /**
+        * Drag and Drop Operation: no drag/drop operation performed
+        * (value is 0).
+        */
+       public final 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 final static int DROP_COPY = 1 << 0;
+
+       /**
+        * Drag and Drop Operation: a copy of the data is added to the drop target and
+        * the drag source removes the original data and any references to the data,
+        * and updates its display (value is 1 &lt;&lt; 1).
+        * <p>
+        * <b>Warning:</b> Some applications (most notably Firefox, Thunderbird, and Safari) return
+        * {@link DND#DROP_MOVE} even if they just open a dropped file and don't copy
+        * anything, see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=30543">bug 30543</a>.
+        * </p>
+        * <p>
+        * <b>To avoid data loss</b>, you may want to not remove the original data
+        * when you handle a {@link DND#DragEnd} for a {@link FileTransfer} whose
+        * {@link org.eclipse.swt.widgets.Event#detail} is {@link #DROP_MOVE}.
+        * </p>
+        */
+       public final 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 final 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 final 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 final 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 final int DragEnd         = 2000;
+
+       /**
+        * DragSource Event: the data to be dropped is required from the drag source (value is 2001).
+        */
+       public static final int DragSetData = 2001;
+
+       /**
+        * DropTarget Event: the cursor has entered the drop target boundaries (value is 2002).
+        */
+       public static final 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 final int DragLeave       = 2003;
+
+       /**
+        * DropTarget Event: the cursor is over the drop target (value is 2004).
+        */
+       public static final 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 final int DragOperationChanged = 2005;
+
+       /**
+        * DropTarget Event: the data has been dropped (value is 2006).
+        */
+       public static final int Drop = 2006;
+
+       /**
+        * DropTarget Event: the drop target is given a last chance to modify the drop (value is 2007).
+        */
+       public static final int DropAccept      = 2007;
+
+       /**
+        * DragSource Event: a drag is about to begin (value is 2008).
+        */
+       public static final int DragStart = 2008;
+
+       /**
+        * DropTarget drag under effect: No effect is shown (value is 0).
+        */
+       public static final 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 final int FEEDBACK_SELECT = 1;
+
+       /**
+        * DropTarget drag under effect: An insertion mark is shown before the item under the cursor; applies to
+        * tables and trees (value is 2).
+        */
+       public static final int FEEDBACK_INSERT_BEFORE = 2;
+
+       /**
+        * DropTarget drag under effect: An insertion mark is shown after the item under the cursor; applies to
+        * tables and trees (value is 4).
+        */
+       public static final 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 final 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 final int FEEDBACK_EXPAND = 16;
+
+       /**
+        * Error code: drag source can not be initialized (value is 2000).
+        */
+       public static final int ERROR_CANNOT_INIT_DRAG = 2000;
+
+       /**
+        * Error code: drop target cannot be initialized (value is 2001).
+        */
+       public static final int ERROR_CANNOT_INIT_DROP = 2001;
+
+       /**
+        * Error code: Data can not be set on system clipboard (value is 2002).
+        */
+       public static final int ERROR_CANNOT_SET_CLIPBOARD = 2002;
+
+       /**
+        * Error code: Data does not have correct format for type (value is 2003).
+        * @since 3.1
+        */
+       public static final 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 final String INIT_DRAG_MESSAGE = "Cannot initialize Drag"; //$NON-NLS-1$
+       static final String INIT_DROP_MESSAGE = "Cannot initialize Drop"; //$NON-NLS-1$
+       static final String CANNOT_SET_CLIPBOARD_MESSAGE = "Cannot set data in clipboard"; //$NON-NLS-1$
+       static final 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:</p>
+ * <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>
+ * <p>
+ * 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 != 0) msg += " result = "+hresult; //$NON-NLS-1$
+                       throw new SWTError (code, msg);
+               }
+               case DND.ERROR_CANNOT_INIT_DROP:{
+                       String msg = DND.INIT_DROP_MESSAGE;
+                       if (hresult != 0) msg += " result = "+hresult; //$NON-NLS-1$
+                       throw new SWTError (code, msg);
+               }
+               case DND.ERROR_CANNOT_SET_CLIPBOARD:{
+                       String msg = DND.CANNOT_SET_CLIPBOARD_MESSAGE;
+                       if (hresult != 0) msg += " result = "+hresult; //$NON-NLS-1$
+                       throw new SWTError (code, msg);
+               }
+               case DND.ERROR_INVALID_DATA:{
+                       String msg = DND.INVALID_DATA_MESSAGE;
+                       if (hresult != 0) msg += " result = "+hresult; //$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+       }
+
+       /* Unknown/Undefined Error */
+       SWT.error(code);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DNDEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DNDEvent.java
new file mode 100644 (file)
index 0000000..e2c0b1f
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+class DNDEvent extends Event {
+       public TransferData dataType;
+       public TransferData[] dataTypes;
+       public int operations;
+       public int feedback;
+       public Image image;
+       public int offsetX;
+       public int offsetY;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DNDListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DNDListener.java
new file mode 100644 (file)
index 0000000..3b341e8
--- /dev/null
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.widgets.*;
+
+
+class DNDListener extends TypedListener {
+       Widget dndWidget;
+/**
+ * DNDListener constructor comment.
+ * @param listener org.eclipse.swt.internal.SWTEventListener
+ */
+DNDListener(SWTEventListener listener) {
+       super(listener);
+}
+@Override
+public void handleEvent (Event e) {
+       switch (e.type) {
+               case DND.DragStart: {
+                       DragSourceEvent event = new DragSourceEvent((DNDEvent)e);
+                       DragSourceEffect sourceEffect = ((DragSource) dndWidget).getDragSourceEffect();
+                       if (sourceEffect != null) {
+                               sourceEffect.dragStart (event);
+                       }
+                       ((DragSourceListener) eventListener).dragStart (event);
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DragEnd: {
+                       DragSourceEvent event = new DragSourceEvent((DNDEvent)e);
+                       DragSourceEffect sourceEffect = ((DragSource) dndWidget).getDragSourceEffect();
+                       if (sourceEffect != null) {
+                               sourceEffect.dragFinished (event);
+                       }
+                       ((DragSourceListener) eventListener).dragFinished (event);
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DragSetData: {
+                       DragSourceEvent event = new DragSourceEvent((DNDEvent)e);
+                       DragSourceEffect sourceEffect = ((DragSource) dndWidget).getDragSourceEffect();
+                       if (sourceEffect != null) {
+                               sourceEffect.dragSetData (event);
+                       }
+                       ((DragSourceListener) eventListener).dragSetData (event);
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DragEnter: {
+                       DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+                       ((DropTargetListener) eventListener).dragEnter (event);
+                       DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+                       if (dropEffect != null) {
+                               dropEffect.dragEnter (event);
+                       }
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DragLeave: {
+                       DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+                       ((DropTargetListener) eventListener).dragLeave (event);
+                       DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+                       if (dropEffect != null) {
+                               dropEffect.dragLeave (event);
+                       }
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DragOver: {
+                       DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+                       ((DropTargetListener) eventListener).dragOver (event);
+                       DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+                       if (dropEffect != null) {
+                               dropEffect.dragOver (event);
+                       }
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.Drop: {
+                       DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+                       ((DropTargetListener) eventListener).drop (event);
+                       DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+                       if (dropEffect != null) {
+                               dropEffect.drop (event);
+                       }
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DropAccept: {
+                       DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+                       ((DropTargetListener) eventListener).dropAccept (event);
+                       DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+                       if (dropEffect != null) {
+                               dropEffect.dropAccept (event);
+                       }
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+               case DND.DragOperationChanged: {
+                       DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+                       ((DropTargetListener) eventListener).dragOperationChanged (event);
+                       DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+                       if (dropEffect != null) {
+                               dropEffect.dragOperationChanged (event);
+                       }
+                       event.updateEvent((DNDEvent)e);
+                       break;
+               }
+
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSource.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSource.java
new file mode 100644 (file)
index 0000000..611a7a3
--- /dev/null
@@ -0,0 +1,836 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 497807
+ *     Paul Pazderski - Improved implementation of IDataObject for bug 549643, 549661 and 567422
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ *
+ * <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>
+ *
+ * <pre><code>
+ *     // 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() == 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 == DND.DROP_MOVE)
+ *                             label.setText("");
+ *             }
+ *     });
+ * </code></pre>
+ *
+ *
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class DragSource extends Widget {
+
+       // info for registering as a drag source
+       Control control;
+       Listener controlListener;
+       Transfer[] transferAgents = new Transfer[0];
+       DragSourceEffect dragEffect;
+       Composite topControl;
+       long hwndDrag;
+
+       // ole interfaces
+       COMIDropSource iDropSource;
+       COMIDataObject iDataObject;
+
+       //workaround - track the operation performed by the drop target for DragEnd event
+       int dataEffect = DND.DROP_NONE;
+
+       static final String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$
+       static final int CFSTR_PERFORMEDDROPEFFECT  = Transfer.registerType("Performed DropEffect");     //$NON-NLS-1$
+       static final TCHAR WindowClass = new TCHAR (0, "#32770", true);
+
+       private class COMIDropSource extends COMObject {
+
+               private long refCount = 0;
+
+               /**
+                * Create a new IDropSource COM object. Object is created with one active
+                * reference. (see {@link #Release()})
+                */
+               public COMIDropSource() {
+                       super(new int[]{2, 0, 0, 2, 1});
+                       AddRef();
+               }
+
+               @Override
+               public long method0(long[] args) {return QueryInterface(this, args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return QueryContinueDrag((int)args[0], (int)args[1]);}
+               @Override
+               public long method4(long[] args) {return GiveFeedback((int)args[0]);}
+
+               public long AddRef() {
+                       refCount++;
+                       return refCount;
+               }
+
+               public long Release() {
+                       refCount--;
+                       if (refCount == 0) {
+                               if (DragSource.this.iDropSource == this) {
+                                       DragSource.this.iDropSource = null;
+                               }
+                               this.dispose();
+                               if (COM.FreeUnusedLibraries) {
+                                       COM.CoFreeUnusedLibraries();
+                               }
+                       }
+                       return refCount;
+               }
+       }
+
+       private class COMIDataObject extends COMObject {
+               /*
+                * A SWT application is used to provide the data to drag in an event callback
+                * which is called while the DND operation is performed. However Windows expects
+                * the data to passed around in an object whose lifetime is managed through
+                * reference counting. The drop target can keep a reference on the IDataObject
+                * and even try to query the data long after the DND operation is finished. One
+                * such case is Windows Explorer when showing a Portal Device (see bug 549661).
+                * SWT does two things to support this case:
+                * 1. Implement reference counting as intended. I.e. do not force release the
+                * object after DND is finished but trust that all involved applications are
+                * able to count correctly and will release the object at some point.
+                * 2. Cache the data which was last transfered/generated from the DragSource
+                * to be able to send it again after the DND operation is finished.
+                */
+
+               private long refCount = 0;
+
+               private final Transfer[] transferAgents;
+
+               /**
+                * The most recent data send in a GetData request (or GetDataHere if
+                * implemented). Or from another perspective the data the application returned
+                * in the most recent {@link DND#DragSetData} event.
+                */
+               private Object lastData = null;
+
+               /**
+                * Create a new IDataObject COM object. Objects are created with one active
+                * reference. (see {@link #Release()})
+                *
+                * @param transferAgents should be the transfer agents which are set on
+                *                       DragSource at the time this object is created.
+                */
+               public COMIDataObject(Transfer[] transferAgents) {
+                       super(new int[]{2, 0, 0, 2, 2, 1, 2, 3, 2, 4, 1, 1});
+                       AddRef();
+                       this.transferAgents = transferAgents;
+               }
+
+               @Override
+               public long method0(long[] args) {return QueryInterface(this, args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return GetData(args[0], args[1]);}
+               // method4 GetDataHere - not implemented
+               @Override
+               public long method5(long[] args) {return QueryGetData(transferAgents, args[0]);}
+               // method6 GetCanonicalFormatEtc - not implemented
+               @Override
+               public long method7(long[] args) {return SetData(args[0], args[1], (int)args[2]);}
+               @Override
+               public long method8(long[] args) {return EnumFormatEtc(transferAgents, (int)args[0], args[1]);}
+               // method9 DAdvise - not implemented
+               // method10 DUnadvise - not implemented
+               // method11 EnumDAdvise - not implemented
+
+               public long AddRef() {
+                       refCount++;
+                       return refCount;
+               }
+
+               public long Release() {
+                       refCount--;
+                       if (refCount == 0) {
+                               if (DragSource.this.iDataObject == this) {
+                                       DragSource.this.iDataObject = null;
+                               }
+                               this.dispose();
+                               if (COM.FreeUnusedLibraries) {
+                                       COM.CoFreeUnusedLibraries();
+                               }
+                       }
+                       return refCount;
+               }
+
+               /**
+                * Check if this IDataObject is currently used in a DND operation.
+                *
+                * @return <code>true</true> if this object currently used for DND
+                */
+               private boolean isActive() {
+                       return DragSource.this.iDataObject == this;
+               }
+
+               private int GetData(long pFormatetc, long 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 == 0 || pmedium == 0) return COM.E_INVALIDARG;
+
+                       if (QueryGetData(transferAgents, pFormatetc) != 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;
+
+                       final Object data;
+                       if (isActive()) {
+                               DNDEvent event = new DNDEvent();
+                               event.widget = DragSource.this;
+                               event.time = OS.GetMessageTime();
+                               event.dataType = transferData;
+                               notifyListeners(DND.DragSetData,event);
+
+                               if (!event.doit) return COM.E_FAIL;
+
+                               lastData = event.data;
+                               data = event.data;
+                       } else {
+                               if (lastData == null) {
+                                       return COM.E_FAIL;
+                               }
+                               data = lastData;
+                       }
+
+                       // get matching transfer agent to perform conversion
+                       Transfer transfer = null;
+                       for (Transfer transferAgent : transferAgents) {
+                               if (transferAgent != null && transferAgent.isSupportedType(transferData)){
+                                       transfer = transferAgent;
+                                       break;
+                               }
+                       }
+
+                       if (transfer == null) return COM.DV_E_FORMATETC;
+                       transfer.javaToNative(data, transferData);
+                       if (transferData.result != COM.S_OK) return transferData.result;
+                       COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof);
+                       return transferData.result;
+               }
+
+               private int SetData(long pFormatetc, long pmedium, int fRelease) {
+                       if (pFormatetc == 0 || pmedium == 0) return COM.E_INVALIDARG;
+                       FORMATETC formatetc = new FORMATETC();
+                       COM.MoveMemory(formatetc, pFormatetc, FORMATETC.sizeof);
+                       if (formatetc.cfFormat == CFSTR_PERFORMEDDROPEFFECT && formatetc.tymed == COM.TYMED_HGLOBAL) {
+                               STGMEDIUM stgmedium = new STGMEDIUM();
+                               COM.MoveMemory(stgmedium, pmedium,STGMEDIUM.sizeof);
+                               //TODO - this should be GlobalLock()
+                               long[] ptrEffect = new long[1];
+                               OS.MoveMemory(ptrEffect, stgmedium.unionField, C.PTR_SIZEOF);
+                               int[] effect = new int[1];
+                               OS.MoveMemory(effect, ptrEffect[0], 4);
+                               if (isActive()) {
+                                       dataEffect = osToOp(effect[0]);
+                               }
+                       }
+                       if (fRelease == 1) {
+                               COM.ReleaseStgMedium(pmedium);
+                       }
+                       return COM.S_OK;
+               }
+       }
+
+/**
+ * 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 DragSource(Control control, int style) {
+       super(control, checkStyle(style));
+       this.control = control;
+       if (control.getData(DND.DRAG_SOURCE_KEY) != null) {
+               DND.error(DND.ERROR_CANNOT_INIT_DRAG);
+       }
+       control.setData(DND.DRAG_SOURCE_KEY, this);
+
+       controlListener = event -> {
+               if (event.type == SWT.Dispose) {
+                       if (!DragSource.this.isDisposed()) {
+                               DragSource.this.dispose();
+                       }
+               }
+               if (event.type == SWT.DragDetect) {
+                       if (!DragSource.this.isDisposed()) {
+                               DragSource.this.drag(event);
+                       }
+               }
+       };
+       control.addListener(SWT.Dispose, controlListener);
+       control.addListener(SWT.DragDetect, controlListener);
+
+       this.addListener(SWT.Dispose, e -> DragSource.this.onDispose());
+
+       Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT);
+       if (effect instanceof DragSourceEffect) {
+               dragEffect = (DragSourceEffect) effect;
+       } else if (control instanceof Tree) {
+               dragEffect = new TreeDragSourceEffect((Tree) control);
+       } else if (control instanceof Table) {
+               dragEffect = new TableDragSourceEffect((Table) control);
+       }
+}
+
+static int checkStyle(int style) {
+       if (style == 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.
+ *
+ * <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>
+ *
+ * @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 == 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 void createCOMInterfaces() {
+       releaseCOMInterfaces();
+       iDropSource = new COMIDropSource();
+       iDataObject = new COMIDataObject(transferAgents);
+}
+
+@Override
+protected void checkSubclass() {
+       String name = getClass().getName();
+       String validName = DragSource.class.getName();
+       if (!validName.equals(name)) {
+               DND.error(SWT.ERROR_INVALID_SUBCLASS);
+       }
+}
+
+private void releaseCOMInterfaces() {
+       if (iDropSource != null)
+               iDropSource.Release();
+       iDropSource = null;
+
+       if (iDataObject != null)
+               iDataObject.Release();
+       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 == null || transferAgents.length == 0 ) return;
+
+       int[] pdwEffect = new int[1];
+       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, Boolean.TRUE);
+       ImageList imagelist = null;
+       Image image = event.image;
+       hwndDrag = 0;
+       topControl = null;
+       if (image != 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 offsetX = event.offsetX;
+               hwndDrag = topControl.handle;
+               if ((topControl.getStyle() & SWT.RIGHT_TO_LEFT) != 0) {
+                       offsetX = image.getBoundsInPixels().width - offsetX;
+                       RECT rect = new RECT ();
+                       OS.GetClientRect (topControl.handle, rect);
+                       hwndDrag = OS.CreateWindowEx (
+                               OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT,
+                               WindowClass,
+                               null,
+                               OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
+                               0, 0,
+                               rect.right - rect.left, rect.bottom - rect.top,
+                               topControl.handle,
+                               0,
+                               OS.GetModuleHandle (null),
+                               null);
+                       OS.ShowWindow (hwndDrag, OS.SW_SHOW);
+               }
+               OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offsetX, event.offsetY);
+               /*
+               * 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().
+               */
+               int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+               OS.RedrawWindow (topControl.handle, null, 0, flags);
+               POINT pt = new POINT ();
+               pt.x = DPIUtil.autoScaleUp(dragEvent.x);// To Pixels
+               pt.y = DPIUtil.autoScaleUp(dragEvent.y);// To Pixels
+               OS.MapWindowPoints (control.handle, 0, pt, 1);
+               RECT rect = new RECT ();
+               OS.GetWindowRect (hwndDrag, rect);
+               OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top);
+       }
+       String externalLoopKey = "org.eclipse.swt.internal.win32.externalEventLoop";
+       int result = COM.DRAGDROP_S_CANCEL;
+       try {
+               createCOMInterfaces();
+               display.setData(externalLoopKey, Boolean.TRUE);
+               result = COM.DoDragDrop(iDataObject.getAddress(), iDropSource.getAddress(), operations, pdwEffect);
+       } finally {
+               display.setData(externalLoopKey, Boolean.FALSE);
+               // ensure that we don't leave transparent window around
+               if (hwndDrag != 0) {
+                       OS.ImageList_DragLeave(hwndDrag);
+                       OS.ImageList_EndDrag();
+                       imagelist.dispose();
+                       if (hwndDrag != topControl.handle) OS.DestroyWindow(hwndDrag);
+                       hwndDrag = 0;
+                       topControl = null;
+               }
+               display.setData(key, oldValue);
+               releaseCOMInterfaces();
+       }
+       int operation = osToOp(pdwEffect[0]);
+       if (dataEffect == DND.DROP_MOVE) {
+               operation = (operation == DND.DROP_NONE || operation == DND.DROP_COPY) ? DND.DROP_TARGET_MOVE : DND.DROP_MOVE;
+       } else {
+               if (dataEffect != DND.DROP_NONE) {
+                       operation = dataEffect;
+               }
+       }
+
+       event = new DNDEvent();
+       event.widget = this;
+       event.time = OS.GetMessageTime();
+       event.doit = (result == 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 static int EnumFormatEtc(Transfer[] transferAgents, int dwDirection, long ppenumFormatetc) {
+       // only allow getting of data - SetData is not currently supported
+       if (dwDirection == COM.DATADIR_SET) return COM.E_NOTIMPL;
+
+       // what types have been registered?
+       TransferData[] allowedDataTypes = new TransferData[0];
+       for (Transfer transferAgent : transferAgents) {
+               if (transferAgent != 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);
+
+       OS.MoveMemory(ppenumFormatetc, new long[] {enumFORMATETC.getAddress()}, C.PTR_SIZEOF);
+       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;
+}
+
+/**
+ * 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 (listener instanceof DNDListener) {
+                       dragListeners[count] = (DragSourceListener) ((DNDListener) listener).getEventListener();
+                       count++;
+               }
+       }
+       if (count == length) return dragListeners;
+       DragSourceListener[] result = new DragSourceListener[count];
+       System.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;
+}
+
+private int GiveFeedback(int dwEffect) {
+       return COM.DRAGDROP_S_USEDEFAULTCURSORS;
+}
+
+private int QueryContinueDrag(int fEscapePressed, int grfKeyState) {
+       if (topControl != null && topControl.isDisposed()) return COM.DRAGDROP_S_CANCEL;
+       if (fEscapePressed != 0){
+               if (hwndDrag != 0) 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) == 0) {
+               if (hwndDrag != 0) OS.ImageList_DragLeave(hwndDrag);
+               return COM.DRAGDROP_S_DROP;
+       }
+
+       if (hwndDrag != 0) {
+               POINT pt = new POINT ();
+               OS.GetCursorPos (pt);
+               RECT rect = new 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 == null) return;
+       releaseCOMInterfaces();
+       if (controlListener != 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) != 0){
+               osOperation |= COM.DROPEFFECT_COPY;
+       }
+       if ((operation & DND.DROP_LINK) != 0) {
+               osOperation |= COM.DROPEFFECT_LINK;
+       }
+       if ((operation & DND.DROP_MOVE) != 0) {
+               osOperation |= COM.DROPEFFECT_MOVE;
+       }
+       return osOperation;
+}
+
+private int osToOp(int osOperation){
+       int operation = 0;
+       if ((osOperation & COM.DROPEFFECT_COPY) != 0){
+               operation |= DND.DROP_COPY;
+       }
+       if ((osOperation & COM.DROPEFFECT_LINK) != 0) {
+               operation |= DND.DROP_LINK;
+       }
+       if ((osOperation & COM.DROPEFFECT_MOVE) != 0) {
+               operation |= DND.DROP_MOVE;
+       }
+       return operation;
+}
+
+private static int QueryGetData(Transfer[] transferAgents, long pFormatetc) {
+       if (transferAgents == 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 (Transfer transferAgent : transferAgents) {
+               if (transferAgent != null && transferAgent.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 static int QueryInterface(COMObject comObject, long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+
+       if (comObject != null && COM.IsEqualGUID(guid, COM.IIDIUnknown)
+                       || (COM.IsEqualGUID(guid, COM.IIDIDropSource) && (comObject instanceof COMIDropSource))
+                       || (COM.IsEqualGUID(guid, COM.IIDIDataObject) && (comObject instanceof COMIDataObject))) {
+               OS.MoveMemory(ppvObject, new long[] {comObject.getAddress()}, C.PTR_SIZEOF);
+               comObject.method1(null); // AddRef
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+/**
+ * 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 == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+       removeListener(DND.DragStart, listener);
+       removeListener(DND.DragSetData, listener);
+       removeListener(DND.DragEnd, listener);
+}
+
+/**
+ * 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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceAdapter.java
new file mode 100644 (file)
index 0000000..c2680d1
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+/**
+ * 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 implements 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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+public void dragSetData(DragSourceEvent event){}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceEffect.java
new file mode 100644 (file)
index 0000000..0f617eb
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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 DragSourceEffect(Control control) {
+               if (control == 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;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceEvent.java
new file mode 100644 (file)
index 0000000..3b287c5
--- /dev/null
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 extends 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>
+        * In dragStart:</p>
+        * <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 dragSetData:</p>
+        * <p>This will be set to true when the call to dragSetData is made.  Set it to
+        * false to cancel the drag.</p>
+        * <p>In dragFinished:</p>
+        * <p>Flag to indicate if the operation was performed successfully.
+        * True if the operation was performed successfully.</p>
+        */
+       public boolean 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;
+
+       /**
+        * In dragStart, the x offset (relative to the image) where the drag source image will be displayed.
+        *
+        * @since 3.5
+        */
+       public int offsetX;
+       /**
+        * In dragStart, the y offset (relative to the image) where the drag source image will be displayed.
+        *
+        * @since 3.5
+        */
+       public int offsetY;
+
+       static final 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 DragSourceEvent(DNDEvent e) {
+       super(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;
+       this.offsetX = e.offsetX;
+       this.offsetY = e.offsetY;
+}
+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;
+       e.offsetX = this.offsetX;
+       e.offsetY = this.offsetY;
+}
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " operation=" + detail
+               + " type=" + (dataType != null ? dataType.type : 0)
+               + " doit=" + doit
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DragSourceListener.java
new file mode 100644 (file)
index 0000000..4d508cb
--- /dev/null
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 extends 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:</p>
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in,out)doit
+ * </ul>
+ *
+ * @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:</p>
+ * <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)
+ * <li>(out)doit    - set this to cancel the drag
+ * </ul>
+ *
+ * @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:</p>
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)doit
+ * <li>(in)detail
+ * </ul>
+ *
+ * @param event the information associated with the drag finished event
+ *
+ * @see DragSourceEvent
+ */
+public void dragFinished(DragSourceEvent event);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTarget.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTarget.java
new file mode 100644 (file)
index 0000000..844cc84
--- /dev/null
@@ -0,0 +1,807 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ *
+ * Class <code>DropTarget</code> defines the target object for a drag and drop transfer.
+ *
+ * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p>
+ *
+ * <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>
+ *
+ * <pre><code>
+ *     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.
+ *
+ * <pre><code>
+ *     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 == 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
+ *             }
+ *     });
+ * </code></pre>
+ *
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class DropTarget extends Widget {
+
+       Control control;
+       Listener controlListener;
+       Transfer[] transferAgents = new Transfer[0];
+       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
+       COMObject 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 DropTarget(Control control, int style) {
+       super (control, checkStyle(style));
+       this.control = control;
+       if (control.getData(DND.DROP_TARGET_KEY) != null) {
+               DND.error(DND.ERROR_CANNOT_INIT_DROP);
+       }
+       control.setData(DND.DROP_TARGET_KEY, this);
+       createCOMInterfaces();
+       this.AddRef();
+
+       if (COM.CoLockObjectExternal(iDropTarget.getAddress(), true, true) != COM.S_OK)
+               DND.error(DND.ERROR_CANNOT_INIT_DROP);
+       if (COM.RegisterDragDrop( control.handle, iDropTarget.getAddress()) != COM.S_OK)
+               DND.error(DND.ERROR_CANNOT_INIT_DROP);
+
+       controlListener = event -> {
+               if (!DropTarget.this.isDisposed()){
+                       DropTarget.this.dispose();
+               }
+       };
+       control.addListener (SWT.Dispose, controlListener);
+
+       this.addListener(SWT.Dispose, event -> onDispose());
+
+       Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT);
+       if (effect instanceof DropTargetEffect) {
+               dropEffect = (DropTargetEffect) effect;
+       } else if (control instanceof Table) {
+               dropEffect = new TableDropTargetEffect((Table) control);
+       } else if (control instanceof Tree) {
+               dropEffect = new TreeDropTargetEffect((Tree) control);
+       }
+}
+
+static int checkStyle (int style) {
+       if (style == 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.
+ *
+ * <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>
+ *
+ * @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 == 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);
+}
+
+int AddRef() {
+       refCount++;
+       return refCount;
+}
+
+@Override
+protected void checkSubclass () {
+       String name = getClass().getName ();
+       String validName = DropTarget.class.getName();
+       if (!validName.equals(name)) {
+               DND.error (SWT.ERROR_INVALID_SUBCLASS);
+       }
+}
+
+void createCOMInterfaces() {
+       // register each of the interfaces that this object implements
+       boolean is32 = C.PTR_SIZEOF == 4;
+       iDropTarget = new COMObject(new int[]{2, 0, 0, is32 ? 5 : 4, is32 ? 4 : 3, 0, is32 ? 5 : 4}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {
+                       if (args.length == 5) {
+                               return DragEnter(args[0], (int)args[1], (int)args[2], (int)args[3], args[4]);
+                       } else {
+                               return DragEnter_64(args[0], (int)args[1], args[2], args[3]);
+                       }
+               }
+               @Override
+               public long method4(long[] args) {
+                       if (args.length == 4) {
+                               return DragOver((int)args[0], (int)args[1], (int)args[2], args[3]);
+                       } else {
+                               return DragOver_64((int)args[0], args[1], args[2]);
+                       }
+               }
+               @Override
+               public long method5(long[] args) {return DragLeave();}
+               @Override
+               public long method6(long[] args) {
+                       if (args.length == 5) {
+                               return Drop(args[0], (int)args[1], (int)args[2], (int)args[3], args[4]);
+                       } else {
+                               return Drop_64(args[0], (int)args[1], args[2], args[3]);
+                       }
+               }
+       };
+}
+
+void disposeCOMInterfaces() {
+       if (iDropTarget != null)
+               iDropTarget.dispose();
+       iDropTarget = null;
+}
+
+int DragEnter_64(long pDataObject, int grfKeyState, long pt, long pdwEffect) {
+       POINT point = new POINT();
+       OS.MoveMemory(point, new long[]{pt}, 8);
+       return DragEnter(pDataObject, grfKeyState, point.x, point.y, pdwEffect);
+}
+
+int DragEnter(long pDataObject, int grfKeyState, int pt_x, int pt_y, long pdwEffect) {
+       pt_x = DPIUtil.autoScaleDown(pt_x);// To Points
+       pt_y = DPIUtil.autoScaleDown(pt_y);// To Points
+       selectedDataType = null;
+       selectedOperation = DND.DROP_NONE;
+       if (iDataObject != null) iDataObject.Release();
+       iDataObject = null;
+
+       DNDEvent event = new DNDEvent();
+       if (!setEventData(event, pDataObject, grfKeyState, pt_x, pt_y, pdwEffect)) {
+               OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4);
+               return COM.S_FALSE;
+       }
+
+       // Remember the iDataObject because it is not passed into the DragOver callback
+       iDataObject = new 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 == DND.DROP_DEFAULT) {
+               event.detail = (allowedOperations & DND.DROP_MOVE) != 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 != null && ((allowedOperations & event.detail) != 0)) {
+               selectedOperation = event.detail;
+       }
+
+       OS.MoveMemory(pdwEffect, new int[] {opToOs(selectedOperation)}, 4);
+       return COM.S_OK;
+}
+
+int DragLeave() {
+       keyOperation = -1;
+
+       if (iDataObject == 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, long pdwEffect) {
+       POINT point = new POINT();
+       OS.MoveMemory(point, new long[]{pt}, 8);
+       return DragOver(grfKeyState, point.x, point.y, pdwEffect);
+}
+
+int DragOver(int grfKeyState, int pt_x, int pt_y, long pdwEffect) {
+       pt_x = DPIUtil.autoScaleDown(pt_x);// To Points
+       pt_y = DPIUtil.autoScaleDown(pt_y);// To Points
+       if (iDataObject == null) return COM.S_FALSE;
+       int oldKeyOperation = keyOperation;
+
+       DNDEvent event = new DNDEvent();
+       if (!setEventData(event, iDataObject.getAddress(), grfKeyState, pt_x, pt_y, pdwEffect)) {
+               keyOperation = -1;
+               OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4);
+               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 == 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 == DND.DROP_DEFAULT) {
+               event.detail = (allowedOperations & DND.DROP_MOVE) != 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 != null && ((allowedOperations & event.detail) == event.detail)) {
+               selectedOperation = event.detail;
+       }
+
+       OS.MoveMemory(pdwEffect, new int[] {opToOs(selectedOperation)}, 4);
+       return COM.S_OK;
+}
+
+int Drop_64(long pDataObject, int grfKeyState, long pt, long pdwEffect) {
+       POINT point = new POINT();
+       OS.MoveMemory(point, new long[]{pt}, 8);
+       return Drop(pDataObject, grfKeyState, point.x, point.y, pdwEffect);
+}
+
+int Drop(long pDataObject, int grfKeyState, int pt_x, int pt_y, long pdwEffect) {
+       try {
+               pt_x = DPIUtil.autoScaleDown(pt_x);// To Points
+               pt_y = DPIUtil.autoScaleDown(pt_y);// To Points
+               DNDEvent event = new DNDEvent();
+               event.widget = this;
+               event.time = OS.GetMessageTime();
+               if (dropEffect != 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_x, pt_y, pdwEffect)) {
+                       keyOperation = -1;
+                       OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4);
+                       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 != null && (allowedOperations & event.detail) == event.detail) {
+                       selectedOperation = event.detail;
+               }
+
+               if (selectedOperation == DND.DROP_NONE){
+                       OS.MoveMemory(pdwEffect, new int[] {COM.DROPEFFECT_NONE}, 4);
+                       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 != null && transfer.isSupportedType(selectedDataType)){
+                               object = transfer.nativeToJava(selectedDataType);
+                               break;
+                       }
+               }
+               if (object == 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) == event.detail) {
+                       selectedOperation = event.detail;
+               }
+               //notify source of action taken
+               OS.MoveMemory(pdwEffect, new int[] {opToOs(selectedOperation)}, 4);
+               return COM.S_OK;
+       } finally {
+               if (iDataObject != null) {
+                       iDataObject.Release();
+                       iDataObject = null;
+               }
+       }
+}
+
+/**
+ * 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 (listener instanceof DNDListener) {
+                       dropListeners[count] = (DropTargetListener) ((DNDListener) listener).getEventListener();
+                       count++;
+               }
+       }
+       if (count == length) return dropListeners;
+       DropTargetListener[] result = new DropTargetListener[count];
+       System.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) {
+       boolean ctrl = (grfKeyState & OS.MK_CONTROL) != 0;
+       boolean shift = (grfKeyState & OS.MK_SHIFT) != 0;
+       boolean alt = (grfKeyState & OS.MK_ALT) != 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 == null) return;
+
+       COM.RevokeDragDrop(control.handle);
+
+       if (controlListener != null)
+               control.removeListener(SWT.Dispose, controlListener);
+       controlListener = null;
+       control.setData(DND.DROP_TARGET_KEY, null);
+       transferAgents = null;
+       control = null;
+
+       COM.CoLockObjectExternal(iDropTarget.getAddress(), false, true);
+
+       this.Release();
+       if (iDataObject != null) {
+               iDataObject.Release();
+       }
+       iDataObject = null;
+
+       if (COM.FreeUnusedLibraries) {
+               COM.CoFreeUnusedLibraries();
+       }
+}
+
+int opToOs(int operation) {
+       int osOperation = 0;
+       if ((operation & DND.DROP_COPY) != 0){
+               osOperation |= COM.DROPEFFECT_COPY;
+       }
+       if ((operation & DND.DROP_LINK) != 0) {
+               osOperation |= COM.DROPEFFECT_LINK;
+       }
+       if ((operation & DND.DROP_MOVE) != 0) {
+               osOperation |= COM.DROPEFFECT_MOVE;
+       }
+       return osOperation;
+}
+
+int osToOp(int osOperation){
+       int operation = 0;
+       if ((osOperation & COM.DROPEFFECT_COPY) != 0){
+               operation |= DND.DROP_COPY;
+       }
+       if ((osOperation & COM.DROPEFFECT_LINK) != 0) {
+               operation |= DND.DROP_LINK;
+       }
+       if ((osOperation & COM.DROPEFFECT_MOVE) != 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.
+ */
+int QueryInterface(long riid, long ppvObject) {
+
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDropTarget)) {
+               OS.MoveMemory(ppvObject, new long[] {iDropTarget.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+
+int Release() {
+       refCount--;
+
+       if (refCount == 0) {
+               disposeCOMInterfaces();
+               if (COM.FreeUnusedLibraries) {
+                       COM.CoFreeUnusedLibraries();
+               }
+       }
+
+       return refCount;
+}
+
+void refresh() {
+       if (control == null || control.isDisposed()) return;
+       long handle = control.handle;
+       RECT lpRect = new RECT();
+       if (OS.GetUpdateRect(handle, lpRect, false)) {
+               OS.ImageList_DragShowNolock(false);
+               OS.RedrawWindow(handle, lpRect, 0, 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 == 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;
+}
+
+boolean setEventData(DNDEvent event, long pDataObject, int grfKeyState, int pt_x, int pt_y, long pdwEffect) {
+       if (pDataObject == 0 || pdwEffect == 0) return false;
+
+       // get allowed operations
+       int style = getStyle();
+       int[] operations = new int[1];
+       OS.MoveMemory(operations, pdwEffect, 4);
+       operations[0] = osToOp(operations[0]) & style;
+       if (operations[0] == DND.DROP_NONE) return false;
+
+       // get current operation
+       int operation = getOperationFromKeyState(grfKeyState);
+       keyOperation = operation;
+       if (operation == DND.DROP_DEFAULT) {
+               if ((style & DND.DROP_DEFAULT) == 0) {
+                       operation = (operations[0] & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+               }
+       } else {
+               if ((operation & operations[0]) == 0) operation = DND.DROP_NONE;
+       }
+
+       // Get allowed transfer types
+       TransferData[] dataTypes = new TransferData[0];
+       IDataObject dataObject = new IDataObject(pDataObject);
+       dataObject.AddRef();
+       try {
+               long[] address = new long[1];
+               if (dataObject.EnumFormatEtc(COM.DATADIR_GET, address) != COM.S_OK) {
+                       return false;
+               }
+               IEnumFORMATETC enumFormatetc = new IEnumFORMATETC(address[0]);
+               try {
+                       // Loop over enumerator and save any types that match what we are looking for
+                       long rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+                       try {
+                               int[] pceltFetched = new int[1];
+                               enumFormatetc.Reset();
+                               while (enumFormatetc.Next(1, rgelt, pceltFetched) == COM.S_OK && pceltFetched[0] == 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 != 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 == 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 != 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 == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+       this.transferAgents = transferAgents;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetAdapter.java
new file mode 100644 (file)
index 0000000..c3e9585
--- /dev/null
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+/**
+ * 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>
+ *
+ *<p>
+ * Please note, there are subtle difference in DND behavior on different OS's.
+ * For example during a file transfer, Windows will put out the file path
+ * as soon as the drag begins, where as Linux will make it available only
+ * on a drop operation. For correct crossplatform behavior, it is recommended
+ * to delay OS interaction until drop has occurred or verify the correctness of
+ * the operation across platforms.
+ * </p>
+ *
+ *
+ * @see DropTargetListener
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @see <a href="https://eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html"> Eclipse corner article on DND </a>
+ */
+public class DropTargetAdapter implements 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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+public void dropAccept(DropTargetEvent event){}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetEffect.java
new file mode 100644 (file)
index 0000000..ab9f3b3
--- /dev/null
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_EXPAND, FEEDBACK_INSERT_AFTER, FEEDBACK_INSERT_BEFORE,
+ * FEEDBACK_NONE, FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
+ * </dl>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class DropTargetEffect extends 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 DropTargetEffect(Control control) {
+               if (control == 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 (control instanceof Table) {
+                       return getItem((Table) control, x, y);
+               }
+               if (control instanceof Tree) {
+                       return getItem((Tree) control, 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 != 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 == null) {
+                       Rectangle area = tree.getClientArea();
+                       if (area.contains(point)) {
+                               int treeBottom = area.y + area.height;
+                               item = tree.getTopItem();
+                               while (item != 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 == null) return null;
+               if (item.getExpanded() && item.getItemCount() > 0) return item.getItem(0);
+               TreeItem childItem = item;
+               TreeItem parentItem = childItem.getParentItem();
+               int index = parentItem == null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+               int count = parentItem == null ? tree.getItemCount() : parentItem.getItemCount();
+               while (true) {
+                       if (index + 1 < count) return parentItem == null ? tree.getItem(index + 1) : parentItem.getItem(index + 1);
+                       if (parentItem == null) return null;
+                       childItem = parentItem;
+                       parentItem = childItem.getParentItem();
+                       index = parentItem == null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+                       count = parentItem == null ? tree.getItemCount() : parentItem.getItemCount();
+               }
+       }
+
+       TreeItem previousItem(Tree tree, TreeItem item) {
+               if (item == null) return null;
+               TreeItem childItem = item;
+               TreeItem parentItem = childItem.getParentItem();
+               int index = parentItem == null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+               if (index == 0) return parentItem;
+               TreeItem nextItem = parentItem == 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;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetEvent.java
new file mode 100644 (file)
index 0000000..c6a3f17
--- /dev/null
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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
+        * @see DND#DROP_DEFAULT
+        */
+       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
+        * @see DND#DROP_DEFAULT
+        */
+       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 final 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 DropTargetEvent(DNDEvent e) {
+       super(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;
+}
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       StringBuilder sb = new StringBuilder();
+       sb.append(string.substring (0, string.length() - 1)); // remove trailing '}'
+       sb.append(" x="); sb.append(x);
+       sb.append(" y="); sb.append(y);
+       sb.append(" item="); sb.append(item);
+       sb.append(" operations="); sb.append(operations);
+       sb.append(" operation="); sb.append(detail);
+       sb.append(" feedback="); sb.append(feedback);
+       sb.append(" dataTypes={ ");
+       if (dataTypes != null) {
+               for (int i = 0; i < dataTypes.length; i++) {
+                       sb.append(dataTypes[i].type); sb.append(' ');
+               }
+       }
+       sb.append('}');
+       sb.append(" currentDataType="); sb.append(currentDataType != null ? currentDataType.type : '0');
+       sb.append('}');
+       return sb.toString();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/DropTargetListener.java
new file mode 100644 (file)
index 0000000..0e40f22
--- /dev/null
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 extends SWTEventListener {
+
+/**
+ * The cursor has entered the drop target boundaries.
+ *
+ * <p>The following fields in the DropTargetEvent apply:</p>
+ * <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>The <code>operations</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:</p>
+ * <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>
+ *
+ * @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:</p>
+ * <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>The <code>operations</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:</p>
+ * <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>The <code>operations</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 != 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:</p>
+ * <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>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:</p>
+ * <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>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);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/FileTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/FileTransfer.java
new file mode 100644 (file)
index 0000000..618b91e
--- /dev/null
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ *
+ * <pre><code>
+ *     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 extends ByteArrayTransfer {
+
+       private static FileTransfer _instance = new FileTransfer();
+       private static final String CF_HDROP = "CF_HDROP"; //$NON-NLS-1$
+       private static final int CF_HDROPID = COM.CF_HDROP;
+       private static final String CFSTR_SHELLIDLIST = "Shell IDList Array"; //$NON-NLS-1$
+       private static final int CFSTR_SHELLIDLISTID = registerType(CFSTR_SHELLIDLIST);
+
+private FileTransfer() {}
+
+/**
+ * Returns the singleton instance of the FileTransfer class.
+ *
+ * @return the singleton instance of the FileTransfer class
+ */
+public static FileTransfer getInstance () {
+       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
+ */
+@Override
+public void javaToNative(Object object, TransferData transferData) {
+       if (!checkFile(object) || !isSupportedType(transferData)) {
+               DND.error(DND.ERROR_INVALID_DATA);
+       }
+       String[] fileNames = (String[]) object;
+       long newPtr = 0;
+       if (transferData.type == CF_HDROPID) {
+               StringBuilder allFiles = new StringBuilder();
+               for (int i = 0; i < fileNames.length; i++) {
+                       allFiles.append(fileNames[i]);
+                       allFiles.append('\0'); // each name is null terminated
+               }
+               allFiles.append('\0'); // there is an extra null terminator at the very end
+               char [] buffer = new char [allFiles.length()];
+               allFiles.getChars(0, allFiles.length(), buffer, 0);
+               DROPFILES dropfiles = new DROPFILES();
+               dropfiles.pFiles = DROPFILES.sizeof;
+               dropfiles.pt_x = dropfiles.pt_y = 0;
+               dropfiles.fNC = 0;
+               dropfiles.fWide = 1;
+               // 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;
+               newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, DROPFILES.sizeof + byteCount);
+               if (newPtr != 0) {
+                       OS.MoveMemory(newPtr, dropfiles, DROPFILES.sizeof);
+                       OS.MoveMemory(newPtr + DROPFILES.sizeof, buffer, byteCount);
+               }
+       } else if (transferData.type == CFSTR_SHELLIDLISTID) {
+               newPtr =  generateCidaFromFilepaths(fileNames);
+       }
+       transferData.stgmedium = new STGMEDIUM();
+       transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+       transferData.stgmedium.unionField = newPtr;
+       transferData.stgmedium.pUnkForRelease = 0;
+       transferData.result = newPtr != 0 ? COM.S_OK : COM.E_FAIL;
+}
+
+/**
+ * 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
+ */
+@Override
+public Object nativeToJava(TransferData transferData) {
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0)  return null;
+
+       // get file names from IDataObject
+       IDataObject dataObject = new IDataObject(transferData.pIDataObject);
+       dataObject.AddRef();
+       FORMATETC formatetc = new FORMATETC();
+       formatetc.cfFormat = COM.CF_HDROP;
+       formatetc.ptd = 0;
+       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 != 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);
+               char [] lpszFile = new char [size + 1];
+               // Get file name and append it to string
+               OS.DragQueryFile(stgmedium.unionField, i, lpszFile, size + 1);
+               fileNames[i] = new String(lpszFile, 0, size);
+       }
+       OS.DragFinish(stgmedium.unionField); // frees data associated with HDROP data
+       return fileNames;
+}
+
+/**
+ * Generate {@link CIDA} structure and trailing data to transfer filenames
+ * as {@link #CFSTR_SHELLIDLIST}.
+ * <p>
+ * For more information on the {@link CIDA} structure see also {@link #resolveCidaToFilepaths(long)}.
+ * </p>
+ *
+ * @param fileNames filenames to pack in {@link CIDA}.
+ * @return pointer to global memory chunk filled with generated data or <code>0</code> on failure
+ */
+private long generateCidaFromFilepaths(String[] fileNames) {
+       final int n = fileNames.length;
+       long [] pidls = new long [n];
+       try {
+               CIDA cida = new CIDA();
+               cida.cidl = n;
+               int cidaSize = CIDA.sizeof + 4 * n;
+               cida.aoffset = cidaSize; // offsets are from cida begin so the first is equal to cida size
+
+               int[] pidlOffsets = new int[n];
+               int[] pidlSizes = new int[n];
+               int pidlSizeSum = 2; // initialize with 2 for the empty (but double null terminated) parent pidl
+               for (int i = 0; i < n; i++) {
+                       TCHAR szfileName = new TCHAR(0, fileNames[i], true);
+                       long [] ppv = new long [1];
+                       int hr = COM.PathToPIDL(szfileName.chars, ppv);
+                       if (hr != OS.S_OK) {
+                               return 0;
+                       }
+                       pidls[i] = ppv[0];
+                       pidlSizes[i] = OS.ILGetSize(pidls[i]);
+                       pidlSizeSum += pidlSizes[i];
+
+                       if (i == 0) {
+                               pidlOffsets[0] = cidaSize + 2;
+                       }
+                       else {
+                               pidlOffsets[i] = pidlOffsets[i - 1] + pidlSizes[i - 1];
+                       }
+               }
+
+               long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cidaSize + pidlSizeSum);
+               if (newPtr != 0) {
+                       OS.MoveMemory(newPtr, cida, CIDA.sizeof);
+                       OS.MoveMemory(newPtr + CIDA.sizeof, pidlOffsets, 4 * cida.cidl);
+                       for (int i = 0; i < n; i++) {
+                               OS.MoveMemory(newPtr + pidlOffsets[i], pidls[i], pidlSizes[i]);
+                       }
+               }
+               return newPtr;
+       } finally {
+               for (int i = 0; i < n; i++) {
+                       if (pidls[i] != 0) {
+                               OS.CoTaskMemFree(pidls[i]);
+                       }
+               }
+       }
+}
+
+@Override
+public boolean isSupportedType(TransferData transferData) {
+       // filter Shell ID List Array transfer only for dropping
+       if (transferData != null && transferData.pIDataObject != 0 && transferData.type == CFSTR_SHELLIDLISTID) {
+               return false;
+       }
+       return super.isSupportedType(transferData);
+}
+
+@Override
+protected int[] getTypeIds(){
+       // Note: FileTransfer adds Shell ID List as transfer type but later
+       //       limit this type for dragging only.
+       return new int[] {CF_HDROPID, CFSTR_SHELLIDLISTID};
+}
+
+@Override
+protected String[] getTypeNames(){
+       return new String[] {CF_HDROP, CFSTR_SHELLIDLIST};
+}
+boolean checkFile(Object object) {
+       if (object == null || !(object instanceof String[]) || ((String[])object).length == 0) return false;
+       String[] strings = (String[])object;
+       for (int i = 0; i < strings.length; i++) {
+               if (strings[i] == null || strings[i].length() == 0) return false;
+       }
+       return true;
+}
+
+@Override
+protected boolean validate(Object object) {
+       return checkFile(object);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/HTMLTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/HTMLTransfer.java
new file mode 100644 (file)
index 0000000..1be51db
--- /dev/null
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ *
+ * <pre><code>
+ *     String htmlData = "&lt;p&gt;This is a paragraph of text.&lt;/p&gt;";
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class HTMLTransfer extends ByteArrayTransfer {
+
+       static HTMLTransfer _instance = new HTMLTransfer();
+       static final String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
+       static final int HTML_FORMATID = registerType(HTML_FORMAT);
+       static final String NUMBER = "00000000"; //$NON-NLS-1$
+       static final String HEADER = "Version:0.9\r\nStartHTML:"+NUMBER+"\r\nEndHTML:"+NUMBER+"\r\nStartFragment:"+NUMBER+"\r\nEndFragment:"+NUMBER+"\r\n";
+       static final String PREFIX = "<html><body><!--StartFragment-->"; //$NON-NLS-1$
+       static final String SUFFIX = "<!--EndFragment--></body></html>"; //$NON-NLS-1$
+       static final String StartFragment = "StartFragment:"; //$NON-NLS-1$
+       static final String EndFragment = "EndFragment:"; //$NON-NLS-1$
+
+private HTMLTransfer() {}
+
+/**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+public static HTMLTransfer getInstance () {
+       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
+ */
+@Override
+public void javaToNative (Object object, TransferData transferData){
+       if (!checkHTML(object) || !isSupportedType(transferData)) {
+               DND.error(DND.ERROR_INVALID_DATA);
+       }
+       String string = (String)object;
+       int count = string.length();
+       char[] chars = new char[count + 1];
+       string.getChars(0, count, chars, 0);
+       /* NOTE: CF_HTML uses UTF-8 encoding. */
+       int cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, -1, null, 0, null, null);
+       if (cchMultiByte == 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();
+
+       StringBuilder buffer = new StringBuilder(HEADER);
+       int maxLength = NUMBER.length();
+       //startHTML
+       int start = buffer.toString().indexOf(NUMBER);
+       String temp = Integer.toString(startHTML);
+       buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+       //endHTML
+       start = buffer.toString().indexOf(NUMBER, start);
+       temp = Integer.toString(endHTML);
+       buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+       //startFragment
+       start = buffer.toString().indexOf(NUMBER, start);
+       temp = Integer.toString(startFragment);
+       buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+       //endFragment
+       start = buffer.toString().indexOf(NUMBER, start);
+       temp = Integer.toString(endFragment);
+       buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+
+       buffer.append(PREFIX);
+       buffer.append(string);
+       buffer.append(SUFFIX);
+
+       count = buffer.length();
+       chars = new char[count + 1];
+       buffer.getChars(0, count, chars, 0);
+       cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, -1, null, 0, null, null);
+       long lpMultiByteStr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+       OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+       transferData.stgmedium = new STGMEDIUM();
+       transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+       transferData.stgmedium.unionField = lpMultiByteStr;
+       transferData.stgmedium.pUnkForRelease = 0;
+       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
+ */
+@Override
+public Object nativeToJava(TransferData transferData){
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
+       IDataObject data = new IDataObject(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 != COM.S_OK) return null;
+       long hMem = stgmedium.unionField;
+
+       try {
+               long lpMultiByteStr = OS.GlobalLock(hMem);
+               if (lpMultiByteStr == 0) 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. */
+                       int cchWideChar  = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, null, 0);
+                       if (cchWideChar == 0) return null;
+                       char[] lpWideCharStr = new char [cchWideChar - 1];
+                       OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+                       String string = new String(lpWideCharStr);
+                       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 > C.strlen(lpMultiByteStr)) return null;
+                       cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr+fragmentStart, fragmentEnd - fragmentStart, lpWideCharStr, lpWideCharStr.length);
+                       if (cchWideChar == 0) return null;
+                       String s = new String(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 != -1) {
+                               prefix += foxStart.length();
+                               s = s.substring(prefix);
+                       }
+                       return s;
+               } finally {
+                       OS.GlobalUnlock(hMem);
+               }
+       } finally {
+               OS.GlobalFree(hMem);
+       }
+}
+@Override
+protected int[] getTypeIds(){
+       return new int[] {HTML_FORMATID};
+}
+@Override
+protected String[] getTypeNames(){
+       return new String[] {HTML_FORMAT};
+}
+boolean checkHTML(Object object) {
+       return (object != null && object instanceof String && ((String)object).length() > 0);
+}
+@Override
+protected boolean validate(Object object) {
+       return checkHTML(object);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ImageTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ImageTransfer.java
new file mode 100644 (file)
index 0000000..0c678f1
--- /dev/null
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ *
+ * <pre><code>
+ *     Image image = new Image(display, "C:\\temp\\img1.gif");
+ *     ImageData imgData = image.getImageData();
+ * </code></pre>
+ *
+ * @see Transfer
+ *
+ * @since 3.4
+ */
+public class ImageTransfer extends ByteArrayTransfer {
+
+       private static ImageTransfer _instance = new ImageTransfer();
+       private static final String CF_DIB = "CF_DIB"; //$NON-NLS-1$
+       private static final int CF_DIBID = COM.CF_DIB;
+
+private ImageTransfer() {}
+
+/**
+ * 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
+ */
+@Override
+public void javaToNative(Object object, TransferData transferData) {
+       if (!checkImage(object) || !isSupportedType(transferData)) {
+               DND.error(DND.ERROR_INVALID_DATA);
+       }
+       ImageData imgData = (ImageData)object;
+       if (imgData == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+       int imageSize = imgData.data.length;
+       int imageHeight = imgData.height;
+       int bytesPerLine = imgData.bytesPerLine;
+
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+       bmiHeader.biSizeImage = imageSize;
+       bmiHeader.biWidth = imgData.width;
+       bmiHeader.biHeight = imageHeight;
+       bmiHeader.biPlanes = 1;
+       bmiHeader.biBitCount = (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, bmiHeader, BITMAPINFOHEADER.sizeof);
+
+       RGB[] rgbs = imgData.palette.getRGBs();
+       if (rgbs != null && colorSize > 0) {
+               int offset = BITMAPINFOHEADER.sizeof;
+               for (int j = 0; j < rgbs.length; j++) {
+                       bmi[offset] = (byte)rgbs[j].blue;
+                       bmi[offset + 1] = (byte)rgbs[j].green;
+                       bmi[offset + 2] = (byte)rgbs[j].red;
+                       bmi[offset + 3] = 0;
+                       offset += 4;
+               }
+       }
+       long newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize);
+       OS.MoveMemory(newPtr, bmi, bmi.length);
+       long pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize;
+
+       if (imageHeight <= 0) {
+               OS.MoveMemory(pBitDest, imgData.data, 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, bytesPerLine);
+                       offset += bytesPerLine;
+                       pBitDest -= bytesPerLine;
+               }
+       }
+       transferData.stgmedium = new STGMEDIUM();
+       transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+       transferData.stgmedium.unionField = newPtr;
+       transferData.stgmedium.pUnkForRelease = 0;
+       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
+ */
+@Override
+public Object nativeToJava(TransferData transferData) {
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
+       IDataObject dataObject = new IDataObject(transferData.pIDataObject);
+       dataObject.AddRef();
+       FORMATETC formatetc = new FORMATETC();
+       formatetc.cfFormat = COM.CF_DIB;
+       formatetc.ptd = 0;
+       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 != COM.S_OK) return null;
+       long hMem = stgmedium.unionField;
+       dataObject.Release();
+       try {
+               long ptr = OS.GlobalLock(hMem);
+               if (ptr == 0) return null;
+               try {
+                       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+                       OS.MoveMemory(bmiHeader, ptr, BITMAPINFOHEADER.sizeof);
+                       long[] pBits = new long[1];
+                       long memDib = OS.CreateDIBSection(0, ptr, OS.DIB_RGB_COLORS, pBits, 0, 0);
+                       if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       long bits = ptr + bmiHeader.biSize;
+                       if (bmiHeader.biBitCount <= 8) {
+                               bits += (bmiHeader.biClrUsed == 0 ? (1 << bmiHeader.biBitCount) : bmiHeader.biClrUsed) * 4;
+                       } else if (bmiHeader.biCompression == OS.BI_BITFIELDS) {
+                               bits += 12;
+                       }
+                       if (bmiHeader.biHeight < 0) {
+                               OS.MoveMemory(pBits[0], bits, bmiHeader.biSizeImage);
+                       } else {
+                               DIBSECTION dib = new DIBSECTION();
+                               OS.GetObject(memDib, DIBSECTION.sizeof, dib);
+                               int biHeight = dib.biHeight;
+                               int scanline = dib.biSizeImage / biHeight;
+                               long pDestBits = pBits[0];
+                               long 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 (DPIUtil.getDeviceZoom ());
+                       OS.DeleteObject(memDib);
+                       image.dispose();
+                       return data;
+               } finally {
+                       OS.GlobalUnlock(hMem);
+               }
+       } finally {
+               OS.GlobalFree(hMem);
+       }
+}
+
+@Override
+protected int[] getTypeIds(){
+       return new int[] {CF_DIBID};
+}
+
+@Override
+protected String[] getTypeNames(){
+       return new String[] {CF_DIB};
+}
+boolean checkImage(Object object) {
+       if (object == null || !(object instanceof ImageData))  return false;
+       return true;
+}
+
+@Override
+protected boolean validate(Object object) {
+       return checkImage(object);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/OleEnumFORMATETC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/OleEnumFORMATETC.java
new file mode 100644 (file)
index 0000000..cb7278f
--- /dev/null
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+final class OleEnumFORMATETC {
+
+       private COMObject iEnumFORMATETC;
+
+       private int refCount;
+       private int index;
+
+       private FORMATETC[] formats;
+
+OleEnumFORMATETC() {
+
+       createCOMInterfaces();
+
+}
+int AddRef() {
+       refCount++;
+       return refCount;
+}
+private void createCOMInterfaces() {
+       iEnumFORMATETC = new COMObject(new int[] {2, 0, 0, 3, 1, 0, 1}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return Next((int)args[0], args[1], args[2]);}
+               @Override
+               public long method4(long[] args) {return Skip((int)args[0]);}
+               @Override
+               public long method5(long[] args) {return Reset();}
+               // method6 Clone - not implemented
+       };
+}
+private void disposeCOMInterfaces() {
+       if (iEnumFORMATETC != null)
+               iEnumFORMATETC.dispose();
+       iEnumFORMATETC = null;
+}
+long getAddress() {
+       return iEnumFORMATETC.getAddress();
+}
+private FORMATETC[] getNextItems(int numItems){
+
+       if (formats == 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;
+}
+private int Next(int celt, long rgelt, long 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 == 0) return COM.E_INVALIDARG;
+       if (pceltFetched == 0 && celt != 1) return COM.E_INVALIDARG;
+
+       FORMATETC[] nextItems = getNextItems(celt);
+       if (nextItems != null) {
+               for (int i = 0; i < nextItems.length; i++) {
+                       COM.MoveMemory(rgelt + i*FORMATETC.sizeof, nextItems[i], FORMATETC.sizeof);
+               }
+
+               if (pceltFetched != 0)
+                       OS.MoveMemory(pceltFetched, new int[] {nextItems.length}, 4);
+
+               if (nextItems.length == celt) return COM.S_OK;
+
+       } else {
+               if (pceltFetched != 0)
+                       OS.MoveMemory(pceltFetched, new int[] {0}, 4);
+               COM.MoveMemory(rgelt, new FORMATETC(), FORMATETC.sizeof);
+
+       }
+       return COM.S_FALSE;
+}
+private int QueryInterface(long riid, long ppvObject) {
+
+       if (riid == 0 || ppvObject == 0) return COM.E_NOINTERFACE;
+
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIEnumFORMATETC)) {
+               OS.MoveMemory(ppvObject, new long[] {iEnumFORMATETC.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+int Release() {
+       refCount--;
+
+       if (refCount == 0) {
+               disposeCOMInterfaces();
+               if (COM.FreeUnusedLibraries) {
+                       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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/RTFTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/RTFTransfer.java
new file mode 100644 (file)
index 0000000..ab1fbb1
--- /dev/null
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ *
+ * <pre><code>
+ *     String rtfData = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class RTFTransfer extends ByteArrayTransfer {
+
+       private static RTFTransfer _instance = new RTFTransfer();
+       private static final String CF_RTF = "Rich Text Format"; //$NON-NLS-1$
+       private static final int CF_RTFID = registerType(CF_RTF);
+
+private RTFTransfer() {}
+
+/**
+ * Returns the singleton instance of the RTFTransfer class.
+ *
+ * @return the singleton instance of the RTFTransfer class
+ */
+public static RTFTransfer getInstance () {
+       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
+ */
+@Override
+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 = (String)object;
+       int count = string.length();
+       char[] chars = new char[count + 1];
+       string.getChars(0, count, chars, 0);
+       int codePage = OS.GetACP();
+       int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+       if (cchMultiByte == 0) {
+               transferData.stgmedium = new STGMEDIUM();
+               transferData.result = COM.DV_E_STGMEDIUM;
+               return;
+       }
+       long lpMultiByteStr = 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 = 0;
+       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
+ */
+@Override
+public Object nativeToJava(TransferData transferData){
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
+       IDataObject data = new IDataObject(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 != COM.S_OK) return null;
+       long hMem = stgmedium.unionField;
+       try {
+               long lpMultiByteStr = OS.GlobalLock(hMem);
+               if (lpMultiByteStr == 0) return null;
+               try {
+                       int codePage = OS.GetACP();
+                       int cchWideChar  = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+                       if (cchWideChar == 0) return null;
+                       char[] lpWideCharStr = new char [cchWideChar - 1];
+                       OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+                       return new String(lpWideCharStr);
+               } finally {
+                       OS.GlobalUnlock(hMem);
+               }
+       } finally {
+               OS.GlobalFree(hMem);
+       }
+}
+
+@Override
+protected int[] getTypeIds(){
+       return new int[] {CF_RTFID};
+}
+
+@Override
+protected String[] getTypeNames(){
+       return new String[] {CF_RTF};
+}
+
+boolean checkRTF(Object object) {
+       return (object != null  && object instanceof String && ((String)object).length() > 0);
+}
+
+@Override
+protected boolean validate(Object object) {
+       return checkRTF(object);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TableDragSourceEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TableDragSourceEffect.java
new file mode 100644 (file)
index 0000000..8eac76a
--- /dev/null
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.DPIUtil.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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 TableDragSourceEffect(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
+        */
+       @Override
+       public void dragFinished(DragSourceEvent event) {
+               if (dragSourceImage != 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
+        */
+       @Override
+       public void dragStart(DragSourceEvent event) {
+               event.image = getDragSourceImage(event);
+       }
+
+       Image getDragSourceImage(DragSourceEvent event) {
+               if (dragSourceImage != null) dragSourceImage.dispose();
+               dragSourceImage = null;
+               SHDRAGIMAGE shdi = new SHDRAGIMAGE();
+               int DI_GETDRAGIMAGE = OS.RegisterWindowMessage (new TCHAR (0, "ShellGetDragImage", true)); //$NON-NLS-1$
+               if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, shdi) != 0) {
+                       if ((control.getStyle() & SWT.MIRRORED) != 0) {
+                               event.offsetX = shdi.sizeDragImage.cx - shdi.ptOffset.x;
+                       } else {
+                               event.offsetX = shdi.ptOffset.x;
+                       }
+                       event.offsetY = shdi.ptOffset.y;
+                       long hImage = shdi.hbmpDragImage;
+                       if (hImage != 0) {
+                               BITMAP bm = new BITMAP ();
+                               OS.GetObject (hImage, BITMAP.sizeof, bm);
+                               int srcWidth = bm.bmWidth;
+                               int srcHeight = bm.bmHeight;
+
+                               /* Create resources */
+                               long hdc = OS.GetDC (0);
+                               long srcHdc = OS.CreateCompatibleDC (hdc);
+                               long oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+                               long memHdc = OS.CreateCompatibleDC (hdc);
+                               BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+                               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];
+                               OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+                               long [] pBits = new long [1];
+                               long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+                               if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+                               long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+                               BITMAP dibBM = new BITMAP ();
+                               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);
+
+                               PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                               ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+                               if (shdi.crColorKey == -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;
+                               }
+                               Display display = control.getDisplay();
+                               dragSourceImage = new Image(display, new AutoScaleImageDataProvider(display, data, DPIUtil.getDeviceZoom()));
+                               OS.SelectObject (memHdc, oldMemBitmap);
+                               OS.DeleteDC (memHdc);
+                               OS.DeleteObject (memDib);
+                               OS.SelectObject (srcHdc, oldSrcBitmap);
+                               OS.DeleteDC (srcHdc);
+                               OS.ReleaseDC (0, hdc);
+                               OS.DeleteObject (hImage);
+                               return dragSourceImage;
+                       }
+               }
+               return null;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TableDropTargetEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TableDropTargetEffect.java
new file mode 100644 (file)
index 0000000..42cb9d6
--- /dev/null
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
+ * </dl>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class TableDropTargetEffect extends DropTargetEffect {
+       static final int SCROLL_HYSTERESIS = 200; // milli seconds
+
+       int scrollIndex = -1;
+       long scrollBeginTime;
+       TableItem dropHighlight;
+       int iItemInsert = -1;
+
+       /**
+        * 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 TableDropTargetEffect(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) != 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+               if ((effect & DND.FEEDBACK_INSERT_BEFORE) != 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
+        */
+       @Override
+       public void dragEnter(DropTargetEvent event) {
+               scrollBeginTime = 0;
+               scrollIndex = -1;
+               dropHighlight = null;
+               iItemInsert = -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
+        */
+       @Override
+       public void dragLeave(DropTargetEvent event) {
+               Table table = (Table) control;
+               long handle = table.handle;
+               if (dropHighlight != null) {
+                       LVITEM lvItem = new LVITEM ();
+                       lvItem.stateMask = OS.LVIS_DROPHILITED;
+                       OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, lvItem);
+                       dropHighlight = null;
+               }
+               if (iItemInsert != -1) {
+                       LVINSERTMARK plvim = new LVINSERTMARK ();
+                       plvim.cbSize = LVINSERTMARK.sizeof;
+                       plvim.iItem = -1;
+                       OS.SendMessage(handle, OS.LVM_SETINSERTMARK, 0, plvim);
+                       iItemInsert = -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>. 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
+        */
+       @Override
+       public void dragOver(DropTargetEvent event) {
+               Table table = (Table) getControl();
+               int effect = checkEffect(event.feedback);
+               long handle = table.handle;
+               Point coordinates = new Point(event.x, event.y);
+               coordinates = DPIUtil.autoScaleUp(table.toControl(coordinates)); // To Pixels
+               LVHITTESTINFO pinfo = new LVHITTESTINFO();
+               pinfo.x = coordinates.x;
+               pinfo.y = coordinates.y;
+               OS.SendMessage(handle, OS.LVM_HITTEST, 0, pinfo);
+               if ((effect & DND.FEEDBACK_SCROLL) == 0) {
+                       scrollBeginTime = 0;
+                       scrollIndex = -1;
+               } else {
+                       if (pinfo.iItem != -1 && scrollIndex == pinfo.iItem && scrollBeginTime != 0) {
+                               if (System.currentTimeMillis() >= scrollBeginTime) {
+                                       int top = Math.max (0, (int)OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0));
+                                       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+                                       int index = (scrollIndex - 1 < top) ? Math.max(0, scrollIndex - 1) : Math.min(count - 1, scrollIndex + 1);
+                                       boolean scroll = true;
+                                       if (pinfo.iItem == top) {
+                                               scroll = pinfo.iItem != index;
+                                       } else {
+                                               RECT itemRect = new RECT ();
+                                               itemRect.left = OS.LVIR_BOUNDS;
+                                               if (OS.SendMessage (handle, OS.LVM_GETITEMRECT, pinfo.iItem, itemRect) != 0) {
+                                                       RECT rect = new RECT ();
+                                                       OS.GetClientRect (handle, rect);
+                                                       POINT pt = new POINT ();
+                                                       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 != -1 && (effect & DND.FEEDBACK_SELECT) != 0) {
+                       TableItem item = table.getItem(pinfo.iItem);
+                       if (dropHighlight != item) {
+                               LVITEM lvItem = new 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 != null) {
+                               LVITEM lvItem = new LVITEM ();
+                               lvItem.stateMask = OS.LVIS_DROPHILITED;
+                               OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, lvItem);
+                               dropHighlight = null;
+                       }
+               }
+               if (pinfo.iItem != -1 && (effect & (DND.FEEDBACK_INSERT_BEFORE | DND.FEEDBACK_INSERT_AFTER)) != 0) {
+                               LVINSERTMARK plvim = new LVINSERTMARK ();
+                               plvim.cbSize = LVINSERTMARK.sizeof;
+                               plvim.dwFlags = (effect & DND.FEEDBACK_INSERT_AFTER) != 0 ? OS.LVIM_AFTER : 0;
+                               plvim.iItem = pinfo.iItem;
+                               if (OS.SendMessage(handle, OS.LVM_SETINSERTMARK, 0, plvim) != 0) {
+                                       iItemInsert = pinfo.iItem;
+                               }
+               } else {
+                       if (iItemInsert != -1) {
+                               LVINSERTMARK plvim = new LVINSERTMARK ();
+                               plvim.cbSize = LVINSERTMARK.sizeof;
+                               plvim.iItem = -1;
+                               OS.SendMessage(handle, OS.LVM_SETINSERTMARK, 0, plvim);
+                               iItemInsert = -1;
+                       }
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TextTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TextTransfer.java
new file mode 100644 (file)
index 0000000..c9c233e
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ *
+ * <pre><code>
+ *     String textData = "Hello World";
+ * </code></pre>
+ *
+ * <p>Note the <code>TextTransfer</code> does not change the content of the text
+ * data. For a better integration with the platform, the application should convert
+ * the line delimiters used in the text data to the standard line delimiter used by the
+ * platform.
+ * </p>
+ *
+ * @see Transfer
+ */
+public class TextTransfer extends ByteArrayTransfer {
+
+       private static TextTransfer _instance = new TextTransfer();
+       private static final String CF_UNICODETEXT = "CF_UNICODETEXT"; //$NON-NLS-1$
+       private static final String CF_TEXT = "CF_TEXT"; //$NON-NLS-1$
+       private static final int CF_UNICODETEXTID = COM.CF_UNICODETEXT;
+       private static final int CF_TEXTID = COM.CF_TEXT;
+
+private TextTransfer() {}
+
+/**
+ * Returns the singleton instance of the TextTransfer class.
+ *
+ * @return the singleton instance of the TextTransfer class
+ */
+public static TextTransfer getInstance () {
+       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
+ */
+@Override
+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 = (String)object;
+       switch (transferData.type) {
+               case COM.CF_UNICODETEXT: {
+                       int charCount = string.length ();
+                       char[] chars = new char[charCount+1];
+                       string.getChars (0, charCount, chars, 0);
+                       int byteCount = chars.length * 2;
+                       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, byteCount);
+                       OS.MoveMemory(newPtr, chars, byteCount);
+                       transferData.stgmedium = new STGMEDIUM();
+                       transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+                       transferData.stgmedium.unionField = newPtr;
+                       transferData.stgmedium.pUnkForRelease = 0;
+                       transferData.result = COM.S_OK;
+                       break;
+               }
+               case COM.CF_TEXT: {
+                       int count = string.length();
+                       char[] chars = new char[count + 1];
+                       string.getChars(0, count, chars, 0);
+                       int codePage = OS.GetACP();
+                       int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+                       if (cchMultiByte == 0) {
+                               transferData.stgmedium = new STGMEDIUM();
+                               transferData.result = COM.DV_E_STGMEDIUM;
+                               return;
+                       }
+                       long lpMultiByteStr = 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 = 0;
+                       transferData.result = COM.S_OK;
+                       break;
+               }
+       }
+       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
+ */
+@Override
+public Object nativeToJava(TransferData transferData){
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
+
+       IDataObject data = new IDataObject(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 != COM.S_OK) return null;
+       long 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 == 0) return null;
+                               char[] chars = new char[size/2];
+                               long ptr = OS.GlobalLock(hMem);
+                               if (ptr == 0) return null;
+                               try {
+                                       OS.MoveMemory(chars, ptr, size);
+                                       int length = chars.length;
+                                       for (int i=0; i<chars.length; i++) {
+                                               if (chars [i] == '\0') {
+                                                       length = i;
+                                                       break;
+                                               }
+                                       }
+                                       return new String (chars, 0, length);
+                               } finally {
+                                       OS.GlobalUnlock(hMem);
+                               }
+                       }
+                       case CF_TEXTID: {
+                               long lpMultiByteStr = OS.GlobalLock(hMem);
+                               if (lpMultiByteStr == 0) return null;
+                               try {
+                                       int codePage = OS.GetACP();
+                                       int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+                                       if (cchWideChar == 0) return null;
+                                       char[] lpWideCharStr = new char [cchWideChar - 1];
+                                       OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+                                       return new String(lpWideCharStr);
+                               } finally {
+                                       OS.GlobalUnlock(hMem);
+                               }
+                       }
+               }
+       } finally {
+               OS.GlobalFree(hMem);
+       }
+       return null;
+}
+
+@Override
+protected int[] getTypeIds(){
+       return new int[] {CF_UNICODETEXTID, CF_TEXTID};
+}
+
+@Override
+protected String[] getTypeNames(){
+       return new String[] {CF_UNICODETEXT, CF_TEXT};
+}
+
+boolean checkText(Object object) {
+       return (object != null  && object instanceof String && ((String)object).length() > 0);
+}
+
+@Override
+protected boolean validate(Object object) {
+       return checkText(object);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/Transfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/Transfer.java
new file mode 100644 (file)
index 0000000..ecba24d
--- /dev/null
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * <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) == COM.S_OK) return COM.S_OK;
+       try {Thread.sleep(50);} catch (Throwable t) {}
+       int result = dataObject.GetData(pFormatetc, pmedium);
+       int retryCount = 0;
+       while (result != COM.S_OK && retryCount++ < RETRY_LIMIT) {
+               MSG msg = new MSG();
+               OS.PeekMessage(msg, 0, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+               try {Thread.sleep(50);} catch (Throwable 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 boolean 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:</p>
+ * <ul>
+ * <li>Windows: COM.S_OK
+ * <li>GTK: 1
+ * </ul>
+ *
+ * <p>If this transfer agent is unable to perform the conversion, the transferData.result
+ * field will be set to a failure value as follows:</p>
+ * <ul>
+ * <li>Windows: COM.DV_E_TYMED or COM.E_FAIL
+ * <li>GTK: 0
+ * </ul>
+ *
+ * @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 protected 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 protected 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 = new TCHAR(0, formatName, true);
+       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
+ */
+protected boolean validate(Object object) {
+       return true;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TransferData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TransferData.java
new file mode 100644 (file)
index 0000000..80240e2
--- /dev/null
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+/**
+ * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long pIDataObject;
+
+       static boolean sameType(TransferData data1, TransferData data2) {
+               if (data1 == data2) return true;
+               if (data1 == null || data2 == null) return false;
+               return (data1.type == data2.type &&
+                               data1.formatetc.cfFormat == data2.formatetc.cfFormat &&
+                               data1.formatetc.dwAspect == data2.formatetc.dwAspect &&
+                               data1.formatetc.tymed == data2.formatetc.tymed);
+       }
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TreeDragSourceEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TreeDragSourceEffect.java
new file mode 100644 (file)
index 0000000..363bf9c
--- /dev/null
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.DPIUtil.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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 TreeDragSourceEffect(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
+        */
+       @Override
+       public void dragFinished(DragSourceEvent event) {
+               if (dragSourceImage != 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
+        */
+       @Override
+       public void dragStart(DragSourceEvent event) {
+               event.image = getDragSourceImage(event);
+       }
+
+       Image getDragSourceImage(DragSourceEvent event) {
+               if (dragSourceImage != null) dragSourceImage.dispose();
+               dragSourceImage = null;
+               SHDRAGIMAGE shdi = new SHDRAGIMAGE();
+               int DI_GETDRAGIMAGE = OS.RegisterWindowMessage (new TCHAR (0, "ShellGetDragImage", true)); //$NON-NLS-1$
+               if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, shdi) != 0) {
+                       if ((control.getStyle() & SWT.MIRRORED) != 0) {
+                               event.offsetX = shdi.sizeDragImage.cx - shdi.ptOffset.x;
+                       } else {
+                               event.offsetX = shdi.ptOffset.x;
+                       }
+                       event.offsetY = shdi.ptOffset.y;
+                       long hImage = shdi.hbmpDragImage;
+                       if (hImage != 0) {
+                               BITMAP bm = new BITMAP ();
+                               OS.GetObject (hImage, BITMAP.sizeof, bm);
+                               int srcWidth = bm.bmWidth;
+                               int srcHeight = bm.bmHeight;
+
+                               /* Create resources */
+                               long hdc = OS.GetDC (0);
+                               long srcHdc = OS.CreateCompatibleDC (hdc);
+                               long oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+                               long memHdc = OS.CreateCompatibleDC (hdc);
+                               BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+                               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];
+                               OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+                               long [] pBits = new long [1];
+                               long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+                               if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+                               long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+                               BITMAP dibBM = new BITMAP ();
+                               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);
+
+                               PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                               ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+                               if (shdi.crColorKey == -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;
+                               }
+                               Display display = control.getDisplay ();
+                               dragSourceImage = new Image (display, new AutoScaleImageDataProvider(display, data, DPIUtil.getDeviceZoom()));
+                               OS.SelectObject (memHdc, oldMemBitmap);
+                               OS.DeleteDC (memHdc);
+                               OS.DeleteObject (memDib);
+                               OS.SelectObject (srcHdc, oldSrcBitmap);
+                               OS.DeleteDC (srcHdc);
+                               OS.ReleaseDC (0, hdc);
+                               OS.DeleteObject (hImage);
+                               return dragSourceImage;
+                       }
+               }
+               return null;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TreeDropTargetEffect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/TreeDropTargetEffect.java
new file mode 100644 (file)
index 0000000..87385ad
--- /dev/null
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE, FEEDBACK_INSERT_AFTER, FEEDBACK_EXPAND, FEEDBACK_SCROLL</dd>
+ * </dl>
+ * <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 extends DropTargetEffect {
+       static final int SCROLL_HYSTERESIS = 200; // milli seconds
+       static final int EXPAND_HYSTERESIS = 1000; // milli seconds
+
+       long dropIndex;
+       long scrollIndex;
+       long scrollBeginTime;
+       long expandIndex;
+       long expandBeginTime;
+       TreeItem insertItem;
+       boolean 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 TreeDropTargetEffect(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) != 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+               if ((effect & DND.FEEDBACK_INSERT_BEFORE) != 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
+        */
+       @Override
+       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
+        */
+       @Override
+       public void dragLeave(DropTargetEvent event) {
+               Tree tree = (Tree) control;
+               long handle = tree.handle;
+               if (dropIndex != -1) {
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.hItem = 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 != 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
+        */
+       @Override
+       public void dragOver(DropTargetEvent event) {
+               Tree tree = (Tree) getControl();
+               int effect = checkEffect(event.feedback);
+               long handle = tree.handle;
+               Point coordinates = new Point(event.x, event.y);
+               coordinates = DPIUtil.autoScaleUp(tree.toControl(coordinates)); // To Pixels
+               TVHITTESTINFO lpht = new TVHITTESTINFO ();
+               lpht.x = coordinates.x;
+               lpht.y = coordinates.y;
+               OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+               long hItem = lpht.hItem;
+               if ((effect & DND.FEEDBACK_SCROLL) == 0) {
+                       scrollBeginTime = 0;
+                       scrollIndex = -1;
+               } else {
+                       if (hItem != -1 && scrollIndex == hItem && scrollBeginTime != 0) {
+                               if (System.currentTimeMillis() >= scrollBeginTime) {
+                                       long topItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                                       long nextItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem == topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem);
+                                       boolean scroll = true;
+                                       if (hItem == topItem) {
+                                               scroll = nextItem != 0;
+                                       } else {
+                                               RECT itemRect = new RECT ();
+                                               if (OS.TreeView_GetItemRect (handle, nextItem, itemRect, true)) {
+                                                       RECT rect = new RECT ();
+                                                       OS.GetClientRect (handle, rect);
+                                                       POINT pt = new POINT ();
+                                                       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 = hItem;
+                       }
+               }
+               if ((effect & DND.FEEDBACK_EXPAND) == 0) {
+                       expandBeginTime = 0;
+                       expandIndex = -1;
+               } else {
+                       if (hItem != -1 && expandIndex == hItem && expandBeginTime != 0) {
+                               if (System.currentTimeMillis() >= expandBeginTime) {
+                                       if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem) != 0) {
+                                               TreeItem item = (TreeItem)tree.getDisplay().findWidget(tree.handle, hItem);
+                                               if (item != 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 = hItem;
+                       }
+               }
+               if (dropIndex != -1 && (dropIndex != hItem || (effect & DND.FEEDBACK_SELECT) == 0)) {
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.hItem = 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 (hItem != -1 && hItem != dropIndex && (effect & DND.FEEDBACK_SELECT) != 0) {
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.hItem = hItem;
+                       tvItem.mask = OS.TVIF_STATE;
+                       tvItem.stateMask = OS.TVIS_DROPHILITED;
+                       tvItem.state = OS.TVIS_DROPHILITED;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                       dropIndex = hItem;
+               }
+               if ((effect & DND.FEEDBACK_INSERT_BEFORE) != 0 || (effect & DND.FEEDBACK_INSERT_AFTER) != 0) {
+                       boolean before = (effect & DND.FEEDBACK_INSERT_BEFORE) != 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 = (TreeItem)tree.getDisplay().findWidget(tree.handle, hItem);
+                       if (item != null) {
+                               if (item != insertItem || before != insertBefore) {
+                                       tree.setInsertMark(item, before);
+                               }
+                               insertItem = item;
+                               insertBefore = before;
+                       } else {
+                               if (insertItem != null) {
+                                       tree.setInsertMark(null, false);
+                               }
+                               insertItem = null;
+                       }
+               } else {
+                       if (insertItem != null) {
+                               tree.setInsertMark(null, false);
+                       }
+                       insertItem = null;
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/URLTransfer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/URLTransfer.java
new file mode 100644 (file)
index 0000000..1581e80
--- /dev/null
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 20007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ *
+ * <pre><code>
+ *     String url = "http://www.eclipse.org";
+ * </code></pre>
+ *
+ * @see Transfer
+ * @since 3.4
+ */
+public class URLTransfer extends ByteArrayTransfer {
+
+       static URLTransfer _instance = new URLTransfer();
+       static final String CFSTR_INETURLW = "UniformResourceLocatorW"; //$NON-NLS-1$
+       static final int CFSTR_INETURLIDW = registerType(CFSTR_INETURLW);
+       static final String CFSTR_INETURL = "UniformResourceLocator"; //$NON-NLS-1$
+       static final int CFSTR_INETURLID = registerType(CFSTR_INETURL);
+
+private URLTransfer() {}
+
+/**
+ * Returns the singleton instance of the URLTransfer class.
+ *
+ * @return the singleton instance of the URLTransfer class
+ */
+public static URLTransfer getInstance () {
+       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
+ */
+@Override
+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 = ((String)object);
+       if (transferData.type == CFSTR_INETURLIDW) {
+               int charCount = url.length ();
+               char[] chars = new char[charCount+1];
+               url.getChars (0, charCount, chars, 0);
+               int byteCount = chars.length * 2;
+               long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, byteCount);
+               OS.MoveMemory(newPtr, chars, byteCount);
+               transferData.stgmedium = new STGMEDIUM();
+               transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+               transferData.stgmedium.unionField = newPtr;
+               transferData.stgmedium.pUnkForRelease = 0;
+               transferData.result = COM.S_OK;
+       } else if (transferData.type == CFSTR_INETURLID) {
+               int count = url.length();
+               char[] chars = new char[count + 1];
+               url.getChars(0, count, chars, 0);
+               int codePage = OS.GetACP();
+               int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+               if (cchMultiByte == 0) {
+                       transferData.stgmedium = new STGMEDIUM();
+                       transferData.result = COM.DV_E_STGMEDIUM;
+                       return;
+               }
+               long lpMultiByteStr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.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 = 0;
+               transferData.result = COM.S_OK;
+       }
+}
+
+/**
+ * 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
+ */
+@Override
+public Object nativeToJava(TransferData transferData){
+       if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
+       IDataObject data = new IDataObject(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 != COM.S_OK) return null;
+       long hMem = stgmedium.unionField;
+       try {
+               if (transferData.type == CFSTR_INETURLIDW) {
+                       /* Ensure byteCount is a multiple of 2 bytes */
+                       int size = OS.GlobalSize(hMem) / 2 * 2;
+                       if (size == 0) return null;
+                       char[] chars = new char[size/2];
+                       long ptr = OS.GlobalLock(hMem);
+                       if (ptr == 0) return null;
+                       try {
+                               OS.MoveMemory(chars, ptr, size);
+                               int length = chars.length;
+                               for (int i=0; i<chars.length; i++) {
+                                       if (chars [i] == '\0') {
+                                               length = i;
+                                               break;
+                                       }
+                               }
+                               return new String (chars, 0, length);
+                       } finally {
+                               OS.GlobalUnlock(hMem);
+                       }
+               } else if (transferData.type == CFSTR_INETURLID) {
+                       long lpMultiByteStr = OS.GlobalLock(hMem);
+                       if (lpMultiByteStr == 0) return null;
+                       try {
+                               int codePage = OS.GetACP();
+                               int cchWideChar  = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+                               if (cchWideChar == 0) return null;
+                               char[] lpWideCharStr = new char [cchWideChar - 1];
+                               OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+                               return new String(lpWideCharStr);
+                       } finally {
+                               OS.GlobalUnlock(hMem);
+                       }
+               }
+       } finally {
+               OS.GlobalFree(hMem);
+       }
+       return null;
+}
+
+@Override
+protected int[] getTypeIds(){
+       return new int[] {CFSTR_INETURLIDW, CFSTR_INETURLID};
+}
+
+@Override
+protected String[] getTypeNames(){
+       return new String[] {CFSTR_INETURLW, CFSTR_INETURL};
+}
+
+boolean checkURL(Object object) {
+       return object != null && (object instanceof String) && ((String)object).length() > 0;
+}
+
+@Override
+protected boolean validate(Object object) {
+       return checkURL(object);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/package.html
new file mode 100644 (file)
index 0000000..6773fd5
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Drag and Drop support.
+<h2>
+Package Specification</h2>
+This package contains the classes which make up the public API of the SWT
+Drag and Drop support.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ArmEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ArmEvent.java
new file mode 100644 (file)
index 0000000..5c16506
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 ArmEvent(Event e) {
+       super(e);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ArmListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ArmListener.java
new file mode 100644 (file)
index 0000000..bd4a4d3
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface ArmListener extends SWTEventListener {
+
+/**
+ * Sent when a widget is armed, or 'about to be selected'.
+ *
+ * @param e an event containing information about the arm
+ */
+void widgetArmed(ArmEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlAdapter.java
new file mode 100644 (file)
index 0000000..f51fa5e
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods
+ * {@link ControlListener#controlMovedAdapter(java.util.function.Consumer)}
+ * and
+ * {@link ControlListener#controlResizedAdapter(java.util.function.Consumer)},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see ControlListener
+ * @see ControlEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class ControlAdapter implements 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
+ */
+@Override
+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
+ */
+@Override
+public void controlResized(ControlEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlEvent.java
new file mode 100644 (file)
index 0000000..3818e4d
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 ControlEvent(Event e) {
+       super(e);
+}
+
+}
+
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ControlListener.java
new file mode 100644 (file)
index 0000000..d5fd210
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends 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
+ */
+void controlMoved(ControlEvent e);
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ *
+ * @param e an event containing information about the resize
+ */
+void controlResized(ControlEvent e);
+
+/**
+ * Static helper method to create a <code>ControlListener</code> for the
+ * {@link #controlMoved(ControlEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ControlListener
+ * @since 3.107
+ */
+static ControlListener controlMovedAdapter(Consumer<ControlEvent> c) {
+       return new ControlAdapter() {
+               @Override
+               public void controlMoved(ControlEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ControlListener</code> for the
+ * {@link #controlResized(ControlEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ControlListener
+ * @since 3.107
+ */
+static ControlListener controlResizedAdapter(Consumer<ControlEvent> c) {
+       return new ControlAdapter() {
+               @Override
+               public void controlResized(ControlEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DisposeEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DisposeEvent.java
new file mode 100644 (file)
index 0000000..3d3b49e
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 DisposeEvent(Event e) {
+       super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DisposeListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DisposeListener.java
new file mode 100644 (file)
index 0000000..8cb02a8
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface DisposeListener extends SWTEventListener {
+
+/**
+ * Sent when the widget is disposed.
+ *
+ * @param e an event containing information about the dispose
+ */
+void widgetDisposed(DisposeEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DragDetectEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DragDetectEvent.java
new file mode 100644 (file)
index 0000000..904b81c
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 DragDetectEvent(Event e) {
+       super(e);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DragDetectListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/DragDetectListener.java
new file mode 100644 (file)
index 0000000..bfdf19d
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface DragDetectListener extends SWTEventListener {
+
+/**
+ * Sent when a drag gesture is detected.
+ *
+ * @param e an event containing information about the drag
+ */
+void dragDetected(DragDetectEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandAdapter.java
new file mode 100644 (file)
index 0000000..da64f5f
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods
+ * {@link ExpandListener#itemCollapsedAdapter(java.util.function.Consumer)}
+ * and
+ * {@link ExpandListener#itemExpandedAdapter(java.util.function.Consumer)},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </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 implements ExpandListener {
+
+/**
+ * Sent when an item is collapsed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the operation
+ */
+@Override
+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
+ */
+@Override
+public void itemExpanded(ExpandEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandEvent.java
new file mode 100644 (file)
index 0000000..8c14118
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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 ExpandEvent(Event e) {
+       super(e);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ExpandListener.java
new file mode 100644 (file)
index 0000000..3829a9f
--- /dev/null
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * Sent when an item is collapsed.
+ *
+ * @param e an event containing information about the operation
+ */
+void itemCollapsed(ExpandEvent e);
+
+/**
+ * Sent when an item is expanded.
+ *
+ * @param e an event containing information about the operation
+ */
+void itemExpanded(ExpandEvent e);
+
+/**
+ * Static helper method to create a <code>ExpandListener</code> for the
+ * {@link #itemCollapsed(ExpandEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ExpandListener
+ * @since 3.107
+ */
+static ExpandListener itemCollapsedAdapter(Consumer<ExpandEvent> c) {
+       return new ExpandAdapter() {
+               @Override
+               public void itemCollapsed(ExpandEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ExpandListener</code> for the
+ * {@link #itemExpanded(ExpandEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ExpandListener
+ * @since 3.107
+ */
+static ExpandListener itemExpandedAdapter(Consumer<ExpandEvent> c) {
+       return new ExpandAdapter() {
+               @Override
+               public void itemExpanded(ExpandEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusAdapter.java
new file mode 100644 (file)
index 0000000..d6d9e0a
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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 implements FocusListener {
+
+/**
+ * Sent when a control gets focus.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the focus change
+ */
+@Override
+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
+ */
+@Override
+public void focusLost(FocusEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusEvent.java
new file mode 100644 (file)
index 0000000..e89d021
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 FocusEvent(Event e) {
+       super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/FocusListener.java
new file mode 100644 (file)
index 0000000..8580248
--- /dev/null
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 506538
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * Sent when a control gets focus.
+ *
+ * @param e an event containing information about the focus change
+ */
+void focusGained(FocusEvent e);
+
+/**
+ * Sent when a control loses focus.
+ *
+ * @param e an event containing information about the focus change
+ */
+void focusLost(FocusEvent e);
+
+
+/**
+ * Static helper method to create a <code>FocusListener</code> for the
+ * {@link #focusGained(FocusEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return FocusListener
+ * @since 3.106
+ */
+static FocusListener focusGainedAdapter(Consumer<FocusEvent> c) {
+       return new FocusAdapter() {
+               @Override
+               public void focusGained(FocusEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>FocusListener</code> for the
+ * {@link #focusLost(FocusEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return FocusListener
+ * @since 3.106
+*/
+static FocusListener focusLostAdapter(Consumer<FocusEvent> c) {
+       return new FocusAdapter() {
+               @Override
+               public void focusLost(FocusEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/GestureEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/GestureEvent.java
new file mode 100644 (file)
index 0000000..05837da
--- /dev/null
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Instances of this class are sent in response to
+ * touch-based gestures that are triggered by the user.
+ *
+ * @see GestureListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.7
+ */
+public class GestureEvent extends TypedEvent {
+
+       /**
+        * The state of the keyboard modifier keys and mouse masks
+        * at the time the event was generated.
+        *
+        * @see org.eclipse.swt.SWT#MODIFIER_MASK
+        * @see org.eclipse.swt.SWT#BUTTON_MASK
+        */
+       public int stateMask;
+
+       /**
+        * The gesture type.
+        * <ul>
+        * <li>{@link org.eclipse.swt.SWT#GESTURE_BEGIN}</li>
+        * <li>{@link org.eclipse.swt.SWT#GESTURE_END}</li>
+        * <li>{@link org.eclipse.swt.SWT#GESTURE_MAGNIFY}</li>
+        * <li>{@link org.eclipse.swt.SWT#GESTURE_PAN}</li>
+        * <li>{@link org.eclipse.swt.SWT#GESTURE_ROTATE}</li>
+        * <li>{@link org.eclipse.swt.SWT#GESTURE_SWIPE}</li>
+        * </ul>
+        *
+        * This field determines the <code>GestureEvent</code> fields that contain valid data.
+        */
+       public int detail;
+
+       /**
+        * The meaning of this field is dependent on the value of the <code>detail</code> field
+        * and the platform.  It can represent either the x coordinate of the centroid of the
+        * touches that make up the gesture, or the x coordinate of the cursor at the time the
+        * gesture was performed.
+        */
+       public int x;
+
+       /**
+        * The meaning of this field is dependent on the value of the <code>detail</code> field
+        * and the platform.  It can represent either the y coordinate of the centroid of the
+        * touches that make up the gesture, or the y coordinate of the cursor at the time the
+        * gesture was performed.
+        */
+       public int y;
+
+       /**
+        * This field is valid when the <code>detail</code> field is set to <code>GESTURE_ROTATE</code>.
+        * It specifies the number of degrees rotated on the device since the gesture started. Positive
+        * values indicate counter-clockwise rotation, and negative values indicate clockwise rotation.
+        */
+       public double rotation;
+
+       /**
+        * This field is valid when the <code>detail</code> field is set to <code>GESTURE_SWIPE</code>
+        * or <code>GESTURE_PAN</code>.  Both <code>xDirection</code> and <code>yDirection</code>
+        * can be valid for an individual gesture.  The meaning of this field is dependent on the value
+        * of the <code>detail</code> field.
+        * <p>
+        * If <code>detail</code> is <code>GESTURE_SWIPE</code> then a positive value indicates a swipe
+        * to the right and a negative value indicates a swipe to the left.
+        *
+        * If <code>detail</code> is <code>GESTURE_PAN</code> then a positive value indicates a pan to
+        * the right by this field's count of points and a negative value indicates a pan to the left
+        * by this field's count of points.
+        */
+       public int xDirection;
+
+       /**
+        * This field is valid when the <code>detail</code> field is set to <code>GESTURE_SWIPE</code>
+        * or <code>GESTURE_PAN</code>.  Both <code>xDirection</code> and <code>yDirection</code>
+        * can be valid for an individual gesture.  The meaning of this field is dependent on the value
+        * of the <code>detail</code> field.
+        *
+        * If <code>detail</code> is <code>GESTURE_SWIPE</code> then a positive value indicates a downward
+        * swipe and a negative value indicates an upward swipe.
+        *
+        * If <code>detail</code> is <code>GESTURE_PAN</code> then a positive value indicates a downward
+        * pan by this field's count of points and a negative value indicates an upward pan by this
+        * field's count of points.
+        */
+       public int yDirection;
+
+       /**
+        * This field is valid when the <code>detail</code> field is set to <code>GESTURE_MAGNIFY</code>.
+        * This is the scale factor to be applied. This value will be 1.0 in the first received event with
+        * <code>GESTURE_MAGNIFY</code>, and will then fluctuate in subsequent events as the user moves
+        * their fingers.
+        */
+       public double magnification;
+
+       /**
+        * This flag indicates whether the operation should be allowed.
+        * Setting it to <code>false</code> will cancel the operation.
+        */
+       public boolean doit;
+
+       static final long serialVersionUID = -8348741538373572182L;
+
+/**
+ * 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 GestureEvent(Event e) {
+       super(e);
+       this.stateMask = e.stateMask;
+       this.x = e.x;
+       this.y = e.y;
+       this.detail = e.detail;
+       this.rotation = e.rotation;
+       this.xDirection = e.xDirection;
+       this.yDirection = e.yDirection;
+       this.magnification = e.magnification;
+       this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " stateMask=0x" + Integer.toHexString(stateMask)
+               + " detail=" + detail
+               + " x=" + x
+               + " y=" + y
+               + " rotation=" + rotation
+               + " xDirection=" + xDirection
+               + " yDirection=" + yDirection
+               + " magnification=" + magnification
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/GestureListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/GestureListener.java
new file mode 100644 (file)
index 0000000..7193e78
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as gestures
+ * are triggered by the user interacting with a touch pad or
+ * touch screen.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addGestureListener</code> method and removed using
+ * the <code>removeGestureListener</code> method. When a
+ * gesture is triggered, the appropriate method will be invoked.
+ * </p>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
+ * SWT doesn't send Gesture or Touch events on GTK.
+ * </p>
+ *
+ * @see GestureEvent
+ *
+ * @since 3.7
+ */
+@FunctionalInterface
+public interface GestureListener extends SWTEventListener {
+
+/**
+ * Sent when a recognized gesture has occurred.
+ *
+ * @param e an event containing information about the gesture.
+ */
+void gesture(GestureEvent e);
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/HelpEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/HelpEvent.java
new file mode 100644 (file)
index 0000000..44c5d65
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 HelpEvent(Event e) {
+       super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/HelpListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/HelpListener.java
new file mode 100644 (file)
index 0000000..74eb24a
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface HelpListener extends SWTEventListener {
+
+/**
+ * Sent when help is requested for a control, typically
+ * when the user presses F1.
+ *
+ * @param e an event containing information about the help
+ */
+void helpRequested(HelpEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyAdapter.java
new file mode 100644 (file)
index 0000000..c523b46
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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 implements 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
+ */
+@Override
+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
+ */
+@Override
+public void keyReleased(KeyEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyEvent.java
new file mode 100644 (file)
index 0000000..10700e5
--- /dev/null
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 char character;
+
+       /**
+        * 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;
+
+       /**
+        * depending on the event, the location of key specified by the
+        * keyCode or character. The possible values for this field are
+        * <code>SWT.LEFT</code>, <code>SWT.RIGHT</code>, <code>SWT.KEYPAD</code>,
+        * or <code>SWT.NONE</code> representing the main keyboard area.
+        * <p>
+        * The location field can be used to differentiate key events that have
+        * the same key code and character but are generated by different keys
+        * on the keyboard. For example, a key down event with the key code equal
+        * to SWT.SHIFT can be generated by the left and the right shift keys on
+        * the keyboard.
+        * </p><p>
+        * The location field can only be used to determine the location of
+        * the key code or character in the current event. It does not include
+        * information about the location of modifiers in the state mask.
+        * </p>
+        *
+        * @see org.eclipse.swt.SWT#LEFT
+        * @see org.eclipse.swt.SWT#RIGHT
+        * @see org.eclipse.swt.SWT#KEYPAD
+        *
+        * @since 3.6
+        */
+       public int keyLocation;
+
+       /**
+        * the state of the keyboard modifier keys and mouse masks
+        * at the time the event was generated.
+        *
+        * @see org.eclipse.swt.SWT#MODIFIER_MASK
+        * @see org.eclipse.swt.SWT#BUTTON_MASK
+        */
+       public int stateMask;
+
+       /**
+        * A flag indicating whether the operation should be allowed.
+        * Setting this field to <code>false</code> will cancel the operation.
+        */
+       public boolean 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 KeyEvent(Event e) {
+       super(e);
+       this.character = e.character;
+       this.keyCode = e.keyCode;
+       this.keyLocation = e.keyLocation;
+       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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " character='" + ((character == 0) ? "\\0" : String.valueOf(character)) + "'=0x" + Integer.toHexString(character)
+               + " keyCode=0x" + Integer.toHexString(keyCode)
+               + " keyLocation=0x" + Integer.toHexString(keyLocation)
+               + " stateMask=0x" + Integer.toHexString(stateMask)
+               + " doit=" + doit
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/KeyListener.java
new file mode 100644 (file)
index 0000000..8d55ef2
--- /dev/null
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 507185
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * Sent when a key is pressed on the system keyboard.
+ *
+ * @param e an event containing information about the key press
+ */
+void keyPressed(KeyEvent e);
+
+/**
+ * Sent when a key is released on the system keyboard.
+ *
+ * @param e an event containing information about the key release
+ */
+void keyReleased(KeyEvent e);
+
+/**
+ * Static helper method to create a <code>KeyListener</code> for the
+ * {@link #keyPressed(KeyEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return KeyListener
+ * @since 3.106
+ */
+static KeyListener keyPressedAdapter(Consumer<KeyEvent> c) {
+       return new KeyAdapter() {
+               @Override
+               public void keyPressed(KeyEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>KeyListener</code> for the
+ * {@link #keyReleased(KeyEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return KeyListener
+ * @since 3.106
+*/
+static KeyListener keyReleasedAdapter(Consumer<KeyEvent> c) {
+       return new KeyAdapter() {
+               @Override
+               public void keyReleased(KeyEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuAdapter.java
new file mode 100644 (file)
index 0000000..450ce00
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods
+ * {@link MenuListener#menuHiddenAdapter(java.util.function.Consumer)}
+ * and
+ * {@link MenuListener#menuShownAdapter(java.util.function.Consumer)},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see MenuListener
+ * @see MenuEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class MenuAdapter implements MenuListener {
+
+/**
+ * Sent when a menu is hidden.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the menu operation
+ */
+@Override
+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
+ */
+@Override
+public void menuShown(MenuEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuDetectEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuDetectEvent.java
new file mode 100644 (file)
index 0000000..99c5b7a
--- /dev/null
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends 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 boolean doit;
+
+       /**
+        * The context menu trigger type.
+        * <ul>
+        * <li>{@link org.eclipse.swt.SWT#MENU_MOUSE}</li>
+        * <li>{@link org.eclipse.swt.SWT#MENU_KEYBOARD}</li>
+        * </ul>
+        *
+        * A field indicating whether the context menu was triggered by a
+        * pointing device such as a mouse (indicated by <code>MENU_MOUSE</code>),
+        * or by a focus-based device such as a keyboard (<code>MENU_KEYBOARD</code>).
+        * If the trigger was <code>MENU_KEYBOARD</code>, then the application should
+        * provide new display-relative x and y coordinates based on the current
+        * selection or the current focus.
+        *
+        * @since 3.8
+        */
+       public int detail;
+
+
+       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 MenuDetectEvent(Event e) {
+       super(e);
+       this.x = e.x;
+       this.y = e.y;
+       this.doit = e.doit;
+       this.detail = e.detail;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " x=" + x
+               + " y=" + y
+               + " doit=" + doit
+               + " detail=" + detail
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuDetectListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuDetectListener.java
new file mode 100644 (file)
index 0000000..41d0f3f
--- /dev/null
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface MenuDetectListener extends SWTEventListener {
+
+/**
+ * Sent when the platform-dependent trigger for showing a menu item is detected.
+ *
+ * @param e an event containing information about the menu detect
+ */
+void menuDetected (MenuDetectEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuEvent.java
new file mode 100644 (file)
index 0000000..179e899
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 MenuEvent(Event e) {
+       super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MenuListener.java
new file mode 100644 (file)
index 0000000..a16bdc7
--- /dev/null
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * Sent when a menu is hidden.
+ *
+ * @param e an event containing information about the menu operation
+ */
+void menuHidden(MenuEvent e);
+
+/**
+ * Sent when a menu is shown.
+ *
+ * @param e an event containing information about the menu operation
+ */
+void menuShown(MenuEvent e);
+
+/**
+ * Static helper method to create a <code>MenuListener</code> for the
+ * {@link #menuHidden(MenuEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return MenuListener
+ * @since 3.107
+ */
+static MenuListener menuHiddenAdapter(Consumer<MenuEvent> c) {
+       return new MenuAdapter() {
+               @Override
+               public void menuHidden(MenuEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>MenuListener</code> for the
+ * {@link #menuShown(MenuEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return MenuListener
+ * @since 3.107
+ */
+static MenuListener menuShownAdapter(Consumer<MenuEvent> c) {
+       return new MenuAdapter() {
+               @Override
+               public void menuShown(MenuEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ModifyEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ModifyEvent.java
new file mode 100644 (file)
index 0000000..7a59e89
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 ModifyEvent(Event e) {
+       super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ModifyListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ModifyListener.java
new file mode 100644 (file)
index 0000000..108e350
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface ModifyListener extends SWTEventListener {
+
+/**
+ * Sent when the text is modified.
+ *
+ * @param e an event containing information about the modify
+ */
+void modifyText(ModifyEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseAdapter.java
new file mode 100644 (file)
index 0000000..fb830b8
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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 implements 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()
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+public void mouseUp(MouseEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseEvent.java
new file mode 100644 (file)
index 0000000..24a36df
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends TypedEvent {
+
+       /**
+        * the button that was pressed or released;
+        * <ul>
+        * <li>1 for the first button (usually 'left')</li>
+        * <li>2 for the second button (usually 'middle')</li>
+        * <li>3 for the third button (usually 'right')</li>
+        * <li>etc.</li>
+        * </ul>
+        */
+       public int button;
+
+       /**
+        * the state of the keyboard modifier keys and mouse masks
+        * at the time the event was generated.
+        *
+        * @see org.eclipse.swt.SWT#MODIFIER_MASK
+        * @see org.eclipse.swt.SWT#BUTTON_MASK
+        */
+       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 MouseEvent(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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " button=" + button
+               + " stateMask=0x" + Integer.toHexString(stateMask)
+               + " x=" + x
+               + " y=" + y
+               + " count=" + count
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseListener.java
new file mode 100644 (file)
index 0000000..ec7c13d
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com>  - Bug 513037
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends 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()
+ */
+void mouseDoubleClick(MouseEvent e);
+
+/**
+ * Sent when a mouse button is pressed.
+ *
+ * @param e an event containing information about the mouse button press
+ */
+void mouseDown(MouseEvent e);
+
+/**
+ * Sent when a mouse button is released.
+ *
+ * @param e an event containing information about the mouse button release
+ */
+void mouseUp(MouseEvent e);
+
+
+/**
+ * Static helper method to create a <code>MouseListener</code> for the
+ * {@link #mouseDoubleClick(MouseEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return MouseListener
+ * @since 3.106
+ */
+
+static MouseListener mouseDoubleClickAdapter(Consumer<MouseEvent> c) {
+       return new MouseAdapter() {
+               @Override
+               public void mouseDoubleClick(MouseEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>MouseListener</code> for the
+ * {@link #mouseDown(MouseEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return MouseListener
+ * @since 3.106
+ */
+
+static MouseListener mouseDownAdapter(Consumer<MouseEvent> c) {
+       return new MouseAdapter() {
+               @Override
+               public void mouseDown(MouseEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>MouseListener</code> for the
+ * {@link #mouseUp(MouseEvent e)}) method with a lambda expression.
+ *
+ * @param c the consumer of the event
+ * @return MouseListener
+ * @since 3.106
+ */
+
+static MouseListener mouseUpAdapter(Consumer<MouseEvent> c) {
+       return new MouseAdapter() {
+               @Override
+               public void mouseUp(MouseEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseMoveListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseMoveListener.java
new file mode 100644 (file)
index 0000000..5912e65
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface MouseMoveListener extends SWTEventListener {
+
+/**
+ * Sent when the mouse moves.
+ *
+ * @param e an event containing information about the mouse move
+ */
+void mouseMove(MouseEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseTrackAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseTrackAdapter.java
new file mode 100644 (file)
index 0000000..5266479
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods
+ * {@link MouseTrackListener#mouseEnterAdapter(java.util.function.Consumer)},
+ * {@link MouseTrackListener#mouseExitAdapter(java.util.function.Consumer)}
+ * and
+ * {@link MouseTrackListener#mouseHoverAdapter(java.util.function.Consumer)},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see MouseTrackListener
+ * @see MouseEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class MouseTrackAdapter implements 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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+public void mouseHover(MouseEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseTrackListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseTrackListener.java
new file mode 100644 (file)
index 0000000..135d78b
--- /dev/null
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends 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
+ */
+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
+ */
+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
+ */
+void mouseHover(MouseEvent e);
+
+/**
+ * Static helper method to create a <code>MouseTrackListener</code> for the
+ * {@link #mouseEnter(MouseEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return MouseTrackListener
+ * @since 3.107
+ */
+static MouseTrackListener mouseEnterAdapter(Consumer<MouseEvent> c) {
+       return new MouseTrackAdapter() {
+               @Override
+               public void mouseEnter(MouseEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>MouseTrackListener</code> for the
+ * {@link #mouseExit(MouseEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return MouseTrackListener
+ * @since 3.107
+ */
+static MouseTrackListener mouseExitAdapter(Consumer<MouseEvent> c) {
+       return new MouseTrackAdapter() {
+               @Override
+               public void mouseExit(MouseEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>MouseTrackListener</code> for the
+ * {@link #mouseHover(MouseEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return MouseTrackListener
+ * @since 3.107
+ */
+static MouseTrackListener mouseHoverAdapter(Consumer<MouseEvent> c) {
+       return new MouseTrackAdapter() {
+               @Override
+               public void mouseHover(MouseEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseWheelListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/MouseWheelListener.java
new file mode 100644 (file)
index 0000000..8766e14
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface MouseWheelListener extends SWTEventListener {
+
+/**
+ * Sent when the mouse wheel is scrolled.
+ *
+ * @param e an event containing information about the mouse wheel action
+ */
+void mouseScrolled (MouseEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/PaintEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/PaintEvent.java
new file mode 100644 (file)
index 0000000..ca80848
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.graphics.GC;
+
+/**
+ * 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 extends 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 PaintEvent(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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " gc=" + gc
+               + " x=" + x
+               + " y=" + y
+               + " width=" + width
+               + " height=" + height
+               + " count=" + count
+               + "}";
+}
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/PaintListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/PaintListener.java
new file mode 100644 (file)
index 0000000..070c3e9
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface PaintListener extends SWTEventListener {
+
+/**
+ * Sent when a paint event occurs for the control.
+ *
+ * @param e an event containing information about the paint
+ */
+void paintControl(PaintEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SegmentEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SegmentEvent.java
new file mode 100644 (file)
index 0000000..19349ec
--- /dev/null
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This event is sent to SegmentListeners when a text content is to be modified.
+ * The segments field can be used in conjunction with the segmentsChars field or
+ * by itself. Setting only the segmentsChars field has no effect. When used by
+ * itself, the segments field specify text ranges that should be treated as
+ * separate segments.
+ * <p>
+ * The elements in the segments field specify the start offset of a segment
+ * relative to the start of the text. They must follow the following rules:</p>
+ * <ul>
+ * <li>elements must be in ascending order and must not have duplicates
+ * <li>elements must not exceed the text length
+ * </ul>
+ * In addition, the first element may be set to zero and the last element may
+ * be set to the end of the line but this is not required.
+ * <p>
+ * The segments field may be left null if the entire text content doesn't
+ * require segmentation.
+ * </p>
+ * A SegmentListener 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 text = "R1R2R3" + "R4R5R6"
+ *             R1 to R6 are right-to-left characters. The quotation marks
+ *             are part of the text. The text is 13 characters long.
+ *
+ *     segments = null:
+ *             entire text content will be reordered and thus the two R2L segments
+ *             swapped (as per the bidi algorithm).
+ *             visual display (rendered on screen) = "R6R5R4" + "R3R2R1"
+ *
+ *     segments = [0, 5, 8]
+ *             "R1R2R3" will be reordered, followed by [blank]+[blank] and
+ *             "R4R5R6".
+ *             visual display = "R3R2R1" + "R6R5R4"
+ * </pre>
+ *
+ * <p>
+ * The segments and segmentsChars fields can be used together to obtain different
+ * types of bidi reordering and text display. The application can use these two fields
+ * to insert Unicode Control Characters in specific offsets in the text, the character
+ * at segmentsChars[i] is inserted at the offset specified by segments[i]. When both fields
+ * are set, the rules for the segments field are less restrictive:
+ * </p>
+ * <ul>
+ * <li>elements must be in ascending order, duplicates are allowed
+ * <li>elements must not exceed the text length
+ * </ul>
+ *
+ * @since 3.8
+ */
+
+public class SegmentEvent extends TypedEvent {
+
+       /**
+        * The start offset of the <code>lineText</code> relative to text (always zero for single line widget)
+        */
+       public int lineOffset;
+
+       /**
+        * Text used to calculate the segments
+        */
+       public String lineText;
+
+       /**
+        * Text ranges that should be treated as separate segments (e.g. for bidi reordering)
+        */
+       public int[] segments;
+
+       /**
+        * Characters to be used in the segment boundaries (optional)
+        */
+       public char[] segmentsChars;
+
+       static final long serialVersionUID = -2414889726745247762L;
+
+       public SegmentEvent(Event e) {
+               super(e);
+               lineText = e.text;
+               lineOffset = e.detail;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SegmentListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SegmentListener.java
new file mode 100644 (file)
index 0000000..37016ee
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016s IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * SegmentEvents.
+ * @see SegmentEvent
+ *
+ * @since 3.8
+ */
+@FunctionalInterface
+public interface SegmentListener extends SWTEventListener {
+
+/**
+ * This method is called when text content is being modified.
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.lineText text content (input)</li>
+ * <li>event.segments text offsets for segment characters (output)</li>
+ * <li>event.segmentsChars characters that should be inserted (output, optional)</li>
+ * </ul>
+ *
+ * @param event the given event
+ * @see SegmentEvent
+ */
+void getSegments(SegmentEvent event);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionAdapter.java
new file mode 100644 (file)
index 0000000..12452be
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods
+ * {@link SelectionListener#widgetSelectedAdapter(java.util.function.Consumer)}
+ * and
+ * {@link SelectionListener#widgetDefaultSelectedAdapter(java.util.function.Consumer)},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see SelectionListener
+ * @see SelectionEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class SelectionAdapter implements SelectionListener {
+
+/**
+ * Sent when selection occurs in the control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the selection
+ */
+@Override
+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
+ */
+@Override
+public void widgetDefaultSelected(SelectionEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionEvent.java
new file mode 100644 (file)
index 0000000..aa6bc87
--- /dev/null
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends TypedEvent {
+
+       /**
+        * The item that was selected.
+        */
+       public Widget item;
+
+       /**
+        * Extra detail information about the selection, depending on the widget.
+        *
+        * <p><b>Sash</b></p>
+        * <ul>
+        * <li>{@link org.eclipse.swt.SWT#DRAG}</li>
+        * </ul>
+        * <p><b>ScrollBar and Slider</b></p>
+        * <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><b>Table and Tree</b></p>
+        * <ul>
+        * <li>{@link org.eclipse.swt.SWT#CHECK}</li>
+        * </ul>
+        * <p><b>Text</b></p>
+        * <ul>
+        * <li>{@link org.eclipse.swt.SWT#CANCEL}</li>
+        * </ul>
+        * <p><b>CoolItem and ToolItem</b></p>
+        * <ul>
+        * <li>{@link org.eclipse.swt.SWT#ARROW}</li>
+        * </ul>
+        */
+       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 and mouse masks
+        * at the time the event was generated.
+        * <p>
+        * <b>Note:</b> Mouse button states are currently not included consistently
+        * for all widgets on all platforms. Clients should be prepared to receive
+        * button states, but should not rely on getting them everywhere.
+        * </p>
+        *
+        * @see org.eclipse.swt.SWT#MODIFIER_MASK
+        * @see org.eclipse.swt.SWT#BUTTON_MASK
+        */
+       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 boolean 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 SelectionEvent(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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " item=" + item
+               + " detail=" + detail
+               + " x=" + x
+               + " y=" + y
+               + " width=" + width
+               + " height=" + height
+               + " stateMask=0x" + Integer.toHexString(stateMask)
+               + " text=" + text
+               + " doit=" + doit
+               + "}";
+}
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/SelectionListener.java
new file mode 100644 (file)
index 0000000..44e0af9
--- /dev/null
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com>  - Bug 441116
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * 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
+ */
+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
+ */
+void widgetDefaultSelected(SelectionEvent e);
+
+
+
+/**
+ * Static helper method to create a <code>SelectionListener</code> for the
+ * {@link #widgetSelected(SelectionEvent e)}) method, given a lambda expression
+ * or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return SelectionListener
+ * @since 3.106
+ */
+static SelectionListener widgetSelectedAdapter(Consumer<SelectionEvent> c) {
+       return new SelectionAdapter() {
+               @Override
+               public void widgetSelected(SelectionEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>SelectionListener</code> for the
+ * {@link #widgetDefaultSelected(SelectionEvent e)}) method, given a lambda expression
+ * or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return SelectionListener
+ * @since 3.106
+*/
+static SelectionListener widgetDefaultSelectedAdapter(Consumer<SelectionEvent> c) {
+       return new SelectionAdapter() {
+               @Override
+               public void widgetDefaultSelected(SelectionEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellAdapter.java
new file mode 100644 (file)
index 0000000..7ac95a2
--- /dev/null
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods in
+ * {@link ShellListener},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see ShellListener
+ * @see ShellEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class ShellAdapter implements 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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+public void shellIconified(ShellEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellEvent.java
new file mode 100644 (file)
index 0000000..c726bf8
--- /dev/null
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends TypedEvent {
+
+       /**
+        * A flag indicating whether the operation should be allowed.
+        * Setting this field to <code>false</code> will cancel the operation.
+        */
+       public boolean 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 ShellEvent(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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " doit=" + doit
+               + "}";
+}
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/ShellListener.java
new file mode 100644 (file)
index 0000000..fc30f65
--- /dev/null
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * Sent when a shell becomes the active window.
+ *
+ * @param e an event containing information about the activation
+ */
+void shellActivated(ShellEvent e);
+
+/**
+ * Sent when a shell is closed.
+ *
+ * @param e an event containing information about the close
+ */
+void shellClosed(ShellEvent e);
+
+/**
+ * Sent when a shell stops being the active window.
+ *
+ * @param e an event containing information about the deactivation
+ */
+void shellDeactivated(ShellEvent e);
+
+/**
+ * Sent when a shell is un-minimized.
+ *
+ * @param e an event containing information about the un-minimization
+ */
+void shellDeiconified(ShellEvent e);
+
+/**
+ * Sent when a shell is minimized.
+ *
+ * @param e an event containing information about the minimization
+ */
+void shellIconified(ShellEvent e);
+
+/**
+ * Static helper method to create a <code>ShellListener</code> for the
+ * {@link #shellActivated(ShellEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ShellListener
+ * @since 3.107
+ */
+static ShellListener shellActivatedAdapter(Consumer<ShellEvent> c) {
+       return new ShellAdapter() {
+               @Override
+               public void shellActivated(ShellEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ShellListener</code> for the
+ * {@link #shellClosed(ShellEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ShellListener
+ * @since 3.107
+ */
+static ShellListener shellClosedAdapter(Consumer<ShellEvent> c) {
+       return new ShellAdapter() {
+               @Override
+               public void shellClosed(ShellEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ShellListener</code> for the
+ * {@link #shellDeactivated(ShellEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ShellListener
+ * @since 3.107
+ */
+static ShellListener shellDeactivatedAdapter(Consumer<ShellEvent> c) {
+       return new ShellAdapter() {
+               @Override
+               public void shellDeactivated(ShellEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ShellListener</code> for the
+ * {@link #shellDeiconified(ShellEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ShellListener
+ * @since 3.107
+ */
+static ShellListener shellDeiconifiedAdapter(Consumer<ShellEvent> c) {
+       return new ShellAdapter() {
+               @Override
+               public void shellDeiconified(ShellEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>ShellListener</code> for the
+ * {@link #shellIconified(ShellEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return ShellListener
+ * @since 3.107
+ */
+static ShellListener shellIconifiedAdapter(Consumer<ShellEvent> c) {
+       return new ShellAdapter() {
+               @Override
+               public void shellIconified(ShellEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TouchEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TouchEvent.java
new file mode 100644 (file)
index 0000000..08d9149
--- /dev/null
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Instances of this class are sent in response to
+ * a touch-based input source being touched.
+ *
+ * @see TouchListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.7
+ */
+public class TouchEvent extends TypedEvent {
+
+       /**
+        * The set of touches representing the state of all contacts with touch input
+        * device at the time the event was generated.
+        *
+        * @see org.eclipse.swt.widgets.Touch
+        */
+       public Touch[] touches;
+
+       /**
+        * The state of the keyboard modifier keys and mouse masks
+        * at the time the event was generated.
+        *
+        * @see org.eclipse.swt.SWT#MODIFIER_MASK
+        * @see org.eclipse.swt.SWT#BUTTON_MASK
+        */
+       public int stateMask;
+
+       /**
+        * The widget-relative x coordinate of the pointer
+        * at the time the touch occurred.
+        */
+       public int x;
+
+       /**
+        * The widget-relative y coordinate of the pointer
+        * at the time the touch occurred.
+        */
+       public int y;
+
+       static final long serialVersionUID = -8348741538373572182L;
+
+/**
+ * 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 TouchEvent(Event e) {
+       super(e);
+       this.touches = e.touches;
+       this.stateMask = e.stateMask;
+       this.x = e.x;
+       this.y = e.y;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       String string = super.toString();
+       string = string.substring (0, string.length() - 1); // remove trailing '}'
+       string += " stateMask=0x" + Integer.toHexString(stateMask)
+                       + " x=" + x
+                       + " y=" + y;
+       if (touches != null) {
+               for (int i = 0; i < touches.length; i++) {
+                       string += "\n     " + touches[i].toString();
+               }
+               string += "\n";
+       }
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TouchListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TouchListener.java
new file mode 100644 (file)
index 0000000..0c9913a
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as touches
+ * occur on a touch-aware input surface.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addTouchListener</code> method and removed using
+ * the <code>removeTouchListener</code> method. When a
+ * touch occurs or changes state, the <code>touch</code> method
+ * will be invoked.
+ * </p>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
+ * SWT doesn't send Gesture or Touch events on GTK.
+ * </p>
+ *
+ * @see TouchEvent
+ *
+ * @since 3.7
+ */
+@FunctionalInterface
+public interface TouchListener extends SWTEventListener {
+
+/**
+ * Sent when a touch sequence begins, changes state, or ends.
+ *
+ * @param e an event containing information about the touch
+ */
+void touch(TouchEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TraverseEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TraverseEvent.java
new file mode 100644 (file)
index 0000000..3cdf708
--- /dev/null
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends KeyEvent {
+
+       /**
+        * The traversal type.
+        * <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>
+        *
+        * 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 TraverseEvent(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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " detail=" + detail
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TraverseListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TraverseListener.java
new file mode 100644 (file)
index 0000000..14a51d7
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface TraverseListener extends 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
+ */
+void keyTraversed(TraverseEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeAdapter.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeAdapter.java
new file mode 100644 (file)
index 0000000..3b70642
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+/**
+ * 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>
+ * <p>
+ * An alternative to this class are the static helper methods
+ * {@link TreeListener#treeCollapsedAdapter(java.util.function.Consumer)}
+ * and
+ * {@link TreeListener#treeExpandedAdapter(java.util.function.Consumer)},
+ * which accept a lambda expression or a method reference that implements the event consumer.
+ * </p>
+ *
+ * @see TreeListener
+ * @see TreeEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class TreeAdapter implements 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
+ */
+@Override
+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
+ */
+@Override
+public void treeExpanded(TreeEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeEvent.java
new file mode 100644 (file)
index 0000000..51f7afd
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 TreeEvent(Event e) {
+       super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TreeListener.java
new file mode 100644 (file)
index 0000000..ceacdfe
--- /dev/null
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.function.*;
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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 extends SWTEventListener {
+
+/**
+ * Sent when a tree branch is collapsed.
+ *
+ * @param e an event containing information about the tree operation
+ */
+void treeCollapsed(TreeEvent e);
+
+/**
+ * Sent when a tree branch is expanded.
+ *
+ * @param e an event containing information about the tree operation
+ */
+void treeExpanded(TreeEvent e);
+
+/**
+ * Static helper method to create a <code>TreeListener</code> for the
+ * {@link #treeCollapsed(TreeEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return TreeListener
+ * @since 3.107
+ */
+static TreeListener treeCollapsedAdapter(Consumer<TreeEvent> c) {
+       return new TreeAdapter() {
+               @Override
+               public void treeCollapsed(TreeEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+
+/**
+ * Static helper method to create a <code>TreeListener</code> for the
+ * {@link #treeExpanded(TreeEvent e)}) method, given a lambda expression or a method reference.
+ *
+ * @param c the consumer of the event
+ * @return TreeListener
+ * @since 3.107
+ */
+static TreeListener treeExpandedAdapter(Consumer<TreeEvent> c) {
+       return new TreeAdapter() {
+               @Override
+               public void treeExpanded(TreeEvent e) {
+                       c.accept(e);
+               }
+       };
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TypedEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/TypedEvent.java
new file mode 100644 (file)
index 0000000..a87fabf
--- /dev/null
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import java.util.*;
+
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends EventObject {
+
+       /**
+        * 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 TypedEvent(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 TypedEvent(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 package name.
+ *
+ * @return the name of the event
+ */
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (index + 1, string.length ());
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       return getName ()
+               + "{" + widget
+               + " time=" + time
+               + " data=" + data
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/VerifyEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/VerifyEvent.java
new file mode 100644 (file)
index 0000000..4e2db42
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * 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 extends 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 VerifyEvent(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
+ */
+@Override
+public String toString() {
+       String string = super.toString ();
+       return string.substring (0, string.length() - 1) // remove trailing '}'
+               + " start=" + start
+               + " end=" + end
+               + " text=" + text
+               + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/VerifyListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/VerifyListener.java
new file mode 100644 (file)
index 0000000..06360f5
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 502576
+ *******************************************************************************/
+package org.eclipse.swt.events;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements
+ * 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
+ */
+@FunctionalInterface
+public interface VerifyListener extends 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
+ */
+void verifyText(VerifyEvent e);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/events/package.html
new file mode 100644 (file)
index 0000000..b6325f9
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT typed listener support.
+<h2>
+Package Specification</h2>
+This package provides the typed events and listener interfaces and,
+where appropriate, matching adapter classes which make up the 
+"high level" <em>typed listener</em> support provided by SWT.
+<p>
+For contrast, see also the <em>untyped listener</em> support provided
+by class <code>org.eclipse.swt.widgets.Event</code> and interface 
+<code>org.eclipse.swt.widgets.Listener</code>, and the
+<code>addListener</code> and <code>removeListener</code> methods in
+class <code>org.eclipse.swt.widgets.Widget</code>.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Color.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Color.java
new file mode 100644 (file)
index 0000000..1ea30e4
--- /dev/null
@@ -0,0 +1,432 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+
+/**
+ * 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> or <code>RGBA</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 RGBA
+ * @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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public int handle;
+       int alpha = 255;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Color(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 Color (Device device, int red, int green, int blue) {
+       super(device);
+       init(red, green, blue, 255);
+       init();
+}
+
+/**
+ * Constructs a new instance of this class given a device and the
+ * desired red, green, blue &amp; alpha 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
+ * @param alpha the amount of alpha in the color. Currently, SWT only honors extreme values for alpha i.e. 0 (transparent) or 255 (opaque).
+ *
+ * @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, blue or alpha argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ * @since 3.104
+ */
+public Color (Device device, int red, int green, int blue, int alpha) {
+       super(device);
+       init(red, green, blue, alpha);
+       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 Color (Device device, RGB rgb) {
+       super(device);
+       if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       init(rgb.red, rgb.green, rgb.blue, 255);
+       init();
+}
+
+/**
+ * Constructs a new instance of this class given a device and an
+ * <code>RGBA</code> describing the desired red, green, blue &amp; alpha values.
+ * On limited color devices, the color instance created by this call
+ * may not have the same RGBA values as the ones specified by the
+ * argument. The RGBA values on the returned instance will be the color
+ * values of the operating system color + alpha.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param rgba the RGBA values of the desired color. Currently, SWT only honors extreme values for alpha i.e. 0 (transparent) or 255 (opaque).
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the rgba argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green, blue or alpha components of the argument are not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ * @since 3.104
+ */
+public Color(Device device, RGBA rgba) {
+       super(device);
+       if (rgba == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       init(rgba.rgb.red, rgba.rgb.green, rgba.rgb.blue, rgba.alpha);
+       init();
+}
+
+/**
+ * Constructs a new instance of this class given a device, an
+ * <code>RGB</code> describing the desired red, green and blue values,
+ * alpha specifying the level of transparency.
+ * 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
+ * @param alpha the alpha value of the desired color. Currently, SWT only honors extreme values for alpha i.e. 0 (transparent) or 255 (opaque).
+ *
+ * @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, blue or alpha components of the argument are not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ * @since 3.104
+ */
+public Color(Device device, RGB rgb, int alpha) {
+       super(device);
+       if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       init(rgb.red, rgb.green, rgb.blue, alpha);
+       init();
+}
+
+@Override
+void destroy() {
+       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
+ */
+@Override
+public boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Color)) return false;
+       Color color = (Color) object;
+       return device == color.device && (handle & 0xFFFFFF) == (color.handle & 0xFFFFFF) && (alpha == color.alpha);
+}
+
+/**
+ * Returns the amount of alpha in the color, from 0 (transparent) to 255 (opaque).
+ *
+ * @return the alpha component of the color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.104
+ */
+public int getAlpha () {
+       return this.alpha;
+}
+
+/**
+ * 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(handle & 0xFF, (handle & 0xFF00) >> 8, (handle & 0xFF0000) >> 16);
+}
+
+/**
+ * Returns an <code>RGBA</code> representing the receiver.
+ *
+ * @return the RGBA for the color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.104
+ */
+public RGBA getRGBA () {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return new RGBA(handle & 0xFF, (handle & 0xFF00) >> 8, (handle & 0xFF0000) >> 16, alpha);
+}
+
+/**
+ * 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 int hashCode () {
+       return handle ^ alpha;
+}
+
+/**
+ * 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
+ * @param alpha the amount of alpha in the color. Currently, SWT only honors extreme values for alpha i.e. 0 (transparent) or 255 (opaque).
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green, blue or alpha argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+void init(int red, int green, int blue, int alpha) {
+       if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0 || alpha > 255 || alpha < 0) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       handle = (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
+       this.alpha = alpha;
+}
+
+/**
+ * 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 (except {@link #dispose()}) using the color.
+ *
+ * @return <code>true</code> when the color is disposed and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == -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 "Color {" + getRed() + ", " + getGreen() + ", " + getBlue() + ", " + getAlpha() + "}"; //$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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Color win32_new(Device device, int handle) {
+       return win32_new(device, handle, 255);
+}
+
+/**
+ * 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
+ * @param alpha the int for the alpha content in the color
+ * @return a new color object containing the specified device and handle
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Color win32_new(Device device, int handle, int alpha) {
+       Color color = new Color(device);
+       color.handle = handle;
+       color.alpha = alpha;
+       return color;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Cursor.java
new file mode 100644 (file)
index 0000000..a677a4b
--- /dev/null
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+       boolean isIcon;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Cursor(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>
+ * NOTE:
+ * It is recommended to use {@link org.eclipse.swt.widgets.Display#getSystemCursor(int)}
+ * instead of using this constructor. This way you can avoid the
+ * overhead of disposing the Cursor resource.
+ *
+ * @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
+ * @see #dispose()
+ */
+public Cursor(Device device, int style) {
+       super(device);
+       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(0, lpCursorName);
+       if (handle == 0) 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>
+ *
+ * @see #dispose()
+ */
+public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
+       super(device);
+       if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (mask == null) {
+               if (source.getTransparencyType() != 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 != source.width || mask.height != 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 */
+       long hInst = OS.GetModuleHandle(null);
+       handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData, maskData);
+       if (handle == 0) 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>
+ *
+ * @see #dispose()
+ *
+ * @since 3.0
+ */
+public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
+       super(device);
+       if (source == 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);
+       }
+       long hBitmap = 0;
+       long hMask = 0;
+       if (source.maskData == null && source.transparentPixel == -1 && (source.alpha != -1 || source.alphaData != null)) {
+               PaletteData palette = source.palette;
+               PaletteData newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+               ImageData img = new ImageData(source.width, source.height, 32, newPalette);
+               if (palette.isDirect) {
+                       ImageData.blit(ImageData.BLIT_SRC,
+                               source.data, source.depth, source.bytesPerLine, source.getByteOrder(), 0, 0, source.width, source.height, palette.redMask, palette.greenMask, palette.blueMask,
+                               ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+                               img.data, img.depth, img.bytesPerLine, img.getByteOrder(), 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+                               false, false);
+               } else {
+                       RGB[] rgbs = palette.getRGBs();
+                       int length = rgbs.length;
+                       byte[] srcReds = new byte[length];
+                       byte[] srcGreens = new byte[length];
+                       byte[] srcBlues = new byte[length];
+                       for (int i = 0; i < rgbs.length; i++) {
+                               RGB rgb = rgbs[i];
+                               if (rgb == null) continue;
+                               srcReds[i] = (byte)rgb.red;
+                               srcGreens[i] = (byte)rgb.green;
+                               srcBlues[i] = (byte)rgb.blue;
+                       }
+                       ImageData.blit(ImageData.BLIT_SRC,
+                               source.data, source.depth, source.bytesPerLine, source.getByteOrder(), 0, 0, source.width, source.height, srcReds, srcGreens, srcBlues,
+                               ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+                               img.data, img.depth, img.bytesPerLine, img.getByteOrder(), 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+                               false, false);
+               }
+               hBitmap = Image.createDIB(source.width, source.height, 32);
+               if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               BITMAP dibBM = new BITMAP();
+               OS.GetObject(hBitmap, BITMAP.sizeof, dibBM);
+               byte[] srcData = img.data;
+               if (source.alpha != -1) {
+                       for (int i = 3; i < srcData.length; i+=4) {
+                               srcData[i] = (byte)source.alpha;
+                       }
+               } else if (source.alphaData != null) {
+                       for (int sp = 3, ap=0; sp < srcData.length; sp+=4, ap++) {
+                               srcData[sp] = source.alphaData[ap];
+                       }
+               }
+               OS.MoveMemory(dibBM.bmBits, srcData, srcData.length);
+               hMask = OS.CreateBitmap(source.width, source.height, 1, 1, new byte[(((source.width + 7) / 8) + 3) / 4 * 4 * source.height]);
+               if (hMask == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       } else {
+               ImageData mask = source.getTransparencyMask();
+               long [] result = Image.init(this.device, null, source, mask);
+               hBitmap = result[0];
+               hMask = result[1];
+       }
+       /* Create the icon */
+       ICONINFO info = new ICONINFO();
+       info.fIcon = false;
+       info.hbmColor = hBitmap;
+       info.hbmMask = hMask;
+       info.xHotspot = hotspotX;
+       info.yHotspot = hotspotY;
+       handle = OS.CreateIconIndirect(info);
+       OS.DeleteObject(hBitmap);
+       OS.DeleteObject(hMask);
+       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       isIcon = true;
+       init();
+}
+
+@Override
+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() == 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.
+               */
+               OS.DestroyCursor(handle);
+       }
+       handle = 0;
+}
+
+/**
+ * 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 boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Cursor)) return false;
+       Cursor cursor = (Cursor) object;
+       return device == cursor.device && handle == 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
+ */
+@Override
+public int hashCode () {
+       return (int)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 (except {@link #dispose()}) using the cursor.
+ *
+ * @return <code>true</code> when the cursor is disposed and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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 "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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Cursor win32_new(Device device, int handle) {
+       Cursor cursor = new Cursor(device);
+       cursor.handle = handle;
+       return cursor;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Device.java
new file mode 100644 (file)
index 0000000..79ba567
--- /dev/null
@@ -0,0 +1,915 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 implements Drawable {
+
+       /* Debugging */
+       public static boolean DEBUG;
+       boolean debug = DEBUG;
+       boolean tracking = DEBUG;
+       Error [] errors;
+       Object [] objects;
+       Object trackingLock;
+
+       /* System Font */
+       Font systemFont;
+
+       /* Font Enumeration */
+       int nFonts = 256;
+       LOGFONT [] logFonts;
+       TEXTMETRIC metrics;
+       int[] pixels;
+
+       /* Scripts */
+       long [] scripts;
+
+       /* Advanced Graphics */
+       long [] gdipToken;
+       long fontCollection;
+       String[] loadedFonts;
+
+       boolean disposed;
+
+       /* Auto-Scaling*/
+       boolean enableAutoScaling = true;
+
+       /*
+       * 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.
+       */
+       protected static Device CurrentDevice;
+       protected static Runnable DeviceFinder;
+       static {
+               try {
+                       Class.forName ("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$
+               } catch (ClassNotFoundException e) {}
+       }
+
+/*
+* TEMPORARY CODE.
+*/
+static synchronized Device getDevice () {
+       if (DeviceFinder != 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 Device() {
+       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 Device(DeviceData data) {
+       synchronized (Device.class) {
+               if (data != null) {
+                       debug = data.debug;
+                       tracking = data.tracking;
+               }
+               if (tracking) {
+                       errors = new Error [128];
+                       objects = new Object [128];
+                       trackingLock = new Object ();
+               }
+               create (data);
+               init ();
+       }
+}
+
+void addFont (String font) {
+       if (loadedFonts == null) loadedFonts = new String [4];
+       int length = loadedFonts.length;
+       for (int i=0; i<length; i++) {
+               if (font.equals(loadedFonts [i])) return;
+       }
+       int index = 0;
+       while (index < length) {
+               if (loadedFonts [index] == null) break;
+               index++;
+       }
+       if (index == length) {
+               String [] temp = new String [length + 4];
+               System.arraycopy (loadedFonts, 0, temp, 0, length);
+               loadedFonts = temp;
+       }
+       loadedFonts [index] = font;
+}
+
+/**
+ * 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 != null) return;
+       long [] token = new long [1];
+       GdiplusStartupInput input = new GdiplusStartupInput ();
+       input.GdiplusVersion = 1;
+       if (Gdip.GdiplusStartup (token, input, 0) != 0) SWT.error (SWT.ERROR_NO_HANDLES);
+       gdipToken = token;
+       if (loadedFonts != null) {
+               fontCollection = Gdip.PrivateFontCollection_new();
+               if (fontCollection == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               for (int i = 0; i < loadedFonts.length; i++) {
+                       String path = loadedFonts[i];
+                       if (path == null) break;
+                       int length = path.length();
+                       char [] buffer = new char [length + 1];
+                       path.getChars(0, length, buffer, 0);
+                       Gdip.PrivateFontCollection_AddFontFile(fontCollection, buffer);
+               }
+               loadedFonts = null;
+       }
+}
+
+/**
+ * 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) {
+       long hDC = internal_new_GC (null);
+       int pixels = -(int)(0.5f + (height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY) / 72f));
+       internal_dispose_GC (hDC, null);
+       return pixels;
+}
+
+float computePoints(LOGFONT logFont, long hFont) {
+       long 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.
+                */
+               long 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.class) {
+               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] == object) {
+                               objects [i] = null;
+                               errors [i] = null;
+                               return;
+                       }
+               }
+       }
+}
+
+long EnumFontFamProc (long lpelfe, long lpntme, long FontType, long lParam) {
+       boolean isScalable = ((int)FontType & OS.RASTER_FONTTYPE) == 0;
+       boolean scalable = lParam == 1;
+       if (isScalable == scalable) {
+               /* Add the log font to the list of log fonts */
+               if (nFonts == logFonts.length) {
+                       LOGFONT [] newLogFonts = new LOGFONT [logFonts.length + 128];
+                       System.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 == null) logFont = new LOGFONT ();
+               OS.MoveMemory (logFont, lpelfe, LOGFONT.sizeof);
+               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.
+                        */
+                       OS.MoveMemory(metrics, lpntme, TEXTMETRIC.sizeof);
+                       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 ();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+private Rectangle getBoundsInPixels () {
+       long 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] != null) count++;
+                       }
+                       int index = 0;
+                       data.objects = new Object [count];
+                       data.errors = new Error [count];
+                       for (int i=0; i<length; i++) {
+                               if (objects [i] != null) {
+                                       data.objects [index] = objects [i];
+                                       data.errors [index] = errors [i];
+                                       index++;
+                               }
+                       }
+               }
+       } else {
+               data.objects = new Object [0];
+               data.errors = new Error [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 ();
+       long 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 logical horizontal
+ * dots per inch of the display, and whose y coordinate
+ * is the logical 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 ();
+       long 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 DPIUtil.autoScaleDown(new Point (dpiX, dpiY));
+}
+
+/**
+ * Returns DPI in x direction. In the modern monitors DPI for
+ * X and Y directions is same.
+ *
+ * @return the horizontal DPI
+ */
+int _getDPIx () {
+       long hDC = internal_new_GC (null);
+       int dpi = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX);
+       internal_dispose_GC (hDC, null);
+       return dpi;
+}
+/**
+ * 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, boolean scalable) {
+       checkDevice ();
+
+       /* Create the callback */
+       Callback callback = new Callback (this, "EnumFontFamProc", 4); //$NON-NLS-1$
+       long lpEnumFontFamProc = callback.getAddress ();
+       if (lpEnumFontFamProc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+       /* Initialize the instance variables */
+       metrics = new TEXTMETRIC ();
+       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;
+       long hDC = internal_new_GC (null);
+       if (faceName == null) {
+               /* The user did not specify a face name, so they want all versions of all available face names */
+               OS.EnumFontFamilies (hDC, null, lpEnumFontFamProc, scalable ? 1 : 0);
+
+               /**
+                * 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];
+                       OS.EnumFontFamilies (hDC, lf.lfFaceName, lpEnumFontFamProc, scalable ? 1 : 0);
+               }
+       } else {
+               /* Use the character encoding for the default locale */
+               TCHAR lpFaceName = new TCHAR (0, faceName, true);
+               OS.EnumFontFamilies (hDC, lpFaceName.chars, lpEnumFontFamProc, scalable ? 1 : 0);
+       }
+       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.equals (result [j])) break;
+               }
+               if (j == count) result [count++] = fd;
+       }
+       if (count != result.length) {
+               FontData [] newResult = new FontData [count];
+               System.arraycopy (result, 0, newResult, 0, count);
+               result = newResult;
+       }
+
+       /* Clean up */
+       callback.dispose ();
+       logFonts = null;
+       pixels = null;
+       metrics = null;
+       return result;
+}
+
+String getLastError () {
+       int error = OS.GetLastError();
+       if (error == 0) return ""; //$NON-NLS-1$
+       return " [GetLastError=0x" + Integer.toHexString(error) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+String getLastErrorText () {
+       int error = OS.GetLastError();
+       if (error == 0) return ""; //$NON-NLS-1$
+       long [] buffer = new long [1];
+       int dwFlags = OS.FORMAT_MESSAGE_ALLOCATE_BUFFER | OS.FORMAT_MESSAGE_FROM_SYSTEM | OS.FORMAT_MESSAGE_IGNORE_INSERTS;
+       int length = OS.FormatMessage(dwFlags, 0, error, OS.LANG_USER_DEFAULT, buffer, 0, 0);
+       if (length == 0) return " [GetLastError=0x" + Integer.toHexString(error) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+       char [] buffer1 = new char [length];
+       OS.MoveMemory(buffer1, buffer[0], length * TCHAR.sizeof);
+       if (buffer[0] != 0) OS.LocalFree(buffer[0]);
+       return new String(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;
+       int alpha = 255;
+       switch (id) {
+               case SWT.COLOR_TRANSPARENT:                     alpha = 0;
+               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;
+       }
+       return Color.win32_new (this, pixel, alpha);
+}
+
+/**
+ * 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 ();
+       long 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 boolean 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) {
+               OS.GdiSetBatchLimit(1);
+       }
+
+       /* Initialize the system font slot */
+       systemFont = getSystemFont();
+
+       /* Initialize scripts list */
+       long [] ppSp = new long [1];
+       int [] piNumScripts = new int [1];
+       OS.ScriptGetProperties (ppSp, piNumScripts);
+       scripts = new long [piNumScripts [0]];
+       OS.MoveMemory (scripts, ppSp [0], scripts.length * C.PTR_SIZEOF);
+}
+/**
+ * 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public abstract long 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public abstract void /*long*/ internal_dispose_GC (long 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 boolean isDisposed () {
+       synchronized (Device.class) {
+               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 boolean loadFont (String path) {
+       checkDevice();
+       if (path == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       TCHAR lpszFilename = new TCHAR (0, path, true);
+       boolean loaded = OS.AddFontResourceEx (lpszFilename, OS.FR_PRIVATE, 0) != 0;
+       if (loaded) {
+               if (gdipToken != null) {
+                       if (fontCollection == 0) {
+                               fontCollection = Gdip.PrivateFontCollection_new();
+                               if (fontCollection == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       }
+                       int length = path.length();
+                       char [] buffer = new char [length + 1];
+                       path.getChars(0, length, buffer, 0);
+                       Gdip.PrivateFontCollection_AddFontFile(fontCollection, buffer);
+               } else {
+                       addFont(path);
+               }
+       }
+       return loaded;
+}
+
+void new_Object (Object object) {
+       synchronized (trackingLock) {
+               for (int i=0; i<objects.length; i++) {
+                       if (objects [i] == null) {
+                               objects [i] = object;
+                               errors [i] = new Error ();
+                               return;
+                       }
+               }
+               Object [] newObjects = new Object [objects.length + 128];
+               System.arraycopy (objects, 0, newObjects, 0, objects.length);
+               newObjects [objects.length] = object;
+               objects = newObjects;
+               Error [] newErrors = new Error [errors.length + 128];
+               System.arraycopy (errors, 0, newErrors, 0, errors.length);
+               newErrors [errors.length] = new Error ();
+               errors = newErrors;
+       }
+}
+
+void printErrors () {
+       if (!DEBUG) return;
+       if (tracking) {
+               synchronized (trackingLock) {
+                       if (objects == null || errors == 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 != null) {
+                                       objectCount++;
+                                       if (object instanceof Color) colors++;
+                                       if (object instanceof Cursor) cursors++;
+                                       if (object instanceof Font) fonts++;
+                                       if (object instanceof GC) gcs++;
+                                       if (object instanceof Image) images++;
+                                       if (object instanceof Path) paths++;
+                                       if (object instanceof Pattern) patterns++;
+                                       if (object instanceof Region) regions++;
+                                       if (object instanceof TextLayout) textLayouts++;
+                                       if (object instanceof Transform) transforms++;
+                               }
+                       }
+                       if (objectCount != 0) {
+                               String string = "Summary: ";
+                               if (colors != 0) string += colors + " Color(s), ";
+                               if (cursors != 0) string += cursors + " Cursor(s), ";
+                               if (fonts != 0) string += fonts + " Font(s), ";
+                               if (gcs != 0) string += gcs + " GC(s), ";
+                               if (images != 0) string += images + " Image(s), ";
+                               if (paths != 0) string += paths + " Path(s), ";
+                               if (patterns != 0) string += patterns + " Pattern(s), ";
+                               if (regions != 0) string += regions + " Region(s), ";
+                               if (textLayouts != 0) string += textLayouts + " TextLayout(s), ";
+                               if (transforms != 0) string += transforms + " Transforms(s), ";
+                               if (string.length () != 0) {
+                                       string = string.substring (0, string.length () - 2);
+                                       System.err.println (string);
+                               }
+                               for (int i=0; i<errors.length; i++) {
+                                       if (errors [i] != null) errors [i].printStackTrace (System.err);
+                               }
+                       }
+               }
+       }
+}
+
+/**
+ * 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>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #destroy
+ */
+protected void release () {
+       if (gdipToken != null) {
+               if (fontCollection != 0) {
+                       Gdip.PrivateFontCollection_delete(fontCollection);
+               }
+               fontCollection = 0;
+               Gdip.GdiplusShutdown (gdipToken[0]);
+       }
+       gdipToken = null;
+       scripts = 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 (boolean warnings) {
+       checkDevice ();
+}
+
+boolean getEnableAutoScaling() {
+       return enableAutoScaling;
+}
+
+void setEnableAutoScaling(boolean value) {
+       enableAutoScaling = value;
+}
+
+/**
+ * Gets the scaling factor from the device and calculates the zoom level.
+ * @return zoom in percentage
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @since 3.105
+ */
+protected int getDeviceZoom () {
+       return DPIUtil.mapDPIToZoom ( _getDPIx ());
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/DeviceData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/DeviceData.java
new file mode 100644 (file)
index 0000000..003a63c
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+public class DeviceData {
+       /*
+       * Debug fields - may not be honoured
+       * on some SWT platforms.
+       */
+       public boolean debug;
+       public boolean tracking;
+       public Error [] errors;
+       public Object [] objects;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Drawable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Drawable.java
new file mode 100644 (file)
index 0000000..f46baba
--- /dev/null
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+/**
+ * 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 interface 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+
+long  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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+void internal_dispose_GC (long  handle, GCData data);
+
+/**
+ * Returns <code>true</code> iff coordinates can be auto-scaled on this
+ * drawable and <code>false</code> if not. E.g. a {@link GC} method should not
+ * auto-scale the bounds of a figure drawn on a Printer device, but it may have
+ * to auto-scale when drawing on a high-DPI Display monitor.
+ *
+ * @return <code>true</code> if auto-scaling is enabled for this drawable
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+default boolean isAutoScalable () {
+       return true;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Font.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Font.java
new file mode 100644 (file)
index 0000000..1223d16
--- /dev/null
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Font(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>
+ *
+ * @see #dispose()
+ */
+public Font(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>
+ *
+ * @see #dispose()
+ *
+ * @since 2.1
+ */
+public Font(Device device, FontData[] fds) {
+       super(device);
+       if (fds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (fds.length == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       for (int i=0; i<fds.length; i++) {
+               if (fds[i] == 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>
+ *
+ * @see #dispose()
+ */
+public Font(Device device, String name, int height, int style) {
+       super(device);
+       if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       init(new FontData (name, height, style));
+       init();
+}
+
+/*public*/ Font(Device device, String name, float height, int style) {
+       super(device);
+       if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       init(new FontData (name, height, style));
+       init();
+}
+@Override
+void destroy() {
+       OS.DeleteObject(handle);
+       handle = 0;
+}
+
+/**
+ * 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 boolean equals(Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Font)) return false;
+       Font font = (Font) object;
+       return device == font.device && handle == font.handle;
+}
+
+/**
+ * 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 = new LOGFONT ();
+       OS.GetObject(handle, LOGFONT.sizeof, logFont);
+       return new 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 int hashCode () {
+       return (int)handle;
+}
+
+void init (FontData fd) {
+       if (fd == 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 == 0) 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 (except {@link #dispose()}) using the font.
+ *
+ * @return <code>true</code> when the font is disposed and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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 "Font {" + handle + "}";
+}
+
+/**
+ * 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Font win32_new(Device device, long handle) {
+       Font font = new Font(device);
+       font.handle = handle;
+       return font;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/FontData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/FontData.java
new file mode 100644 (file)
index 0000000..f1b8c52
--- /dev/null
@@ -0,0 +1,661 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.*;
+
+/**
+ * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public float height;
+
+       /**
+        * The locales of the font
+        */
+       String lang, country, variant;
+
+/**
+ * Constructs a new uninitialized font data.
+ */
+public FontData() {
+       data = new LOGFONT ();
+       // We set the charset field so that
+       // wildcard searching will work properly
+       // out of the box
+       data.lfCharSet = (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
+ */
+FontData(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 FontData(String string) {
+       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       int start = 0;
+       int end = string.indexOf('|');
+       if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       String version1 = string.substring(start, end);
+       try {
+               if (Integer.parseInt(version1) != 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 == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       String name = string.substring(start, end);
+
+       start = end + 1;
+       end = string.indexOf('|', start);
+       if (end == -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 == -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 = new LOGFONT ();
+       data.lfCharSet = (byte)OS.DEFAULT_CHARSET;
+       setName(name);
+       setHeight(height);
+       setStyle(style);
+       if (end == -1) return;
+       String platform = string.substring(start, end);
+
+       start = end + 1;
+       end = string.indexOf('|', start);
+       if (end == -1) return;
+       String version2 = string.substring(start, end);
+
+       if (platform.equals("WINDOWS") && version2.equals("1")) {  //$NON-NLS-1$//$NON-NLS-2$
+               LOGFONT newData = new LOGFONT ();
+               try {
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfHeight = Integer.parseInt(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfWidth = Integer.parseInt(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfEscapement = Integer.parseInt(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfOrientation = Integer.parseInt(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfWeight = Integer.parseInt(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfItalic = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfUnderline = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfStrikeOut = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfCharSet = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfOutPrecision = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfClipPrecision = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfQuality = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+                       end = string.indexOf('|', start);
+                       if (end == -1) return;
+                       newData.lfPitchAndFamily = Byte.parseByte(string.substring(start, end));
+                       start = end + 1;
+               } catch (NumberFormatException e) {
+                       setName(name);
+                       setHeight(height);
+                       setStyle(style);
+                       return;
+               }
+               int length = Math.min(newData.lfFaceName.length - 1, string.length() - start);
+               string.getChars(start, start + length, newData.lfFaceName, 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 FontData(String name, int height, int style) {
+       if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       data = new LOGFONT ();
+       setName(name);
+       setHeight(height);
+       setStyle(style);
+       // We set the charset field so that
+       // wildcard searching will work properly
+       // out of the box
+       data.lfCharSet = (byte)OS.DEFAULT_CHARSET;
+}
+
+/*public*/ FontData(String name, float height, int style) {
+       if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       data = new LOGFONT ();
+       setName(name);
+       setHeight(height);
+       setStyle(style);
+       // We set the charset field so that
+       // wildcard searching will work properly
+       // out of the box
+       data.lfCharSet = (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 boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof FontData)) return false;
+       FontData fd = (FontData)object;
+       LOGFONT lf = fd.data;
+       return data.lfCharSet == 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 == lf.lfHeight &&
+               height == fd.height &&
+               data.lfWidth == lf.lfWidth &&
+               data.lfEscapement == lf.lfEscapement &&
+               data.lfOrientation == lf.lfOrientation &&
+               data.lfWeight == lf.lfWeight &&
+               data.lfItalic == lf.lfItalic &&
+               data.lfUnderline == lf.lfUnderline &&
+               data.lfStrikeOut == lf.lfStrikeOut &&
+               data.lfCharSet == lf.lfCharSet &&
+               data.lfOutPrecision == lf.lfOutPrecision &&
+               data.lfClipPrecision == lf.lfClipPrecision &&
+               data.lfQuality == lf.lfQuality &&
+               data.lfPitchAndFamily == lf.lfPitchAndFamily &&
+               getName().equals(fd.getName());
+}
+
+long EnumLocalesProc(long lpLocaleString) {
+
+       /* Get the locale ID */
+       int length = 8;
+       TCHAR buffer = new TCHAR(0, length);
+       int byteCount = length * TCHAR.sizeof;
+       OS.MoveMemory(buffer, lpLocaleString, byteCount);
+       int lcid = Integer.parseInt(buffer.toString(0, buffer.strlen ()), 16);
+
+       /* Check the language */
+       int size = OS.GetLocaleInfo(lcid, OS.LOCALE_SISO639LANGNAME, buffer, length);
+       if (size <= 0 || !lang.equals(buffer.toString(0, size - 1))) return 1;
+
+       /* Check the country */
+       if (country != null) {
+               size = OS.GetLocaleInfo(lcid, OS.LOCALE_SISO3166CTRYNAME, buffer, length);
+               if (size <= 0 || !country.equals(buffer.toString(0, size - 1))) return 1;
+       }
+
+       /* Get the charset */
+       size = OS.GetLocaleInfo(lcid, OS.LOCALE_IDEFAULTANSICODEPAGE, buffer, length);
+       if (size <= 0) return 1;
+       int cp = Integer.parseInt(buffer.toString(0, size - 1));
+       int [] lpCs = new int[8];
+       OS.TranslateCharsetInfo(cp, lpCs, OS.TCI_SRCCODEPAGE);
+       data.lfCharSet = (byte)lpCs[0];
+
+       return 0;
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight(int)
+ */
+public int getHeight() {
+       return (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 () {
+       StringBuilder buffer = new StringBuilder ();
+       char sep = '_';
+       if (lang != null) {
+               buffer.append (lang);
+               buffer.append (sep);
+       }
+       if (country != null) {
+               buffer.append (country);
+               buffer.append (sep);
+       }
+       if (variant != null) {
+               buffer.append (variant);
+       }
+
+       String result = buffer.toString ();
+       int length = result.length ();
+       if (length > 0) {
+               if (result.charAt (length - 1) == 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() {
+       char[] chars = data.lfFaceName;
+       int index = 0;
+       while (index < chars.length) {
+               if (chars [index] == 0) break;
+               index++;
+       }
+       return new String (chars, 0, index);
+}
+
+/**
+ * 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 == 700) style |= SWT.BOLD;
+       if (data.lfItalic != 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 int hashCode () {
+       return data.lfCharSet ^ getHeight() << 8 ^ data.lfWidth ^ data.lfEscapement ^
+               data.lfOrientation ^ data.lfWeight ^ data.lfItalic ^ data.lfUnderline ^
+               data.lfStrikeOut ^ data.lfCharSet ^ data.lfOutPrecision ^
+               data.lfClipPrecision ^ data.lfQuality ^ data.lfPitchAndFamily ^
+               getName().hashCode();
+}
+
+/**
+ * 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;
+       data.lfWidth = 0;
+}
+
+/*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 != null) {
+               char sep = '_';
+               int length = locale.length();
+               int firstSep, secondSep;
+
+               firstSep = locale.indexOf(sep);
+               if (firstSep == -1) {
+                       firstSep = secondSep = length;
+               } else {
+                       secondSep = locale.indexOf(sep, firstSep + 1);
+                       if (secondSep == -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 == null) {
+               data.lfCharSet = (byte)OS.DEFAULT_CHARSET;
+       } else {
+               Callback callback = new Callback (this, "EnumLocalesProc", 1); //$NON-NLS-1$
+               long lpEnumLocalesProc = callback.getAddress ();
+               if (lpEnumLocalesProc == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+               OS.EnumSystemLocales(lpEnumLocalesProc, OS.LCID_SUPPORTED);
+               callback.dispose ();
+       }
+}
+
+/**
+ * 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:</p>
+ * <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>
+ * <p>
+ * 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+       /* The field lfFaceName must be NULL terminated */
+       char[] lfFaceName = data.lfFaceName;
+       int length = Math.min(lfFaceName.length - 1, name.length());
+       name.getChars (0, length, lfFaceName, 0);
+       for (int i = length; i < lfFaceName.length; i++) lfFaceName[i] = 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) == SWT.BOLD) {
+               data.lfWeight = 700;
+       } else {
+               data.lfWeight = 0;
+       }
+       if ((style & SWT.ITALIC) == 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() {
+       StringBuilder buffer = new StringBuilder(128);
+       buffer.append("1|"); //$NON-NLS-1$
+       String name = getName();
+       buffer.append(name);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(getHeightF());
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(getStyle());
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append("WINDOWS|1|"); //$NON-NLS-1$
+       buffer.append(data.lfHeight);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfWidth);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfEscapement);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfOrientation);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfWeight);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfItalic);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfUnderline);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfStrikeOut);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfCharSet);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfOutPrecision);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfClipPrecision);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfQuality);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(data.lfPitchAndFamily);
+       buffer.append("|"); //$NON-NLS-1$
+       buffer.append(name);
+       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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static FontData win32_new(LOGFONT data, float height) {
+       return new FontData(data, height);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/FontMetrics.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/FontMetrics.java
new file mode 100644 (file)
index 0000000..5bca68c
--- /dev/null
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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
+        * (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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public TEXTMETRIC handle;
+
+/**
+ * Prevents instances from being created outside the package.
+ */
+FontMetrics() {
+}
+
+/**
+ * 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 boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof FontMetrics)) return false;
+       TEXTMETRIC metric = ((FontMetrics)object).handle;
+       return handle.tmHeight == metric.tmHeight &&
+               handle.tmAscent == metric.tmAscent &&
+               handle.tmDescent == metric.tmDescent &&
+               handle.tmInternalLeading == metric.tmInternalLeading &&
+               handle.tmExternalLeading == metric.tmExternalLeading &&
+               handle.tmAveCharWidth == metric.tmAveCharWidth &&
+               handle.tmMaxCharWidth == metric.tmMaxCharWidth &&
+               handle.tmWeight == metric.tmWeight &&
+               handle.tmOverhang == metric.tmOverhang &&
+               handle.tmDigitizedAspectX == metric.tmDigitizedAspectX &&
+               handle.tmDigitizedAspectY == metric.tmDigitizedAspectY &&
+//             handle.tmFirstChar == metric.tmFirstChar &&
+//             handle.tmLastChar == metric.tmLastChar &&
+//             handle.tmDefaultChar == metric.tmDefaultChar &&
+//             handle.tmBreakChar == metric.tmBreakChar &&
+               handle.tmItalic == metric.tmItalic &&
+               handle.tmUnderlined == metric.tmUnderlined &&
+               handle.tmStruckOut == metric.tmStruckOut &&
+               handle.tmPitchAndFamily == metric.tmPitchAndFamily &&
+               handle.tmCharSet == metric.tmCharSet;
+}
+
+/**
+ * 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 points.
+ *
+ * @return the ascent of the font
+ */
+public int getAscent() {
+       return DPIUtil.autoScaleDown(handle.tmAscent - handle.tmInternalLeading);
+}
+
+/**
+ * Returns the average character width, measured in points,
+ * of the font described by the receiver.
+ *
+ * @return the average character width of the font
+ * @since 3.107
+ */
+public double getAverageCharacterWidth() {
+       return getAverageCharWidth();
+}
+
+/**
+ * Returns the average character width, measured in points,
+ * of the font described by the receiver.
+ *
+ * @return the average character width of the font
+ * @deprecated Use getAverageCharacterWidth() instead
+ */
+public int getAverageCharWidth() {
+       return DPIUtil.autoScaleDown(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 points.
+ *
+ * @return the descent of the font
+ */
+public int getDescent() {
+       return DPIUtil.autoScaleDown(handle.tmDescent);
+}
+
+/**
+ * Returns the height of the font described by the receiver,
+ * measured in points. 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 DPIUtil.autoScaleDown(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() {
+       /*
+        * HiHPI rounding problem (bug 490743 comment 17):
+        *
+        * API clients expect this invariant:
+        *    getHeight() == getLeading() + getAscent() + getDescent()
+        *
+        * Separate rounding of each RHS term can break the invariant.
+        *
+        * An additional problem is that ascent and descent are more important to
+        * be as close as possible to the real value. Any necessary rounding
+        * adjustment should go into leading, that's why compute this as a derived
+        * value here:
+        */
+       return getHeight() - getAscent() - getDescent();
+}
+
+/**
+ * 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 int hashCode() {
+       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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static FontMetrics win32_new(TEXTMETRIC handle) {
+       FontMetrics fontMetrics = new FontMetrics();
+       fontMetrics.handle = handle;
+       return fontMetrics;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GC.java
new file mode 100644 (file)
index 0000000..2db1ba8
--- /dev/null
@@ -0,0 +1,5053 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * The result of drawing on an image that was created with an indexed
+ * palette using a color that is not in the palette is platform specific.
+ * Some platforms will match to the nearest color while other will draw
+ * the color itself. This happens because the allocated image might use
+ * a direct palette on platforms that do not support indexed palette.
+ * </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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+       Drawable drawable;
+       GCData data;
+
+       static final int FOREGROUND = 1 << 0;
+       static final int BACKGROUND = 1 << 1;
+       static final int FONT = 1 << 2;
+       static final int LINE_STYLE = 1 << 3;
+       static final int LINE_WIDTH = 1 << 4;
+       static final int LINE_CAP = 1 << 5;
+       static final int LINE_JOIN = 1 << 6;
+       static final int LINE_MITERLIMIT = 1 << 7;
+       static final int FOREGROUND_TEXT = 1 << 8;
+       static final int BACKGROUND_TEXT = 1 << 9;
+       static final int BRUSH = 1 << 10;
+       static final int PEN = 1 << 11;
+       static final int NULL_BRUSH = 1 << 12;
+       static final int NULL_PEN = 1 << 13;
+       static final int DRAW_OFFSET = 1 << 14;
+
+       static final int DRAW = FOREGROUND | LINE_STYLE | LINE_WIDTH | LINE_CAP | LINE_JOIN | LINE_MITERLIMIT | PEN | NULL_BRUSH | DRAW_OFFSET;
+       static final int FILL = BACKGROUND | BRUSH | NULL_PEN;
+
+       static final float[] LINE_DOT_ZERO = new float[]{3, 3};
+       static final float[] LINE_DASH_ZERO = new float[]{18, 6};
+       static final float[] LINE_DASHDOT_ZERO = new float[]{9, 6, 3, 6};
+       static final float[] LINE_DASHDOTDOT_ZERO = new float[]{9, 3, 3, 3, 3, 3};
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+GC() {
+}
+
+/**
+ * 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>
+ * @see #dispose()
+ */
+public GC(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>
+ *
+ * @see #dispose()
+ *
+ * @since 2.1.2
+ */
+public GC(Drawable drawable, int style) {
+       if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       GCData data = new GCData ();
+       data.style = checkStyle(style);
+       long hDC = drawable.internal_new_GC(data);
+       Device device = data.device;
+       if (device == null) device = Device.getDevice();
+       if (device == 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) != 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) == mask) return;
+       state = (state ^ mask) & mask;
+       data.state |= mask;
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               long pen = data.gdipPen;
+               float width = data.lineWidth;
+               if ((state & FOREGROUND) != 0 || (pen == 0 && (state & (LINE_WIDTH | LINE_STYLE | LINE_MITERLIMIT | LINE_JOIN | LINE_CAP)) != 0)) {
+                       if (data.gdipFgBrush != 0) Gdip.SolidBrush_delete(data.gdipFgBrush);
+                       data.gdipFgBrush = 0;
+                       long brush;
+                       Pattern pattern = data.foregroundPattern;
+                       if (pattern != null) {
+                               brush = pattern.handle;
+                               if ((data.style & SWT.MIRRORED) != 0) {
+                                       switch (Gdip.Brush_GetType(brush)) {
+                                               case Gdip.BrushTypeTextureFill:
+                                                       brush = Gdip.Brush_Clone(brush);
+                                                       if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                                                       Gdip.TextureBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                                                       data.gdipFgBrush = brush;
+                                       }
+                               }
+                       } else {
+                               int foreground = data.foreground;
+                               int color = (data.alpha << 24) | ((foreground >> 16) & 0xFF) | (foreground & 0xFF00) | ((foreground & 0xFF) << 16);
+                               brush = Gdip.SolidBrush_new(color);
+                               if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               data.gdipFgBrush = brush;
+                       }
+                       if (pen != 0) {
+                               Gdip.Pen_SetBrush(pen, brush);
+                       } else {
+                               pen = data.gdipPen = Gdip.Pen_new(brush, width);
+                       }
+               }
+               if ((state & LINE_WIDTH) != 0) {
+                       Gdip.Pen_SetWidth(pen, width);
+                       switch (data.lineStyle) {
+                               case SWT.LINE_CUSTOM:
+                                       state |= LINE_STYLE;
+                       }
+               }
+               if ((state & LINE_STYLE) != 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 == 0) dashes = LINE_DOT_ZERO; break;
+                               case SWT.LINE_DASH: dashStyle = Gdip.DashStyleDash; if (width == 0) dashes = LINE_DASH_ZERO; break;
+                               case SWT.LINE_DASHDOT: dashStyle = Gdip.DashStyleDashDot; if (width == 0) dashes = LINE_DASHDOT_ZERO; break;
+                               case SWT.LINE_DASHDOTDOT: dashStyle = Gdip.DashStyleDashDotDot; if (width == 0) dashes = LINE_DASHDOTDOT_ZERO; break;
+                               case SWT.LINE_CUSTOM: {
+                                       if (data.lineDashes != 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;
+                                               }
+                                       }
+                               }
+                       }
+                       if (dashes != null) {
+                               Gdip.Pen_SetDashPattern(pen, dashes, dashes.length);
+                               Gdip.Pen_SetDashStyle(pen, Gdip.DashStyleCustom);
+                               Gdip.Pen_SetDashOffset(pen, dashOffset);
+                       } else {
+                               Gdip.Pen_SetDashStyle(pen, dashStyle);
+                       }
+               }
+               if ((state & LINE_MITERLIMIT) != 0) {
+                       Gdip.Pen_SetMiterLimit(pen, data.lineMiterLimit);
+               }
+               if ((state & LINE_JOIN) != 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;
+                       }
+                       Gdip.Pen_SetLineJoin(pen, joinStyle);
+               }
+               if ((state & LINE_CAP) != 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;
+                       }
+                       Gdip.Pen_SetLineCap(pen, capStyle, capStyle, dashCap);
+               }
+               if ((state & BACKGROUND) != 0) {
+                       if (data.gdipBgBrush != 0) Gdip.SolidBrush_delete(data.gdipBgBrush);
+                       data.gdipBgBrush = 0;
+                       Pattern pattern = data.backgroundPattern;
+                       if (pattern != null) {
+                               data.gdipBrush = pattern.handle;
+                               if ((data.style & SWT.MIRRORED) != 0) {
+                                       switch (Gdip.Brush_GetType(data.gdipBrush)) {
+                                               case Gdip.BrushTypeTextureFill:
+                                                       long brush = Gdip.Brush_Clone(data.gdipBrush);
+                                                       if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                                                       Gdip.TextureBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                                                       data.gdipBrush = data.gdipBgBrush = brush;
+                                       }
+                               }
+                       } else {
+                               int background = data.background;
+                               int color = (data.alpha << 24) | ((background >> 16) & 0xFF) | (background & 0xFF00) | ((background & 0xFF) << 16);
+                               long brush = Gdip.SolidBrush_new(color);
+                               if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               data.gdipBrush = data.gdipBgBrush = brush;
+                       }
+               }
+               if ((state & FONT) != 0) {
+                       Font font = data.font;
+                       OS.SelectObject(handle, font.handle);
+                       long[] hFont = new long[1];
+                       long gdipFont = createGdipFont(handle, font.handle, gdipGraphics, device.fontCollection, null, hFont);
+                       if (hFont[0] != 0) OS.SelectObject(handle, hFont[0]);
+                       if (data.hGDIFont != 0) OS.DeleteObject(data.hGDIFont);
+                       data.hGDIFont = hFont[0];
+                       if (data.gdipFont != 0) Gdip.Font_delete(data.gdipFont);
+                       data.gdipFont = gdipFont;
+               }
+               if ((state & DRAW_OFFSET) != 0) {
+                       data.gdipXOffset = data.gdipYOffset = 0;
+                       long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+                       PointF point = new PointF();
+                       point.X = point.Y = 1;
+                       Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+                       Gdip.Matrix_TransformVectors(matrix, point, 1);
+                       Gdip.Matrix_delete(matrix);
+                       float scaling = point.X;
+                       if (scaling < 0) scaling = -scaling;
+                       float penWidth = data.lineWidth * scaling;
+                       if (penWidth == 0 || ((int)penWidth % 2) == 1) {
+                               data.gdipXOffset = 0.5f / scaling;
+                       }
+                       scaling = point.Y;
+                       if (scaling < 0) scaling = -scaling;
+                       penWidth = data.lineWidth * scaling;
+                       if (penWidth == 0 || ((int)penWidth % 2) == 1) {
+                               data.gdipYOffset = 0.5f / scaling;
+                       }
+               }
+               return;
+       }
+       if ((state & (FOREGROUND | LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) != 0) {
+               int color = data.foreground;
+               int width = (int)data.lineWidth;
+               int[] 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 != null) {
+                                       lineStyle = OS.PS_USERSTYLE;
+                                       dashes = new int[data.lineDashes.length];
+                                       for (int i = 0; i < dashes.length; i++) {
+                                               dashes[i] = (int)data.lineDashes[i];
+                                       }
+                               }
+                               break;
+                       }
+               }
+               if ((state & LINE_STYLE) != 0) {
+                       OS.SetBkMode(handle, data.lineStyle == 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;
+               }
+               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;
+               }
+               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.
+               */
+               long newPen;
+               if ((width == 0 && lineStyle != OS.PS_USERSTYLE) || style == 0) {
+                       newPen = OS.CreatePen(style & OS.PS_STYLE_MASK, width, color);
+               } else {
+                       LOGBRUSH logBrush = new 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 != null ? dashes.length : 0, dashes);
+               }
+               OS.SelectObject(handle, newPen);
+               data.state |= PEN;
+               data.state &= ~NULL_PEN;
+               if (data.hPen != 0) OS.DeleteObject(data.hPen);
+               data.hPen = data.hOldPen = newPen;
+       } else if ((state & PEN) != 0) {
+               OS.SelectObject(handle, data.hOldPen);
+               data.state &= ~NULL_PEN;
+       } else if ((state & NULL_PEN) != 0) {
+               data.hOldPen = OS.SelectObject(handle, OS.GetStockObject(OS.NULL_PEN));
+               data.state &= ~PEN;
+       }
+       if ((state & BACKGROUND) != 0) {
+               long newBrush = OS.CreateSolidBrush(data.background);
+               OS.SelectObject(handle, newBrush);
+               data.state |= BRUSH;
+               data.state &= ~NULL_BRUSH;
+               if (data.hBrush != 0) OS.DeleteObject(data.hBrush);
+               data.hOldBrush = data.hBrush = newBrush;
+       } else if ((state & BRUSH) != 0) {
+               OS.SelectObject(handle, data.hOldBrush);
+               data.state &= ~NULL_BRUSH;
+       } else if ((state & NULL_BRUSH) != 0) {
+               data.hOldBrush = OS.SelectObject(handle, OS.GetStockObject(OS.NULL_BRUSH));
+               data.state &= ~BRUSH;
+       }
+       if ((state & BACKGROUND_TEXT) != 0) {
+               OS.SetBkColor(handle, data.background);
+       }
+       if ((state & FOREGROUND_TEXT) != 0) {
+               OS.SetTextColor(handle, data.foreground);
+       }
+       if ((state & FONT) != 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) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       copyAreaInPixels(image, x, y);
+}
+
+void copyAreaInPixels(Image image, int x, int y) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       /* Copy the bitmap area */
+       Rectangle rect = image.getBoundsInPixels();
+       long memHdc = OS.CreateCompatibleDC(handle);
+       long 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, boolean paint) {
+       srcX = DPIUtil.autoScaleUp(drawable, srcX);
+       srcY = DPIUtil.autoScaleUp(drawable, srcY);
+       width = DPIUtil.autoScaleUp(drawable, width);
+       height = DPIUtil.autoScaleUp(drawable, height);
+       destX = DPIUtil.autoScaleUp(drawable, destX);
+       destY = DPIUtil.autoScaleUp(drawable, destY);
+       copyAreaInPixels(srcX, srcY, width, height, destX, destY, paint);
+}
+
+void copyAreaInPixels(int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       long hwnd = data.hwnd;
+       if (hwnd == 0) {
+               OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+       } else {
+               RECT lprcClip = null;
+               long hrgn = OS.CreateRectRgn(0, 0, 0, 0);
+               if (OS.GetClipRgn(handle, hrgn) == 1) {
+                       lprcClip = new RECT();
+                       OS.GetRgnBox(hrgn, lprcClip);
+               }
+               OS.DeleteObject(hrgn);
+               RECT lprcScroll = new RECT();
+               OS.SetRect(lprcScroll, srcX, srcY, srcX + width, srcY + height);
+               int flags = paint ? OS.SW_INVALIDATE | OS.SW_ERASE : 0;
+               OS.ScrollWindowEx(hwnd, destX - srcX, destY - srcY, lprcScroll, lprcClip, 0, null, flags);
+       }
+}
+static long createGdipFont(long hDC, long hFont, long graphics, long fontCollection, long [] outFamily, long[] outFont) {
+       long font = Gdip.Font_new(hDC, hFont);
+       if (font == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       long family = 0;
+       if (!Gdip.Font_IsAvailable(font)) {
+               Gdip.Font_delete(font);
+               LOGFONT logFont = new LOGFONT ();
+               OS.GetObject(hFont, LOGFONT.sizeof, logFont);
+               int size = Math.abs(logFont.lfHeight);
+               int style = Gdip.FontStyleRegular;
+               if (logFont.lfWeight == 700) style |= Gdip.FontStyleBold;
+               if (logFont.lfItalic != 0) style |= Gdip.FontStyleItalic;
+               char[] chars = logFont.lfFaceName;
+               int index = 0;
+               while (index < chars.length) {
+                       if (chars [index] == 0) break;
+                       index++;
+               }
+               String name = new String (chars, 0, index);
+               if (name.equalsIgnoreCase("Courier")) { //$NON-NLS-1$
+                       name = "Courier New"; //$NON-NLS-1$
+               }
+               char[] buffer = new char[name.length() + 1];
+               name.getChars(0, name.length(), buffer, 0);
+               if (fontCollection != 0) {
+                       family = Gdip.FontFamily_new(buffer, fontCollection);
+                       if (!Gdip.FontFamily_IsAvailable(family)) {
+                               Gdip.FontFamily_delete(family);
+                               family = Gdip.FontFamily_new(buffer, 0);
+                               if (!Gdip.FontFamily_IsAvailable(family)) {
+                                       Gdip.FontFamily_delete(family);
+                                       family = 0;
+                               }
+                       }
+               }
+               if (family != 0) {
+                       font = Gdip.Font_new(family, size, style, Gdip.UnitPixel);
+               } else {
+                       font = Gdip.Font_new(buffer, size, style, Gdip.UnitPixel, 0);
+               }
+               if (outFont != null && font != 0) {
+                       long hHeap = OS.GetProcessHeap();
+                       long pLogFont = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, LOGFONT.sizeof);
+                       Gdip.Font_GetLogFontW(font, graphics, pLogFont);
+                       outFont[0] = OS.CreateFontIndirect(pLogFont);
+                       OS.HeapFree(hHeap, 0, pLogFont);
+               }
+       }
+       if (outFamily != null && font != 0) {
+               if (family == 0) {
+                       family = Gdip.FontFamily_new();
+                       Gdip.Font_GetFamily(font, family);
+               }
+               outFamily [0] = family;
+       } else {
+               if (family != 0) Gdip.FontFamily_delete(family);
+       }
+       if (font == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       return font;
+}
+
+static void destroyGdipBrush(long brush) {
+       int type = Gdip.Brush_GetType(brush);
+       switch (type) {
+               case Gdip.BrushTypeSolidColor:
+                       Gdip.SolidBrush_delete(brush);
+                       break;
+               case Gdip.BrushTypeHatchFill:
+                       Gdip.HatchBrush_delete(brush);
+                       break;
+               case Gdip.BrushTypeLinearGradient:
+                       Gdip.LinearGradientBrush_delete(brush);
+                       break;
+               case Gdip.BrushTypeTextureFill:
+                       Gdip.TextureBrush_delete(brush);
+                       break;
+       }
+}
+
+/**
+ * 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>
+ */
+@Override
+void destroy() {
+       boolean gdip = data.gdipGraphics != 0;
+       disposeGdip();
+       if (gdip && (data.style & SWT.MIRRORED) != 0) {
+               OS.SetLayout(handle, OS.GetLayout(handle) | OS.LAYOUT_RTL);
+       }
+
+       /* Select stock pen and brush objects and free resources */
+       if (data.hPen != 0) {
+               OS.SelectObject(handle, OS.GetStockObject(OS.NULL_PEN));
+               OS.DeleteObject(data.hPen);
+               data.hPen = 0;
+       }
+       if (data.hBrush != 0) {
+               OS.SelectObject(handle, OS.GetStockObject(OS.NULL_BRUSH));
+               OS.DeleteObject(data.hBrush);
+               data.hBrush = 0;
+       }
+
+       /*
+       * 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.
+       */
+       long hNullBitmap = data.hNullBitmap;
+       if (hNullBitmap != 0) {
+               OS.SelectObject(handle, hNullBitmap);
+               data.hNullBitmap = 0;
+       }
+       Image image = data.image;
+       if (image != null) image.memGC = null;
+
+       /*
+       * Dispose the HDC.
+       */
+       if (drawable != null) drawable.internal_dispose_GC(handle, data);
+       drawable = null;
+       handle = 0;
+       data.image = null;
+       data.ps = null;
+       data = null;
+}
+
+void disposeGdip() {
+       if (data.gdipPen != 0) Gdip.Pen_delete(data.gdipPen);
+       if (data.gdipBgBrush != 0) destroyGdipBrush(data.gdipBgBrush);
+       if (data.gdipFgBrush != 0) destroyGdipBrush(data.gdipFgBrush);
+       if (data.gdipFont != 0) Gdip.Font_delete(data.gdipFont);
+       if (data.hGDIFont != 0) OS.DeleteObject(data.hGDIFont);
+       if (data.gdipGraphics != 0) Gdip.Graphics_delete(data.gdipGraphics);
+       data.gdipGraphics = data.gdipBrush = data.gdipBgBrush = data.gdipFgBrush =
+               data.gdipFont = data.gdipPen = data.hGDIFont = 0;
+}
+
+/**
+ * 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> points wide
+ * by <code>height + 1</code> points 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) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       width = DPIUtil.autoScaleUp(drawable, width);
+       height = DPIUtil.autoScaleUp(drawable, height);
+       drawArcInPixels(x, y, width, height, startAngle, arcAngle);
+}
+
+void drawArcInPixels (int x, int y, int width, int height, int startAngle, int arcAngle) {
+       if (handle == 0) 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 == 0 || height == 0 || arcAngle == 0) return;
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+               if (width == height) {
+                       Gdip.Graphics_DrawArc(gdipGraphics, data.gdipPen, x, y, width, height, -startAngle, -arcAngle);
+               } else {
+                       long path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+                       if (path == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       long matrix = Gdip.Matrix_new(width, 0, 0, height, x, y);
+                       if (matrix == 0) 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) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 0) x--;
+       }
+       int x1, y1, x2, y2,tmp;
+       boolean 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 = cos(startAngle, width) + x + width/2;
+               y1 = -1 * sin(startAngle, height) + y + height/2;
+
+               x2 = cos(arcAngle, width) + x + width/2;
+               y2 = -1 * 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       drawFocusInPixels(x, y, width, height);
+}
+
+void drawFocusInPixels (int x, int y, int width, int height) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if ((data.uiState & OS.UISF_HIDEFOCUS) != 0) return;
+       data.focusDrawn = true;
+       long hdc = handle;
+       int state = 0;
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               long clipRgn = 0;
+               Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+               long rgn = Gdip.Region_new();
+               if (rgn == 0) 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[] lpXform = null;
+               long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+               if (matrix == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+               if (!Gdip.Matrix_IsIdentity(matrix)) {
+                       lpXform = new float[6];
+                       Gdip.Matrix_GetElements(matrix, lpXform);
+               }
+               Gdip.Matrix_delete(matrix);
+               hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+               state = OS.SaveDC(hdc);
+               if (lpXform != null) {
+                       OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
+                       OS.SetWorldTransform(hdc, lpXform);
+               }
+               if (clipRgn != 0) {
+                       OS.SelectClipRgn(hdc, clipRgn);
+                       OS.DeleteObject(clipRgn);
+               }
+       }
+       OS.SetBkColor(hdc, 0xFFFFFF);
+       OS.SetTextColor(hdc, 0x000000);
+       RECT rect = new RECT();
+       OS.SetRect(rect, x, y, x + width, y + height);
+       OS.DrawFocusRect(hdc, rect);
+       if (gdipGraphics != 0) {
+               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></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 x, int y) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       drawImageInPixels(image, x, y);
+}
+
+void drawImageInPixels(Image image, int x, int y) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (image == 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 points to copy from the source
+ * @param srcHeight the height in points 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 points of the destination rectangle
+ * @param destHeight the height in points 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return;
+       if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) {
+               SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+       Rectangle src = DPIUtil.autoScaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight));
+       Rectangle dest = DPIUtil.autoScaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight));
+       int deviceZoom = DPIUtil.getDeviceZoom();
+       if (deviceZoom != 100) {
+               /*
+                * This is a HACK! Due to rounding errors at fractional scale factors,
+                * the coordinates may be slightly off. The workaround is to restrict
+                * coordinates to the allowed bounds.
+                */
+               Rectangle b = image.getBoundsInPixels();
+               int errX = src.x + src.width - b.width;
+               int errY = src.y + src.height - b.height;
+               if (errX != 0 || errY != 0) {
+                       if (errX <= deviceZoom / 100 && errY <= deviceZoom / 100) {
+                               src.intersect(b);
+                       } else {
+                               SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+                       }
+               }
+       }
+       drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false);
+}
+
+void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+       /* Refresh Image as per zoom level, if required. */
+       srcImage.refreshImageForZoom ();
+
+       if (data.gdipGraphics != 0) {
+               //TODO - cache bitmap
+               long [] gdipImage = srcImage.createGdipImage();
+               long img = 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 == 0 && srcY == 0 &&
+                               srcWidth == destWidth && destWidth == imgWidth &&
+                               srcHeight == destHeight && destHeight == imgHeight;
+               }
+               Rect rect = new 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.
+               */
+               long attrib = Gdip.ImageAttributes_new();
+               Gdip.ImageAttributes_SetWrapMode(attrib, Gdip.WrapModeTileFlipXY);
+               if (data.alpha != 0xFF) {
+                       float[] matrix = new float[]{
+                               1,0,0,0,0,
+                               0,1,0,0,0,
+                               0,0,1,0,0,
+                               0,0,0,data.alpha / (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, 0, 0);
+               if ((data.style & SWT.MIRRORED) != 0) {
+                       Gdip.Graphics_Restore(data.gdipGraphics, gstate);
+               }
+               Gdip.ImageAttributes_delete(attrib);
+               Gdip.Bitmap_delete(img);
+               if (gdipImage[1] != 0) {
+                       long hHeap = OS.GetProcessHeap ();
+                       OS.HeapFree(hHeap, 0, 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;
+       }
+}
+
+void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+       int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY);
+
+       boolean drawIcon = true;
+       int flags = OS.DI_NORMAL;
+       int offsetX = 0, offsetY = 0;
+
+       if ((OS.GetLayout(handle) & OS.LAYOUT_RTL) != 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 = new POINT();
+               OS.GetWindowOrgEx(handle, pt);
+               offsetX = pt.x;
+               offsetY = pt.y;
+       }
+
+       /* Simple case: no stretching, entire icon */
+       if (simple && technology != OS.DT_RASPRINTER && drawIcon) {
+               if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, 0, 0, null);
+               OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, srcImage.handle, 0, 0, 0, 0, flags);
+               if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null);
+               return;
+       }
+
+       /* Get the icon info */
+       ICONINFO srcIconInfo = new ICONINFO();
+       OS.GetIconInfo(srcImage.handle, srcIconInfo);
+
+       /* Get the icon width and height */
+       long hBitmap = srcIconInfo.hbmColor;
+       if (hBitmap == 0) hBitmap = srcIconInfo.hbmMask;
+       BITMAP bm = new BITMAP();
+       OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+       int iconWidth = bm.bmWidth, iconHeight = bm.bmHeight;
+       if (hBitmap == srcIconInfo.hbmMask) iconHeight /= 2;
+
+       if (simple) {
+               srcWidth = destWidth = iconWidth;
+               srcHeight = destHeight = iconHeight;
+       }
+
+       /* Draw the icon */
+       boolean failed = srcX + srcWidth > iconWidth || srcY + srcHeight > iconHeight;
+       if (!failed) {
+               simple = srcX == 0 && srcY == 0 &&
+                       srcWidth == destWidth && srcHeight == destHeight &&
+                       srcWidth == iconWidth && srcHeight == 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 != OS.DT_RASPRINTER) {
+                       /* Simple case: no stretching, entire icon */
+                       if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, 0, 0, null);
+                       OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, srcImage.handle, 0, 0, 0, 0, flags);
+                       if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null);
+               } else {
+                       /* Create the icon info and HDC's */
+                       ICONINFO newIconInfo = new ICONINFO();
+                       newIconInfo.fIcon = true;
+                       long srcHdc = OS.CreateCompatibleDC(handle);
+                       long dstHdc = OS.CreateCompatibleDC(handle);
+
+                       /* Blt the color bitmap */
+                       int srcColorY = srcY;
+                       long srcColor = srcIconInfo.hbmColor;
+                       if (srcColor == 0) {
+                               srcColor = srcIconInfo.hbmMask;
+                               srcColorY += iconHeight;
+                       }
+                       long oldSrcBitmap = OS.SelectObject(srcHdc, srcColor);
+                       newIconInfo.hbmColor = OS.CreateCompatibleBitmap(srcHdc, destWidth, destHeight);
+                       if (newIconInfo.hbmColor == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       long oldDestBitmap = OS.SelectObject(dstHdc, newIconInfo.hbmColor);
+                       boolean stretch = !simple && (srcWidth != destWidth || srcHeight != destHeight);
+                       if (stretch) {
+                               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 == 0) 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 == 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);
+                               long hIcon = OS.CreateIconIndirect(newIconInfo);
+                               if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               if (offsetX != 0 || offsetY != 0) OS.SetWindowOrgEx(handle, 0, 0, null);
+                               OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, hIcon, destWidth, destHeight, 0, 0, flags);
+                               if (offsetX != 0 || offsetY != 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 != 0) {
+               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, boolean simple) {
+       BITMAP bm = new BITMAP();
+       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 == 0 && srcY == 0 &&
+                       srcWidth == destWidth && destWidth == imgWidth &&
+                       srcHeight == destHeight && destHeight == imgHeight;
+       }
+       boolean mustRestore = false;
+       GC memGC = srcImage.memGC;
+       if (memGC != null && !memGC.isDisposed()) {
+               memGC.flush();
+               mustRestore = true;
+               GCData data = memGC.data;
+               if (data.hNullBitmap != 0) {
+                       OS.SelectObject(memGC.handle, data.hNullBitmap);
+                       data.hNullBitmap = 0;
+               }
+       }
+       if (srcImage.alpha != -1 || srcImage.alphaData != null) {
+               drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+       } else if (srcImage.transparentPixel != -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) {
+               long 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, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
+       /* Simple cases */
+       if (srcImage.alpha == 0) return;
+       if (srcImage.alpha == 255) {
+               drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+               return;
+       }
+
+       boolean alphaBlendSupport = true;
+       boolean isPrinter = OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER;
+       if (isPrinter) {
+               int caps = OS.GetDeviceCaps(handle, OS.SHADEBLENDCAPS);
+               if (caps != 0) {
+                       if (srcImage.alpha != -1) {
+                               alphaBlendSupport = (caps & OS.SB_CONST_ALPHA) != 0;
+                       } else {
+                               alphaBlendSupport = (caps & OS.SB_PIXEL_ALPHA) != 0;
+                       }
+               }
+       }
+       if (alphaBlendSupport) {
+               BLENDFUNCTION blend = new BLENDFUNCTION();
+               blend.BlendOp = OS.AC_SRC_OVER;
+               long srcHdc = OS.CreateCompatibleDC(handle);
+               long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+               if (srcImage.alpha != -1) {
+                       blend.SourceConstantAlpha = (byte)srcImage.alpha;
+                       OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, blend);
+               } else {
+                       long memDib = Image.createDIB(srcWidth, srcHeight, 32);
+                       if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       long memHdc = OS.CreateCompatibleDC(handle);
+                       long oldMemBitmap = OS.SelectObject(memHdc, memDib);
+                       BITMAP dibBM = new BITMAP();
+                       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];
+                       OS.MoveMemory(srcData, dibBM.bmBits, 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] = (byte)r;
+                                       srcData[sp+1] = (byte)g;
+                                       srcData[sp+2] = (byte)b;
+                                       srcData[sp+3] = (byte)alpha;
+                                       sp += 4;
+                               }
+                               ap += apinc;
+                       }
+                       OS.MoveMemory(dibBM.bmBits, srcData, srcData.length);
+                       blend.SourceConstantAlpha = (byte)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 = getClippingInPixels();
+       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 */
+       long srcHdc = OS.CreateCompatibleDC(handle);
+       long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+       long memHdc = OS.CreateCompatibleDC(handle);
+       long memDib = Image.createDIB(Math.max(srcWidth, destWidth), Math.max(srcHeight, destHeight), 32);
+       if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       long oldMemBitmap = OS.SelectObject(memHdc, memDib);
+
+       BITMAP dibBM = new BITMAP();
+       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];
+       OS.MoveMemory(destData, dibBM.bmBits, sizeInBytes);
+
+       /* Get the foreground pixels */
+       OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+       byte[] srcData = new byte[sizeInBytes];
+       OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
+
+       /* Merge the alpha channel in place */
+       int alpha = srcImage.alpha;
+       final boolean hasAlphaChannel = (srcImage.alpha == -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 */
+       OS.MoveMemory(dibBM.bmBits, srcData, sizeInBytes);
+       /*
+       * When drawing to a printer, StretchBlt does not correctly stretch if
+       * the source and destination HDCs are the same.  The workaround is to
+       * stretch to a temporary HDC and blit back into the original HDC.
+       */
+       if (isPrinter) {
+               long tempHdc = OS.CreateCompatibleDC(handle);
+               long tempDib = Image.createDIB(destWidth, destHeight, 32);
+               if (tempDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               long oldTempBitmap = OS.SelectObject(tempHdc, tempDib);
+               if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+                       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 != destWidth || srcHeight != destHeight)) {
+                       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);
+               }
+       }
+       OS.MoveMemory(srcData, dibBM.bmBits, 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 */
+       OS.MoveMemory(dibBM.bmBits, destData, sizeInBytes);
+       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(long srcHdc, long maskHdc, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight) {
+       /* Create a clipping region from the mask */
+       long 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) == 0) {
+                               long 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 != srcWidth || destHeight != srcHeight) {
+               int nBytes = OS.GetRegionData (rgn, 0, null);
+               int[] lpRgnData = new int[nBytes / 4];
+               OS.GetRegionData (rgn, nBytes, lpRgnData);
+               float[] lpXform = new float[] {(float)destWidth/srcWidth, 0, 0, (float)destHeight/srcHeight, 0, 0};
+               long tmpRgn = OS.ExtCreateRegion(lpXform, nBytes, lpRgnData);
+               OS.DeleteObject(rgn);
+               rgn = tmpRgn;
+       }
+       OS.OffsetRgn(rgn, destX, destY);
+       long clip = OS.CreateRectRgn(0, 0, 0, 0);
+       int result = OS.GetClipRgn(handle, clip);
+       if (result == 1) OS.CombineRgn(rgn, rgn, clip, OS.RGN_AND);
+       OS.SelectClipRgn(handle, rgn);
+       int dwRop = OS.GetROP2(handle) == OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY;
+       if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+               int mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+               OS.StretchBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, dwRop);
+               OS.SetStretchBltMode(handle, mode);
+       } else {
+               OS.BitBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, dwRop);
+       }
+       OS.SelectClipRgn(handle, result == 1 ? clip : 0);
+       OS.DeleteObject(clip);
+       OS.DeleteObject(rgn);
+}
+
+void drawBitmapMask(Image srcImage, long srcColor, long srcMask, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight, boolean offscreen) {
+       int srcColorY = srcY;
+       if (srcColor == 0) {
+               srcColor = srcMask;
+               srcColorY += imgHeight;
+       }
+       long srcHdc = OS.CreateCompatibleDC(handle);
+       long oldSrcBitmap = OS.SelectObject(srcHdc, srcColor);
+       long destHdc = handle;
+       int x = destX, y = destY;
+       long tempHdc = 0, tempBitmap = 0, oldTempBitmap = 0;
+       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 != destWidth || srcHeight != destHeight)) {
+               int 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);
+               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, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
+
+       /* Find the RGB values for the transparent pixel. */
+       boolean isDib = bm.bmBits != 0;
+       long hBitmap = srcImage.handle;
+       long srcHdc = OS.CreateCompatibleDC(handle);
+       long oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap);
+       byte[] originalColors = null;
+       int transparentColor = srcImage.transparentColor;
+       if (transparentColor == -1) {
+               int transBlue = 0, transGreen = 0, transRed = 0;
+               boolean fixPalette = false;
+               if (bm.bmBitsPixel <= 8) {
+                       if (isDib) {
+                               int maxColors = 1 << bm.bmBitsPixel;
+                               byte[] oldColors = new byte[maxColors * 4];
+                               OS.GetDIBColorTable(srcHdc, 0, maxColors, oldColors);
+                               int offset = srcImage.transparentPixel * 4;
+                               for (int i = 0; i < oldColors.length; i += 4) {
+                                       if (i != offset) {
+                                               if (oldColors[offset] == oldColors[i] && oldColors[offset+1] == oldColors[i+1] && oldColors[offset+2] == oldColors[i+2]) {
+                                                       fixPalette = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (fixPalette) {
+                                       byte[] newColors = new byte[oldColors.length];
+                                       transRed = transGreen = transBlue = 0xff;
+                                       newColors[offset] = (byte)transBlue;
+                                       newColors[offset+1] = (byte)transGreen;
+                                       newColors[offset+2] = (byte)transRed;
+                                       OS.SetDIBColorTable(srcHdc, 0, maxColors, newColors);
+                                       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 = new BITMAPINFOHEADER();
+                               bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                               bmiHeader.biPlanes = bm.bmPlanes;
+                               bmiHeader.biBitCount = bm.bmBitsPixel;
+                               byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+                               OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+                               OS.GetDIBits(srcHdc, srcImage.handle, 0, 0, null, bmi, 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;
+                       }
+               }
+               transparentColor = transBlue << 16 | transGreen << 8 | transRed;
+               if (!fixPalette) srcImage.transparentColor = transparentColor;
+       }
+
+       if (originalColors == null) {
+               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 */
+               long maskHdc = OS.CreateCompatibleDC(handle);
+               long maskBitmap = OS.CreateBitmap(imgWidth, imgHeight, 1, 1, null);
+               long oldMaskBitmap = OS.SelectObject(maskHdc, maskBitmap);
+               OS.SetBkColor(srcHdc, transparentColor);
+               OS.BitBlt(maskHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
+               if (originalColors != null) OS.SetDIBColorTable(srcHdc, 0, 1 << bm.bmBitsPixel, originalColors);
+
+               if (OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == 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 */
+                       long tempHdc = OS.CreateCompatibleDC(handle);
+                       long tempBitmap = OS.CreateCompatibleBitmap(handle, destWidth, destHeight);
+                       long oldTempBitmap = OS.SelectObject(tempHdc, tempBitmap);
+                       OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY);
+                       if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+                               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 != 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, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
+       long srcHdc = OS.CreateCompatibleDC(handle);
+       long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+       int dwRop = OS.GetROP2(handle) == OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY;
+       if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+               int mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+               OS.StretchBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, dwRop);
+               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) {
+       x1 = DPIUtil.autoScaleUp (drawable, x1);
+       x2 = DPIUtil.autoScaleUp (drawable, x2);
+       y1 = DPIUtil.autoScaleUp (drawable, y1);
+       y2 = DPIUtil.autoScaleUp (drawable, y2);
+       drawLineInPixels(x1, y1, x2, y2);
+}
+
+void drawLineInPixels (int x1, int y1, int x2, int y2) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(DRAW);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               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) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 0) {
+                       x1--;
+                       x2--;
+               }
+       }
+       OS.MoveToEx (handle, x1, y1, 0);
+       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>
+ * points wide and <code>height + 1</code> points 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       drawOvalInPixels(x, y, width, height);
+}
+
+void drawOvalInPixels (int x, int y, int width, int height) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(DRAW);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               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) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (path.handle == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       initGdip();
+       checkGC(DRAW);
+       long 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 an SWT logical point, 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       drawPointInPixels(x, y);
+}
+
+void drawPointInPixels (int x, int y) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics != 0) {
+               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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawPolygon (int[] pointArray) {
+       if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       drawPolygonInPixels(DPIUtil.autoScaleUp(drawable, pointArray));
+}
+
+void drawPolygonInPixels(int[] pointArray) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(DRAW);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+               Gdip.Graphics_DrawPolygon(gdipGraphics, data.gdipPen, pointArray, pointArray.length / 2);
+               Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+               return;
+       }
+       if ((data.style & SWT.MIRRORED) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 0) {
+                       for (int i = 0; i < pointArray.length; i+=2) {
+                               pointArray[i]--;
+                       }
+               }
+       }
+       OS.Polygon(handle, pointArray, pointArray.length / 2);
+       if ((data.style & SWT.MIRRORED) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 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 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 drawPolyline (int[] pointArray) {
+       drawPolylineInPixels(DPIUtil.autoScaleUp(drawable, pointArray));
+}
+
+void drawPolylineInPixels(int[] pointArray) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       checkGC(DRAW);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+               Gdip.Graphics_DrawLines(gdipGraphics, data.gdipPen, pointArray, pointArray.length / 2);
+               Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+               return;
+       }
+       if ((data.style & SWT.MIRRORED) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 0) {
+                       for (int i = 0; i < pointArray.length; i+=2) {
+                               pointArray[i]--;
+                       }
+               }
+       }
+       OS.Polyline(handle, pointArray, 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) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       drawRectangleInPixels(x, y, width, height);
+}
+
+void drawRectangleInPixels (int x, int y, int width, int height) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(DRAW);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               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) != 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) == 1) x++;
+               } else {
+                       if (data.hPen != 0 && OS.GetObject(data.hPen, 0, 0) != 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       rect = DPIUtil.autoScaleUp(drawable, rect);
+       drawRectangleInPixels(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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       arcWidth = DPIUtil.autoScaleUp (drawable, arcWidth);
+       arcHeight = DPIUtil.autoScaleUp (drawable, arcHeight);
+       drawRoundRectangleInPixels(x, y, width, height, arcWidth, arcHeight);
+}
+
+void drawRoundRectangleInPixels (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(DRAW);
+       if (data.gdipGraphics != 0) {
+               drawRoundRectangleGdip(data.gdipGraphics, data.gdipPen, x, y, width, height, arcWidth, arcHeight);
+               return;
+       }
+       if ((data.style & SWT.MIRRORED) != 0) {
+               if (data.lineWidth != 0 && data.lineWidth % 2 == 0) x--;
+       }
+       OS.RoundRect(handle, x,y,x+width+1,y+height+1, arcWidth, arcHeight);
+}
+
+void drawRoundRectangleGdip (long gdipGraphics, long 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 == 0 || nah == 0) {
+               Gdip.Graphics_DrawRectangle(gdipGraphics, data.gdipPen, x, y, width, height);
+       } else {
+               long path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+               if (path == 0) 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawString (String string, int x, int y) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       drawStringInPixels(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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawString (String string, int x, int y, boolean isTransparent) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       drawStringInPixels(string, x, y, isTransparent);
+}
+
+void drawStringInPixels (String string, int x, int y, boolean isTransparent) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (string.isEmpty()) return;
+       char[] buffer = string.toCharArray();
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               checkGC(FONT | FOREGROUND | (isTransparent ? 0 : BACKGROUND));
+               drawText(gdipGraphics, string, x, y, isTransparent ? SWT.DRAW_TRANSPARENT : 0, null);
+               return;
+       }
+       checkGC(FONT | FOREGROUND_TEXT | BACKGROUND_TEXT);
+       int oldBkMode = OS.SetBkMode(handle, isTransparent ? OS.TRANSPARENT : OS.OPAQUE);
+       RECT rect = null;
+       SIZE size = null;
+       int flags = 0;
+       if ((data.style & SWT.MIRRORED) != 0) {
+               if (!isTransparent) {
+                       size = new SIZE();
+                       OS.GetTextExtentPoint32(handle, buffer, buffer.length, size);
+                       rect = new RECT ();
+                       rect.left = x;
+                       rect.right = x + size.cx;
+                       rect.top = y;
+                       rect.bottom = y + size.cy;
+                       flags = OS.ETO_CLIPPED;
+               }
+               x--;
+       }
+       if (OS.GetROP2(handle) != OS.R2_XORPEN) {
+               OS.ExtTextOut(handle, x, y, flags, rect, buffer, buffer.length, null);
+       } else {
+               int foreground = OS.GetTextColor(handle);
+               if (isTransparent) {
+                       if (size == null) {
+                               size = new SIZE();
+                               OS.GetTextExtentPoint32(handle, buffer, buffer.length, size);
+                       }
+                       int width = size.cx, height = size.cy;
+                       long hBitmap = OS.CreateCompatibleBitmap(handle, width, height);
+                       if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       long memDC = OS.CreateCompatibleDC(handle);
+                       long 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.ExtTextOut(memDC, 0, 0, 0, null, buffer, 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 {
+                       int background = OS.GetBkColor(handle);
+                       OS.SetTextColor(handle, foreground ^ background);
+                       OS.ExtTextOut(handle, x, y, flags, rect, buffer, 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       drawTextInPixels(string, x, y);
+}
+
+void drawTextInPixels (String string, int x, int y) {
+       drawTextInPixels(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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y, boolean isTransparent) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       drawTextInPixels(string, x, y, isTransparent);
+}
+
+void drawTextInPixels (String string, int x, int y, boolean isTransparent) {
+       int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
+       if (isTransparent) flags |= SWT.DRAW_TRANSPARENT;
+       drawTextInPixels(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:
+ * </p>
+ * <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>
+ *
+ * @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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @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) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       drawTextInPixels(string, x, y, flags);
+}
+
+void drawTextInPixels (String string, int x, int y, int flags) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (string.isEmpty()) return;
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               checkGC(FONT | FOREGROUND | ((flags & SWT.DRAW_TRANSPARENT) != 0 ? 0 : BACKGROUND));
+               drawText(gdipGraphics, string, x, y, flags, null);
+               return;
+       }
+       char [] buffer = string.toCharArray();
+       RECT rect = new RECT();
+       OS.SetRect(rect, x, y, 0x6FFFFFF, 0x6FFFFFF);
+       int uFormat = OS.DT_LEFT;
+       if ((flags & SWT.DRAW_DELIMITER) == 0) uFormat |= OS.DT_SINGLELINE;
+       if ((flags & SWT.DRAW_TAB) != 0) uFormat |= OS.DT_EXPANDTABS;
+       if ((flags & SWT.DRAW_MNEMONIC) == 0) uFormat |= OS.DT_NOPREFIX;
+       if ((flags & SWT.DRAW_MNEMONIC) != 0 && (data.uiState & OS.UISF_HIDEACCEL) != 0) {
+               uFormat |= OS.DT_HIDEPREFIX;
+       }
+       checkGC(FONT | FOREGROUND_TEXT | BACKGROUND_TEXT);
+       int oldBkMode = OS.SetBkMode(handle, (flags & SWT.DRAW_TRANSPARENT) != 0 ? OS.TRANSPARENT : OS.OPAQUE);
+       if (OS.GetROP2(handle) != OS.R2_XORPEN) {
+               OS.DrawText(handle, buffer, buffer.length, rect, uFormat);
+       } else {
+               int foreground = OS.GetTextColor(handle);
+               if ((flags & SWT.DRAW_TRANSPARENT) != 0) {
+                       OS.DrawText(handle, buffer, buffer.length, rect, uFormat | OS.DT_CALCRECT);
+                       int width = rect.right - rect.left;
+                       int height = rect.bottom - rect.top;
+                       long hBitmap = OS.CreateCompatibleBitmap(handle, width, height);
+                       if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       long memDC = OS.CreateCompatibleDC(handle);
+                       long 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, 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, buffer.length, rect, uFormat);
+                       OS.SetTextColor(handle, foreground);
+               }
+       }
+       OS.SetBkMode(handle, oldBkMode);
+}
+
+boolean useGDIP (long hdc, char[] buffer) {
+       short[] glyphs = new short[buffer.length];
+       OS.GetGlyphIndices(hdc, buffer, buffer.length, glyphs, OS.GGI_MARK_NONEXISTING_GLYPHS);
+       for (int i = 0; i < glyphs.length; i++) {
+               if (glyphs [i] == -1) {
+                       switch (buffer[i]) {
+                               case '\t':
+                               case '\n':
+                               case '\r':
+                                       break;
+                               default:
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
+void drawText(long gdipGraphics, String string, int x, int y, int flags, Point size) {
+       int length = string.length();
+       char[] chars = string.toCharArray();
+       long hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+       long hFont = data.hGDIFont;
+       if (hFont == 0 && data.font != null) hFont = data.font.handle;
+       long oldFont = 0;
+       if (hFont != 0) oldFont = OS.SelectObject(hdc, hFont);
+       TEXTMETRIC lptm = new TEXTMETRIC();
+       OS.GetTextMetrics(hdc, lptm);
+       boolean gdip = useGDIP(hdc, chars);
+       if (hFont != 0) OS.SelectObject(hdc, oldFont);
+       Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
+       if (gdip) {
+               drawTextGDIP(gdipGraphics, string, x, y, flags, size == null, size);
+               return;
+       }
+       int i = 0, start = 0, end = 0, drawX = x, drawY = y, width = 0, mnemonicIndex = -1;
+       if ((flags & (SWT.DRAW_DELIMITER | SWT.DRAW_TAB | SWT.DRAW_MNEMONIC)) != 0) {
+               int tabWidth = lptm.tmAveCharWidth * 8;
+               while (i < length) {
+                       char c = chars [end++] = chars [i++];
+                       switch (c) {
+                               case '\t':
+                                       if ((flags & SWT.DRAW_TAB) != 0) {
+                                               int l = end - start - 1;
+                                               RectF bounds = drawText(gdipGraphics, chars, start, l, drawX, drawY, flags, mnemonicIndex, lptm, size == null);
+                                               drawX += Math.ceil(bounds.Width);
+                                               drawX = x + (((drawX - x) / tabWidth) + 1) * tabWidth;
+                                               mnemonicIndex = -1;
+                                               start = end;
+                                       }
+                                       break;
+                               case '&':
+                                       if ((flags & SWT.DRAW_MNEMONIC) != 0) {
+                                               if (i == length) {end--; continue;}
+                                               if (chars [i] == '&') {i++; continue;}
+                                               end--;
+                                               mnemonicIndex = end - start;
+                                       }
+                                       break;
+                               case '\r':
+                               case '\n':
+                                       if ((flags & SWT.DRAW_DELIMITER) != 0) {
+                                               int l = end - start - 1;
+                                               if (c == '\r' && end != length && chars[end] == '\n') {
+                                                       end++;
+                                                       i++;
+                                               }
+                                               RectF bounds = drawText(gdipGraphics, chars, start, l, drawX, drawY, flags, mnemonicIndex, lptm, size == null);
+                                               drawY += Math.ceil(bounds.Height);
+                                               width = Math.max(width, drawX + (int)Math.ceil(bounds.Width));
+                                               drawX = x;
+                                               mnemonicIndex = -1;
+                                               start = end;
+                                       }
+                                       break;
+                       }
+               }
+               length = end;
+       }
+       RectF bounds = drawText(gdipGraphics, chars, start, length - start, drawX, drawY, flags, mnemonicIndex, lptm, size == null);
+       if (size != null) {
+               drawY += Math.ceil(bounds.Height);
+               width = Math.max(width, drawX + (int)Math.ceil(bounds.Width));
+               size.x = width;
+               size.y = drawY;
+       }
+}
+
+RectF drawText(long gdipGraphics, char[] buffer, int start, int length, int x, int y, int flags, int mnemonicIndex, TEXTMETRIC lptm, boolean draw) {
+       boolean drawMnemonic = draw && mnemonicIndex != -1 && (data.uiState & OS.UISF_HIDEACCEL) == 0;
+       boolean needsBounds = !draw || drawMnemonic || (flags & SWT.DRAW_TRANSPARENT) == 0 || (data.style & SWT.MIRRORED) != 0 || (flags & SWT.DRAW_DELIMITER) != 0;
+       if (length <= 0) {
+               RectF bounds = null;
+               if (needsBounds) {
+                       bounds = new RectF();
+                       bounds.Height = lptm.tmHeight;
+               }
+               return bounds;
+       }
+       int nGlyphs = (length * 3 / 2) + 16;
+       GCP_RESULTS result = new GCP_RESULTS();
+       result.lStructSize = GCP_RESULTS.sizeof;
+       result.nGlyphs = nGlyphs;
+       long hHeap = OS.GetProcessHeap();
+       long lpDx = result.lpDx = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
+       long lpGlyphs = result.lpGlyphs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 2);
+       long lpOrder = 0;
+       int dwFlags = OS.GCP_GLYPHSHAPE | OS.GCP_REORDER | OS.GCP_LIGATE;
+       if (drawMnemonic) {
+               lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
+       }
+       long hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+       long hFont = data.hGDIFont;
+       if (hFont == 0 && data.font != null) hFont = data.font.handle;
+       long oldFont = 0;
+       if (hFont != 0) oldFont = OS.SelectObject(hdc, hFont);
+       if (start != 0) {
+               char[] temp = new char[length];
+               System.arraycopy(buffer, start, temp, 0, length);
+               buffer = temp;
+       }
+       if ((data.style & SWT.MIRRORED) != 0) OS.SetLayout(hdc, OS.GetLayout(hdc) | OS.LAYOUT_RTL);
+       OS.GetCharacterPlacement(hdc, buffer, length, 0, result, dwFlags);
+       if ((data.style & SWT.MIRRORED) != 0) OS.SetLayout(hdc, OS.GetLayout(hdc) & ~OS.LAYOUT_RTL);
+       if (hFont != 0) OS.SelectObject(hdc, oldFont);
+       Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
+       nGlyphs = result.nGlyphs;
+       int drawX = x, drawY = y + lptm.tmAscent;
+       int[] dx = new int[nGlyphs];
+       OS.MoveMemory(dx, result.lpDx, nGlyphs * 4);
+       float[] points = new float[dx.length * 2];
+       for (int i = 0, j = 0; i < dx.length; i++) {
+               points[j++] = drawX;
+               points[j++] = drawY;
+               drawX += dx[i];
+       }
+       RectF bounds = null;
+       if (needsBounds) {
+               bounds = new RectF();
+               Gdip.Graphics_MeasureDriverString(gdipGraphics, lpGlyphs, nGlyphs, data.gdipFont, points, 0, 0, bounds);
+       }
+       if (draw) {
+               if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
+                       Gdip.Graphics_FillRectangle(gdipGraphics, data.gdipBrush, x, y, (int)Math.ceil(bounds.Width), (int)Math.ceil(bounds.Height));
+               }
+               int gstate = 0;
+               long brush = getFgBrush();
+               if ((data.style & SWT.MIRRORED) != 0) {
+                       switch (Gdip.Brush_GetType(brush)) {
+                               case Gdip.BrushTypeLinearGradient:
+                                       Gdip.LinearGradientBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                                       Gdip.LinearGradientBrush_TranslateTransform(brush, - 2 * x - bounds.Width, 0, Gdip.MatrixOrderPrepend);
+                                       break;
+                               case Gdip.BrushTypeTextureFill:
+                                       Gdip.TextureBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                                       Gdip.TextureBrush_TranslateTransform(brush, - 2 * x - bounds.Width, 0, Gdip.MatrixOrderPrepend);
+                                       break;
+                       }
+                       gstate = Gdip.Graphics_Save(gdipGraphics);
+                       Gdip.Graphics_ScaleTransform(gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend);
+                       Gdip.Graphics_TranslateTransform(gdipGraphics, - 2 * x - bounds.Width, 0, Gdip.MatrixOrderPrepend);
+               }
+               Gdip.Graphics_DrawDriverString(gdipGraphics, lpGlyphs, result.nGlyphs, data.gdipFont, brush, points, 0, 0);
+               if ((data.style & SWT.MIRRORED) != 0) {
+                       switch (Gdip.Brush_GetType(brush)) {
+                               case Gdip.BrushTypeLinearGradient:
+                                       Gdip.LinearGradientBrush_ResetTransform(brush);
+                                       break;
+                               case Gdip.BrushTypeTextureFill:
+                                       Gdip.TextureBrush_ResetTransform(brush);
+                                       break;
+                       }
+                       Gdip.Graphics_Restore(gdipGraphics, gstate);
+               }
+               if (drawMnemonic) {
+                       long pen = Gdip.Pen_new(brush, 1);
+                       if (pen != 0) {
+                               int[] order = new int[1];
+                               OS.MoveMemory(order, result.lpOrder + mnemonicIndex * 4, 4);
+                               int mnemonicLeft, mnemonicRight;
+                               if ((data.style & SWT.MIRRORED) != 0) {
+                                       mnemonicLeft = (int)Math.ceil(bounds.Width) - (int)points[order[0] * 2] + 2 * x;
+                                       mnemonicRight = mnemonicLeft - dx[order[0]];
+                               } else {
+                                       mnemonicLeft = (int)points[order[0] * 2];
+                                       mnemonicRight = mnemonicLeft + dx[order[0]];
+                               }
+                               int mnemonicY = y + lptm.tmAscent + 2;
+                               int smoothingMode = Gdip.Graphics_GetSmoothingMode(gdipGraphics);
+                               Gdip.Graphics_SetSmoothingMode(gdipGraphics, Gdip.SmoothingModeNone);
+                               Gdip.Graphics_DrawLine(gdipGraphics, pen, mnemonicLeft, mnemonicY, mnemonicRight, mnemonicY);
+                               Gdip.Graphics_SetSmoothingMode(gdipGraphics, smoothingMode);
+                               Gdip.Pen_delete(pen);
+                       }
+               }
+       }
+       if (lpOrder != 0) OS.HeapFree(hHeap, 0, lpOrder);
+       OS.HeapFree(hHeap, 0, lpGlyphs);
+       OS.HeapFree(hHeap, 0, lpDx);
+       return bounds;
+}
+
+void drawTextGDIP(long gdipGraphics, String string, int x, int y, int flags, boolean draw, Point size) {
+       boolean needsBounds = !draw || (flags & SWT.DRAW_TRANSPARENT) == 0;
+       char[] buffer;
+       int length = string.length();
+       if (length != 0) {
+               buffer = string.toCharArray();
+       } else {
+               if (draw) return;
+               buffer = new char[]{' '};
+       }
+       PointF pt = new PointF();
+       long format = Gdip.StringFormat_Clone(Gdip.StringFormat_GenericTypographic());
+       int formatFlags = Gdip.StringFormat_GetFormatFlags(format) | Gdip.StringFormatFlagsMeasureTrailingSpaces;
+       if ((data.style & SWT.MIRRORED) != 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
+       Gdip.StringFormat_SetFormatFlags(format, formatFlags);
+       float[] tabs = (flags & SWT.DRAW_TAB) != 0 ? new float[]{measureSpace(data.gdipFont, format) * 8} : new float[1];
+       Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs);
+       int hotkeyPrefix = (flags & SWT.DRAW_MNEMONIC) != 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone;
+       if ((flags & SWT.DRAW_MNEMONIC) != 0 && (data.uiState & OS.UISF_HIDEACCEL) != 0) hotkeyPrefix = Gdip.HotkeyPrefixHide;
+       Gdip.StringFormat_SetHotkeyPrefix(format, hotkeyPrefix);
+       RectF bounds = null;
+       if (needsBounds) {
+               bounds = new RectF();
+               Gdip.Graphics_MeasureString(gdipGraphics, buffer, buffer.length, data.gdipFont, pt, format, bounds);
+       }
+       if (draw) {
+               if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
+                       Gdip.Graphics_FillRectangle(gdipGraphics, data.gdipBrush, x, y, (int)Math.ceil(bounds.Width), (int)Math.ceil(bounds.Height));
+               }
+               int gstate = 0;
+               long brush = getFgBrush();
+               if ((data.style & SWT.MIRRORED) != 0) {
+                       switch (Gdip.Brush_GetType(brush)) {
+                               case Gdip.BrushTypeLinearGradient:
+                                       Gdip.LinearGradientBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                                       Gdip.LinearGradientBrush_TranslateTransform(brush, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+                                       break;
+                               case Gdip.BrushTypeTextureFill:
+                                       Gdip.TextureBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                                       Gdip.TextureBrush_TranslateTransform(brush, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+                                       break;
+                       }
+                       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, buffer.length, data.gdipFont, pt, format, brush);
+               if ((data.style & SWT.MIRRORED) != 0) {
+                       switch (Gdip.Brush_GetType(brush)) {
+                               case Gdip.BrushTypeLinearGradient:
+                                       Gdip.LinearGradientBrush_ResetTransform(brush);
+                                       break;
+                               case Gdip.BrushTypeTextureFill:
+                                       Gdip.TextureBrush_ResetTransform(brush);
+                                       break;
+                       }
+                       Gdip.Graphics_Restore(gdipGraphics, gstate);
+               }
+       }
+       Gdip.StringFormat_delete(format);
+       if (length == 0) bounds.Width = 0;
+       if (size != null) {
+               size.x = (int)Math.ceil(bounds.Width);
+               size.y = (int)Math.ceil(bounds.Height);
+       }
+}
+
+/**
+ * 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 boolean equals (Object object) {
+       return (object == this) || ((object instanceof GC) && (handle == ((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> points wide
+ * by <code>height + 1</code> points 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       fillArcInPixels(x, y, width, height, startAngle, arcAngle);
+}
+
+void fillArcInPixels (int x, int y, int width, int height, int startAngle, int arcAngle) {
+       if (handle == 0) 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 == 0 || height == 0 || arcAngle == 0) return;
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               if (width == 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) != 0) x--;
+       int x1, y1, x2, y2,tmp;
+       boolean 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 = cos(startAngle, width) + x + width/2;
+               y1 = -1 * sin(startAngle, height) + y + height/2;
+
+               x2 = cos(arcAngle, width) + x + width/2;
+               y2 = -1 * 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, boolean vertical) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       fillGradientRectangleInPixels(x, y, width, height, vertical);
+}
+
+void fillGradientRectangleInPixels(int x, int y, int width, int height, boolean vertical) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (width == 0 || height == 0) return;
+
+       RGB backgroundRGB, foregroundRGB;
+       backgroundRGB = getBackground().getRGB();
+       foregroundRGB = getForeground().getRGB();
+
+       RGB fromRGB, toRGB;
+       fromRGB = foregroundRGB;
+       toRGB   = backgroundRGB;
+
+       boolean 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.equals(toRGB)) {
+               fillRectangleInPixels(x, y, width, height);
+               return;
+       }
+       if (data.gdipGraphics != 0) {
+               initGdip();
+               PointF p1= new PointF(), p2 = new PointF();
+               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 fromGpColor = (data.alpha << 24) | ((fromRGB.red & 0xFF) << 16) | ((fromRGB.green & 0xFF) << 8) | (fromRGB.blue & 0xFF);
+               int toGpColor = (data.alpha << 24) | ((toRGB.red & 0xFF) << 16) | ((toRGB.green & 0xFF) << 8) | (toRGB.blue & 0xFF);
+               long brush = Gdip.LinearGradientBrush_new(p1, p2, fromGpColor, toGpColor);
+               Gdip.Graphics_FillRectangle(data.gdipGraphics, brush, x, y, width, height);
+               Gdip.LinearGradientBrush_delete(brush);
+               return;
+       }
+       /*
+       * 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. The fix is not to use
+       * GradientFill for printer devices.
+       */
+       if (OS.GetROP2(handle) != OS.R2_XORPEN && OS.GetDeviceCaps(handle, OS.TECHNOLOGY) != OS.DT_RASPRINTER) {
+               final long hHeap = OS.GetProcessHeap();
+               final long pMesh = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, GRADIENT_RECT.sizeof + TRIVERTEX.sizeof * 2);
+               if (pMesh == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               final long pVertex = pMesh + GRADIENT_RECT.sizeof;
+
+               GRADIENT_RECT gradientRect = new GRADIENT_RECT();
+               gradientRect.UpperLeft = 0;
+               gradientRect.LowerRight = 1;
+               OS.MoveMemory(pMesh, gradientRect, GRADIENT_RECT.sizeof);
+
+               TRIVERTEX trivertex = new TRIVERTEX();
+               trivertex.x = x;
+               trivertex.y = y;
+               trivertex.Red = (short)((fromRGB.red << 8) | fromRGB.red);
+               trivertex.Green = (short)((fromRGB.green << 8) | fromRGB.green);
+               trivertex.Blue = (short)((fromRGB.blue << 8) | fromRGB.blue);
+               trivertex.Alpha = -1;
+               OS.MoveMemory(pVertex, trivertex, TRIVERTEX.sizeof);
+
+               trivertex.x = x + width;
+               trivertex.y = y + height;
+               trivertex.Red = (short)((toRGB.red << 8) | toRGB.red);
+               trivertex.Green = (short)((toRGB.green << 8) | toRGB.green);
+               trivertex.Blue = (short)((toRGB.blue << 8) | toRGB.blue);
+               trivertex.Alpha = -1;
+               OS.MoveMemory(pVertex + TRIVERTEX.sizeof, trivertex, TRIVERTEX.sizeof);
+
+               boolean success = 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       fillOvalInPixels(x, y, width, height);
+}
+
+void fillOvalInPixels (int x, int y, int width, int height) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FILL);
+       if (data.gdipGraphics != 0) {
+               Gdip.Graphics_FillEllipse(data.gdipGraphics, data.gdipBrush, x, y, width, height);
+               return;
+       }
+       if ((data.style & SWT.MIRRORED) != 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (path.handle == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       initGdip();
+       checkGC(FILL);
+       int mode = OS.GetPolyFillMode(handle) == 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawPolygon
+ */
+public void fillPolygon (int[] pointArray) {
+       if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       fillPolygonInPixels(DPIUtil.autoScaleUp(drawable, pointArray));
+}
+
+void fillPolygonInPixels (int[] pointArray) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FILL);
+       if (data.gdipGraphics != 0) {
+               int mode = OS.GetPolyFillMode(handle) == OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate;
+               /*
+                * GC.fillPolygon method paints at wrong coordinates when GDI+ is used, the
+                * difference is marginal, hence applying the transformation with additional
+                * 0.5f pixel correction to avoid the issue seen in bug 139791
+                */
+               float offsetCorrection = 0.5f;
+               Gdip.Graphics_TranslateTransform(data.gdipGraphics, data.gdipXOffset + offsetCorrection, data.gdipYOffset + offsetCorrection, Gdip.MatrixOrderPrepend);
+               Gdip.Graphics_FillPolygon(data.gdipGraphics, data.gdipBrush, pointArray, pointArray.length / 2, mode);
+               Gdip.Graphics_TranslateTransform(data.gdipGraphics, -(data.gdipXOffset + offsetCorrection), -(data.gdipYOffset + offsetCorrection), Gdip.MatrixOrderPrepend);
+               return;
+       }
+       if ((data.style & SWT.MIRRORED) != 0) {
+               for (int i = 0; i < pointArray.length; i+=2) {
+                       pointArray[i]--;
+               }
+       }
+       OS.Polygon(handle, pointArray, pointArray.length / 2);
+       if ((data.style & SWT.MIRRORED) != 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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       fillRectangleInPixels(x, y, width, height);
+}
+
+void fillRectangleInPixels (int x, int y, int width, int height) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FILL);
+       if (data.gdipGraphics != 0) {
+               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 dwRop = OS.GetROP2(handle) == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       rect = DPIUtil.autoScaleUp(drawable, rect);
+       fillRectangleInPixels(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) {
+       x = DPIUtil.autoScaleUp (drawable, x);
+       y = DPIUtil.autoScaleUp (drawable, y);
+       width = DPIUtil.autoScaleUp (drawable, width);
+       height = DPIUtil.autoScaleUp (drawable, height);
+       arcWidth = DPIUtil.autoScaleUp (drawable, arcWidth);
+       arcHeight = DPIUtil.autoScaleUp (drawable, arcHeight);
+       fillRoundRectangleInPixels(x, y, width, height, arcWidth, arcHeight);
+}
+
+void fillRoundRectangleInPixels (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FILL);
+       if (data.gdipGraphics != 0) {
+               fillRoundRectangleGdip(data.gdipGraphics, data.gdipBrush, x, y, width, height, arcWidth, arcHeight);
+               return;
+       }
+       if ((data.style & SWT.MIRRORED) != 0) x--;
+       OS.RoundRect(handle, x,y,x+width+1,y+height+1,arcWidth, arcHeight);
+}
+
+void fillRoundRectangleGdip (long gdipGraphics, long 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 == 0 || nah == 0) {
+               Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height);
+       } else {
+               long path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+               if (path == 0) 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 != 0) {
+               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().
+               */
+               long 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FONT);
+       int[] width = new int[1];
+       OS.GetCharWidth(handle, ch, ch, width);
+       return width[0];
+}
+
+/**
+ * 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 boolean getAdvanced() {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return data.gdipGraphics != 0;
+}
+
+/**
+ * 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 == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0) 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;
+       }
+       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 == 0) 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 == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FONT);
+
+       /* GetCharABCWidths only succeeds on truetype fonts */
+       int[] width = new int[3];
+       if (OS.GetCharABCWidths(handle, ch, ch, width)) {
+               return width[1];
+       }
+
+       /* It wasn't a truetype font */
+       TEXTMETRIC lptm = new TEXTMETRIC();
+       OS.GetTextMetrics(handle, lptm);
+       SIZE size = new SIZE();
+       OS.GetTextExtentPoint32(handle, new char[]{ch}, 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 () {
+       return DPIUtil.autoScaleDown(drawable, getClippingInPixels());
+}
+
+Rectangle getClippingInPixels() {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Rect rect = new 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 = new 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (region == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               long rgn = Gdip.Region_new();
+               Gdip.Graphics_GetClip(data.gdipGraphics, rgn);
+               if (Gdip.Region_IsInfinite(rgn, gdipGraphics)) {
+                       Rect rect = new 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 {
+                       long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+                       long identity = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+                       Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+                       Gdip.Graphics_SetTransform(gdipGraphics, identity);
+                       long hRgn = Gdip.Region_GetHRGN(rgn, data.gdipGraphics);
+                       Gdip.Graphics_SetTransform(gdipGraphics, matrix);
+                       Gdip.Matrix_delete(identity);
+                       Gdip.Matrix_delete(matrix);
+                       POINT pt = new POINT ();
+                       OS.GetWindowOrgEx (handle, pt);
+                       OS.OffsetRgn (hRgn, pt.x, pt.y);
+                       OS.CombineRgn(region.handle, hRgn, 0, OS.RGN_COPY);
+                       OS.DeleteObject(hRgn);
+               }
+               Gdip.Region_delete(rgn);
+               return;
+       }
+       POINT pt = new POINT ();
+       OS.GetWindowOrgEx (handle, pt);
+       int result = OS.GetClipRgn (handle, region.handle);
+       if (result != 1) {
+               RECT rect = new 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);
+       }
+       long metaRgn = OS.CreateRectRgn (0, 0, 0, 0);
+       if (OS.GetMetaRgn (handle, metaRgn) != 0) {
+               OS.OffsetRgn (metaRgn, pt.x, pt.y);
+               OS.CombineRgn (region.handle, metaRgn, region.handle, OS.RGN_AND);
+       }
+       OS.DeleteObject(metaRgn);
+       long hwnd = data.hwnd;
+       if (hwnd != 0 && data.ps != null) {
+               long sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
+               if (OS.GetRandomRgn (handle, sysRgn, OS.SYSRGN) == 1) {
+                       if ((OS.GetLayout(handle) & OS.LAYOUT_RTL) != 0) {
+                               int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                               int [] lpRgnData = new int [nBytes / 4];
+                               OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                               long newSysRgn = OS.ExtCreateRegion(new float [] {-1, 0, 0, 1, 0, 0}, nBytes, lpRgnData);
+                               OS.DeleteObject(sysRgn);
+                               sysRgn = newSysRgn;
+                       }
+                       OS.MapWindowPoints (0, hwnd, pt, 1);
+                       OS.OffsetRgn (sysRgn, pt.x, pt.y);
+                       OS.CombineRgn (region.handle, sysRgn, region.handle, OS.RGN_AND);
+               }
+               OS.DeleteObject(sysRgn);
+       }
+}
+
+long getFgBrush() {
+       return data.foregroundPattern != null ? data.foregroundPattern.handle : 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return OS.GetPolyFillMode(handle) == 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 == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FONT);
+       TEXTMETRIC lptm = new TEXTMETRIC();
+       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 == 0) 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 == 0) 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.2
+ */
+public GCData getGCData() {
+       if (handle == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0) 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;
+       }
+       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 () {
+       LineAttributes attributes = getLineAttributesInPixels();
+       attributes.width = DPIUtil.autoScaleDown(drawable, attributes.width);
+       return attributes;
+}
+
+LineAttributes getLineAttributesInPixels () {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       float[] dashes = null;
+       if (data.lineDashes != 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 == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.lineDashes == null) return null;
+       int[] lineDashes = new int[data.lineDashes.length];
+       for (int i = 0; i < lineDashes.length; i++) {
+               lineDashes[i] = (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 == 0) 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 == 0) 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 () {
+       return DPIUtil.autoScaleDown(drawable, getLineWidthInPixels());
+}
+
+int getLineWidthInPixels() {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return (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 == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0) 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;
+       }
+       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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (transform == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Gdip.Graphics_GetTransform(gdipGraphics, transform.handle);
+               long 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 boolean getXORMode() {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return OS.GetROP2(handle) == OS.R2_XORPEN;
+}
+
+void initGdip() {
+       data.device.checkGDIP();
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) 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.
+       */
+       long hRgn = OS.CreateRectRgn(0, 0, 0, 0);
+       int result = OS.GetClipRgn(handle, hRgn);
+       POINT pt = new POINT ();
+       OS.GetWindowOrgEx (handle, pt);
+       OS.OffsetRgn (hRgn, pt.x, pt.y);
+       OS.SelectClipRgn(handle, 0);
+
+       /*
+       * 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) != 0) {
+               OS.SetLayout(handle, OS.GetLayout(handle) & ~OS.LAYOUT_RTL);
+       }
+
+       gdipGraphics = data.gdipGraphics = Gdip.Graphics_new(handle);
+       if (gdipGraphics == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       Gdip.Graphics_SetPageUnit(gdipGraphics, Gdip.UnitPixel);
+       Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+       if ((data.style & SWT.MIRRORED) != 0) {
+               long matrix = identity();
+               Gdip.Graphics_SetTransform(gdipGraphics, matrix);
+               Gdip.Matrix_delete(matrix);
+       }
+       if (result == 1) setClipping(hRgn);
+       OS.DeleteObject(hRgn);
+       data.state = 0;
+       if (data.hPen != 0) {
+               OS.SelectObject(handle, OS.GetStockObject(OS.NULL_PEN));
+               OS.DeleteObject(data.hPen);
+               data.hPen = 0;
+       }
+       if (data.hBrush != 0) {
+               OS.SelectObject(handle, OS.GetStockObject(OS.NULL_BRUSH));
+               OS.DeleteObject(data.hBrush);
+               data.hBrush = 0;
+       }
+}
+
+long identity() {
+       if ((data.style & SWT.MIRRORED) != 0) {
+               int width = 0;
+               int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY);
+               if (technology == OS.DT_RASPRINTER) {
+                       width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+               } else {
+                       Image image = data.image;
+                       if (image != null) {
+                               BITMAP bm = new BITMAP();
+                               OS.GetObject(image.handle, BITMAP.sizeof, bm);
+                               width = bm.bmWidth;
+                       } else {
+                               long hwnd = OS.WindowFromDC(handle);
+                               if (hwnd != 0) {
+                                       RECT rect = new RECT();
+                                       OS.GetClientRect(hwnd, rect);
+                                       width = rect.right - rect.left;
+                               } else {
+                                       long hBitmap = OS.GetCurrentObject(handle, OS.OBJ_BITMAP);
+                                       BITMAP bm = new BITMAP();
+                                       OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+                                       width = bm.bmWidth;
+                               }
+                       }
+               }
+               POINT pt = new POINT ();
+               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, long hDC) {
+       int foreground = data.foreground;
+       if (foreground != -1) {
+               data.state &= ~(FOREGROUND | FOREGROUND_TEXT | PEN);
+       } else {
+               data.foreground = OS.GetTextColor(hDC);
+       }
+       int background = data.background;
+       if (background != -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 != null) {
+               data.state &= ~FONT;
+       } else {
+               data.font = Font.win32_new(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT));
+       }
+       Image image = data.image;
+       if (image != null) {
+               data.hNullBitmap = OS.SelectObject(hDC, image.handle);
+               image.memGC = this;
+       }
+       int layout = data.layout;
+       if (layout != -1) {
+               int flags = OS.GetLayout(hDC);
+               if ((flags & OS.LAYOUT_RTL) != (layout & OS.LAYOUT_RTL)) {
+                       flags &= ~OS.LAYOUT_RTL;
+                       OS.SetLayout(hDC, flags | layout);
+               }
+               if ((data.style & SWT.RIGHT_TO_LEFT) != 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
+ */
+@Override
+public int hashCode () {
+       return (int)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 boolean isClipped() {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               long rgn = Gdip.Region_new();
+               Gdip.Graphics_GetClip(data.gdipGraphics, rgn);
+               boolean isInfinite = Gdip.Region_IsInfinite(rgn, gdipGraphics);
+               Gdip.Region_delete(rgn);
+               return !isInfinite;
+       }
+       long 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 (except {@link #dispose()}) using the GC.
+ *
+ * @return <code>true</code> when the GC is disposed and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+float measureSpace(long font, long format) {
+       PointF pt = new PointF();
+       RectF bounds = new RectF();
+       Gdip.Graphics_MeasureString(data.gdipGraphics, new char[]{' '}, 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(boolean advanced) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (advanced && data.gdipGraphics != 0) return;
+       if (advanced) {
+               initGdip();
+       } else {
+               disposeGdip();
+               data.alpha = 0xFF;
+               data.backgroundPattern = data.foregroundPattern = null;
+               data.state = 0;
+               setClipping(0);
+               if ((data.style & SWT.MIRRORED) != 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0 && antialias == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0 && (alpha & 0xFF) == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (data.backgroundPattern == null && data.background == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (data.gdipGraphics == 0 && pattern == null) return;
+       initGdip();
+       if (data.backgroundPattern == pattern) return;
+       data.backgroundPattern = pattern;
+       data.state &= ~BACKGROUND;
+}
+
+void setClipping(long clipRgn) {
+       long hRgn = clipRgn;
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               if (hRgn != 0) {
+                       long region = Gdip.Region_new(hRgn);
+                       Gdip.Graphics_SetClip(gdipGraphics, region, Gdip.CombineModeReplace);
+                       Gdip.Region_delete(region);
+               } else {
+                       Gdip.Graphics_ResetClip(gdipGraphics);
+               }
+       } else {
+               POINT pt = null;
+               if (hRgn != 0) {
+                       pt = new POINT();
+                       OS.GetWindowOrgEx(handle, pt);
+                       OS.OffsetRgn(hRgn, -pt.x, -pt.y);
+               }
+               OS.SelectClipRgn(handle, hRgn);
+               if (hRgn != 0) {
+                       OS.OffsetRgn(hRgn, pt.x, pt.y);
+               }
+       }
+}
+
+/**
+ * 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) {
+       x = DPIUtil.autoScaleUp(drawable, x);
+       y = DPIUtil.autoScaleUp(drawable, y);
+       width = DPIUtil.autoScaleUp(drawable, width);
+       height = DPIUtil.autoScaleUp(drawable, height);
+       setClippingInPixels(x, y, width, height);
+}
+
+void setClippingInPixels (int x, int y, int width, int height) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       long 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       setClipping(0);
+       if (path != null) {
+               initGdip();
+               int mode = OS.GetPolyFillMode(handle) == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (rect == null) {
+               setClipping(0);
+       }
+       else {
+               rect = DPIUtil.autoScaleUp(drawable, rect);
+               setClippingInPixels(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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (region != null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       setClipping(region != null ? region.handle : 0);
+}
+
+/**
+ * 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       data.font = font != 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (data.foregroundPattern == null && color.handle == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (data.gdipGraphics == 0 && pattern == null) return;
+       initGdip();
+       if (data.foregroundPattern == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0 && interpolation == 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 (attributes == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       attributes.width = DPIUtil.autoScaleUp(drawable, attributes.width);
+       setLineAttributesInPixels(attributes);
+}
+
+void setLineAttributesInPixels (LineAttributes attributes) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       int mask = 0;
+       float lineWidth = attributes.width;
+       if (lineWidth != data.lineWidth) {
+               mask |= LINE_WIDTH | DRAW_OFFSET;
+       }
+       int lineStyle = attributes.style;
+       if (lineStyle != 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 == null) lineStyle = SWT.LINE_SOLID;
+                               break;
+                       default:
+                               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       int join = attributes.join;
+       if (join != data.lineJoin) {
+               mask |= LINE_JOIN;
+               switch (join) {
+                       case SWT.JOIN_MITER:
+                       case SWT.JOIN_ROUND:
+                       case SWT.JOIN_BEVEL:
+                               break;
+                       default:
+                               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       int cap = attributes.cap;
+       if (cap != data.lineCap) {
+               mask |= LINE_CAP;
+               switch (cap) {
+                       case SWT.CAP_FLAT:
+                       case SWT.CAP_ROUND:
+                       case SWT.CAP_SQUARE:
+                               break;
+                       default:
+                               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       float[] dashes = attributes.dash;
+       float[] lineDashes = data.lineDashes;
+       if (dashes != null && dashes.length > 0) {
+               boolean changed = lineDashes == null || lineDashes.length != 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] != 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 != null && lineDashes.length > 0) {
+                       mask |= LINE_STYLE;
+               } else {
+                       dashes = lineDashes;
+               }
+       }
+       float dashOffset = attributes.dashOffset;
+       if (dashOffset != data.lineDashesOffset) {
+               mask |= LINE_STYLE;
+       }
+       float miterLimit = attributes.miterLimit;
+       if (miterLimit != data.lineMiterLimit) {
+               mask |= LINE_MITERLIMIT;
+       }
+       initGdip();
+       if (mask == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.lineCap == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       float[] lineDashes = data.lineDashes;
+       if (dashes != null && dashes.length > 0) {
+               boolean changed = data.lineStyle != SWT.LINE_CUSTOM || lineDashes == null || lineDashes.length != 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] != 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 == SWT.LINE_SOLID && (lineDashes == null || lineDashes.length == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.lineJoin == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.lineStyle == 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 == 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 and
+ * specially at high DPI it's not recommended to mix
+ * line width zero with other line widths.
+ * </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) {
+       lineWidth = DPIUtil.autoScaleUp (drawable, lineWidth);
+       setLineWidthInPixels(lineWidth);
+}
+
+void setLineWidthInPixels(int lineWidth) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.lineWidth == 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.
+ *
+ * @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>
+ */
+public void setXORMode(boolean xor) {
+       if (handle == 0) 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (data.gdipGraphics == 0 && antialias == 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 = new int[1];
+                       OS.SystemParametersInfo(OS.SPI_GETFONTSMOOTHINGTYPE, 0, type, 0);
+                       if (type[0] == 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 == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (transform != null && transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (data.gdipGraphics == 0 && transform == null) return;
+       initGdip();
+       long identity = identity();
+       if (transform != 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point stringExtent (String string) {
+       if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return DPIUtil.autoScaleDown(drawable, stringExtentInPixels(string));
+}
+
+Point stringExtentInPixels (String string) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       checkGC(FONT);
+       int length = string.length();
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Point size = new Point(0, 0);
+               drawText(gdipGraphics, string, 0, 0, 0, size);
+               return size;
+       }
+       SIZE size = new SIZE();
+       if (length == 0) {
+//             OS.GetTextExtentPoint32(handle, SPACE, SPACE.length(), size);
+               OS.GetTextExtentPoint32(handle, new char[]{' '}, 1, size);
+               return new Point(0, size.cy);
+       } else {
+               char[] buffer = string.toCharArray();
+               OS.GetTextExtentPoint32(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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point textExtent (String string) {
+       return DPIUtil.autoScaleDown(drawable, textExtentInPixels(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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point textExtent (String string, int flags) {
+       return DPIUtil.autoScaleDown(drawable, textExtentInPixels(string, flags));
+}
+
+Point textExtentInPixels(String string, int flags) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       checkGC(FONT);
+       long gdipGraphics = data.gdipGraphics;
+       if (gdipGraphics != 0) {
+               Point size = new Point(0, 0);
+               drawText(gdipGraphics, string, 0, 0, flags, size);
+               return size;
+       }
+       if (string.length () == 0) {
+               SIZE size = new SIZE();
+               OS.GetTextExtentPoint32(handle, new char [] {' '}, 1, size);
+               return new Point(0, size.cy);
+       }
+       RECT rect = new RECT();
+       char [] buffer = string.toCharArray();
+       int uFormat = OS.DT_LEFT | OS.DT_CALCRECT;
+       if ((flags & SWT.DRAW_DELIMITER) == 0) uFormat |= OS.DT_SINGLELINE;
+       if ((flags & SWT.DRAW_TAB) != 0) uFormat |= OS.DT_EXPANDTABS;
+       if ((flags & SWT.DRAW_MNEMONIC) == 0) uFormat |= OS.DT_NOPREFIX;
+       OS.DrawText(handle, buffer, 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 "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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static GC win32_new(Drawable drawable, GCData data) {
+       GC gc = new GC();
+       long hDC = drawable.internal_new_GC(data);
+       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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static GC win32_new(long hDC, GCData data) {
+       GC gc = new GC();
+       gc.device = data.device;
+       data.style |= SWT.LEFT_TO_RIGHT;
+       int flags = OS.GetLayout (hDC);
+       if ((flags & OS.LAYOUT_RTL) != 0) {
+               data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+       }
+       gc.init(null, data, hDC);
+       return gc;
+}
+
+/**
+ * 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).
+ *
+ * @param angle the angle in degrees
+ * @param length the length of the triangle's hypotenuse
+ * @return the integer conversion of length * cos (angle)
+ */
+private static int cos(int angle, int length) {
+       return (int)(Math.cos(angle * (Math.PI/180)) * 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).
+ *
+ * @param angle the angle in degrees
+ * @param length the length of the triangle's hypotenuse
+ * @return the integer conversion of length * sin (angle)
+ */
+private static int sin(int angle, int length) {
+       return (int)(Math.sin(angle * (Math.PI/180)) * length);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GCData.java
new file mode 100644 (file)
index 0000000..8f03afb
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noreference This class is not intended to be referenced by clients
+ */
+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 PAINTSTRUCT ps;
+       public int layout = -1;
+       public long hPen, hOldPen, hBrush, hOldBrush, hNullBitmap,
+               hwnd, gdipGraphics, gdipPen, gdipBrush, gdipFgBrush, gdipBgBrush,
+               gdipFont, hGDIFont;
+       public float gdipXOffset, gdipYOffset;
+       public int uiState = 0;
+       public boolean focusDrawn;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GlyphMetrics.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/GlyphMetrics.java
new file mode 100644 (file)
index 0000000..7d55d3c
--- /dev/null
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 GlyphMetrics(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;
+}
+
+int getAscentInPixels() {
+       return DPIUtil.autoScaleUp(ascent);
+}
+
+int getDescentInPixels() {
+       return DPIUtil.autoScaleUp(descent);
+}
+
+int getWidthInPixels() {
+       return DPIUtil.autoScaleUp(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()
+ */
+@Override
+public boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof GlyphMetrics)) return false;
+       GlyphMetrics metrics = (GlyphMetrics)object;
+       return metrics.ascent == ascent && metrics.descent == descent && metrics.width == width;
+}
+
+/**
+ * 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 int hashCode () {
+       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>
+ */
+@Override
+public String toString () {
+       return "GlyphMetrics {" + ascent + ", " + descent + ", " + width + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Image.java
new file mode 100644 (file)
index 0000000..65d9729
--- /dev/null
@@ -0,0 +1,2148 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Resource implements Drawable {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long 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;
+
+       /**
+        * ImageFileNameProvider to provide file names at various Zoom levels
+        */
+       private ImageFileNameProvider imageFileNameProvider;
+
+       /**
+        * ImageDataProvider to provide ImageData at various Zoom levels
+        */
+       private ImageDataProvider imageDataProvider;
+
+       /**
+        * Style flag used to differentiate normal, gray-scale and disabled images based
+        * on image data providers. Without this, a normal and a disabled image of the
+        * same image data provider would be considered equal.
+        */
+       private int styleFlag = SWT.IMAGE_COPY;
+
+       /**
+        * Attribute to cache current device zoom level
+        */
+       private int currentDeviceZoom = 100;
+
+       /**
+        * width of the image
+        */
+       int width = -1;
+
+       /**
+        * height of the image
+        */
+       int height = -1;
+
+       /**
+        * specifies the default scanline padding
+        */
+       static final int DEFAULT_SCANLINE_PAD = 4;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Image (Device device) {
+       super(device);
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+}
+
+/**
+ * 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>
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </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>
+ *
+ * @see #dispose()
+ */
+public Image(Device device, int width, int height) {
+       super(device);
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       width = DPIUtil.autoScaleUp (width);
+       height = DPIUtil.autoScaleUp (height);
+       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>
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </p>
+ *
+ * @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>
+ *
+ * @see #dispose()
+ */
+public Image(Device device, Image srcImage, int flag) {
+       super(device);
+       device = this.device;
+       if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       Rectangle rect = srcImage.getBoundsInPixels();
+       this.type = srcImage.type;
+       this.imageDataProvider = srcImage.imageDataProvider;
+       this.imageFileNameProvider = srcImage.imageFileNameProvider;
+       this.styleFlag = srcImage.styleFlag | flag;
+       this.currentDeviceZoom = srcImage.currentDeviceZoom;
+       switch (flag) {
+               case SWT.IMAGE_COPY: {
+                       switch (type) {
+                               case SWT.BITMAP:
+                                       /* Get the HDC for the device */
+                                       long hDC = device.internal_new_GC(null);
+
+                                       /* Copy the bitmap */
+                                       long hdcSource = OS.CreateCompatibleDC(hDC);
+                                       long hdcDest = OS.CreateCompatibleDC(hDC);
+                                       long hOldSrc = OS.SelectObject(hdcSource, srcImage.handle);
+                                       BITMAP bm = new BITMAP();
+                                       OS.GetObject(srcImage.handle, BITMAP.sizeof, bm);
+                                       handle = OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits != 0 ? -rect.height : rect.height);
+                                       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                                       long 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 != null) {
+                                               alphaData = new byte[srcImage.alphaData.length];
+                                               System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
+                                       }
+                                       break;
+                               case SWT.ICON:
+                                       handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0);
+                                       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                                       break;
+                               default:
+                                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+                       }
+                       break;
+               }
+               case SWT.IMAGE_DISABLE: {
+                       ImageData data = srcImage.getImageDataAtCurrentZoom();
+                       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 != -1) newData.transparentPixel = 0;
+
+                       /* Convert the pixels. */
+                       int[] scanline = new int[rect.width];
+                       int[] maskScanline = null;
+                       ImageData mask = null;
+                       if (data.maskData != null) mask = data.getTransparencyMask();
+                       if (mask != 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 != null) mask.getPixels(0, y, rect.width, maskScanline, 0);
+                               for (int x=0; x<rect.width; x++) {
+                                       int pixel = scanline[x];
+                                       if (!((data.transparentPixel != -1 && pixel == data.transparentPixel) || (mask != null && maskScanline[x] == 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] = (byte)1;
+                                               } else {
+                                                       newData.data[offset] = (byte)2;
+                                               }
+                                       }
+                                       offset++;
+                               }
+                       }
+                       init (newData);
+                       break;
+               }
+               case SWT.IMAGE_GRAY: {
+                       ImageData data = srcImage.getImageDataAtCurrentZoom();
+                       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 != 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 != -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 != 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 == intensity) intensity = 255;
+                                                       newData.data[offset] = (byte)intensity;
+                                               } else {
+                                                       newData.data[offset] = (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>
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </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>
+ *
+ * @see #dispose()
+ */
+public Image(Device device, Rectangle bounds) {
+       super(device);
+       if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       bounds = DPIUtil.autoScaleUp (bounds);
+       init(bounds.width, bounds.height);
+       init();
+}
+
+/**
+ * Constructs an instance of this class from the given
+ * <code>ImageData</code>.
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </p>
+ *
+ * @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>
+ *
+ * @see #dispose()
+ */
+public Image(Device device, ImageData data) {
+       super(device);
+       if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       data = DPIUtil.autoScaleUp (device, data);
+       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>
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </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>
+ *
+ * @see #dispose()
+ */
+public Image(Device device, ImageData source, ImageData mask) {
+       super(device);
+       if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (mask == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (source.width != mask.width || source.height != mask.height) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       source = DPIUtil.autoScaleUp(device, source);
+       mask = DPIUtil.autoScaleUp(device, mask);
+       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 == 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>
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </p>
+ *
+ * @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>
+ *
+ * @see #dispose()
+ */
+public Image (Device device, InputStream stream) {
+       super(device);
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       ImageData data = DPIUtil.autoScaleUp(device, new ImageData(stream));
+       init(data);
+       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.
+ * <p>
+ * You must dispose the image when it is no longer required.
+ * </p>
+ *
+ * @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>
+ *
+ * @see #dispose()
+ */
+public Image (Device device, String filename) {
+       super(device);
+       if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       ImageData data = DPIUtil.autoScaleUp(device, new ImageData(filename));
+       init(data);
+       init();
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the file retrieved from the ImageFileNameProvider. 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 for loading image as
+ * per DPI level.
+ *
+ * @param device the device on which to create the image
+ * @param imageFileNameProvider the ImageFileNameProvider object that is
+ * to be used to get the file name
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the ImageFileNameProvider is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the fileName provided by ImageFileNameProvider is null at 100% zoom</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>
+ * @since 3.104
+ */
+public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
+       super(device);
+       this.imageFileNameProvider = imageFileNameProvider;
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       boolean[] found = new boolean[1];
+       String fileName = DPIUtil.validateAndGetImagePathAtZoom (imageFileNameProvider, currentDeviceZoom, found);
+       if (found[0]) {
+               initNative (fileName);
+               if (this.handle == 0) init(new ImageData (fileName));
+       } else {
+               ImageData resizedData = DPIUtil.autoScaleUp (device, new ImageData (fileName));
+               init(resizedData);
+       }
+       init();
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the ImageData retrieved from the ImageDataProvider. 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 for loading image as
+ * per DPI level.
+ *
+ * @param device the device on which to create the image
+ * @param imageDataProvider the ImageDataProvider object that is
+ * to be used to get the ImageData
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the ImageDataProvider is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the ImageData provided by ImageDataProvider is null at 100% zoom</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>
+ * @since 3.104
+ */
+public Image(Device device, ImageDataProvider imageDataProvider) {
+       super(device);
+       this.imageDataProvider = imageDataProvider;
+       currentDeviceZoom = DPIUtil.getDeviceZoom ();
+       boolean[] found = new boolean[1];
+       ImageData data =  DPIUtil.validateAndGetImageDataAtZoom(imageDataProvider, currentDeviceZoom, found);
+       if (found[0]) {
+               init(data);
+       } else {
+               ImageData resizedData = DPIUtil.autoScaleUp(device, data);
+               init (resizedData);
+       }
+       init();
+}
+
+/**
+ * Refresh the Image based on the zoom level, if required.
+ *
+ * @return true if image is refreshed
+ */
+boolean refreshImageForZoom () {
+       boolean refreshed = false;
+       int deviceZoomLevel = DPIUtil.getDeviceZoom();
+       if (imageFileNameProvider != null) {
+               if (deviceZoomLevel != currentDeviceZoom) {
+                       boolean[] found = new boolean[1];
+                       String filename = DPIUtil.validateAndGetImagePathAtZoom (imageFileNameProvider, deviceZoomLevel, found);
+                       /* Avoid re-creating the fall-back image, when current zoom is already 100% */
+                       if (found[0] || currentDeviceZoom != 100) {
+                               /* Release current native resources */
+                               destroy ();
+                               initNative(filename);
+                               if (this.handle == 0) init(new ImageData (filename));
+                               init();
+                               refreshed = true;
+                       }
+                       if (!found[0]) {
+                               /* Release current native resources */
+                               destroy ();
+                               ImageData resizedData = DPIUtil.autoScaleUp (device, new ImageData (filename));
+                               init(resizedData);
+                               init ();
+                               refreshed = true;
+                       }
+                       currentDeviceZoom = deviceZoomLevel;
+               }
+       } else if (imageDataProvider != null) {
+               if (deviceZoomLevel != currentDeviceZoom) {
+                       boolean[] found = new boolean[1];
+                       ImageData data = DPIUtil.validateAndGetImageDataAtZoom (imageDataProvider, deviceZoomLevel, found);
+                       /* Avoid re-creating the fall-back image, when current zoom is already 100% */
+                       if (found[0] || currentDeviceZoom != 100) {
+                               /* Release current native resources */
+                               destroy ();
+                               init(data);
+                               init();
+                               refreshed = true;
+                       }
+                       if (!found[0]) {
+                               /* Release current native resources */
+                               destroy ();
+                               ImageData resizedData = DPIUtil.autoScaleUp (device, data);
+                               init(resizedData);
+                               init();
+                               refreshed = true;
+                       }
+                       currentDeviceZoom = deviceZoomLevel;
+               }
+       } else {
+               if (deviceZoomLevel != currentDeviceZoom) {
+                       ImageData data = getImageDataAtCurrentZoom();
+                       destroy ();
+                       ImageData resizedData = DPIUtil.autoScaleImageData(device, data, deviceZoomLevel, currentDeviceZoom);
+                       init(resizedData);
+                       init();
+                       refreshed = true;
+                       currentDeviceZoom = deviceZoomLevel;
+               }
+       }
+       return refreshed;
+}
+
+void initNative(String filename) {
+       device.checkGDIP();
+       boolean gdip = true;
+       /*
+       * 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 && C.PTR_SIZEOF == 8 && filename.toLowerCase().endsWith(".gif")) gdip = false;
+       /*
+       * Bug in GDI+. Bitmap.LockBits() fails to load GIF files in
+       * Windows 7 when the image has a position offset in the first frame.
+       * The fix is to not use GDI+ image loading in this case.
+       */
+       if (OS.WIN32_VERSION >= OS.VERSION(6, 1) && filename.toLowerCase().endsWith(".gif")) gdip = false;
+       if (gdip) {
+               int length = filename.length();
+               char[] chars = new char[length+1];
+               filename.getChars(0, length, chars, 0);
+               long bitmap = Gdip.Bitmap_new(chars, false);
+               if (bitmap != 0) {
+                       int error = SWT.ERROR_NO_HANDLES;
+                       int status = Gdip.Image_GetLastStatus(bitmap);
+                       if (status == 0) {
+                               if (filename.toLowerCase().endsWith(".ico")) {
+                                       this.type = SWT.ICON;
+                                       long[] hicon = new long[1];
+                                       status = Gdip.Bitmap_GetHICON(bitmap, hicon);
+                                       this.handle = hicon[0];
+                               } else {
+                                       this.type = SWT.BITMAP;
+                                       int width = Gdip.Image_GetWidth(bitmap);
+                                       int height = Gdip.Image_GetHeight(bitmap);
+                                       int pixelFormat = Gdip.Image_GetPixelFormat(bitmap);
+                                       switch (pixelFormat) {
+                                               case Gdip.PixelFormat16bppRGB555:
+                                               case Gdip.PixelFormat16bppRGB565:
+                                                       this.handle = createDIB(width, height, 16);
+                                                       break;
+                                               case Gdip.PixelFormat24bppRGB:
+                                               case Gdip.PixelFormat32bppCMYK:
+                                                       this.handle = createDIB(width, height, 24);
+                                                       break;
+                                               case Gdip.PixelFormat32bppRGB:
+                                               // These will lose 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;
+                                       }
+                                       if (this.handle != 0) {
+                                               /*
+                                               * This performs better than getting the bits with Bitmap.LockBits(),
+                                               * but it cannot be used when there is transparency.
+                                               */
+                                               long hDC = device.internal_new_GC(null);
+                                               long srcHDC = OS.CreateCompatibleDC(hDC);
+                                               long oldSrcBitmap = OS.SelectObject(srcHDC, this.handle);
+                                               long graphics = Gdip.Graphics_new(srcHDC);
+                                               if (graphics != 0) {
+                                                       Rect rect = new Rect();
+                                                       rect.Width = width;
+                                                       rect.Height = height;
+                                                       status = Gdip.Graphics_DrawImage(graphics, bitmap, rect, 0, 0, width, height, Gdip.UnitPixel, 0, 0, 0);
+                                                       if (status != 0) {
+                                                               error = SWT.ERROR_INVALID_IMAGE;
+                                                               OS.DeleteObject(handle);
+                                                               this.handle = 0;
+                                                       }
+                                                       Gdip.Graphics_delete(graphics);
+                                               }
+                                               OS.SelectObject(srcHDC, oldSrcBitmap);
+                                               OS.DeleteDC(srcHDC);
+                                               device.internal_dispose_GC(hDC, null);
+                                       } else {
+                                               long lockedBitmapData = Gdip.BitmapData_new();
+                                               if (lockedBitmapData != 0) {
+                                                       status = Gdip.Bitmap_LockBits(bitmap, 0, 0, pixelFormat, lockedBitmapData);
+                                                       if (status == 0) {
+                                                               BitmapData bitmapData = new BitmapData();
+                                                               Gdip.MoveMemory(bitmapData, lockedBitmapData);
+                                                               int stride = bitmapData.Stride;
+                                                               long pixels = bitmapData.Scan0;
+                                                               int depth = 0, scanlinePad = 4, transparentPixel = -1;
+                                                               switch (bitmapData.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;
+                                                               }
+                                                               if (depth != 0) {
+                                                                       PaletteData paletteData = null;
+                                                                       switch (bitmapData.PixelFormat) {
+                                                                               case Gdip.PixelFormat1bppIndexed:
+                                                                               case Gdip.PixelFormat4bppIndexed:
+                                                                               case Gdip.PixelFormat8bppIndexed:
+                                                                                       int paletteSize = Gdip.Image_GetPaletteSize(bitmap);
+                                                                                       long hHeap = OS.GetProcessHeap();
+                                                                                       long palette = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, paletteSize);
+                                                                                       if (palette == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                                                                                       Gdip.Image_GetPalette(bitmap, palette, paletteSize);
+                                                                                       ColorPalette colorPalette = new ColorPalette();
+                                                                                       Gdip.MoveMemory(colorPalette, palette, ColorPalette.sizeof);
+                                                                                       int[] entries = new int[colorPalette.Count];
+                                                                                       OS.MoveMemory(entries, palette + 8, entries.length * 4);
+                                                                                       OS.HeapFree(hHeap, 0, palette);
+                                                                                       RGB[] rgbs = new RGB[colorPalette.Count];
+                                                                                       paletteData = new PaletteData(rgbs);
+                                                                                       for (int i = 0; i < entries.length; i++) {
+                                                                                               if (((entries[i] >> 24) & 0xFF) == 0 && (colorPalette.Flags & Gdip.PaletteFlagsHasAlpha) != 0) {
+                                                                                                       transparentPixel = i;
+                                                                                               }
+                                                                                               rgbs[i] = new RGB(((entries[i] & 0xFF0000) >> 16), ((entries[i] & 0xFF00) >> 8), ((entries[i] & 0xFF) >> 0));
+                                                                                       }
+                                                                                       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;
+                                                                       }
+                                                                       byte[] data = new byte[stride * height], alphaData = null;
+                                                                       OS.MoveMemory(data, pixels, data.length);
+                                                                       switch (bitmapData.PixelFormat) {
+                                                                               case Gdip.PixelFormat16bppARGB1555:
+                                                                                       alphaData = new byte[width * height];
+                                                                                       for (int i = 1, j = 0; i < data.length; i += 2, j++) {
+                                                                                               alphaData[j] = (byte)((data[i] & 0x80) != 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;
+                                                                       }
+                                                                       ImageData img = new ImageData(width, height, depth, paletteData, scanlinePad, data);
+                                                                       img.transparentPixel = transparentPixel;
+                                                                       img.alphaData = alphaData;
+                                                                       init(img);
+                                                               }
+                                                               Gdip.Bitmap_UnlockBits(bitmap, lockedBitmapData);
+                                                       } else {
+                                                               error = SWT.ERROR_INVALID_IMAGE;
+                                                       }
+                                                       Gdip.BitmapData_delete(lockedBitmapData);
+                                               }
+                                       }
+                               }
+                       }
+                       Gdip.Bitmap_delete(bitmap);
+                       if (status == 0) {
+                               if (this.handle == 0) SWT.error(error);
+                       }
+               }
+       }
+}
+
+long [] createGdipImage() {
+       switch (type) {
+               case SWT.BITMAP: {
+                       if (alpha != -1 || alphaData != null || transparentPixel != -1) {
+                               BITMAP bm = new BITMAP();
+                               OS.GetObject(handle, BITMAP.sizeof, bm);
+                               int imgWidth = bm.bmWidth;
+                               int imgHeight = bm.bmHeight;
+                               long hDC = device.internal_new_GC(null);
+                               long srcHdc = OS.CreateCompatibleDC(hDC);
+                               long oldSrcBitmap = OS.SelectObject(srcHdc, handle);
+                               long memHdc = OS.CreateCompatibleDC(hDC);
+                               long memDib = createDIB(imgWidth, imgHeight, 32);
+                               if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               long oldMemBitmap = OS.SelectObject(memHdc, memDib);
+                               BITMAP dibBM = new BITMAP();
+                               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 != -1) {
+                                       if (bm.bmBitsPixel <= 8)  {
+                                               byte[] color = new byte[4];
+                                               OS.GetDIBColorTable(srcHdc, transparentPixel, 1, color);
+                                               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 = (byte)((transparentPixel & 0xFF0000) >> 16);
+                                                               green = (byte)((transparentPixel & 0xFF00) >> 8);
+                                                               red = (byte)(transparentPixel & 0xFF);
+                                                               break;
+                                                       case 32:
+                                                               blue = (byte)((transparentPixel & 0xFF000000) >>> 24);
+                                                               green = (byte)((transparentPixel & 0xFF0000) >> 16);
+                                                               red = (byte)((transparentPixel & 0xFF00) >> 8);
+                                                               break;
+                                               }
+                                       }
+                               }
+                               OS.SelectObject(srcHdc, oldSrcBitmap);
+                               OS.SelectObject(memHdc, oldMemBitmap);
+                               OS.DeleteObject(srcHdc);
+                               OS.DeleteObject(memHdc);
+                               byte[] srcData = new byte[sizeInBytes];
+                               OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
+                               OS.DeleteObject(memDib);
+                               device.internal_dispose_GC(hDC, null);
+                               if (alpha != -1) {
+                                       for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                                               for (int x = 0; x < imgWidth; ++x) {
+                                                       srcData[dp + 3] = (byte)alpha;
+                                                       dp += 4;
+                                               }
+                                       }
+                               } else if (alphaData != 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 != -1) {
+                                       for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                                               for (int x = 0; x < imgWidth; ++x) {
+                                                       if (srcData[dp] == blue && srcData[dp + 1] == green && srcData[dp + 2] == red) {
+                                                               srcData[dp + 3] = (byte)0;
+                                                       } else {
+                                                               srcData[dp + 3] = (byte)0xFF;
+                                                       }
+                                                       dp += 4;
+                                               }
+                                       }
+                               }
+                               long hHeap = OS.GetProcessHeap();
+                               long pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
+                               if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               OS.MoveMemory(pixels, srcData, sizeInBytes);
+                               return new long []{Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels), pixels};
+                       }
+                       return new long []{Gdip.Bitmap_new(handle, 0), 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 = new ICONINFO();
+                       OS.GetIconInfo(handle, iconInfo);
+                       long hBitmap = iconInfo.hbmColor;
+                       if (hBitmap == 0) hBitmap = iconInfo.hbmMask;
+                       BITMAP bm = new BITMAP();
+                       OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+                       int imgWidth = bm.bmWidth;
+                       int imgHeight = hBitmap == iconInfo.hbmMask ? bm.bmHeight / 2 : bm.bmHeight;
+                       long img = 0, pixels = 0;
+                       /*
+                       * 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 == 32) {
+                               long hDC = device.internal_new_GC(null);
+                               long srcHdc = OS.CreateCompatibleDC(hDC);
+                               long oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap);
+                               long memHdc = OS.CreateCompatibleDC(hDC);
+                               long memDib = createDIB(imgWidth, imgHeight, 32);
+                               if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               long oldMemBitmap = OS.SelectObject(memHdc, memDib);
+                               BITMAP dibBM = new BITMAP();
+                               OS.GetObject(memDib, BITMAP.sizeof, dibBM);
+                               OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, hBitmap == iconInfo.hbmMask ? imgHeight : 0, OS.SRCCOPY);
+                               OS.SelectObject(memHdc, oldMemBitmap);
+                               OS.DeleteObject(memHdc);
+                               byte[] srcData = new byte[dibBM.bmWidthBytes * dibBM.bmHeight];
+                               OS.MoveMemory(srcData, 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] == 0) {
+                                                       if (OS.GetPixel(srcHdc, x, y) != 0) {
+                                                               srcData[dp] = (byte)0;
+                                                       } else {
+                                                               srcData[dp] = (byte)0xFF;
+                                                       }
+                                               }
+                                               dp += 4;
+                                       }
+                               }
+                               OS.SelectObject(srcHdc, oldSrcBitmap);
+                               OS.DeleteObject(srcHdc);
+                               device.internal_dispose_GC(hDC, null);
+                               long hHeap = OS.GetProcessHeap();
+                               pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
+                               if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                               OS.MoveMemory(pixels, srcData, srcData.length);
+                               img = Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels);
+                       } else {
+                               img = Gdip.Bitmap_new(handle);
+                       }
+                       if (iconInfo.hbmColor != 0) OS.DeleteObject(iconInfo.hbmColor);
+                       if (iconInfo.hbmMask != 0) OS.DeleteObject(iconInfo.hbmMask);
+                       return new long []{img, pixels};
+               }
+               default: SWT.error(SWT.ERROR_INVALID_IMAGE);
+       }
+       return null;
+}
+
+@Override
+void destroy () {
+       if (memGC != null) memGC.dispose();
+       if (type == SWT.ICON) {
+               OS.DestroyIcon (handle);
+       } else {
+               OS.DeleteObject (handle);
+       }
+       handle = 0;
+       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 boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Image)) return false;
+       Image image = (Image) object;
+       if (device != image.device || transparentPixel != image.transparentPixel) return false;
+       if (imageDataProvider != null && image.imageDataProvider != null) {
+               return (styleFlag == image.styleFlag) && imageDataProvider.equals (image.imageDataProvider);
+       } else if (imageFileNameProvider != null && image.imageFileNameProvider != null) {
+               return (styleFlag == image.styleFlag) && imageFileNameProvider.equals (image.imageFileNameProvider);
+       } else {
+               return handle == 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 == -1) return null;
+
+       /* Get the HDC for the device */
+       long hDC = device.internal_new_GC(null);
+
+       /* Compute the background color */
+       BITMAP bm = new BITMAP();
+       OS.GetObject(handle, BITMAP.sizeof, bm);
+       long hdcMem = OS.CreateCompatibleDC(hDC);
+       long hOldObject = OS.SelectObject(hdcMem, handle);
+       int red = 0, green = 0, blue = 0;
+       if (bm.bmBitsPixel <= 8)  {
+               byte[] color = new byte[4];
+               OS.GetDIBColorTable(hdcMem, transparentPixel, 1, color);
+               blue = color[0] & 0xFF;
+               green = color[1] & 0xFF;
+               red = color[2] & 0xFF;
+       } 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 in points.
+ *
+ * @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);
+       return getBounds (100);
+}
+
+Rectangle getBounds(int zoom) {
+       Rectangle bounds = getBoundsInPixels();
+       if (bounds != null && zoom != currentDeviceZoom) {
+               bounds = DPIUtil.autoScaleBounds(bounds, zoom, currentDeviceZoom);
+       }
+       return bounds;
+}
+
+/**
+ * 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 in pixels.
+ *
+ * @return a rectangle specifying the image's bounds in pixels.
+ *
+ * @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>
+ * @since 3.105
+ * @deprecated This API doesn't serve the purpose in an environment having
+ *             multiple monitors with different DPIs, hence deprecated.
+ */
+@Deprecated
+public Rectangle getBoundsInPixels() {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (width != -1 && height != -1) {
+               return new Rectangle(0, 0, width, height);
+       }
+       switch (type) {
+               case SWT.BITMAP:
+                       BITMAP bm = new BITMAP();
+                       OS.GetObject(handle, BITMAP.sizeof, bm);
+                       return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight);
+               case SWT.ICON:
+                       ICONINFO info = new ICONINFO();
+                       OS.GetIconInfo(handle, info);
+                       long hBitmap = info.hbmColor;
+                       if (hBitmap == 0) hBitmap = info.hbmMask;
+                       bm = new BITMAP();
+                       OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+                       if (hBitmap == info.hbmMask) bm.bmHeight /= 2;
+                       if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor);
+                       if (info.hbmMask != 0) 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 at 100% zoom level.
+ *
+ * @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);
+       return getImageData(100);
+}
+
+/**
+ * Returns an {@link ImageData} for the given zoom level based on the
+ * receiver.
+ * <p>
+ * Note that this method is mainly intended to be used by custom
+ * implementations of {@link ImageDataProvider} that draw a composite image
+ * at the requested zoom level based on other images. For custom zoom
+ * levels, the image data may be an auto-scaled version of the native image
+ * and may look more blurred or mangled than expected.
+ * </p>
+ * <p>
+ * Modifications made to the returned {@code ImageData} will not affect this
+ * {@code Image}.
+ * </p>
+ *
+ * @param zoom
+ *            The zoom level in % of the standard resolution (which is 1
+ *            physical monitor pixel == 1 SWT logical point). Typically 100,
+ *            150, or 200.
+ * @return an <code>ImageData</code> containing the image's data and
+ *         attributes at the given zoom level
+ *
+ * @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>
+ *
+ * @since 3.106
+ */
+public ImageData getImageData (int zoom) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+
+       if (zoom == currentDeviceZoom) {
+               return getImageDataAtCurrentZoom();
+       } else if (imageDataProvider != null) {
+               boolean[] found = new boolean[1];
+               ImageData data = DPIUtil.validateAndGetImageDataAtZoom (imageDataProvider, zoom, found);
+               // exact image found
+               if (found[0]) {
+                       return data;
+               }
+               // AutoScale the image at 100% zoom
+               return DPIUtil.autoScaleImageData (device, data, zoom, 100);
+       } else if (imageFileNameProvider != null) {
+               boolean[] found = new boolean[1];
+               String fileName = DPIUtil.validateAndGetImagePathAtZoom (imageFileNameProvider, zoom, found);
+               // exact image found
+               if (found[0]) {
+                       return new ImageData (fileName);
+               }
+               // AutoScale the image at 100% zoom
+               return DPIUtil.autoScaleImageData (device, new ImageData (fileName), zoom, 100);
+       } else {
+               return DPIUtil.autoScaleImageData (device, getImageDataAtCurrentZoom (), zoom, currentDeviceZoom);
+       }
+}
+
+/**
+ * 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 at the current zoom level.
+ *
+ * @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
+ * @since 3.105
+ * @deprecated This API doesn't serve the purpose in an environment having
+ *             multiple monitors with different DPIs, hence deprecated. Use
+ *             {@link #getImageData(int)} instead.
+ */
+@Deprecated
+public ImageData getImageDataAtCurrentZoom() {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       BITMAP bm;
+       int depth, width, height;
+       switch (type) {
+               case SWT.ICON: {
+                       ICONINFO info = new ICONINFO();
+                       OS.GetIconInfo(handle, info);
+                       /* Get the basic BITMAP information */
+                       long hBitmap = info.hbmColor;
+                       if (hBitmap == 0) hBitmap = info.hbmMask;
+                       bm = new BITMAP();
+                       OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+                       depth = bm.bmPlanes * bm.bmBitsPixel;
+                       width = bm.bmWidth;
+                       if (hBitmap == info.hbmMask) bm.bmHeight /= 2;
+                       height = bm.bmHeight;
+                       int numColors = 0;
+                       if (depth <= 8) numColors = 1 << depth;
+                       /* Create the BITMAPINFO */
+                       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+                       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                       bmiHeader.biWidth = width;
+                       bmiHeader.biHeight = -height;
+                       bmiHeader.biPlanes = 1;
+                       bmiHeader.biBitCount = (short)depth;
+                       bmiHeader.biCompression = OS.BI_RGB;
+                       byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+                       OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+
+                       /* Get the HDC for the device */
+                       long hDC = device.internal_new_GC(null);
+
+                       /* Create the DC and select the bitmap */
+                       long hBitmapDC = OS.CreateCompatibleDC(hDC);
+                       long hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap);
+                       /* Find the size of the image and allocate data */
+                       int imageSize;
+                       /* Call with null lpBits to get the image size */
+                       OS.GetDIBits(hBitmapDC, hBitmap, 0, height, null, bmi, OS.DIB_RGB_COLORS);
+                       OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
+                       imageSize = bmiHeader.biSizeImage;
+                       byte[] data = new byte[imageSize];
+                       /* Get the bitmap data */
+                       OS.GetDIBits(hBitmapDC, hBitmap, 0, height, data, bmi, OS.DIB_RGB_COLORS);
+                       /* 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 == 16) {
+                               palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+                       } else if (depth == 24) {
+                               palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+                       } else if (depth == 32) {
+                               palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                       } else {
+                               SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+                       }
+
+                       /* Do the mask */
+                       byte [] maskData = null;
+                       if (info.hbmColor == 0) {
+                               /* Do the bottom half of the mask */
+                               maskData = new byte[imageSize];
+                               OS.GetDIBits(hBitmapDC, hBitmap, height, height, maskData, bmi, OS.DIB_RGB_COLORS);
+                       } else {
+                               /* Do the entire mask */
+                               /* Create the BITMAPINFO */
+                               bmiHeader = new BITMAPINFOHEADER();
+                               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, bmiHeader, BITMAPINFOHEADER.sizeof);
+
+                               /* First color black, second color white */
+                               int offset = BITMAPINFOHEADER.sizeof;
+                               bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = (byte)0xFF;
+                               bmi[offset + 7] = 0;
+                               OS.SelectObject(hBitmapDC, info.hbmMask);
+                               /* Call with null lpBits to get the image size */
+                               OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, null, bmi, OS.DIB_RGB_COLORS);
+                               OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
+                               imageSize = bmiHeader.biSizeImage;
+                               maskData = new byte[imageSize];
+                               OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, maskData, bmi, OS.DIB_RGB_COLORS);
+                               /* 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 == bpl) break;
+                               }
+                               maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2);
+                       }
+                       /* Clean up */
+                       OS.SelectObject(hBitmapDC, hOldBitmap);
+                       OS.DeleteDC(hBitmapDC);
+
+                       /* Release the HDC for the device */
+                       device.internal_dispose_GC(hDC, null);
+
+                       if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor);
+                       if (info.hbmMask != 0) 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 = new BITMAP();
+                       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. */
+                       boolean isDib = (bm.bmBits != 0);
+                       /* Get the HDC for the device */
+                       long hDC = device.internal_new_GC(null);
+                       DIBSECTION dib = null;
+                       if (isDib) {
+                               dib = new DIBSECTION();
+                               OS.GetObject(handle, DIBSECTION.sizeof, dib);
+                       }
+                       /* Calculate number of colors */
+                       int numColors = 0;
+                       if (depth <= 8) {
+                               if (isDib) {
+                                       numColors = dib.biClrUsed;
+                               } else {
+                                       numColors = 1 << depth;
+                               }
+                       }
+                       /* Create the BITMAPINFO */
+                       byte[] bmi = null;
+                       BITMAPINFOHEADER bmiHeader = null;
+                       if (!isDib) {
+                               bmiHeader = new BITMAPINFOHEADER();
+                               bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                               bmiHeader.biWidth = width;
+                               bmiHeader.biHeight = -height;
+                               bmiHeader.biPlanes = 1;
+                               bmiHeader.biBitCount = (short)depth;
+                               bmiHeader.biCompression = OS.BI_RGB;
+                               bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+                               OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+                       }
+
+                       /* Create the DC and select the bitmap */
+                       long hBitmapDC = OS.CreateCompatibleDC(hDC);
+                       long hOldBitmap = OS.SelectObject(hBitmapDC, handle);
+                       /* Find the size of the image and allocate data */
+                       int imageSize;
+                       if (isDib) {
+                               imageSize = dib.biSizeImage;
+                       } else {
+                               /* Call with null lpBits to get the image size */
+                               OS.GetDIBits(hBitmapDC, handle, 0, height, null, bmi, OS.DIB_RGB_COLORS);
+                               OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
+                               imageSize = bmiHeader.biSizeImage;
+                       }
+                       byte[] data = new byte[imageSize];
+                       /* Get the bitmap data */
+                       if (isDib) {
+                               OS.MoveMemory(data, bm.bmBits, imageSize);
+                       } else {
+                               OS.GetDIBits(hBitmapDC, handle, 0, height, data, bmi, OS.DIB_RGB_COLORS);
+                       }
+                       /* Calculate the palette */
+                       PaletteData palette = null;
+                       if (depth <= 8) {
+                               RGB[] rgbs = new RGB[numColors];
+                               if (isDib) {
+                                       byte[] colors = new byte[numColors * 4];
+                                       OS.GetDIBColorTable(hBitmapDC, 0, numColors, colors);
+                                       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 == 16) {
+                               palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+                       } else if (depth == 24) {
+                               palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+                       } else if (depth == 32) {
+                               palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                       } else {
+                               SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+                       }
+                       /* Clean up */
+                       OS.SelectObject(hBitmapDC, hOldBitmap);
+                       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 == -1 && alphaData != 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 int hashCode () {
+       if (imageDataProvider != null) {
+               return imageDataProvider.hashCode();
+       } else if (imageFileNameProvider != null) {
+               return imageFileNameProvider.hashCode();
+       } else {
+               return (int)handle;
+       }
+}
+
+void init(int width, int height) {
+       if (width <= 0 || height <= 0) {
+               SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       type = SWT.BITMAP;
+       long 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 == 0) {
+               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 != 0) {
+               long memDC = OS.CreateCompatibleDC(hDC);
+               long 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 == 0) {
+               SWT.error(SWT.ERROR_NO_HANDLES, null, device.getLastError());
+       }
+}
+
+static long createDIB(int width, int height, int depth) {
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+       bmiHeader.biWidth = width;
+       bmiHeader.biHeight = -height;
+       bmiHeader.biPlanes = 1;
+       bmiHeader.biBitCount = (short)depth;
+       bmiHeader.biCompression = OS.BI_RGB;
+       byte[] bmi = new byte[BITMAPINFOHEADER.sizeof];
+       OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+       long[] pBits = new long[1];
+       return OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+}
+
+static long [] init(Device device, Image image, ImageData i) {
+       /* Windows does not support 2-bit images. Convert to 4-bit image. */
+       if (i.depth == 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.
+        */
+       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 == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) {
+                                       newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+                               }
+                               break;
+                       case 24:
+                               if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) {
+                                       newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+                               }
+                               break;
+                       case 32:
+                               if (!(redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+                                       newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                               }
+                               break;
+                       default:
+                               SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+               }
+               if (newPalette != 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 != -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();
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+       bmiHeader.biWidth = i.width;
+       bmiHeader.biHeight = -i.height;
+       bmiHeader.biPlanes = 1;
+       bmiHeader.biBitCount = (short)i.depth;
+       bmiHeader.biCompression = OS.BI_RGB;
+       bmiHeader.biClrUsed = rgbs == null ? 0 : rgbs.length;
+       byte[] bmi;
+       if (i.palette.isDirect)
+               bmi = new byte[BITMAPINFOHEADER.sizeof];
+       else
+               bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
+       OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+       /* Set the rgb colors into the bitmap info */
+       int offset = BITMAPINFOHEADER.sizeof;
+       if (!i.palette.isDirect) {
+               for (int j = 0; j < rgbs.length; j++) {
+                       bmi[offset] = (byte)rgbs[j].blue;
+                       bmi[offset + 1] = (byte)rgbs[j].green;
+                       bmi[offset + 2] = (byte)rgbs[j].red;
+                       bmi[offset + 3] = 0;
+                       offset += 4;
+               }
+       }
+       long[] pBits = new long[1];
+       long hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+       if (hDib == 0) 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 != 4 && (i.bytesPerLine % 4 != 0)) {
+               data = ImageData.convertPad(data, i.width, i.height, i.depth, i.scanlinePad, 4);
+       }
+       OS.MoveMemory(pBits[0], data, data.length);
+
+       long [] result = null;
+       if (i.getTransparencyType() == SWT.TRANSPARENCY_MASK) {
+               /* Get the HDC for the device */
+               long hDC = device.internal_new_GC(null);
+
+               /* Create the color bitmap */
+               long hdcSrc = OS.CreateCompatibleDC(hDC);
+               OS.SelectObject(hdcSrc, hDib);
+               long hBitmap = OS.CreateCompatibleBitmap(hDC, i.width, i.height);
+               if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               long 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);
+               long hMask = OS.CreateBitmap(i.width, i.height, 1, 1, maskData);
+               if (hMask == 0) 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 == null) {
+                       result = new long []{hBitmap, hMask};
+               } else {
+                       /* Create the icon */
+                       ICONINFO info = new ICONINFO();
+                       info.fIcon = true;
+                       info.hbmColor = hBitmap;
+                       info.hbmMask = hMask;
+                       long hIcon = OS.CreateIconIndirect(info);
+                       if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                       OS.DeleteObject(hBitmap);
+                       OS.DeleteObject(hMask);
+                       image.handle = hIcon;
+                       image.type = SWT.ICON;
+               }
+       } else {
+               if (image == null) {
+                       result = new long []{hDib};
+               } else {
+                       image.handle = hDib;
+                       image.type = SWT.BITMAP;
+                       image.transparentPixel = i.transparentPixel;
+                       if (image.transparentPixel == -1) {
+                               image.alpha = i.alpha;
+                               if (i.alpha == -1 && i.alphaData != null) {
+                                       int length = i.alphaData.length;
+                                       image.alphaData = new byte[length];
+                                       System.arraycopy(i.alphaData, 0, image.alphaData, 0, length);
+                               }
+                       }
+               }
+       }
+       return result;
+}
+
+static long [] 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 != -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].equals(black)) break;
+                               blackIndex++;
+                       }
+                       if (blackIndex == 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 == -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] == 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 == 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public long internal_new_GC (GCData data) {
+       if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       /*
+       * Create a new GC that can draw into the image.
+       * Only supported for bitmaps.
+       */
+       if (type != SWT.BITMAP || memGC != null) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+
+       /* Create a compatible HDC for the device */
+       long hDC = device.internal_new_GC(null);
+       long imageDC = OS.CreateCompatibleDC(hDC);
+       device.internal_dispose_GC(hDC, null);
+       if (imageDC == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+
+       if (data != null) {
+               /* Set the GCData fields */
+               int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+               if ((data.style & mask) != 0) {
+                       data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void internal_dispose_GC (long 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 (except {@link #dispose()}) using the image.
+ *
+ * @return <code>true</code> when the image is disposed and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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:</p>
+ * <pre>
+ *    Button b = new Button();
+ *    image.setBackground(b.getBackground());
+ *    b.setImage(image);
+ * </pre>
+ * <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) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (transparentPixel == -1) return;
+       transparentColor = -1;
+
+       /* Get the HDC for the device */
+       long hDC = device.internal_new_GC(null);
+
+       /* Change the background color in the image */
+       BITMAP bm = new BITMAP();
+       OS.GetObject(handle, BITMAP.sizeof, bm);
+       long hdcMem = OS.CreateCompatibleDC(hDC);
+       OS.SelectObject(hdcMem, handle);
+       int maxColors = 1 << bm.bmBitsPixel;
+       byte[] colors = new byte[maxColors * 4];
+       int numColors = OS.GetDIBColorTable(hdcMem, 0, maxColors, colors);
+       int offset = transparentPixel * 4;
+       colors[offset] = (byte)color.getBlue();
+       colors[offset + 1] = (byte)color.getGreen();
+       colors[offset + 2] = (byte)color.getRed();
+       OS.SetDIBColorTable(hdcMem, 0, numColors, colors);
+       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 "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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Image win32_new(Device device, int type, long handle) {
+       Image image = new Image(device);
+       image.type = type;
+       image.handle = handle;
+       return image;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageData.java
new file mode 100644 (file)
index 0000000..2811d54
--- /dev/null
@@ -0,0 +1,3704 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 implements Cloneable {
+
+       /**
+        * 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.
+        */
+       static final byte[][] ANY_TO_EIGHT = new byte[9][];
+       static {
+               for (int b = 0; b < 9; ++b) {
+                       byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b];
+                       if (b == 0) continue;
+                       int inc = 0;
+                       for (int bit = 0x10000; (bit >>= b) != 0;) inc |= bit;
+                       for (int v = 0, p = 0; v < 0x10000; v+= inc) data[p++] = (byte)(v >> 8);
+               }
+       }
+       static final byte[] ONE_TO_ONE_MAPPING = ANY_TO_EIGHT[8];
+
+       /**
+        * Scaled 8x8 Bayer dither matrix.
+        */
+       static final 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 zero or 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 ImageData(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 zero or 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 ImageData(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 == 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 ImageData(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 ImageData(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.
+ */
+ImageData() {
+}
+
+/**
+ * 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>
+ */
+ImageData(
+       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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (!(depth == 1 || depth == 2 || depth == 4 || depth == 8
+               || depth == 16 || depth == 24 || depth == 32)) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (width <= 0 || height <= 0) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (scanlinePad == 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 == SWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine;
+       if (data != null && data.length < minBytesPerLine * height) {
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       setAllFields(
+               width,
+               height,
+               depth,
+               scanlinePad,
+               bytesPerLine,
+               data != 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+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 != -1 && row[i] == pixel) {
+                               row[i] = 0;
+                       } else {
+                               row[i] = 1;
+                       }
+               }
+               mask.setPixels(0, y, width, row, 0);
+       }
+       return mask;
+}
+
+static byte[] checkData(byte [] data) {
+       if (data == 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.
+ */
+@Override
+public Object clone() {
+       byte[] cloneData = new byte[data.length];
+       System.arraycopy(data, 0, cloneData, 0, data.length);
+       byte[] cloneMaskData = null;
+       if (maskData != null) {
+               cloneMaskData = new byte[maskData.length];
+               System.arraycopy(maskData, 0, cloneMaskData, 0, maskData.length);
+       }
+       byte[] cloneAlphaData = null;
+       if (alphaData != 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 == 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 == 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 == 0) return;
+
+       if (alphaData == null) {
+               int endIndex = startIndex + getWidth;
+               for (int i = startIndex; i < endIndex; i++) {
+                       alphas[i] = (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) == 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) == 0) {
+                               return 0;
+                       } else {
+                               return 1;
+                       }
+       }
+       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 == 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 == 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) == 1) {
+                               theByte = data[index] & 0xFF;
+                               pixels[i] = (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] = (byte)(theByte >> 4);
+                               i++;
+                               n--;
+                               srcX++;
+                               if (srcX >= width) {
+                                       srcY++;
+                                       index = srcY * bytesPerLine;
+                                       srcX = 0;
+                               } else {
+                                       pixels[i] = (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] = (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] = (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 == 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) == 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 == 1) {
+                                               index++;
+                                               if (n > 0) theByte = data[index] & 0xFF;
+                                       }
+                               }
+                       }
+                       return;
+       }
+       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 == 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 == 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) == 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] = (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 == 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) == 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 == 1) {
+                                               index++;
+                                               if (n > 0) theByte = data[index] & 0xFF;
+                                       }
+                               }
+                       }
+                       return;
+       }
+       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() {
+       int transparencyType = getTransparencyType();
+       switch (transparencyType) {
+               case SWT.TRANSPARENCY_ALPHA: return getTransparencyMaskFromAlphaData();
+               case SWT.TRANSPARENCY_MASK: return new ImageData(width, height, 1, bwPalette(), maskPad, maskData);
+               case SWT.TRANSPARENCY_PIXEL: return colorMaskImage(transparentPixel);
+               default: return colorMaskImage(transparentPixel);
+       }
+}
+
+ImageData getTransparencyMaskFromAlphaData() {
+       ImageData mask = new ImageData(width, height, 1, bwPalette(), 2, null, 0, null, null, -1, -1, SWT.IMAGE_UNDEFINED, 0, 0, 0, 0);
+       int offset = 0;
+       for (int y = 0; y < height; y++) {
+               for (int x = 0; x < width; x++) {
+                       byte a = alphaData[offset++];
+                       if (a == 0) {
+                               mask.setPixel(x, y, 0);
+                       } else {
+                               mask.setPixel(x, y, 1);
+                       }
+               }
+       }
+       return mask;
+}
+
+/**
+ * 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 != null) return SWT.TRANSPARENCY_MASK;
+       if (transparentPixel != -1) return SWT.TRANSPARENCY_PIXEL;
+       if (alphaData != 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 != 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 */
+       final boolean flipX = (width < 0);
+       if (flipX) width = - width;
+       final boolean 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 != 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 != -1) {
+               dest.alpha = this.alpha;
+       } else if (alphaData != 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 == null) alphaData = new byte[width * height];
+       alphaData[y * width + x] = (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 == 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 == 0) return;
+
+       if (alphaData == 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]  = (byte)((pixelValue >> 24) & 0xFF);
+                       data[index + 1] = (byte)((pixelValue >> 16) & 0xFF);
+                       data[index + 2] = (byte)((pixelValue >> 8) & 0xFF);
+                       data[index + 3] = (byte)(pixelValue & 0xFF);
+                       return;
+               case 24:
+                       index = (y * bytesPerLine) + (x * 3);
+                       data[index] = (byte)((pixelValue >> 16) & 0xFF);
+                       data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
+                       data[index + 2] = (byte)(pixelValue & 0xFF);
+                       return;
+               case 16:
+                       index = (y * bytesPerLine) + (x * 2);
+                       data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
+                       data[index] = (byte)(pixelValue & 0xFF);
+                       return;
+               case 8:
+                       index = (y * bytesPerLine) + x ;
+                       data[index] = (byte)(pixelValue & 0xFF);
+                       return;
+               case 4:
+                       index = (y * bytesPerLine) + (x >> 1);
+                       if ((x & 0x1) == 0) {
+                               data[index] = (byte)((data[index] & 0x0F) | ((pixelValue & 0x0F) << 4));
+                       } else {
+                               data[index] = (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] = (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) == 1) {
+                               data[index] = (byte)(theByte | mask);
+                       } else {
+                               data[index] = (byte)(theByte & (mask ^ -1));
+                       }
+                       return;
+       }
+       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 == 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 == 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] = (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);
+                       boolean high = (x & 0x1) == 0;
+                       while (n > 0) {
+                               theByte = pixels[i] & 0x0F;
+                               if (high) {
+                                       data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
+                               } else {
+                                       data[index] = (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 = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
+                       index = (y * bytesPerLine) + (x >> 2);
+                       int offset = 3 - (x % 4);
+                       while (n > 0) {
+                               theByte = pixels[i] & 0x3;
+                               data[index] = (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 == 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) == 1) {
+                                       data[index] = (byte)((data[index] & 0xFF) | mask);
+                               } else {
+                                       data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
+                               }
+                               i++;
+                               n--;
+                               srcX++;
+                               if (srcX >= width) {
+                                       srcY++;
+                                       index = srcY * bytesPerLine;
+                                       srcX = 0;
+                               } else {
+                                       if (mask == 1) {
+                                               index++;
+                                       }
+                               }
+                       }
+                       return;
+       }
+       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 == 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 == 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] = (byte)((pixel >> 24) & 0xFF);
+                               data[index + 1] = (byte)((pixel >> 16) & 0xFF);
+                               data[index + 2] = (byte)((pixel >> 8) & 0xFF);
+                               data[index + 3] = (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] = (byte)((pixel >> 16) & 0xFF);
+                               data[index + 1] = (byte)((pixel >> 8) & 0xFF);
+                               data[index + 2] = (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] = (byte)(pixel & 0xFF);
+                               data[index + 1] = (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] = (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);
+                       boolean high = (x & 0x1) == 0;
+                       while (n > 0) {
+                               theByte = pixels[i] & 0x0F;
+                               if (high) {
+                                       data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
+                               } else {
+                                       data[index] = (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 = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
+                       index = (y * bytesPerLine) + (x >> 2);
+                       int offset = 3 - (x % 4);
+                       while (n > 0) {
+                               theByte = pixels[i] & 0x3;
+                               data[index] = (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 == 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) == 1) {
+                                       data[index] = (byte)((data[index] & 0xFF) | mask);
+                               } else {
+                                       data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
+                               }
+                               i++;
+                               n--;
+                               srcX++;
+                               if (srcX >= width) {
+                                       srcY++;
+                                       index = srcY * bytesPerLine;
+                                       srcX = 0;
+                               } else {
+                                       if (mask == 1) {
+                                               index++;
+                                       }
+                               }
+                       }
+                       return;
+       }
+       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) != 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 == 0) break;
+                       minDistance = distance;
+               }
+       }
+       return nearestPixel;
+}
+
+static ImageData convertMask(ImageData mask) {
+       if (mask.depth == 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 != null) {
+               while (blackIndex < rgbs.length) {
+                       if (rgbs[blackIndex].equals(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] == blackIndex) {
+                               pixels[i] = 0;
+                       } else {
+                               pixels[i] = 1;
+                       }
+               }
+               newMask.setPixels(0, y, mask.width, pixels, 0);
+       }
+       return newMask;
+}
+
+static byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
+       if (pad == 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 final 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 final 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 final int LSB_FIRST = 0;
+static final int MSB_FIRST = 1;
+
+/**
+ * Data types (internal)
+ */
+private static final 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,
+       boolean flipX, boolean flipY) {
+       if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode == ALPHA_TRANSPARENT)) return;
+
+       // these should be supplied as params later
+       int srcAlphaMask = 0, destAlphaMask = 0;
+
+       /*** Prepare scaling data ***/
+       final int dwm1 = destWidth - 1;
+       final int sfxi = (dwm1 != 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0;
+       final int dhm1 = destHeight - 1;
+       final int sfyi = (dhm1 != 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0;
+
+       /*** Prepare source-related data ***/
+       final int sbpp, stype;
+       switch (srcDepth) {
+               case 8:
+                       sbpp = 1;
+                       stype = TYPE_GENERIC_8;
+                       break;
+               case 16:
+                       sbpp = 2;
+                       stype = (srcOrder == 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 == 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 ***/
+       final int dbpp, dtype;
+       switch (destDepth) {
+               case 8:
+                       dbpp = 1;
+                       dtype = TYPE_GENERIC_8;
+                       break;
+               case 16:
+                       dbpp = 2;
+                       dtype = (destOrder == 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 == 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;
+       final int dprxi = (flipX) ? -dbpp : dbpp;
+       final int dpryi = (flipY) ? -destStride : destStride;
+
+       /*** Prepare special processing data ***/
+       int apr;
+       if ((op & BLIT_ALPHA) != 0) {
+               switch (alphaMode) {
+                       case ALPHA_MASK_UNPACKED:
+                       case ALPHA_CHANNEL_SEPARATE:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               apr = alphaY * alphaStride + alphaX;
+                               break;
+                       case ALPHA_MASK_PACKED:
+                               if (alphaData == 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 == 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 == 0x10000) && (stype == dtype) &&
+               (srcRedMask == destRedMask) && (srcGreenMask == destGreenMask) &&
+               (srcBlueMask == destBlueMask) && (srcAlphaMask == 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;
+               }
+               return;
+       }
+       /*Fast 32 to 32 blit */
+       if (alphaMode == 0x10000 && stype == TYPE_GENERIC_32_MSB && dtype == TYPE_GENERIC_32_MSB) {
+               if (srcRedMask == 0xFF00 && srcGreenMask == 0xff0000 && srcBlueMask == 0xff000000 && destRedMask == 0xFF0000 && destGreenMask == 0xff00 && destBlueMask == 0xff) {
+                       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 + 3];
+                                       destData[dp + 1] = srcData[sp + 2];
+                                       destData[dp + 2] = srcData[sp + 1];
+                                       destData[dp + 3] = srcData[sp];
+                                       sp += (sfx >>> 16) * 4;
+                               }
+                       }
+                       return;
+               }
+       }
+       /*Fast 24 to 32 blit */
+       if (alphaMode == 0x10000 && stype == TYPE_GENERIC_24 && dtype == TYPE_GENERIC_32_MSB) {
+               if (srcRedMask == 0xFF && srcGreenMask == 0xff00 && srcBlueMask == 0xff0000 && destRedMask == 0xFF0000 && destGreenMask == 0xff00 && destBlueMask == 0xff) {
+                       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] = 0;
+                                       destData[dp + 1] = srcData[sp + 2];
+                                       destData[dp + 2] = srcData[sp + 1];
+                                       destData[dp + 3] = srcData[sp];
+                                       sp += (sfx >>> 16) * 3;
+                               }
+                       }
+                       return;
+               }
+       }
+
+       /*** Comprehensive blit (apply transformations) ***/
+       final int srcRedShift = getChannelShift(srcRedMask);
+       final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
+       final int srcGreenShift = getChannelShift(srcGreenMask);
+       final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
+       final int srcBlueShift = getChannelShift(srcBlueMask);
+       final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
+       final int srcAlphaShift = getChannelShift(srcAlphaMask);
+       final byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)];
+
+       final int destRedShift = getChannelShift(destRedMask);
+       final int destRedWidth = getChannelWidth(destRedMask, destRedShift);
+       final byte[] destReds = ANY_TO_EIGHT[destRedWidth];
+       final int destRedPreShift = 8 - destRedWidth;
+       final int destGreenShift = getChannelShift(destGreenMask);
+       final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
+       final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
+       final int destGreenPreShift = 8 - destGreenWidth;
+       final int destBlueShift = getChannelShift(destBlueMask);
+       final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
+       final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
+       final int destBluePreShift = 8 - destBlueWidth;
+       final int destAlphaShift = getChannelShift(destAlphaMask);
+       final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
+       final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
+       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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;
+                       }
+
+                       /*** 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] != 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 == alphaData[i]) && (g == alphaData[i + 1]) && (b == alphaData[i + 2])) {
+                                                       alpha = 0x0000;
+                                                       break;
+                                               }
+                                       }
+                                       break;
+                       }
+                       if (alpha != 0x10000) {
+                               if (alpha == 0x0000) continue;
+                               switch (dtype) {
+                                       case TYPE_GENERIC_8: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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;
+                               }
+                               // 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 ***/
+                       final int data =
+                               (r >>> destRedPreShift << destRedShift) |
+                               (g >>> destGreenPreShift << destGreenShift) |
+                               (b >>> destBluePreShift << destBlueShift) |
+                               (a >>> destAlphaPreShift << destAlphaShift);
+                       switch (dtype) {
+                               case TYPE_GENERIC_8: {
+                                       destData[dp] = (byte) data;
+                               } break;
+                               case TYPE_GENERIC_16_MSB: {
+                                       destData[dp] = (byte) (data >>> 8);
+                                       destData[dp + 1] = (byte) (data & 0xff);
+                               } break;
+                               case TYPE_GENERIC_16_LSB: {
+                                       destData[dp] = (byte) (data & 0xff);
+                                       destData[dp + 1] = (byte) (data >>> 8);
+                               } break;
+                               case TYPE_GENERIC_24: {
+                                       destData[dp] = (byte) (data >>> 16);
+                                       destData[dp + 1] = (byte) (data >>> 8);
+                                       destData[dp + 2] = (byte) (data & 0xff);
+                               } break;
+                               case TYPE_GENERIC_32_MSB: {
+                                       destData[dp] = (byte) (data >>> 24);
+                                       destData[dp + 1] = (byte) (data >>> 16);
+                                       destData[dp + 2] = (byte) (data >>> 8);
+                                       destData[dp + 3] = (byte) (data & 0xff);
+                               } break;
+                               case TYPE_GENERIC_32_LSB: {
+                                       destData[dp] = (byte) (data & 0xff);
+                                       destData[dp + 1] = (byte) (data >>> 8);
+                                       destData[dp + 2] = (byte) (data >>> 16);
+                                       destData[dp + 3] = (byte) (data >>> 24);
+                               } break;
+                       }
+               }
+       }
+}
+
+/**
+ * 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,
+       boolean flipX, boolean flipY) {
+       if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode == ALPHA_TRANSPARENT)) return;
+
+       /*** Prepare scaling data ***/
+       final int dwm1 = destWidth - 1;
+       final int sfxi = (dwm1 != 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0;
+       final int dhm1 = destHeight - 1;
+       final int sfyi = (dhm1 != 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0;
+
+       /*** Prepare source-related data ***/
+       final 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 == 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 ***/
+       final 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 == 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);
+       final int dprxi = (flipX) ? -1 : 1;
+       final int dpryi = (flipY) ? -destStride : destStride;
+
+       /*** Prepare special processing data ***/
+       int apr;
+       if ((op & BLIT_ALPHA) != 0) {
+               switch (alphaMode) {
+                       case ALPHA_MASK_UNPACKED:
+                       case ALPHA_CHANNEL_SEPARATE:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               apr = alphaY * alphaStride + alphaX;
+                               break;
+                       case ALPHA_MASK_PACKED:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               alphaStride <<= 3;
+                               apr = alphaY * alphaStride + alphaX;
+                               break;
+                       case ALPHA_MASK_INDEX:
+                       case ALPHA_MASK_RGB:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               apr = 0;
+                               break;
+                       default:
+                               alphaMode = (alphaMode << 16) / 255; // prescale
+                       case ALPHA_CHANNEL_SOURCE:
+                               apr = 0;
+                               break;
+               }
+       } else {
+               alphaMode = 0x10000;
+               apr = 0;
+       }
+       final boolean ditherEnabled = (op & BLIT_DITHER) != 0;
+
+       /*** Blit ***/
+       int dp = dpr;
+       int sp = spr;
+       int ap = apr;
+       int destPaletteSize = 1 << destDepth;
+       if ((destReds != null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length;
+       byte[] paletteMapping = null;
+       boolean isExactPaletteMapping = true;
+       switch (alphaMode) {
+               case 0x10000:
+                       /*** If the palettes and formats are equivalent use a one-to-one mapping ***/
+                       if ((stype == dtype) &&
+                               (srcReds == destReds) && (srcGreens == destGreens) && (srcBlues == destBlues)) {
+                               paletteMapping = ONE_TO_ONE_MAPPING;
+                               break;
+                       /*** If palettes have not been supplied, supply a suitable mapping ***/
+                       } else if ((srcReds == null) || (destReds == 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] = (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 != 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 == 0) break;
+                                               minDistance = distance;
+                                       }
+                               }
+                               paletteMapping[i] = (byte)index;
+                               if (minDistance != 0) isExactPaletteMapping = false;
+                       }
+                       break;
+       }
+       if ((paletteMapping != null) && (isExactPaletteMapping || ! ditherEnabled)) {
+               if ((stype == dtype) && (alphaMode == 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) {
+                                                       final int v;
+                                                       if ((sp & 1) != 0) v = paletteMapping[srcData[sp >> 1] & 0x0f];
+                                                       else v = (srcData[sp >> 1] >>> 4) & 0x0f;
+                                                       sp += (sfx >>> 16);
+                                                       if ((dp & 1) != 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | v);
+                                                       else destData[dp >> 1] = (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) {
+                                                       final int index = paletteMapping[(srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03];
+                                                       sp += (sfx >>> 16);
+                                                       final int shift = 6 - (dp & 3) * 2;
+                                                       destData[dp >> 2] = (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) {
+                                                       final int index = paletteMapping[(srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01];
+                                                       sp += (sfx >>> 16);
+                                                       final int shift = 7 - (dp & 7);
+                                                       destData[dp >> 3] = (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) {
+                                                       final int index = paletteMapping[(srcData[sp >> 3] >>> (sp & 7)) & 0x01];
+                                                       sp += (sfx >>> 16);
+                                                       final int shift = dp & 7;
+                                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                                               }
+                                       }
+                                       break;
+                       }
+               } 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) != 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: {
+                                                       final byte mask = alphaData[ap];
+                                                       ap += (sfx >> 16);
+                                                       if (mask == 0) continue;
+                                               } break;
+                                               case ALPHA_MASK_PACKED: {
+                                                       final int mask = alphaData[ap >> 3] & (1 << (ap & 7));
+                                                       ap += (sfx >> 16);
+                                                       if (mask == 0) continue;
+                                               } break;
+                                               case ALPHA_MASK_INDEX: {
+                                                       int i = 0;
+                                                       while (i < alphaData.length) {
+                                                               if (index == (alphaData[i] & 0xff)) break;
+                                                       }
+                                                       if (i < alphaData.length) continue;
+                                               } break;
+                                               case ALPHA_MASK_RGB: {
+                                                       final byte r = srcReds[index], g = srcGreens[index], b = srcBlues[index];
+                                                       int i = 0;
+                                                       while (i < alphaData.length) {
+                                                               if ((r == alphaData[i]) && (g == alphaData[i + 1]) && (b == alphaData[i + 2])) break;
+                                                               i += 3;
+                                                       }
+                                                       if (i < alphaData.length) continue;
+                                               } break;
+                                       }
+                                       index = paletteMapping[index] & 0xff;
+
+                                       /*** WRITE NEXT PIXEL ***/
+                                       switch (dtype) {
+                                               case TYPE_INDEX_8:
+                                                       destData[dp] = (byte) index;
+                                                       break;
+                                               case TYPE_INDEX_4:
+                                                       if ((dp & 1) != 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | index);
+                                                       else destData[dp >> 1] = (byte)((destData[dp >> 1] & 0x0f) | (index << 4));
+                                                       break;
+                                               case TYPE_INDEX_2: {
+                                                       final int shift = 6 - (dp & 3) * 2;
+                                                       destData[dp >> 2] = (byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift));
+                                               } break;
+                                               case TYPE_INDEX_1_MSB: {
+                                                       final int shift = 7 - (dp & 7);
+                                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                                               } break;
+                                               case TYPE_INDEX_1_LSB: {
+                                                       final int shift = dp & 7;
+                                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                                               } break;
+                                       }
+                               }
+                       }
+               }
+               return;
+       }
+
+       /*** Comprehensive blit (apply transformations) ***/
+       int alpha = alphaMode;
+       int index = 0;
+       int indexq = 0;
+       int lastindex = 0, lastr = -1, lastg = -1, lastb = -1;
+       final 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) != 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;
+                       }
+
+                       /*** 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] != 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 == (alphaData[i] & 0xff)) break;
+                                       }
+                                       if (i < alphaData.length) continue;
+                               } break;
+                               case ALPHA_MASK_RGB: {
+                                       int i = 0;
+                                       while (i < alphaData.length) {
+                                               if ((r == (alphaData[i] & 0xff)) &&
+                                                       (g == (alphaData[i + 1] & 0xff)) &&
+                                                       (b == (alphaData[i + 2] & 0xff))) break;
+                                               i += 3;
+                                       }
+                                       if (i < alphaData.length) continue;
+                               } break;
+                       }
+                       if (alpha != 0x10000) {
+                               if (alpha == 0x0000) continue;
+                               switch (dtype) {
+                                       case TYPE_INDEX_8:
+                                               indexq = destData[dp] & 0xff;
+                                               break;
+                                       case TYPE_INDEX_4:
+                                               if ((dp & 1) != 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;
+                               }
+                               // Perform alpha blending
+                               final int rq = destReds[indexq] & 0xff;
+                               final int gq = destGreens[indexq] & 0xff;
+                               final 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 != lastr || g != lastg || b != 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 == 0) break;
+                                               minDistance = distance;
+                                       }
+                               }
+                               lastr = r; lastg = g; lastb = b;
+                       }
+                       if (ditherEnabled) {
+                               // Floyd-Steinberg error diffusion, cont'd...
+                               final 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] = (byte) lastindex;
+                                       break;
+                               case TYPE_INDEX_4:
+                                       if ((dp & 1) != 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | lastindex);
+                                       else destData[dp >> 1] = (byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4));
+                                       break;
+                               case TYPE_INDEX_2: {
+                                       final int shift = 6 - (dp & 3) * 2;
+                                       destData[dp >> 2] = (byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift));
+                               } break;
+                               case TYPE_INDEX_1_MSB: {
+                                       final int shift = 7 - (dp & 7);
+                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                               } break;
+                               case TYPE_INDEX_1_LSB: {
+                                       final int shift = dp & 7;
+                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                               } break;
+                       }
+               }
+       }
+}
+
+/**
+ * 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,
+       boolean flipX, boolean flipY) {
+       if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode == ALPHA_TRANSPARENT)) return;
+
+       /*** Fast blit (straight copy) ***/
+       if (srcX == 0 && srcY == 0 && destX == 0 && destY == 0 && destWidth == srcWidth && destHeight == srcHeight) {
+               if (destDepth == 24 && srcDepth == 8 && (op & BLIT_ALPHA) == 0 && destRedMask == 0xFF0000 && destGreenMask == 0xFF00 && destBlueMask == 0xFF) {
+                       for (int y = 0, sp = 0, dp = 0, spad = srcStride - srcWidth, dpad = destStride - (destWidth * 3); y < destHeight; y++, sp += spad, dp += dpad) {
+                               for (int x = 0; x < destWidth; x++) {
+                                       int index = srcData[sp++] & 0xff;
+                                       destData[dp++] = srcReds[index];
+                                       destData[dp++] = srcGreens[index];
+                                       destData[dp++] = srcBlues[index];
+                               }
+                       }
+                       return;
+               }
+               if (destDepth == 32 && destOrder == MSB_FIRST && srcDepth == 8 && (op & BLIT_ALPHA) == 0 && destRedMask == 0xFF0000 && destGreenMask == 0xFF00 && destBlueMask == 0xFF) {
+                       for (int y = 0, sp = 0, dp = 0, spad = srcStride - srcWidth, dpad = destStride - (destWidth * 4); y < destHeight; y++, sp += spad, dp += dpad) {
+                               for (int x = 0; x < destWidth; x++) {
+                                       int index = srcData[sp++] & 0xff;
+                                       dp++;
+                                       destData[dp++] = srcReds[index];
+                                       destData[dp++] = srcGreens[index];
+                                       destData[dp++] = srcBlues[index];
+                               }
+                       }
+                       return;
+               }
+       }
+       // these should be supplied as params later
+       final int destAlphaMask = 0;
+
+       /*** Prepare scaling data ***/
+       final int dwm1 = destWidth - 1;
+       final int sfxi = (dwm1 != 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0;
+       final int dhm1 = destHeight - 1;
+       final int sfyi = (dhm1 != 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0;
+
+       /*** Prepare source-related data ***/
+       final 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 == 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 ***/
+       final int dbpp, dtype;
+       switch (destDepth) {
+               case 8:
+                       dbpp = 1;
+                       dtype = TYPE_GENERIC_8;
+                       break;
+               case 16:
+                       dbpp = 2;
+                       dtype = (destOrder == 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 == 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;
+       final int dprxi = (flipX) ? -dbpp : dbpp;
+       final int dpryi = (flipY) ? -destStride : destStride;
+
+       /*** Prepare special processing data ***/
+       int apr;
+       if ((op & BLIT_ALPHA) != 0) {
+               switch (alphaMode) {
+                       case ALPHA_MASK_UNPACKED:
+                       case ALPHA_CHANNEL_SEPARATE:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               apr = alphaY * alphaStride + alphaX;
+                               break;
+                       case ALPHA_MASK_PACKED:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               alphaStride <<= 3;
+                               apr = alphaY * alphaStride + alphaX;
+                               break;
+                       case ALPHA_MASK_INDEX:
+                       case ALPHA_MASK_RGB:
+                               if (alphaData == 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) ***/
+       final int destRedShift = getChannelShift(destRedMask);
+       final int destRedWidth = getChannelWidth(destRedMask, destRedShift);
+       final byte[] destReds = ANY_TO_EIGHT[destRedWidth];
+       final int destRedPreShift = 8 - destRedWidth;
+       final int destGreenShift = getChannelShift(destGreenMask);
+       final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
+       final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
+       final int destGreenPreShift = 8 - destGreenWidth;
+       final int destBlueShift = getChannelShift(destBlueMask);
+       final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
+       final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
+       final int destBluePreShift = 8 - destBlueWidth;
+       final int destAlphaShift = getChannelShift(destAlphaMask);
+       final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
+       final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
+       final 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) != 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;
+                       }
+
+                       /*** 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] != 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 == (alphaData[i] & 0xff)) break;
+                                       }
+                                       if (i < alphaData.length) continue;
+                               } break;
+                               case ALPHA_MASK_RGB: {
+                                       int i = 0;
+                                       while (i < alphaData.length) {
+                                               if ((r == (alphaData[i] & 0xff)) &&
+                                                       (g == (alphaData[i + 1] & 0xff)) &&
+                                                       (b == (alphaData[i + 2] & 0xff))) break;
+                                               i += 3;
+                                       }
+                                       if (i < alphaData.length) continue;
+                               } break;
+                       }
+                       if (alpha != 0x10000) {
+                               if (alpha == 0x0000) continue;
+                               switch (dtype) {
+                                       case TYPE_GENERIC_8: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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: {
+                                               final 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;
+                               }
+                               // 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 ***/
+                       final int data =
+                               (r >>> destRedPreShift << destRedShift) |
+                               (g >>> destGreenPreShift << destGreenShift) |
+                               (b >>> destBluePreShift << destBlueShift) |
+                               (a >>> destAlphaPreShift << destAlphaShift);
+                       switch (dtype) {
+                               case TYPE_GENERIC_8: {
+                                       destData[dp] = (byte) data;
+                               } break;
+                               case TYPE_GENERIC_16_MSB: {
+                                       destData[dp] = (byte) (data >>> 8);
+                                       destData[dp + 1] = (byte) (data & 0xff);
+                               } break;
+                               case TYPE_GENERIC_16_LSB: {
+                                       destData[dp] = (byte) (data & 0xff);
+                                       destData[dp + 1] = (byte) (data >>> 8);
+                               } break;
+                               case TYPE_GENERIC_24: {
+                                       destData[dp] = (byte) (data >>> 16);
+                                       destData[dp + 1] = (byte) (data >>> 8);
+                                       destData[dp + 2] = (byte) (data & 0xff);
+                               } break;
+                               case TYPE_GENERIC_32_MSB: {
+                                       destData[dp] = (byte) (data >>> 24);
+                                       destData[dp + 1] = (byte) (data >>> 16);
+                                       destData[dp + 2] = (byte) (data >>> 8);
+                                       destData[dp + 3] = (byte) (data & 0xff);
+                               } break;
+                               case TYPE_GENERIC_32_LSB: {
+                                       destData[dp] = (byte) (data & 0xff);
+                                       destData[dp + 1] = (byte) (data >>> 8);
+                                       destData[dp + 2] = (byte) (data >>> 16);
+                                       destData[dp + 3] = (byte) (data >>> 24);
+                               } break;
+                       }
+               }
+       }
+}
+
+/**
+ * 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,
+       boolean flipX, boolean flipY) {
+       if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode == ALPHA_TRANSPARENT)) return;
+
+       // these should be supplied as params later
+       final int srcAlphaMask = 0;
+
+       /*** Prepare scaling data ***/
+       final int dwm1 = destWidth - 1;
+       final int sfxi = (dwm1 != 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0;
+       final int dhm1 = destHeight - 1;
+       final int sfyi = (dhm1 != 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0;
+
+       /*** Prepare source-related data ***/
+       final int sbpp, stype;
+       switch (srcDepth) {
+               case 8:
+                       sbpp = 1;
+                       stype = TYPE_GENERIC_8;
+                       break;
+               case 16:
+                       sbpp = 2;
+                       stype = (srcOrder == 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 == 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 ***/
+       final 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 == 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);
+       final int dprxi = (flipX) ? -1 : 1;
+       final int dpryi = (flipY) ? -destStride : destStride;
+
+       /*** Prepare special processing data ***/
+       int apr;
+       if ((op & BLIT_ALPHA) != 0) {
+               switch (alphaMode) {
+                       case ALPHA_MASK_UNPACKED:
+                       case ALPHA_CHANNEL_SEPARATE:
+                               if (alphaData == null) alphaMode = 0x10000;
+                               apr = alphaY * alphaStride + alphaX;
+                               break;
+                       case ALPHA_MASK_PACKED:
+                               if (alphaData == 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 == null) alphaMode = 0x10000;
+                               apr = 0;
+                               break;
+                       default:
+                               alphaMode = (alphaMode << 16) / 255; // prescale
+                       case ALPHA_CHANNEL_SOURCE:
+                               apr = 0;
+                               break;
+               }
+       } else {
+               alphaMode = 0x10000;
+               apr = 0;
+       }
+       final boolean ditherEnabled = (op & BLIT_DITHER) != 0;
+
+       /*** Comprehensive blit (apply transformations) ***/
+       final int srcRedShift = getChannelShift(srcRedMask);
+       final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
+       final int srcGreenShift = getChannelShift(srcGreenMask);
+       final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
+       final int srcBlueShift = getChannelShift(srcBlueMask);
+       final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
+       final int srcAlphaShift = getChannelShift(srcAlphaMask);
+       final 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;
+       final int[] rerr, gerr, berr;
+       int destPaletteSize = 1 << destDepth;
+       if ((destReds != 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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: {
+                                       final 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;
+                       }
+
+                       /*** 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] != 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 == alphaData[i]) && (g == alphaData[i + 1]) && (b == alphaData[i + 2])) {
+                                                       alpha = 0x0000;
+                                                       break;
+                                               }
+                                       }
+                                       break;
+                       }
+                       if (alpha != 0x10000) {
+                               if (alpha == 0x0000) continue;
+                               switch (dtype) {
+                                       case TYPE_INDEX_8:
+                                               indexq = destData[dp] & 0xff;
+                                               break;
+                                       case TYPE_INDEX_4:
+                                               if ((dp & 1) != 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;
+                               }
+                               // Perform alpha blending
+                               final int rq = destReds[indexq] & 0xff;
+                               final int gq = destGreens[indexq] & 0xff;
+                               final 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 != lastr || g != lastg || b != 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 == 0) break;
+                                               minDistance = distance;
+                                       }
+                               }
+                               lastr = r; lastg = g; lastb = b;
+                       }
+                       if (ditherEnabled) {
+                               // Floyd-Steinberg error diffusion, cont'd...
+                               final 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] = (byte) lastindex;
+                                       break;
+                               case TYPE_INDEX_4:
+                                       if ((dp & 1) != 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | lastindex);
+                                       else destData[dp >> 1] = (byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4));
+                                       break;
+                               case TYPE_INDEX_2: {
+                                       final int shift = 6 - (dp & 3) * 2;
+                                       destData[dp >> 2] = (byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift));
+                               } break;
+                               case TYPE_INDEX_1_MSB: {
+                                       final int shift = 7 - (dp & 7);
+                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                               } break;
+                               case TYPE_INDEX_1_LSB: {
+                                       final int shift = dp & 7;
+                                       destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                               } break;
+                       }
+               }
+       }
+}
+
+/**
+ * Computes the required channel shift from a mask.
+ */
+static int getChannelShift(int mask) {
+       if (mask == 0) return 0;
+       int i;
+       for (i = 0; ((mask & 1) == 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 == 0) return 0;
+       int i;
+       mask >>>= shift;
+       for (i = shift; ((mask & 1) != 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) {
+       final 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, boolean vertical,
+       RGB fromRGB, RGB toRGB,
+       int redBits, int greenBits, int blueBits) {
+       /* Gradients are drawn as tiled bands */
+       final int bandWidth, bandHeight, bitmapDepth;
+       final byte[] bitmapData;
+       final PaletteData paletteData;
+       /* Select an algorithm depending on the depth of the screen */
+       if (redBits != 0 && greenBits != 0 && blueBits != 0) {
+               paletteData = new PaletteData(0x0000ff00, 0x00ff0000, 0xff000000);
+               bitmapDepth = 32;
+               if (redBits >= 8 && greenBits >= 8 && blueBits >= 8) {
+                       /* Precise color */
+                       final 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;
+                       }
+                       final 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 */
+                       final 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;
+                       }
+                       final 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;
+               final 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;
+               }
+               final 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 ? (byte)0 : (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 ? (byte)0 : (byte)1;
+                               }
+                       }
+               }
+       }
+       return new ImageData(bandWidth, bandHeight, bitmapDepth, paletteData, 4, bitmapData);
+}
+
+/*
+ * Fill in gradated values for a color channel
+ */
+static void buildPreciseGradientChannel(int from, int to, int steps,
+       int bandWidth, int bandHeight, boolean vertical,
+       byte[] bitmapData, int dp, int bytesPerLine) {
+       int val = from << 16;
+       final int inc = ((to << 16) - val) / steps + 1;
+       if (vertical) {
+               for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
+                       bitmapData[dp] = (byte)(val >>> 16);
+                       val += inc;
+               }
+       } else {
+               for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
+                       bitmapData[dp] = (byte)(val >>> 16);
+                       val += inc;
+               }
+       }
+}
+
+/*
+ * Fill in dithered gradated values for a color channel
+ */
+static void buildDitheredGradientChannel(int from, int to, int steps,
+       int bandWidth, int bandHeight, boolean vertical,
+       byte[] bitmapData, int dp, int bytesPerLine, int bits) {
+       final int mask = 0xff00 >>> bits;
+       int val = from << 16;
+       final 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) {
+                               final int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits;
+                               int temp = val + thresh;
+                               if (temp > 0xffffff) bitmapData[dptr] = -1;
+                               else bitmapData[dptr] = (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) {
+                               final int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits;
+                               int temp = val + thresh;
+                               if (temp > 0xffffff) bitmapData[dptr] = -1;
+                               else bitmapData[dptr] = (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, boolean 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 == 1) || (band.height == 1)) {
+                       gc.drawImage(image, 0, 0, DPIUtil.autoScaleDown(band.width), DPIUtil.autoScaleDown(band.height),
+                                       DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y), DPIUtil.autoScaleDown(width),
+                                       DPIUtil.autoScaleDown(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, DPIUtil.autoScaleDown(blitWidth), DPIUtil.autoScaleDown(band.height),
+                                                       DPIUtil.autoScaleDown(dx + x), DPIUtil.autoScaleDown(y), DPIUtil.autoScaleDown(blitWidth),
+                                                       DPIUtil.autoScaleDown(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, DPIUtil.autoScaleDown(band.width), DPIUtil.autoScaleDown(blitHeight),
+                                                       DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(dy + y), DPIUtil.autoScaleDown(band.width),
+                                                       DPIUtil.autoScaleDown(blitHeight));
+                               }
+               }
+       }
+       image.dispose();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageDataLoader.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageDataLoader.java
new file mode 100644 (file)
index 0000000..b1fe23d
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.io.*;
+
+/**
+ * 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);
+       }
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageDataProvider.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageDataProvider.java
new file mode 100644 (file)
index 0000000..bfa0ec7
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+/**
+ * Interface to provide a callback mechanism to get information about images
+ * when the application is moved from a low DPI monitor to a high DPI monitor.
+ * This provides API which will be called by SWT during the image rendering.
+ *
+ * This interface needs to be implemented by client code to provide the
+ * image information on demand.
+ *
+ * @since 3.104
+ */
+public interface ImageDataProvider {
+
+
+       /**
+        * Returns the image data for the given zoom level.
+        * <p>
+        * If no image is available for a particular zoom level, this method should
+        * return <code>null</code>. For <code>zoom == 100</code>, returning
+        * <code>null</code> is not allowed, and SWT will throw an exception.
+        *
+        * @param zoom
+        *            The zoom level in % of the standard resolution (which is 1
+        *            physical monitor pixel == 1 SWT logical point). Typically 100,
+        *            150, or 200.
+        * @return the image data, or <code>null</code> if <code>zoom != 100</code>
+        *         and no image is available for the given zoom level.
+        * @since 3.104
+        */
+       ImageData getImageData (int zoom);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageFileNameProvider.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageFileNameProvider.java
new file mode 100644 (file)
index 0000000..2413cda
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+/**
+ * Interface to provide a callback mechanism to get information about images
+ * when the application is moved from a low DPI monitor to a high DPI monitor.
+ * This provides API which will be called by SWT during the image rendering.
+ *
+ * This interface needs to be implemented by client code to provide the
+ * image information on demand.
+ *
+ * @since 3.104
+ */
+public interface ImageFileNameProvider {
+
+       /**
+        * Returns the image filePath for the given zoom level.
+        * <p>
+        * If no image is available for a particular zoom level, this method should
+        * return <code>null</code>. For <code>zoom == 100</code>, returning
+        * <code>null</code> is not allowed, and SWT will throw an exception.
+        *
+        * @param zoom
+        *            The zoom level in % of the standard resolution (which is 1
+        *            physical monitor pixel == 1 SWT logical point). Typically 100,
+        *            150, or 200.
+        * @return the image filePath, or <code>null</code> if
+        *         <code>zoom != 100</code> and no image is available for the given
+        *         zoom level.
+        * @since 3.104
+        */
+       String getImagePath (int zoom);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoader.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoader.java
new file mode 100644 (file)
index 0000000..bbe5ac8
--- /dev/null
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.io.*;
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.image.*;
+
+/**
+ * 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>
+ *
+ * <p>
+ * NOTE: <code>ImageLoader</code> is implemented in Java on some platforms, which has
+ * certain performance implications. Performance and memory sensitive applications may
+ * benefit from using one of the constructors provided by <code>Image</code>, as these
+ * are implemented natively.</p>
+ *
+ * @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;
+
+       /**
+        * This is the compression used when saving jpeg and png files.
+        * <p>
+        * When saving jpeg files, the value is from 1 to 100,
+        * where 1 is very high compression but low quality, and 100 is
+        * no compression and high quality; default is 75.
+        * </p><p>
+        * When saving png files, the value is from 0 to 3, but they do not impact the quality
+        * because PNG is lossless compression. 0 is uncompressed, 1 is low compression and fast,
+        * 2 is default compression, and 3 is high compression but slow.
+        * </p>
+        *
+        * @since 3.8
+        */
+       public int compression;
+
+       /*
+        * the set of ImageLoader event listeners, created on demand
+        */
+       List<ImageLoaderListener> imageLoaderListeners;
+
+/**
+ * Construct a new empty ImageLoader.
+ */
+public ImageLoader() {
+       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;
+       compression = -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 == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       InputStream stream = null;
+       try {
+               stream = new FileInputStream(filename);
+               return load(stream);
+       } catch (IOException e) {
+               SWT.error(SWT.ERROR_IO, e);
+       } finally {
+               try {
+                       if (stream != null) stream.close();
+               } catch (IOException e) {
+                       // Ignore error
+               }
+       }
+       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 == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       OutputStream stream = null;
+       try {
+               stream = new FileOutputStream(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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (imageLoaderListeners == null) {
+               imageLoaderListeners = new ArrayList<>();
+       }
+       imageLoaderListeners.add(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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (imageLoaderListeners == null) return;
+       imageLoaderListeners.remove(listener);
+}
+
+/**
+ * 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 boolean hasListeners() {
+       return imageLoaderListeners != null && imageLoaderListeners.size() > 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;
+       int size = imageLoaderListeners.size();
+       for (int i = 0; i < size; i++) {
+               ImageLoaderListener listener = imageLoaderListeners.get(i);
+               listener.imageDataLoaded(event);
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoaderEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoaderEvent.java
new file mode 100644 (file)
index 0000000..64a9fbe
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.util.*;
+
+/**
+ * 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 extends EventObject {
+
+       /**
+        * 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 boolean 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 ImageLoaderEvent(ImageLoader source, ImageData imageData, int incrementCount, boolean 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
+ */
+@Override
+public String toString () {
+       return "ImageLoaderEvent {source=" + source + " imageData=" + imageData + " incrementCount=" + incrementCount + " endOfImage=" + endOfImage + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoaderListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/ImageLoaderListener.java
new file mode 100644 (file)
index 0000000..6a38575
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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
+ */
+@FunctionalInterface
+public interface ImageLoaderListener extends 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
+ */
+void imageDataLoaded(ImageLoaderEvent e);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/LineAttributes.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/LineAttributes.java
new file mode 100644 (file)
index 0000000..43586cb
--- /dev/null
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.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 LineAttributes(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 LineAttributes(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 LineAttributes(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;
+}
+
+/**
+ * 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 boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof LineAttributes)) return false;
+       LineAttributes p = (LineAttributes)object;
+       if (p.width != width) return false;
+       if (p.cap != cap) return false;
+       if (p.join != join) return false;
+       if (p.style != style) return false;
+       if (p.dashOffset != dashOffset) return false;
+       if (p.miterLimit != miterLimit) return false;
+       if (p.dash != null && dash != null) {
+               if (p.dash.length != dash.length) return false;
+               for (int i = 0; i < dash.length; i++) {
+                       if (p.dash[i] != dash[i]) return false;
+               }
+       } else {
+               if (p.dash != null || dash != 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)
+ */
+@Override
+public int hashCode () {
+       int hashCode = Float.floatToIntBits(width);
+       hashCode = 31 * hashCode + cap;
+       hashCode = 31 * hashCode + join;
+       hashCode = 31 * hashCode + style;
+       hashCode = 31 * hashCode + Float.floatToIntBits(dashOffset);
+       hashCode = 31 * hashCode + Float.floatToIntBits(miterLimit);
+       if (dash != null) {
+               for (int i = 0; i < dash.length; i++) {
+                       hashCode = 31 * hashCode + Float.floatToIntBits(dash[i]);
+               }
+       }
+       return hashCode;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/PaletteData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/PaletteData.java
new file mode 100644 (file)
index 0000000..faabb4e
--- /dev/null
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 483460
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 boolean 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 PaletteData(RGB... colors) {
+       if (colors == 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 PaletteData(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 == 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].equals(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) != 0) return 7 - i;
+       }
+       return 32;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Path.java
new file mode 100644 (file)
index 0000000..249c409
--- /dev/null
@@ -0,0 +1,688 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+       PointF currentPoint = new PointF(), startPoint = new PointF();
+
+/**
+ * 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>
+ * <p>
+ * You must dispose the path when it is no longer required.
+ * </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 Path (Device device) {
+       super(device);
+       this.device.checkGDIP();
+       handle = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+       if (handle == 0) 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>
+ * <p>
+ * You must dispose the path when it is no longer required.
+ * </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 Path (Device device, Path path, float flatness) {
+       super(device);
+       if (path == 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 != 0) Gdip.GraphicsPath_Flatten(handle, 0, flatness);
+       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       init();
+}
+
+/**
+ * Constructs a new Path with the specified PathData.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * <p>
+ * You must dispose the path when it is no longer required.
+ * </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 Path (Device device, PathData data) {
+       this(device);
+       if (data == 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> points wide
+ * by <code>height + 1</code> points 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) {
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       addArcInPixels(x, y, width, height, startAngle, arcAngle);
+}
+
+void addArcInPixels(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 == 0 || height == 0 || arcAngle == 0) return;
+       if (width == height) {
+               Gdip.GraphicsPath_AddArc(handle, x, y, width, height, -startAngle, -arcAngle);
+       } else {
+               long path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+               if (path == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               long matrix = Gdip.Matrix_new(width, 0, 0, height, x, y);
+               if (matrix == 0) 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 == 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) {
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       addRectangleInPixels(x, y, width, height);
+}
+
+void addRectangleInPixels(float x, float y, float width, float height) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       RectF rect = new RectF();
+       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) {
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       addStringInPixels(string, x, y, font);
+}
+
+void addStringInPixels(String string, float x, float y, Font font) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (font == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       char[] buffer = string.toCharArray();
+       long hDC = device.internal_new_GC(null);
+       long [] family = new long [1];
+       long gdipFont = GC.createGdipFont(hDC, font.handle, 0, device.fontCollection, family, null);
+       PointF point = new PointF();
+       point.X = x - (Gdip.Font_GetSize(gdipFont) / 6);
+       point.Y = y;
+       int style = Gdip.Font_GetStyle(gdipFont);
+       float size = Gdip.Font_GetSize(gdipFont);
+       Gdip.GraphicsPath_AddString(handle, buffer, buffer.length, family[0], style, size, point, 0);
+       Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
+       Gdip.FontFamily_delete(family[0]);
+       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 boolean contains (float x, float y, GC gc, boolean outline) {
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       return containsInPixels(x, y, gc, outline);
+}
+
+boolean containsInPixels(float x, float y, GC gc, boolean outline) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (gc == 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) == 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) {
+       cx1 = DPIUtil.autoScaleUp(cx1);
+       cy1 = DPIUtil.autoScaleUp(cy1);
+       cx2 = DPIUtil.autoScaleUp(cx2);
+       cy2 = DPIUtil.autoScaleUp(cy2);
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       cubicToInPixels(cx1, cy1, cx2, cy2, x, y);
+}
+
+void cubicToInPixels(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);
+}
+
+@Override
+void destroy() {
+       Gdip.GraphicsPath_delete(handle);
+       handle = 0;
+}
+
+/**
+ * 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 (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       getBoundsInPixels(bounds);
+       bounds = DPIUtil.autoScaleDown(bounds);
+}
+
+void getBoundsInPixels(float[] bounds) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (bounds.length < 4) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       RectF rect = new RectF();
+       Gdip.GraphicsPath_GetBounds(handle, rect, 0, 0);
+       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 (point == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       getCurrentPointInPixels(point);
+       point = DPIUtil.autoScaleDown(point);
+}
+
+void getCurrentPointInPixels(float[] point) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       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);
+       PathData result = getPathDataInPixels();
+       result.points = DPIUtil.autoScaleDown(result.points);
+       return result;
+}
+
+PathData getPathDataInPixels() {
+       int count = Gdip.GraphicsPath_GetPointCount(handle);
+       byte[] gdipTypes = new byte[count];
+       float[] points = new float[count * 2];
+       Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes, count);
+       Gdip.GraphicsPath_GetPathPoints(handle, points, count);
+       byte[] types = new byte[count * 2];
+       int index = 0, typesIndex = 0;
+       while (index < count) {
+               byte type = gdipTypes[index];
+               boolean close = false;
+               switch (type & Gdip.PathPointTypePathTypeMask) {
+                       case Gdip.PathPointTypeStart:
+                               types[typesIndex++] = SWT.PATH_MOVE_TO;
+                               close = (type & Gdip.PathPointTypeCloseSubpath) != 0;
+                               index += 1;
+                               break;
+                       case Gdip.PathPointTypeLine:
+                               types[typesIndex++] = SWT.PATH_LINE_TO;
+                               close = (type & Gdip.PathPointTypeCloseSubpath) != 0;
+                               index += 1;
+                               break;
+                       case Gdip.PathPointTypeBezier:
+                               types[typesIndex++] = SWT.PATH_CUBIC_TO;
+                               close = (gdipTypes[index + 2] & Gdip.PathPointTypeCloseSubpath) != 0;
+                               index += 3;
+                               break;
+                       default:
+                               index++;
+               }
+               if (close) {
+                       types[typesIndex++] = SWT.PATH_CLOSE;
+               }
+       }
+       if (typesIndex != 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) {
+       lineToInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+void lineToInPixels(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 (except {@link #dispose()}) using the Path.
+ *
+ * @return <code>true</code> when the Path is disposed, and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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) {
+       moveToInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+void moveToInPixels(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) {
+       cx = DPIUtil.autoScaleUp(cx);
+       cy = DPIUtil.autoScaleUp(cy);
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       quadToInPixels(cx, cy, x, y);
+}
+
+void quadToInPixels(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 "Path {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/PathData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/PathData.java
new file mode 100644 (file)
index 0000000..c07dc0e
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+/**
+ * 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;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Pattern.java
new file mode 100644 (file)
index 0000000..5ff9e06
--- /dev/null
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long 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>
+ * <p>
+ * You must dispose the pattern when it is no longer required.
+ * </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 Pattern(Device device, Image image) {
+       super(device);
+       if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       this.device.checkGDIP();
+       long[] gdipImage = image.createGdipImage();
+       long img = gdipImage[0];
+       int width = Gdip.Image_GetWidth(img);
+       int height = Gdip.Image_GetHeight(img);
+       handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
+       Gdip.Bitmap_delete(img);
+       if (gdipImage[1] != 0) {
+               long hHeap = OS.GetProcessHeap ();
+               OS.HeapFree(hHeap, 0, gdipImage[1]);
+       }
+       if (handle == 0) 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>
+ * <p>
+ * You must dispose the pattern when it is no longer required.
+ * </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 Pattern(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>
+ * <p>
+ * You must dispose the pattern when it is no longer required.
+ * </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 Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
+       super(device);
+       x1 = DPIUtil.autoScaleUp(x1);
+       y1 = DPIUtil.autoScaleUp(y1);
+       x2 = DPIUtil.autoScaleUp(x2);
+       y2 = DPIUtil.autoScaleUp(y2);
+       if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       this.device.checkGDIP();
+       int colorRef1 = color1.handle;
+       int foreColor = ((alpha1 & 0xFF) << 24) | ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16);
+       if (x1 == x2 && y1 == y2) {
+               handle = Gdip.SolidBrush_new(foreColor);
+               if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       } else {
+               int colorRef2 = color2.handle;
+               int backColor = ((alpha2 & 0xFF) << 24) | ((colorRef2 >> 16) & 0xFF) | (colorRef2 & 0xFF00) | ((colorRef2 & 0xFF) << 16);
+               PointF p1 = new PointF();
+               p1.X = x1;
+               p1.Y = y1;
+               PointF p2 = new PointF();
+               p2.X = x2;
+               p2.Y = y2;
+               handle = Gdip.LinearGradientBrush_new(p1, p2, foreColor, backColor);
+               if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+               if (alpha1 != 0xFF || alpha2 != 0xFF) {
+                       int a = (int)((alpha1 & 0xFF) * 0.5f + (alpha2 & 0xFF) * 0.5f);
+                       int r = (int)(((colorRef1 & 0xFF) >> 0) * 0.5f + ((colorRef2 & 0xFF) >> 0) * 0.5f);
+                       int g = (int)(((colorRef1 & 0xFF00) >> 8) * 0.5f + ((colorRef2 & 0xFF00) >> 8) * 0.5f);
+                       int b = (int)(((colorRef1 & 0xFF0000) >> 16) * 0.5f + ((colorRef2 & 0xFF0000) >> 16) * 0.5f);
+                       int midColor = a << 24 | r << 16 | g << 8 | b;
+                       Gdip.LinearGradientBrush_SetInterpolationColors(handle, new int [] {foreColor, midColor, backColor}, new float[]{0, 0.5f, 1}, 3);
+               }
+       }
+       init();
+}
+
+@Override
+void destroy() {
+       int type = Gdip.Brush_GetType(handle);
+       switch (type) {
+               case Gdip.BrushTypeSolidColor:
+                       Gdip.SolidBrush_delete(handle);
+                       break;
+               case Gdip.BrushTypeHatchFill:
+                       Gdip.HatchBrush_delete(handle);
+                       break;
+               case Gdip.BrushTypeLinearGradient:
+                       Gdip.LinearGradientBrush_delete(handle);
+                       break;
+               case Gdip.BrushTypeTextureFill:
+                       Gdip.TextureBrush_delete(handle);
+                       break;
+       }
+       handle = 0;
+}
+
+/**
+ * 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 (except {@link #dispose()}) using the Pattern.
+ *
+ * @return <code>true</code> when the Pattern is disposed, and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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 "Pattern {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Point.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Point.java
new file mode 100644 (file)
index 0000000..141c1fe
--- /dev/null
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.io.*;
+
+/**
+ * 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 implements Serializable {
+
+       /**
+        * 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 Point (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()
+ */
+@Override
+public boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Point)) return false;
+       Point p = (Point)object;
+       return (p.x == this.x) && (p.y == this.y);
+}
+
+/**
+ * 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 int hashCode () {
+       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 "Point {" + x + ", " + y + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/RGB.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/RGB.java
new file mode 100644 (file)
index 0000000..ebcb2d7
--- /dev/null
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 implements Serializable {
+
+       /**
+        * 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 RGB(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 RGB(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 == 0) {
+               r = g = b = brightness;
+       } else {
+               if (hue == 360) hue = 0;
+               hue /= 60;
+               int i = (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 = (int)(r * 255 + 0.5);
+       green = (int)(g * 255 + 0.5);
+       blue = (int)(b * 255 + 0.5);
+}
+
+/**
+ * Returns the hue, saturation, and brightness of the color.
+ *
+ * @return color space values in float format:<ul>
+ *             <li>hue (from 0 to 360)</li>
+ *             <li>saturation (from 0 to 1)</li>
+ *             <li>brightness (from 0 to 1)</li>
+ *             </ul>
+ * @see #RGB(float, float, float)
+ *
+ * @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 == 0 ? 0 : (max - min) / max;
+       if (delta != 0) {
+               if (r == max) {
+                       hue = (g  - b) / delta;
+               } else {
+                       if (g == max) {
+                               hue = 2 + (b - r) / delta;
+                       } else {
+                               hue = 4 + (r - g) / delta;
+                       }
+               }
+               hue *= 60;
+               if (hue < 0) hue += 360;
+       }
+       return new float[] {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()
+ */
+@Override
+public boolean equals(Object object) {
+       if (object == this) return true;
+       if (!(object instanceof RGB)) return false;
+       RGB rgb = (RGB)object;
+       return (rgb.red == this.red) && (rgb.green == this.green) && (rgb.blue == this.blue);
+}
+
+/**
+ * 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 int hashCode() {
+       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>
+ */
+@Override
+public String toString() {
+       return "RGB {" + red + ", " + green + ", " + blue + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/RGBA.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/RGBA.java
new file mode 100644 (file)
index 0000000..24d0431
--- /dev/null
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class are descriptions of colors in
+ * terms of the primary additive color model (red, green, blue
+ * and alpha). 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 and for alpha 0 indicates transparent and
+ * 255 indicates opaque.
+ * <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>
+ * @since 3.104
+ */
+public final class RGBA implements Serializable {
+       /**
+        * the RGB component of the RGBA
+        */
+       public final RGB rgb;
+
+       /**
+        * the alpha component of the RGBA
+        */
+       public int alpha;
+
+       static final long serialVersionUID = 1049467103126495855L;
+
+/**
+ * Constructs an instance of this class with the given
+ * red, green, blue and alpha 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
+ * @param alpha the alpha component of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green, blue or alpha argument is not between 0 and 255</li>
+ * </ul>
+ */
+public RGBA(int red, int green, int blue, int alpha) {
+       if ((alpha > 255) || (alpha < 0)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       this.rgb = new RGB (red, green, blue);
+       this.alpha = alpha;
+}
+
+/**
+* Constructs an instance of this class with the given
+* hue, saturation, and brightness.
+*
+* @param hue the hue value for the HSBA color (from 0 to 360)
+* @param saturation the saturation value for the HSBA color (from 0 to 1)
+* @param brightness the brightness value for the HSBA color (from 0 to 1)
+* @param alpha the alpha value for the HSBA color (from 0 to 255)
+*
+* @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 or if the alpha
+*    is not between 0 and 255</li>
+* </ul>
+*
+*/
+public RGBA(float hue, float saturation, float brightness, float alpha) {
+       if ((alpha > 255) || (alpha < 0)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       rgb = new RGB(hue, saturation, brightness);
+       this.alpha = (int)(alpha + 0.5);
+}
+
+/**
+ * Returns the hue, saturation, and brightness of the color.
+ *
+ * @return color space values in float format:<ul>
+ *             <li>hue (from 0 to 360)</li>
+ *             <li>saturation (from 0 to 1)</li>
+ *             <li>brightness (from 0 to 1)</li>
+ *             <li>alpha (from 0 to 255)</li>
+ *             </ul>
+ * @see #RGBA(float, float, float, float)
+ */
+public float[] getHSBA() {
+       float[] hsb = rgb.getHSB();
+       return new float[] {hsb[0], hsb[1], hsb[2], alpha};
+}
+
+/**
+ * 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 boolean equals(Object object) {
+       if (object == this) return true;
+       if (!(object instanceof RGBA)) return false;
+       RGBA rgba = (RGBA)object;
+       return (rgba.rgb.red == this.rgb.red) && (rgba.rgb.green == this.rgb.green) && (rgba.rgb.blue == this.rgb.blue)
+                       && (rgba.alpha == this.alpha);
+}
+
+/**
+ * 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 int hashCode() {
+       return (alpha << 24) | (rgb.blue << 16) | (rgb.green << 8) | rgb.red;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the <code>RGBA</code>
+ */
+@Override
+public String toString() {
+       return "RGBA {" + rgb.red + ", " + rgb.green + ", " + rgb.blue + ", " + alpha + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Rectangle.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Rectangle.java
new file mode 100644 (file)
index 0000000..d6645a7
--- /dev/null
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 implements Serializable {
+
+       /**
+        * 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 Rectangle (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 == 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 boolean 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 boolean contains (Point pt) {
+       if (pt == 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()
+ */
+@Override
+public boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Rectangle)) return false;
+       Rectangle r = (Rectangle)object;
+       return (r.x == this.x) && (r.y == this.y) && (r.width == this.width) && (r.height == this.height);
+}
+
+/**
+ * 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 int hashCode () {
+       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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (this == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (this == 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 boolean 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 boolean intersects (Rectangle rect) {
+       if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       return rect == 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 boolean 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
+ */
+@Override
+public String toString () {
+       return "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 union (Rectangle rect) {
+       if (rect == 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);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Region.java
new file mode 100644 (file)
index 0000000..e2409b4
--- /dev/null
@@ -0,0 +1,654 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+/**
+ * Constructs a new empty region.
+ * <p>
+ * You must dispose the region when it is no longer required.
+ * </p>
+ *
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Region () {
+       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 Region (Device device) {
+       super(device);
+       handle = OS.CreateRectRgn (0, 0, 0, 0);
+       if (handle == 0) 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
+ */
+Region(Device device, int 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       addInPixels(DPIUtil.autoScaleUp(pointArray));
+}
+
+void addInPixels (int[] pointArray) {
+       long polyRgn = OS.CreatePolygonRgn(pointArray, 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       rect = DPIUtil.autoScaleUp(rect);
+       addInPixels(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);
+       addInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void addInPixels (int x, int y, int width, int height) {
+       if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       long 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 == 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 boolean contains (int x, int y) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return containsInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+boolean containsInPixels (int x, int y) {
+       return 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 boolean contains (Point pt) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       pt = DPIUtil.autoScaleUp(pt);
+       return containsInPixels(pt.x, pt.y);
+}
+
+@Override
+void destroy () {
+       OS.DeleteObject(handle);
+       handle = 0;
+}
+
+/**
+ * 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 boolean equals (Object object) {
+       if (this == object) return true;
+       if (!(object instanceof Region)) return false;
+       Region rgn = (Region)object;
+       return handle == 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);
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels() {
+       RECT rect = new 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 int hashCode () {
+       return (int)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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       rect = DPIUtil.autoScaleUp(rect);
+       intersectInPixels(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);
+       intersectInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void intersectInPixels (int x, int y, int width, int height) {
+       if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       long 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 == 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 boolean intersects (int x, int y, int width, int height) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return  intersectsInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+boolean intersectsInPixels (int x, int y, int width, int height) {
+       RECT r = new RECT ();
+       OS.SetRect (r, x, y, x + width, y + height);
+       return 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 boolean intersects (Rectangle rect) {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       rect = DPIUtil.autoScaleUp(rect);
+       return intersectsInPixels(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 (except {@link #dispose()}) using the region.
+ *
+ * @return <code>true</code> when the region is disposed, and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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 boolean isEmpty () {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       RECT rect = new RECT ();
+       int result = OS.GetRgnBox (handle, rect);
+       if (result == 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       subtractInPixels(DPIUtil.autoScaleUp(pointArray));
+}
+
+void subtractInPixels (int[] pointArray) {
+       long polyRgn = OS.CreatePolygonRgn(pointArray, 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       rect = DPIUtil.autoScaleUp(rect);
+       subtractInPixels(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);
+       subtractInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void subtractInPixels (int x, int y, int width, int height) {
+       if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       long 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 == 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);
+       translateInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+void translateInPixels (int x, int y) {
+       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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       pt = DPIUtil.autoScaleUp(pt);
+       translateInPixels(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 "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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Region win32_new(Device device, int handle) {
+       return new Region(device, handle);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Resource.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Resource.java
new file mode 100644 (file)
index 0000000..625b416
--- /dev/null
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 {
+
+       /**
+        * the device where this resource was created
+        */
+       Device device;
+
+public Resource() {
+}
+
+Resource(Device device) {
+       if (device == null) device = Device.getDevice();
+       if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       this.device = device;
+}
+
+void destroy() {
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * this resource. Applications must dispose of all resources
+ * which they allocate.
+ * This method does nothing if the resource is already disposed.
+ */
+public void dispose() {
+       if (device == 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 == 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 (except {@link #dispose()}) using the resource.
+ *
+ * @return <code>true</code> when the resource is disposed and <code>false</code> otherwise
+ */
+public abstract boolean isDisposed();
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/TextLayout.java
new file mode 100644 (file)
index 0000000..52778ac
--- /dev/null
@@ -0,0 +1,3776 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * <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 extends Resource {
+       Font font;
+       String text, segmentsText;
+       int lineSpacingInPoints;
+       int ascentInPixels, descentInPixels;
+       int alignment;
+       int wrapWidth;
+       int orientation;
+       int textDirection;
+       int indent;
+       int wrapIndent;
+       boolean justify;
+       int[] tabs;
+       int[] segments;
+       char[] segmentsChars;
+       StyleItem[] styles;
+       int stylesCount;
+
+       StyleItem[] allRuns;
+       StyleItem[][] runs;
+       int[] lineOffset, lineY, lineWidth;
+       IMLangFontLink2 mLangFontLink2;
+       int verticalIndentInPoints;
+
+       static final char LTR_MARK = '\u200E', RTL_MARK = '\u200F';
+       static final int SCRIPT_VISATTR_SIZEOF = 2;
+       static final int GOFFSET_SIZEOF = 8;
+       static final int MERGE_MAX = 512;
+       static final int TOO_MANY_RUNS = 1024;
+
+       /* IME has a copy of these constants */
+       static final int UNDERLINE_IME_DOT = 1 << 16;
+       static final int UNDERLINE_IME_DASH = 2 << 16;
+       static final int UNDERLINE_IME_THICK = 3 << 16;
+
+       class StyleItem {
+               TextStyle style;
+               int start, length;
+               boolean lineBreak, softBreak, tab;
+
+               /*Script cache and analysis */
+               SCRIPT_ANALYSIS analysis;
+               long psc = 0;
+
+               /*Shape info (malloc when the run is shaped) */
+               long glyphs;
+               int glyphCount;
+               long clusters;
+               long visAttrs;
+
+               /*Place info (malloc when the run is placed) */
+               long advances;
+               long goffsets;
+               int width;
+               int ascentInPoints;
+               int descentInPoints;
+               int leadingInPoints;
+               int x;
+               int underlinePos, underlineThickness;
+               int strikeoutPos, strikeoutThickness;
+
+               /* Justify info (malloc during computeRuns) */
+               long justify;
+
+               /* ScriptBreak */
+               long psla;
+
+               long fallbackFont;
+
+       void free() {
+               long hHeap = OS.GetProcessHeap();
+               if (psc != 0) {
+                       OS.ScriptFreeCache (psc);
+                       OS.HeapFree(hHeap, 0, psc);
+                       psc = 0;
+               }
+               if (glyphs != 0) {
+                       OS.HeapFree(hHeap, 0, glyphs);
+                       glyphs = 0;
+                       glyphCount = 0;
+               }
+               if (clusters != 0) {
+                       OS.HeapFree(hHeap, 0, clusters);
+                       clusters = 0;
+               }
+               if (visAttrs != 0) {
+                       OS.HeapFree(hHeap, 0, visAttrs);
+                       visAttrs = 0;
+               }
+               if (advances != 0) {
+                       OS.HeapFree(hHeap, 0, advances);
+                       advances = 0;
+               }
+               if (goffsets != 0) {
+                       OS.HeapFree(hHeap, 0, goffsets);
+                       goffsets = 0;
+               }
+               if (justify != 0) {
+                       OS.HeapFree(hHeap, 0, justify);
+                       justify = 0;
+               }
+               if (psla != 0) {
+                       OS.HeapFree(hHeap, 0, psla);
+                       psla = 0;
+               }
+               if (fallbackFont != 0) {
+                       OS.DeleteObject(fallbackFont);
+                       fallbackFont = 0;
+               }
+               width = ascentInPoints = descentInPoints = x = 0;
+               lineBreak = softBreak = false;
+       }
+       @Override
+       public String toString () {
+               return "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 TextLayout (Device device) {
+       super(device);
+       wrapWidth = ascentInPixels = descentInPixels = -1;
+       lineSpacingInPoints = 0;
+       verticalIndentInPoints = 0;
+       orientation = SWT.LEFT_TO_RIGHT;
+       textDirection = SWT.LEFT_TO_RIGHT;
+       styles = new StyleItem[2];
+       styles[0] = new StyleItem();
+       styles[1] = new StyleItem();
+       stylesCount = 2;
+       text = ""; //$NON-NLS-1$
+       long[] ppv = new long[1];
+       OS.OleInitialize(0);
+       if (COM.CoCreateInstance(COM.CLSID_CMultiLanguage, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IMLangFontLink2, ppv) == OS.S_OK) {
+               mLangFontLink2 = new IMLangFontLink2(ppv[0]);
+       }
+       init();
+}
+
+RECT addClipRect(StyleItem run, RECT clipRect, RECT rect, int selectionStart, int selectionEnd) {
+       if (rect != null) {
+               if (clipRect == null) {
+                       clipRect = new RECT ();
+                       OS.SetRect(clipRect, -1, rect.top, -1, rect.bottom);
+               }
+               boolean isRTL = (orientation & SWT.RIGHT_TO_LEFT) != 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;
+                       }
+               }
+       }
+       return clipRect;
+}
+
+void breakRun(StyleItem run) {
+       if (run.psla != 0) return;
+       char[] chars = new char[run.length];
+       segmentsText.getChars(run.start, run.start + run.length, chars, 0);
+       long hHeap = OS.GetProcessHeap();
+       run.psla = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, SCRIPT_LOGATTR.sizeof * chars.length);
+       if (run.psla == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       OS.ScriptBreak(chars, 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 != null) return;
+       long hDC = gc != null ? gc.handle : device.internal_new_GC(null);
+       long 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 = new SCRIPT_LOGATTR();
+       SCRIPT_PROPERTIES properties = new SCRIPT_PROPERTIES();
+       int lineWidth = indent, lineStart = 0, lineCount = 1;
+       for (int i=0; i<allRuns.length - 1; i++) {
+               StyleItem run = allRuns[i];
+               if (tabs != null && run.tab) {
+                       int tabsLength = tabs.length, j;
+                       for (j = 0; j < tabsLength; j++) {
+                               if (tabs[j] > lineWidth) {
+                                       run.width = tabs[j] - lineWidth;
+                                       break;
+                               }
+                       }
+                       if (j == 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;
+                               }
+                       }
+                       int length = run.length;
+                       if (length > 1) {
+                               int stop = j + length - 1;
+                               if (stop < tabsLength) {
+                                       run.width += tabs[stop] - tabs[j];
+                               } else {
+                                       if (j < tabsLength) {
+                                               run.width += tabs[tabsLength - 1] - tabs[j];
+                                               length -= (tabsLength - 1) - j;
+                                       }
+                                       int lastTabWidth = tabsLength > 1 ? tabs[tabsLength-1] - tabs[tabsLength-2] : tabs[0];
+                                       run.width += lastTabWidth * (length - 1);
+                               }
+                       }
+               }
+               if (wrapWidth != -1 && lineWidth + run.width > wrapWidth && !run.tab && !run.lineBreak) {
+                       int start = 0;
+                       int[] piDx = new int[run.length];
+                       if (run.style != null && run.style.metrics != null) {
+                               piDx[0] = run.width;
+                       } else {
+                               OS.ScriptGetLogicalWidths(run.analysis, run.length, run.glyphCount, run.advances, run.clusters, run.visAttrs, piDx);
+                       }
+                       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) {
+                                       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 == 0 && i != lineStart && !run.tab) {
+                                       if (logAttr.fSoftBreak && !logAttr.fWhiteSpace) {
+                                               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 == langID || langID == OS.LANG_NEUTRAL || properties.langid == OS.LANG_NEUTRAL) {
+                                                       breakRun(pRun);
+                                                       OS.MoveMemory(logAttr, pRun.psla + ((pRun.length - 1) * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                                                       if (!logAttr.fWhiteSpace) start = -1;
+                                               }
+                                       }
+                               }
+                               if (start >= 0 || i == lineStart) break;
+                               run = allRuns[--i];
+                               start = run.length - 1;
+                       }
+                       boolean wrapEntireRun = start == 0 && i != lineStart && !run.tab;
+                       if (wrapEntireRun) {
+                               breakRun(run);
+                               OS.MoveMemory(logAttr, run.psla + (start * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                               wrapEntireRun = !logAttr.fWhiteSpace;
+                       }
+                       if (wrapEntireRun) {
+                               run = allRuns[--i];
+                               start = run.length;
+                       } else if (start <= 0 && i == lineStart) {
+                               /*
+                                * No soft-break or line-feed found. Avoid breaking a run at
+                                * the first character (firstStart == 0) unless it's the
+                                * only run available (firstIndice == lineStart). See bug 408833.
+                                */
+                               if (firstStart == 0 && firstIndice > lineStart) {
+                                       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) {
+                               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 != allRuns.length - 2) {
+                               run.softBreak = run.lineBreak = true;
+                       }
+               }
+               lineWidth += run.width;
+               if (run.lineBreak) {
+                       lineStart = i + 1;
+                       lineWidth = run.softBreak ?  wrapIndent : 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 ascentInPoints = Math.max(0, DPIUtil.autoScaleDown(getDevice(), this.ascentInPixels));
+       int descentInPoints = Math.max(0, DPIUtil.autoScaleDown(getDevice(), this.descentInPixels));
+       StyleItem[] lineRuns = new StyleItem[allRuns.length];
+       for (int i=0; i<allRuns.length; i++) {
+               StyleItem run = allRuns[i];
+               lineRuns[lineRunCount++] = run;
+               lineWidth += run.width;
+               ascentInPoints = Math.max(ascentInPoints, run.ascentInPoints);
+               descentInPoints = Math.max(descentInPoints, run.descentInPoints);
+               if (run.lineBreak || i == allRuns.length - 1) {
+                       /* Update the run metrics if the last run is a hard break. */
+                       if (lineRunCount == 1 && (i == allRuns.length - 1 || !run.softBreak)) {
+                               TEXTMETRIC lptm = new TEXTMETRIC();
+                               OS.SelectObject(srcHdc, getItemFont(run));
+                               OS.GetTextMetrics(srcHdc, lptm);
+                               run.ascentInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmAscent);
+                               run.descentInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmDescent);
+                               ascentInPoints = Math.max(ascentInPoints, run.ascentInPoints);
+                               descentInPoints = Math.max(descentInPoints, run.descentInPoints);
+                       }
+                       runs[line] = new StyleItem[lineRunCount];
+                       System.arraycopy(lineRuns, 0, runs[line], 0, lineRunCount);
+
+                       if (justify && wrapWidth != -1 && run.softBreak && lineWidth > 0) {
+                               int lineIndent = wrapIndent;
+                               if (line == 0) {
+                                       lineIndent = indent;
+                               } else {
+                                       StyleItem[] previousLine = runs[line - 1];
+                                       StyleItem previousRun = previousLine[previousLine.length - 1];
+                                       if (previousRun.lineBreak && !previousRun.softBreak) {
+                                               lineIndent = indent;
+                                       }
+                               }
+                               lineWidth += lineIndent;
+                               long 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 != item.width) {
+                                               item.justify = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, item.glyphCount * 4);
+                                               if (item.justify == 0) 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 == allRuns.length - 1);
+                       lastRun = runs[line][lineRunCount - 1];
+                       if (run.softBreak && run != 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] + ascentInPoints + descentInPoints + lineSpacingInPoints;
+                       lineOffset[line] = lastOffset;
+                       lineRunCount = lineWidth = 0;
+                       ascentInPoints = Math.max(0, DPIUtil.autoScaleDown(getDevice(), this.ascentInPixels));
+                       descentInPoints = Math.max(0, DPIUtil.autoScaleDown(getDevice(), this.descentInPixels));
+               }
+       }
+       if (srcHdc != 0) OS.DeleteDC(srcHdc);
+       if (gc == null) device.internal_dispose_GC(hDC, null);
+}
+
+@Override
+void destroy () {
+       freeRuns();
+       font = null;
+       text = null;
+       segmentsText = null;
+       tabs = null;
+       styles = null;
+       runs = null;
+       lineOffset = null;
+       lineY = null;
+       lineWidth = null;
+       segments = null;
+       segmentsChars = null;
+       if (mLangFontLink2 != null) {
+               mLangFontLink2.Release();
+               mLangFontLink2 = null;
+       }
+       OS.OleUninitialize();
+}
+
+SCRIPT_ANALYSIS cloneScriptAnalysis (SCRIPT_ANALYSIS src) {
+       SCRIPT_ANALYSIS dst = new SCRIPT_ANALYSIS();
+       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 = new SCRIPT_STATE();
+       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;
+}
+
+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 == 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;
+}
+
+long createGdipBrush(int pixel, int alpha) {
+       int argb = ((alpha & 0xFF) << 24) | ((pixel >> 16) & 0xFF) | (pixel & 0xFF00) | ((pixel & 0xFF) << 16);
+       return Gdip.SolidBrush_new(argb);
+}
+
+long createGdipBrush(Color color, int alpha) {
+       return createGdipBrush(color.handle, alpha);
+}
+
+/**
+ * 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) {
+       checkLayout();
+       drawInPixels(gc, DPIUtil.autoScaleUp(getDevice(), x), DPIUtil.autoScaleUp(getDevice(), y));
+}
+
+void drawInPixels (GC gc, int x, int y) {
+       drawInPixels(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) {
+       checkLayout();
+       drawInPixels(gc, DPIUtil.autoScaleUp(getDevice(), x), DPIUtil.autoScaleUp(getDevice(), y), selectionStart, selectionEnd, selectionForeground, selectionBackground);
+}
+
+void drawInPixels (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) {
+       drawInPixels(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();
+       drawInPixels(gc, DPIUtil.autoScaleUp(getDevice(), x), DPIUtil.autoScaleUp(getDevice(), y), selectionStart, selectionEnd, selectionForeground, selectionBackground, flags);
+}
+
+void drawInPixels (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground, int flags) {
+       computeRuns(gc);
+       if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (selectionForeground != null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (selectionBackground != null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       int length = text.length();
+       if (length == 0 && flags == 0) return;
+       y += getScaledVerticalIndent();
+       long hdc = gc.handle;
+       Rectangle clip = gc.getClippingInPixels();
+       GCData data = gc.data;
+       long gdipGraphics = data.gdipGraphics;
+       int foreground = data.foreground;
+       int linkColor = OS.GetSysColor (OS.COLOR_HOTLIGHT);
+       int alpha = data.alpha;
+       boolean gdip = gdipGraphics != 0;
+       long gdipForeground = 0;
+       long gdipLinkColor = 0;
+       int state = 0;
+       if (gdip) {
+               gc.checkGC(GC.FOREGROUND);
+               gdipForeground = gc.getFgBrush();
+       } else {
+               state = OS.SaveDC(hdc);
+               if ((data.style & SWT.MIRRORED) != 0) {
+                       OS.SetLayout(hdc, OS.GetLayout(hdc) | OS.LAYOUT_RTL);
+               }
+       }
+       boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+       long gdipSelBackground = 0, gdipSelForeground = 0, gdipFont = 0, lastHFont = 0;
+       long selBackground = 0;
+       int selForeground = 0;
+       if (hasSelection || ((flags & SWT.LAST_LINE_SELECTION) != 0 && (flags & (SWT.FULL_SELECTION | SWT.DELIMITER_SELECTION)) != 0)) {
+               int fgSel = selectionForeground != null ? selectionForeground.handle : OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+               int bgSel = selectionBackground != null ? selectionBackground.handle : OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+               if (gdip) {
+                       gdipSelBackground = createGdipBrush(bgSel, alpha);
+                       gdipSelForeground = createGdipBrush(fgSel, alpha);
+               } else {
+                       selBackground = OS.CreateSolidBrush(bgSel);
+                       selForeground = fgSel;
+               }
+               if (hasSelection) {
+                       selectionStart = translateOffset(Math.min(Math.max(0, selectionStart), length - 1));
+                       selectionEnd = translateOffset(Math.min(Math.max(0, selectionEnd), length - 1));
+               }
+       }
+       RECT rect = new RECT();
+       OS.SetBkMode(hdc, OS.TRANSPARENT);
+       for (int line=0; line<runs.length; line++) {
+               int drawX = x + getLineIndent(line);
+               int drawY = y + DPIUtil.autoScaleUp(getDevice(), lineY[line]);
+               StyleItem[] lineRuns = runs[line];
+               int lineHeight = DPIUtil.autoScaleUp(getDevice(), lineY[line+1] - lineY[line] - lineSpacingInPoints);
+
+               //Draw last line selection
+               if ((flags & (SWT.FULL_SELECTION | SWT.DELIMITER_SELECTION)) != 0 && (hasSelection || (flags & SWT.LAST_LINE_SELECTION) != 0)) {
+                       boolean extents = false;
+                       if (line == runs.length - 1 && (flags & SWT.LAST_LINE_SELECTION) != 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 = run.start + run.length - 1;
+                                       if (selectionStart <= endOffset && endOffset < selectionEnd && (flags & SWT.FULL_SELECTION) != 0) {
+                                               extents = true;
+                                       }
+                               }
+                       }
+                       if (extents) {
+                               int width;
+                               if ((flags & SWT.FULL_SELECTION) != 0) {
+                                       width = 0x6FFFFFF;
+                               } else {
+                                       width = lineHeight / 3;
+                               }
+                               if (gdip) {
+                                       Gdip.Graphics_FillRectangle(gdipGraphics, gdipSelBackground, drawX + lineWidth[line], drawY, width, lineHeight);
+                               } else {
+                                       OS.SelectObject(hdc, selBackground);
+                                       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;
+
+               //Draw the background of the runs in the line
+               int alignmentX = drawX;
+               for (int i = 0; i < lineRuns.length; i++) {
+                       StyleItem run = lineRuns[i];
+                       if (run.length == 0) continue;
+                       if (drawX > clip.x + clip.width) break;
+                       if (drawX + run.width >= clip.x) {
+                               if (!run.lineBreak || run.softBreak) {
+                                       OS.SetRect(rect, drawX, drawY, drawX + run.width, drawY + lineHeight);
+                                       if (gdip) {
+                                               drawRunBackgroundGDIP(run, gdipGraphics, rect, selectionStart, selectionEnd, alpha, gdipSelBackground, hasSelection);
+                                       } else {
+                                               drawRunBackground(run, hdc, rect, selectionStart, selectionEnd, selBackground, hasSelection);
+                                       }
+                               }
+                       }
+                       drawX += run.width;
+               }
+
+               //Draw the text, underline, strikeout, and border of the runs in the line
+               int baselineInPixels = Math.max(0, this.ascentInPixels);
+               int lineUnderlinePos = 0;
+               for (int i = 0; i < lineRuns.length; i++) {
+                       baselineInPixels = Math.max(baselineInPixels, DPIUtil.autoScaleUp(getDevice(), lineRuns[i].ascentInPoints));
+                       lineUnderlinePos = Math.min(lineUnderlinePos, lineRuns[i].underlinePos);
+               }
+               RECT borderClip = null, underlineClip = null, strikeoutClip = null, pRect = null;
+               drawX = alignmentX;
+               for (int i = 0; i < lineRuns.length; i++) {
+                       StyleItem run = lineRuns[i];
+                       TextStyle style = run.style;
+                       boolean hasAdorners = style != null && (style.underline || style.strikeout || style.borderStyle != SWT.NONE);
+                       if (run.length == 0) continue;
+                       if (drawX > clip.x + clip.width) break;
+                       if (drawX + run.width >= clip.x) {
+                               boolean skipTab = run.tab && !hasAdorners;
+                               if (!skipTab && (!run.lineBreak || run.softBreak) && !(style != null && style.metrics != null)) {
+                                       OS.SetRect(rect, drawX, drawY, drawX + run.width, drawY + lineHeight);
+                                       if (gdip) {
+                                               long hFont = getItemFont(run);
+                                               if (hFont != lastHFont) {
+                                                       lastHFont = hFont;
+                                                       if (gdipFont != 0) Gdip.Font_delete(gdipFont);
+                                                       long oldFont = OS.SelectObject(hdc, hFont);
+                                                       gdipFont = Gdip.Font_new(hdc, hFont);
+                                                       OS.SelectObject(hdc, oldFont);
+                                                       if (gdipFont == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                                                       if (!Gdip.Font_IsAvailable(gdipFont)) {
+                                                               Gdip.Font_delete(gdipFont);
+                                                               gdipFont = 0;
+                                                       }
+                                               }
+                                               long gdipFg = gdipForeground;
+                                               if (style != null && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) {
+                                                       if (gdipLinkColor == 0) gdipLinkColor = createGdipBrush(linkColor, alpha);
+                                                       gdipFg = gdipLinkColor;
+                                               }
+                                               if (gdipFont != 0 && !run.analysis.fNoGlyphIndex) {
+                                                       pRect = drawRunTextGDIP(gdipGraphics, run, rect, gdipFont, baselineInPixels, gdipFg, gdipSelForeground, selectionStart, selectionEnd, alpha);
+                                               } else {
+                                                       int fg = style != null && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK ? linkColor : foreground;
+                                                       pRect = drawRunTextGDIPRaster(gdipGraphics, run, rect, baselineInPixels, fg, selForeground, selectionStart, selectionEnd);
+                                               }
+                                               underlineClip = drawUnderlineGDIP(gdipGraphics, x, drawY + baselineInPixels, lineUnderlinePos, drawY + lineHeight, lineRuns, i, gdipFg, gdipSelForeground, underlineClip, pRect, selectionStart, selectionEnd, alpha, clip);
+                                               strikeoutClip = drawStrikeoutGDIP(gdipGraphics, x, drawY + baselineInPixels, lineRuns, i, gdipFg, gdipSelForeground, strikeoutClip, pRect, selectionStart, selectionEnd, alpha, clip);
+                                               borderClip = drawBorderGDIP(gdipGraphics, x, drawY, lineHeight, lineRuns, i, gdipFg, gdipSelForeground, borderClip, pRect, selectionStart, selectionEnd, alpha, clip);
+                                       }  else {
+                                               int fg = style != null && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK ? linkColor : foreground;
+                                               pRect = drawRunText(hdc, run, rect, baselineInPixels, fg, selForeground, selectionStart, selectionEnd);
+                                               underlineClip = drawUnderline(hdc, x, drawY + baselineInPixels, lineUnderlinePos, drawY + lineHeight, lineRuns, i, fg, selForeground, underlineClip, pRect, selectionStart, selectionEnd, clip);
+                                               strikeoutClip = drawStrikeout(hdc, x, drawY + baselineInPixels, lineRuns, i, fg, selForeground, strikeoutClip, pRect, selectionStart, selectionEnd, clip);
+                                               borderClip = drawBorder(hdc, x, drawY, lineHeight, lineRuns, i, fg, selForeground, borderClip, pRect,  selectionStart, selectionEnd, clip);
+                                       }
+                               }
+                       }
+                       drawX += run.width;
+               }
+       }
+       if (gdipSelBackground != 0) Gdip.SolidBrush_delete(gdipSelBackground);
+       if (gdipSelForeground != 0) Gdip.SolidBrush_delete(gdipSelForeground);
+       if (gdipLinkColor != 0) Gdip.SolidBrush_delete(gdipLinkColor);
+       if (gdipFont != 0) Gdip.Font_delete(gdipFont);
+       if (state != 0) OS.RestoreDC(hdc, state);
+       if (selBackground != 0) OS.DeleteObject (selBackground);
+}
+
+RECT drawBorder(long hdc, int x, int y, int lineHeight, StyleItem[] line, int index, int color, int selectionColor, RECT clipRect, RECT pRect, int selectionStart, int selectionEnd, Rectangle drawClip) {
+       StyleItem run = line[index];
+       TextStyle style = run.style;
+       if (style == null) return null;
+       if (style.borderStyle == SWT.NONE) return null;
+       clipRect = addClipRect(run, clipRect, pRect, selectionStart, selectionEnd);
+       boolean lastRunVisible = drawClip != null && (x + run.x + run.width) > (drawClip.x + drawClip.width);
+       if (index + 1 >= line.length || lastRunVisible || !style.isAdherentBorder(line[index + 1].style)) {
+               int left = run.x;
+               int start = run.start;
+               int end = run.start + run.length - 1;
+               for (int i = index; i > 0 && style.isAdherentBorder(line[i - 1].style); i--) {
+                       left = line[i - 1].x;
+                       start = Math.min(start, line[i - 1].start);
+                       end = Math.max(end, line[i - 1].start + line[i - 1].length - 1);
+               }
+               boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+               boolean fullSelection = hasSelection && selectionStart <= start && end <= selectionEnd;
+               if (style.borderColor != null) {
+                       color = style.borderColor.handle;
+                       clipRect = null;
+               } else {
+                       if (fullSelection) {
+                               color = selectionColor;
+                               clipRect = null;
+                       } else {
+                               if (style.foreground != null) {
+                                       color = style.foreground.handle;
+                               }
+                       }
+               }
+               int lineWidth = 1;
+               int pattern = 1;
+               int lineStyle = OS.PS_SOLID;
+               switch (style.borderStyle) {
+                       case SWT.BORDER_SOLID: break;
+                       case SWT.BORDER_DASH: {
+                               lineStyle = OS.PS_DASH;
+                               pattern = 4;
+                               break;
+                       }
+                       case SWT.BORDER_DOT: {
+                               lineStyle = OS.PS_DOT;
+                               pattern = 2;
+                               break;
+                       }
+               }
+               long oldBrush = OS.SelectObject(hdc, OS.GetStockObject(OS.NULL_BRUSH));
+               LOGBRUSH logBrush = new LOGBRUSH();
+               logBrush.lbStyle = OS.BS_SOLID;
+               logBrush.lbColor = (int)color;
+               long newPen = OS.ExtCreatePen(lineStyle | OS.PS_GEOMETRIC, lineWidth, logBrush, 0, null);
+               long oldPen = OS.SelectObject(hdc, newPen);
+               RECT drawRect = new RECT();
+               OS.SetRect(drawRect, x + left, y, x + run.x + run.width, y + lineHeight);
+               if (drawClip != null) {
+                       if (drawRect.left < drawClip.x) {
+                               int remainder = drawRect.left % pattern;
+                               drawRect.left = drawClip.x / pattern * pattern + remainder - pattern;
+                       }
+                       if (drawRect.right > drawClip.x + drawClip.width) {
+                               int remainder = drawRect.right % pattern;
+                               drawRect.right = (drawClip.x + drawClip.width) / pattern * pattern + remainder + pattern;
+                       }
+               }
+               OS.Rectangle(hdc, drawRect.left,drawRect.top, drawRect.right, drawRect.bottom);
+               OS.SelectObject(hdc, oldPen);
+               OS.DeleteObject(newPen);
+               if (clipRect != null) {
+                       int state = OS.SaveDC(hdc);
+                       if (clipRect.left == -1) clipRect.left = 0;
+                       if (clipRect.right == -1) clipRect.right = 0x7ffff;
+                       OS.IntersectClipRect(hdc, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+                       logBrush.lbColor = (int)selectionColor;
+                       long selPen = OS.ExtCreatePen (lineStyle | OS.PS_GEOMETRIC, lineWidth, logBrush, 0, null);
+                       oldPen = OS.SelectObject(hdc, selPen);
+                       OS.Rectangle(hdc, drawRect.left, drawRect.top, drawRect.right, drawRect.bottom);
+                       OS.RestoreDC(hdc, state);
+                       OS.SelectObject(hdc, oldPen);
+                       OS.DeleteObject(selPen);
+               }
+               OS.SelectObject(hdc, oldBrush);
+               return null;
+       }
+       return clipRect;
+}
+
+RECT drawBorderGDIP(long graphics, int x, int y, int lineHeight, StyleItem[] line, int index, long color, long selectionColor, RECT clipRect, RECT pRect,  int selectionStart, int selectionEnd, int alpha, Rectangle drawClip) {
+       StyleItem run = line[index];
+       TextStyle style = run.style;
+       if (style == null) return null;
+       if (style.borderStyle == SWT.NONE) return null;
+       clipRect = addClipRect(run, clipRect, pRect, selectionStart, selectionEnd);
+       boolean lastRunVisible = drawClip != null && (x + run.x + run.width) > (drawClip.x + drawClip.width);
+       if (index + 1 >= line.length || lastRunVisible || !style.isAdherentBorder(line[index + 1].style)) {
+               int left = run.x;
+               int start = run.start;
+               int end = run.start + run.length - 1;
+               for (int i = index; i > 0 && style.isAdherentBorder(line[i - 1].style); i--) {
+                       left = line[i - 1].x;
+                       start = Math.min(start, line[i - 1].start);
+                       end = Math.max(end, line[i - 1].start + line[i - 1].length - 1);
+               }
+               boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+               boolean fullSelection = hasSelection && selectionStart <= start && end <= selectionEnd;
+               long brush = color;
+               if (style.borderColor != null) {
+                       brush = createGdipBrush(style.borderColor, alpha);
+                       clipRect = null;
+               } else {
+                       if (fullSelection) {
+                               brush = selectionColor;
+                               clipRect = null;
+                       } else {
+                               if (style.foreground != null) {
+                                       brush = createGdipBrush(style.foreground, alpha);
+                               }
+                       }
+               }
+               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;
+               }
+               long pen = Gdip.Pen_new(brush, lineWidth);
+               Gdip.Pen_SetDashStyle(pen, lineStyle);
+               Gdip.Graphics_SetPixelOffsetMode(graphics, Gdip.PixelOffsetModeNone);
+               int smoothingMode = Gdip.Graphics_GetSmoothingMode(graphics);
+               Gdip.Graphics_SetSmoothingMode(graphics, Gdip.SmoothingModeNone);
+               if (clipRect != null) {
+                       int gstate = Gdip.Graphics_Save(graphics);
+                       if (clipRect.left == -1) clipRect.left = 0;
+                       if (clipRect.right == -1) clipRect.right = 0x7ffff;
+                       Rect gdipRect = new Rect();
+                       gdipRect.X = clipRect.left;
+                       gdipRect.Y = clipRect.top;
+                       gdipRect.Width = clipRect.right - clipRect.left;
+                       gdipRect.Height = clipRect.bottom - clipRect.top;
+                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeExclude);
+                       Gdip.Graphics_DrawRectangle(graphics, pen, x + left, y, run.x + run.width - left - 1, lineHeight - 1);
+                       Gdip.Graphics_Restore(graphics, gstate);
+                       gstate = Gdip.Graphics_Save(graphics);
+                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeIntersect);
+                       long selPen = Gdip.Pen_new(selectionColor, lineWidth);
+                       Gdip.Pen_SetDashStyle(selPen, lineStyle);
+                       Gdip.Graphics_DrawRectangle(graphics, selPen, x + left, y, run.x + run.width - left - 1, lineHeight - 1);
+                       Gdip.Pen_delete(selPen);
+                       Gdip.Graphics_Restore(graphics, gstate);
+               } else {
+                       Gdip.Graphics_DrawRectangle(graphics, pen, x + left, y, run.x + run.width - left - 1, lineHeight - 1);
+               }
+               Gdip.Graphics_SetPixelOffsetMode(graphics, Gdip.PixelOffsetModeHalf);
+               Gdip.Graphics_SetSmoothingMode(graphics, smoothingMode);
+               Gdip.Pen_delete(pen);
+               if (brush != selectionColor && brush != color) Gdip.SolidBrush_delete(brush);
+               return null;
+       }
+       return clipRect;
+}
+
+void drawRunBackground(StyleItem run, long hdc, RECT rect, int selectionStart, int selectionEnd, long selBrush, boolean hasSelection) {
+       int end = run.start + run.length - 1;
+       boolean fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
+       if (fullSelection) {
+               OS.SelectObject(hdc, selBrush);
+               OS.PatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+       } else {
+               if (run.style != null && run.style.background != null) {
+                       int bg = run.style.background.handle;
+                       long hBrush = OS.CreateSolidBrush (bg);
+                       long oldBrush = OS.SelectObject(hdc, hBrush);
+                       OS.PatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+                       OS.SelectObject(hdc, oldBrush);
+                       OS.DeleteObject(hBrush);
+               }
+               boolean partialSelection = hasSelection && !(selectionStart > end || run.start > selectionEnd);
+               if (partialSelection) {
+                       getPartialSelection(run, selectionStart, selectionEnd, rect);
+                       OS.SelectObject(hdc, selBrush);
+                       OS.PatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+               }
+       }
+}
+
+void drawRunBackgroundGDIP(StyleItem run, long graphics, RECT rect, int selectionStart, int selectionEnd, int alpha, long selBrush, boolean hasSelection) {
+       int end = run.start + run.length - 1;
+       boolean fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
+       if (fullSelection) {
+               Gdip.Graphics_FillRectangle(graphics, selBrush, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+       } else {
+               if (run.style != null && run.style.background != null) {
+                       long brush = createGdipBrush(run.style.background, alpha);
+                       Gdip.Graphics_FillRectangle(graphics, brush, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+                       Gdip.SolidBrush_delete(brush);
+               }
+               boolean partialSelection = hasSelection && !(selectionStart > end || run.start > selectionEnd);
+               if (partialSelection) {
+                       getPartialSelection(run, selectionStart, selectionEnd, rect);
+                       if (rect.left > rect.right) {
+                               int tmp = rect.left;
+                               rect.left = rect.right;
+                               rect.right = tmp;
+                       }
+                       Gdip.Graphics_FillRectangle(graphics, selBrush, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+               }
+       }
+}
+
+RECT drawRunText(long hdc, StyleItem run, RECT rect, int baselineInPixels, int color, int selectionColor, int selectionStart, int selectionEnd) {
+       int end = run.start + run.length - 1;
+       boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+       boolean fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
+       boolean partialSelection = hasSelection && !fullSelection && !(selectionStart > end || run.start > selectionEnd);
+       int offset = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? -1 : 0;
+       int x = rect.left + offset;
+       int y = rect.top + (baselineInPixels - DPIUtil.autoScaleUp(getDevice(), run.ascentInPoints));
+       long hFont = getItemFont(run);
+       OS.SelectObject(hdc, hFont);
+       if (fullSelection) {
+               color = selectionColor;
+       } else {
+               if (run.style != null && run.style.foreground != null) {
+                       color = run.style.foreground.handle;
+               }
+       }
+       OS.SetTextColor(hdc, color);
+       OS.ScriptTextOut(hdc, run.psc, x, y, 0, null, run.analysis , 0, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets);
+       if (partialSelection) {
+               getPartialSelection(run, selectionStart, selectionEnd, rect);
+               OS.SetTextColor(hdc, selectionColor);
+               OS.ScriptTextOut(hdc, run.psc, x, y, OS.ETO_CLIPPED, rect, run.analysis , 0, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets);
+       }
+       return fullSelection || partialSelection ? rect : null;
+}
+
+RECT drawRunTextGDIP(long graphics, StyleItem run, RECT rect, long gdipFont, int baselineInPixels, long color, long selectionColor, int selectionStart, int selectionEnd, int alpha) {
+       int end = run.start + run.length - 1;
+       boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+       boolean fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
+       boolean partialSelection = hasSelection && !fullSelection && !(selectionStart > end || run.start > selectionEnd);
+       int drawY = rect.top + baselineInPixels;
+       if (run.style != null && run.style.rise != 0) drawY -= DPIUtil.autoScaleUp(getDevice(), run.style.rise);
+       int drawX = rect.left;
+       long brush = color;
+       if (fullSelection) {
+               brush = selectionColor;
+       } else {
+               if (run.style != null && run.style.foreground != null) {
+                       brush = createGdipBrush(run.style.foreground, alpha);
+               }
+       }
+       int gstate = 0;
+       Rect gdipRect = null;
+       if (partialSelection) {
+               gdipRect = new Rect();
+               getPartialSelection(run, selectionStart, selectionEnd, rect);
+               gdipRect.X = rect.left;
+               gdipRect.Y = rect.top;
+               gdipRect.Width = rect.right - rect.left;
+               gdipRect.Height = rect.bottom - rect.top;
+               gstate = Gdip.Graphics_Save(graphics);
+               Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeExclude);
+       }
+       int gstateMirrored = 0;
+       boolean isMirrored = (orientation & SWT.RIGHT_TO_LEFT) != 0;
+       if (isMirrored) {
+               switch (Gdip.Brush_GetType(brush)) {
+                       case Gdip.BrushTypeLinearGradient:
+                               Gdip.LinearGradientBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                               Gdip.LinearGradientBrush_TranslateTransform(brush, -2 * drawX - run.width, 0, Gdip.MatrixOrderPrepend);
+                               break;
+                       case Gdip.BrushTypeTextureFill:
+                               Gdip.TextureBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
+                               Gdip.TextureBrush_TranslateTransform(brush, -2 * drawX - run.width, 0, Gdip.MatrixOrderPrepend);
+                               break;
+               }
+               gstateMirrored = Gdip.Graphics_Save(graphics);
+               Gdip.Graphics_ScaleTransform(graphics, -1, 1, Gdip.MatrixOrderPrepend);
+               Gdip.Graphics_TranslateTransform(graphics, -2 * drawX - run.width, 0, Gdip.MatrixOrderPrepend);
+       }
+       int[] advances = new int[run.glyphCount];
+       float[] points = new float[run.glyphCount * 2];
+       C.memmove(advances, run.justify != 0 ? run.justify : run.advances, run.glyphCount * 4);
+       int glyphX = drawX;
+       for (int h = 0, j = 0; h < advances.length; h++) {
+               points[j++] = glyphX;
+               points[j++] = drawY;
+               glyphX += advances[h];
+       }
+       Gdip.Graphics_DrawDriverString(graphics, run.glyphs, run.glyphCount, gdipFont, brush, points, 0, 0);
+       if (partialSelection) {
+               if (isMirrored) {
+                       Gdip.Graphics_Restore(graphics, gstateMirrored);
+               }
+               Gdip.Graphics_Restore(graphics, gstate);
+               gstate = Gdip.Graphics_Save(graphics);
+               Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeIntersect);
+               if (isMirrored) {
+                       gstateMirrored = Gdip.Graphics_Save(graphics);
+                       Gdip.Graphics_ScaleTransform(graphics, -1, 1, Gdip.MatrixOrderPrepend);
+                       Gdip.Graphics_TranslateTransform(graphics, -2 * drawX - run.width, 0, Gdip.MatrixOrderPrepend);
+               }
+               Gdip.Graphics_DrawDriverString(graphics, run.glyphs, run.glyphCount, gdipFont, selectionColor, points, 0, 0);
+               Gdip.Graphics_Restore(graphics, gstate);
+       }
+       if (isMirrored) {
+               switch (Gdip.Brush_GetType(brush)) {
+                       case Gdip.BrushTypeLinearGradient:
+                               Gdip.LinearGradientBrush_ResetTransform(brush);
+                               break;
+                       case Gdip.BrushTypeTextureFill:
+                               Gdip.TextureBrush_ResetTransform(brush);
+                               break;
+               }
+               Gdip.Graphics_Restore(graphics, gstateMirrored);
+       }
+       if (brush != selectionColor && brush != color) Gdip.SolidBrush_delete(brush);
+       return fullSelection || partialSelection ? rect : null;
+}
+
+RECT drawRunTextGDIPRaster(long graphics, StyleItem run, RECT rect, int baselineInPixels, int color, int selectionColor, int selectionStart, int selectionEnd) {
+       long clipRgn = 0;
+       Gdip.Graphics_SetPixelOffsetMode(graphics, Gdip.PixelOffsetModeNone);
+       long rgn = Gdip.Region_new();
+       if (rgn == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       Gdip.Graphics_GetClip(graphics, rgn);
+       if (!Gdip.Region_IsInfinite(rgn, graphics)) {
+               clipRgn = Gdip.Region_GetHRGN(rgn, graphics);
+       }
+       Gdip.Region_delete(rgn);
+       Gdip.Graphics_SetPixelOffsetMode(graphics, Gdip.PixelOffsetModeHalf);
+       float[] lpXform = null;
+       long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+       if (matrix == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       Gdip.Graphics_GetTransform(graphics, matrix);
+       if (!Gdip.Matrix_IsIdentity(matrix)) {
+               lpXform = new float[6];
+               Gdip.Matrix_GetElements(matrix, lpXform);
+       }
+       Gdip.Matrix_delete(matrix);
+       long hdc = Gdip.Graphics_GetHDC(graphics);
+       int state = OS.SaveDC(hdc);
+       if (lpXform != null) {
+               OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
+               OS.SetWorldTransform(hdc, lpXform);
+       }
+       if (clipRgn != 0) {
+               OS.SelectClipRgn(hdc, clipRgn);
+               OS.DeleteObject(clipRgn);
+       }
+       if ((orientation & SWT.RIGHT_TO_LEFT) != 0) {
+               OS.SetLayout(hdc, OS.GetLayout(hdc) | OS.LAYOUT_RTL);
+       }
+       OS.SetBkMode(hdc, OS.TRANSPARENT);
+       RECT pRect = drawRunText(hdc, run, rect, baselineInPixels, color, selectionColor, selectionStart, selectionEnd);
+       OS.RestoreDC(hdc, state);
+       Gdip.Graphics_ReleaseHDC(graphics, hdc);
+       return pRect;
+}
+
+RECT drawStrikeout(long hdc, int x, int baselineInPixels, StyleItem[] line, int index, int color, int selectionColor, RECT clipRect, RECT pRect, int selectionStart, int selectionEnd, Rectangle drawClip) {
+       StyleItem run = line[index];
+       TextStyle style = run.style;
+       if (style == null) return null;
+       if (!style.strikeout) return null;
+       clipRect = addClipRect(run, clipRect, pRect, selectionStart, selectionEnd);
+       boolean lastRunVisible = drawClip != null && (x + run.x + run.width) > (drawClip.x + drawClip.width);
+       if (index + 1 >= line.length || lastRunVisible || !style.isAdherentStrikeout(line[index + 1].style)) {
+               int left = run.x;
+               int start = run.start;
+               int end = run.start + run.length - 1;
+               for (int i = index; i > 0 && style.isAdherentStrikeout(line[i - 1].style); i--) {
+                       left = line[i - 1].x;
+                       start = Math.min(start, line[i - 1].start);
+                       end = Math.max(end, line[i - 1].start + line[i - 1].length - 1);
+               }
+               boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+               boolean fullSelection = hasSelection && selectionStart <= start && end <= selectionEnd;
+               if (style.strikeoutColor != null) {
+                       color = style.strikeoutColor.handle;
+                       clipRect = null;
+               } else {
+                       if (fullSelection) {
+                               color = selectionColor;
+                               clipRect = null;
+                       } else {
+                               if (style.foreground != null) {
+                                       color = style.foreground.handle;
+                               }
+                       }
+               }
+               RECT rect = new RECT();
+               int riseInPixels = DPIUtil.autoScaleUp(getDevice(), style.rise);
+               OS.SetRect(rect, x + left, baselineInPixels - run.strikeoutPos - riseInPixels, x + run.x + run.width, baselineInPixels - run.strikeoutPos + run.strikeoutThickness - riseInPixels);
+               long brush = OS.CreateSolidBrush(color);
+               OS.FillRect(hdc, rect, brush);
+               OS.DeleteObject(brush);
+               if (clipRect != null) {
+                       long selBrush = OS.CreateSolidBrush(selectionColor);
+                       if (clipRect.left == -1) clipRect.left = 0;
+                       if (clipRect.right == -1) clipRect.right = 0x7ffff;
+                       OS.SetRect(clipRect, Math.max(rect.left, clipRect.left), rect.top, Math.min(rect.right, clipRect.right), rect.bottom);
+                       OS.FillRect(hdc, clipRect, selBrush);
+                       OS.DeleteObject(selBrush);
+               }
+               return null;
+       }
+       return clipRect;
+}
+
+RECT drawStrikeoutGDIP(long graphics, int x, int baselineInPixels, StyleItem[] line, int index, long color, long selectionColor, RECT clipRect, RECT pRect, int selectionStart, int selectionEnd, int alpha, Rectangle drawClip) {
+       StyleItem run = line[index];
+       TextStyle style = run.style;
+       if (style == null) return null;
+       if (!style.strikeout) return null;
+       clipRect = addClipRect(run, clipRect, pRect, selectionStart, selectionEnd);
+       boolean lastRunVisible = drawClip != null && (x + run.x + run.width) > (drawClip.x + drawClip.width);
+       if (index + 1 >= line.length || lastRunVisible || !style.isAdherentStrikeout(line[index + 1].style)) {
+               int left = run.x;
+               int start = run.start;
+               int end = run.start + run.length - 1;
+               for (int i = index; i > 0 && style.isAdherentStrikeout(line[i - 1].style); i--) {
+                       left = line[i - 1].x;
+                       start = Math.min(start, line[i - 1].start);
+                       end = Math.max(end, line[i - 1].start + line[i - 1].length - 1);
+               }
+               boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+               boolean fullSelection = hasSelection && selectionStart <= start && end <= selectionEnd;
+               long brush = color;
+               if (style.strikeoutColor != null) {
+                       brush = createGdipBrush(style.strikeoutColor, alpha);
+                       clipRect = null;
+               } else {
+                       if (fullSelection) {
+                               brush = selectionColor;
+                               clipRect = null;
+                       } else {
+                               if (style.foreground != null) {
+                                       brush = createGdipBrush(style.foreground, alpha);
+                               }
+                       }
+               }
+               int riseInPixels = DPIUtil.autoScaleUp(getDevice(), style.rise);
+               if (clipRect != null) {
+                       int gstate = Gdip.Graphics_Save(graphics);
+                       if (clipRect.left == -1) clipRect.left = 0;
+                       if (clipRect.right == -1) clipRect.right = 0x7ffff;
+                       Rect gdipRect = new Rect();
+                       gdipRect.X = clipRect.left;
+                       gdipRect.Y = clipRect.top;
+                       gdipRect.Width = clipRect.right - clipRect.left;
+                       gdipRect.Height = clipRect.bottom - clipRect.top;
+                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeExclude);
+                       Gdip.Graphics_FillRectangle(graphics, brush, x + left, baselineInPixels - run.strikeoutPos - riseInPixels, run.x + run.width - left, run.strikeoutThickness);
+                       Gdip.Graphics_Restore(graphics, gstate);
+                       gstate = Gdip.Graphics_Save(graphics);
+                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeIntersect);
+                       Gdip.Graphics_FillRectangle(graphics, selectionColor, x + left, baselineInPixels - run.strikeoutPos - riseInPixels, run.x + run.width - left, run.strikeoutThickness);
+                       Gdip.Graphics_Restore(graphics, gstate);
+               } else {
+                       Gdip.Graphics_FillRectangle(graphics, brush, x + left, baselineInPixels - run.strikeoutPos - riseInPixels, run.x + run.width - left, run.strikeoutThickness);
+               }
+               if (brush != selectionColor && brush != color) Gdip.SolidBrush_delete(brush);
+               return null;
+       }
+       return clipRect;
+}
+
+RECT drawUnderline(long hdc, int x, int baselineInPixels, int lineUnderlinePos, int lineBottom, StyleItem[] line, int index, int color, int selectionColor, RECT clipRect, RECT pRect, int selectionStart, int selectionEnd, Rectangle drawClip) {
+       StyleItem run = line[index];
+       TextStyle style = run.style;
+       if (style == null) return null;
+       if (!style.underline) return null;
+       clipRect = addClipRect(run, clipRect, pRect, selectionStart, selectionEnd);
+       boolean lastRunVisible = drawClip != null && (x + run.x + run.width) > (drawClip.x + drawClip.width);
+       if (index + 1 >= line.length || lastRunVisible || !style.isAdherentUnderline(line[index + 1].style)) {
+               int left = run.x;
+               int start = run.start;
+               int end = run.start + run.length - 1;
+               for (int i = index; i > 0 && style.isAdherentUnderline(line[i - 1].style); i--) {
+                       left = line[i - 1].x;
+                       start = Math.min(start, line[i - 1].start);
+                       end = Math.max(end, line[i - 1].start + line[i - 1].length - 1);
+               }
+               boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+               boolean fullSelection = hasSelection && selectionStart <= start && end <= selectionEnd;
+               if (style.underlineColor != null) {
+                       color = style.underlineColor.handle;
+                       clipRect = null;
+               } else {
+                       if (fullSelection) {
+                               color = selectionColor;
+                               clipRect = null;
+                       } else {
+                               if (style.foreground != null) {
+                                       color = style.foreground.handle;
+                               }
+                       }
+               }
+               RECT rect = new RECT();
+               int riseInPixels = DPIUtil.autoScaleUp(getDevice(), style.rise);
+               OS.SetRect(rect, x + left, baselineInPixels - lineUnderlinePos - riseInPixels, x + run.x + run.width, baselineInPixels - lineUnderlinePos + run.underlineThickness - riseInPixels);
+               if (clipRect != null) {
+                       if (clipRect.left == -1) clipRect.left = 0;
+                       if (clipRect.right == -1) clipRect.right = 0x7ffff;
+                       OS.SetRect(clipRect, Math.max(rect.left, clipRect.left), rect.top, Math.min(rect.right, clipRect.right), rect.bottom);
+               }
+               switch (style.underlineStyle) {
+                       case SWT.UNDERLINE_SQUIGGLE:
+                       case SWT.UNDERLINE_ERROR: {
+                               int squigglyThickness = 1;
+                               int squigglyHeight = 2 * squigglyThickness;
+                               int squigglyY = Math.min(rect.top - squigglyHeight / 2, lineBottom - squigglyHeight - 1);
+                               int[] points = computePolyline(rect.left, squigglyY, rect.right, squigglyY + squigglyHeight);
+                               long pen = OS.CreatePen(OS.PS_SOLID, squigglyThickness, color);
+                               long oldPen = OS.SelectObject(hdc, pen);
+                               int state = OS.SaveDC(hdc);
+                               OS.IntersectClipRect(hdc, rect.left, squigglyY, rect.right + 1, squigglyY + squigglyHeight + 1);
+                               OS.Polyline(hdc, points, points.length / 2);
+                               int length = points.length;
+                               if (length >= 2 && squigglyThickness <= 1) {
+                                       OS.SetPixel (hdc, points[length - 2], points[length - 1], color);
+                               }
+                               OS.SelectObject(hdc, oldPen);
+                               OS.DeleteObject(pen);
+                               OS.RestoreDC(hdc, state);
+                               if (clipRect != null) {
+                                       pen = OS.CreatePen(OS.PS_SOLID, squigglyThickness, selectionColor);
+                                       oldPen = OS.SelectObject(hdc, pen);
+                                       state = OS.SaveDC(hdc);
+                                       OS.IntersectClipRect(hdc, clipRect.left, squigglyY, clipRect.right + 1, squigglyY + squigglyHeight + 1);
+                                       OS.Polyline(hdc, points, points.length / 2);
+                                       if (length >= 2 && squigglyThickness <= 1) {
+                                               OS.SetPixel (hdc, points[length - 2], points[length - 1], selectionColor);
+                                       }
+                                       OS.SelectObject(hdc, oldPen);
+                                       OS.DeleteObject(pen);
+                                       OS.RestoreDC(hdc, state);
+                               }
+                               break;
+                       }
+                       case SWT.UNDERLINE_SINGLE:
+                       case SWT.UNDERLINE_DOUBLE:
+                       case SWT.UNDERLINE_LINK:
+                       case UNDERLINE_IME_THICK:
+                               if (style.underlineStyle == UNDERLINE_IME_THICK) {
+                                       rect.top -= run.underlineThickness;
+                                       if (clipRect != null) clipRect.top -= run.underlineThickness;
+                               }
+                               int bottom = style.underlineStyle == SWT.UNDERLINE_DOUBLE ? rect.bottom + run.underlineThickness * 2 : rect.bottom;
+                               if (bottom > lineBottom) {
+                                       OS.OffsetRect(rect, 0, lineBottom - bottom);
+                                       if (clipRect != null) OS.OffsetRect(clipRect, 0, lineBottom - bottom);
+                               }
+                               long brush = OS.CreateSolidBrush(color);
+                               OS.FillRect(hdc, rect, brush);
+                               if (style.underlineStyle == SWT.UNDERLINE_DOUBLE) {
+                                       OS.SetRect(rect, rect.left, rect.top + run.underlineThickness * 2, rect.right, rect.bottom + run.underlineThickness * 2);
+                                       OS.FillRect(hdc, rect, brush);
+                               }
+                               OS.DeleteObject(brush);
+                               if (clipRect != null) {
+                                       long selBrush = OS.CreateSolidBrush(selectionColor);
+                                       OS.FillRect(hdc, clipRect, selBrush);
+                                       if (style.underlineStyle == SWT.UNDERLINE_DOUBLE) {
+                                               OS.SetRect(clipRect, clipRect.left, rect.top, clipRect.right, rect.bottom);
+                                               OS.FillRect(hdc, clipRect, selBrush);
+                                       }
+                                       OS.DeleteObject(selBrush);
+                               }
+                               break;
+                       case UNDERLINE_IME_DASH:
+                       case UNDERLINE_IME_DOT: {
+                               int penStyle = style.underlineStyle == UNDERLINE_IME_DASH ? OS.PS_DASH : OS.PS_DOT;
+                               long pen = OS.CreatePen(penStyle, 1, color);
+                               long oldPen = OS.SelectObject(hdc, pen);
+                               int descentInPixels = DPIUtil.autoScaleUp(getDevice(), run.descentInPoints);
+                               OS.SetRect(rect, rect.left, baselineInPixels + descentInPixels, rect.right, baselineInPixels + descentInPixels + run.underlineThickness);
+                               OS.MoveToEx(hdc, rect.left, rect.top, 0);
+                               OS.LineTo(hdc, rect.right, rect.top);
+                               OS.SelectObject(hdc, oldPen);
+                               OS.DeleteObject(pen);
+                               if (clipRect != null) {
+                                       pen = OS.CreatePen(penStyle, 1, selectionColor);
+                                       oldPen = OS.SelectObject(hdc, pen);
+                                       OS.SetRect(clipRect, clipRect.left, rect.top, clipRect.right, rect.bottom);
+                                       OS.MoveToEx(hdc, clipRect.left, clipRect.top, 0);
+                                       OS.LineTo(hdc, clipRect.right, clipRect.top);
+                                       OS.SelectObject(hdc, oldPen);
+                                       OS.DeleteObject(pen);
+                               }
+                               break;
+                       }
+               }
+               return null;
+       }
+       return clipRect;
+}
+
+RECT drawUnderlineGDIP (long graphics, int x, int baselineInPixels, int lineUnderlinePos, int lineBottom, StyleItem[] line, int index, long color, long selectionColor, RECT clipRect, RECT pRect, int selectionStart, int selectionEnd, int alpha, Rectangle drawClip) {
+       StyleItem run = line[index];
+       TextStyle style = run.style;
+       if (style == null) return null;
+       if (!style.underline) return null;
+       clipRect = addClipRect(run, clipRect, pRect, selectionStart, selectionEnd);
+       boolean lastRunVisible = drawClip != null && (x + run.x + run.width) > (drawClip.x + drawClip.width);
+       if (index + 1 >= line.length || lastRunVisible || !style.isAdherentUnderline(line[index + 1].style)) {
+               int left = run.x;
+               int start = run.start;
+               int end = run.start + run.length - 1;
+               for (int i = index; i > 0 && style.isAdherentUnderline(line[i - 1].style); i--) {
+                       left = line[i - 1].x;
+                       start = Math.min(start, line[i - 1].start);
+                       end = Math.max(end, line[i - 1].start + line[i - 1].length - 1);
+               }
+               boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+               boolean fullSelection = hasSelection && selectionStart <= start && end <= selectionEnd;
+               long brush = color;
+               if (style.underlineColor != null) {
+                       brush = createGdipBrush(style.underlineColor, alpha);
+                       clipRect = null;
+               } else {
+                       if (fullSelection) {
+                               brush = selectionColor;
+                               clipRect = null;
+                       } else {
+                               if (style.foreground != null) {
+                                       brush = createGdipBrush(style.foreground, alpha);
+                               }
+                       }
+               }
+               RECT rect = new RECT();
+               int riseInPixels = DPIUtil.autoScaleUp(getDevice(), style.rise);
+               OS.SetRect(rect, x + left, baselineInPixels - lineUnderlinePos - riseInPixels, x + run.x + run.width, baselineInPixels - lineUnderlinePos + run.underlineThickness - riseInPixels);
+               Rect gdipRect = null;
+               if (clipRect != null) {
+                       if (clipRect.left == -1) clipRect.left = 0;
+                       if (clipRect.right == -1) clipRect.right = 0x7ffff;
+                       OS.SetRect(clipRect, Math.max(rect.left, clipRect.left), rect.top, Math.min(rect.right, clipRect.right), rect.bottom);
+                       gdipRect = new Rect();
+                       gdipRect.X = clipRect.left;
+                       gdipRect.Y = clipRect.top;
+                       gdipRect.Width = clipRect.right - clipRect.left;
+                       gdipRect.Height = clipRect.bottom - clipRect.top;
+               }
+               int gstate = 0;
+               Gdip.Graphics_SetPixelOffsetMode(graphics, Gdip.PixelOffsetModeNone);
+               int smoothingMode = Gdip.Graphics_GetSmoothingMode(graphics);
+               Gdip.Graphics_SetSmoothingMode(graphics, Gdip.SmoothingModeNone);
+               switch (style.underlineStyle) {
+                       case SWT.UNDERLINE_SQUIGGLE:
+                       case SWT.UNDERLINE_ERROR: {
+                               int squigglyThickness = 1;
+                               int squigglyHeight = 2 * squigglyThickness;
+                               int squigglyY = Math.min(rect.top - squigglyHeight / 2, lineBottom - squigglyHeight - 1);
+                               int[] points = computePolyline(rect.left, squigglyY, rect.right, squigglyY + squigglyHeight);
+                               long pen = Gdip.Pen_new(brush, squigglyThickness);
+                               gstate = Gdip.Graphics_Save(graphics);
+                               if (gdipRect != null) {
+                                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeExclude);
+                               } else {
+                                       Rect r = new Rect();
+                                       r.X = rect.left;
+                                       r.Y = squigglyY;
+                                       r.Width = rect.right - rect.left;
+                                       r.Height = squigglyHeight + 1;
+                                       Gdip.Graphics_SetClip(graphics, r, Gdip.CombineModeIntersect);
+                               }
+                               Gdip.Graphics_DrawLines(graphics, pen, points, points.length / 2);
+                               if (gdipRect != null) {
+                                       long selPen = Gdip.Pen_new(selectionColor, squigglyThickness);
+                                       Gdip.Graphics_Restore(graphics, gstate);
+                                       gstate = Gdip.Graphics_Save(graphics);
+                                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeIntersect);
+                                       Gdip.Graphics_DrawLines(graphics, selPen, points, points.length / 2);
+                                       Gdip.Pen_delete(selPen);
+                               }
+                               Gdip.Graphics_Restore(graphics, gstate);
+                               Gdip.Pen_delete(pen);
+                               if (gstate != 0) Gdip.Graphics_Restore(graphics, gstate);
+                               break;
+                       }
+                       case SWT.UNDERLINE_SINGLE:
+                       case SWT.UNDERLINE_DOUBLE:
+                       case SWT.UNDERLINE_LINK:
+                       case UNDERLINE_IME_THICK:
+                               if (style.underlineStyle == UNDERLINE_IME_THICK) {
+                                       rect.top -= run.underlineThickness;
+                               }
+                               int bottom = style.underlineStyle == SWT.UNDERLINE_DOUBLE ? rect.bottom + run.underlineThickness * 2 : rect.bottom;
+                               if (bottom > lineBottom) {
+                                       OS.OffsetRect(rect, 0, lineBottom - bottom);
+                               }
+                               if (gdipRect != null) {
+                                       gdipRect.Y = rect.top;
+                                       if (style.underlineStyle == UNDERLINE_IME_THICK) {
+                                               gdipRect.Height = run.underlineThickness * 2;
+                                       }
+                                       if (style.underlineStyle == SWT.UNDERLINE_DOUBLE) {
+                                               gdipRect.Height = run.underlineThickness * 3;
+                                       }
+                                       gstate = Gdip.Graphics_Save(graphics);
+                                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeExclude);
+                               }
+                               Gdip.Graphics_FillRectangle(graphics, brush, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+                               if (style.underlineStyle == SWT.UNDERLINE_DOUBLE) {
+                                       Gdip.Graphics_FillRectangle(graphics, brush, rect.left, rect.top + run.underlineThickness * 2, rect.right - rect.left, rect.bottom - rect.top);
+                               }
+                               if (gdipRect != null) {
+                                       Gdip.Graphics_Restore(graphics, gstate);
+                                       gstate = Gdip.Graphics_Save(graphics);
+                                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeIntersect);
+                                       Gdip.Graphics_FillRectangle(graphics, selectionColor, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+                                       if (style.underlineStyle == SWT.UNDERLINE_DOUBLE) {
+                                               Gdip.Graphics_FillRectangle(graphics, selectionColor, rect.left, rect.top + run.underlineThickness * 2, rect.right - rect.left, rect.bottom - rect.top);
+                                       }
+                                       Gdip.Graphics_Restore(graphics, gstate);
+                               }
+                               break;
+                       case UNDERLINE_IME_DOT:
+                       case UNDERLINE_IME_DASH: {
+                               long pen = Gdip.Pen_new(brush, 1);
+                               int dashStyle = style.underlineStyle == UNDERLINE_IME_DOT ? Gdip.DashStyleDot : Gdip.DashStyleDash;
+                               Gdip.Pen_SetDashStyle(pen, dashStyle);
+                               if (gdipRect != null) {
+                                       gstate = Gdip.Graphics_Save(graphics);
+                                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeExclude);
+                               }
+                               int descentInPixels = DPIUtil.autoScaleUp(getDevice(), run.descentInPoints);
+                               Gdip.Graphics_DrawLine(graphics, pen, rect.left, baselineInPixels + descentInPixels, run.width - run.length, baselineInPixels + descentInPixels);
+                               if (gdipRect != null) {
+                                       Gdip.Graphics_Restore(graphics, gstate);
+                                       gstate = Gdip.Graphics_Save(graphics);
+                                       Gdip.Graphics_SetClip(graphics, gdipRect, Gdip.CombineModeIntersect);
+                                       long selPen = Gdip.Pen_new(brush, 1);
+                                       Gdip.Pen_SetDashStyle(selPen, dashStyle);
+                                       Gdip.Graphics_DrawLine(graphics, selPen, rect.left, baselineInPixels + descentInPixels, run.width - run.length, baselineInPixels + descentInPixels);
+                                       Gdip.Graphics_Restore(graphics, gstate);
+                                       Gdip.Pen_delete(selPen);
+                               }
+                               Gdip.Pen_delete(pen);
+                               break;
+                       }
+               }
+               if (brush != selectionColor && brush != color) Gdip.SolidBrush_delete(brush);
+               Gdip.Graphics_SetPixelOffsetMode(graphics, Gdip.PixelOffsetModeHalf);
+               Gdip.Graphics_SetSmoothingMode(graphics, smoothingMode);
+               return null;
+       }
+       return clipRect;
+}
+
+void freeRuns () {
+       if (allRuns == null) return;
+       for (int i=0; i<allRuns.length; i++) {
+               StyleItem run = allRuns[i];
+               run.free();
+       }
+       allRuns = null;
+       runs = null;
+       segmentsText = 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 DPIUtil.autoScaleDown(getDevice(), ascentInPixels);
+}
+
+/**
+ * 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 != -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, DPIUtil.autoScaleDown(getDevice(), width), lineY[lineY.length - 1] + getScaledVerticalIndent());
+}
+
+/**
+ * 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();
+       return DPIUtil.autoScaleDown(getDevice(), getBoundsInPixels(start, end));
+}
+
+Rectangle getBoundsInPixels (int start, int end) {
+       computeRuns(null);
+       int length = text.length();
+       if (length == 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);
+       /* use the high surrogate for the start offset and the low surrogate for the end offset */
+       length = segmentsText.length();
+       char ch = segmentsText.charAt(start);
+       if (0xDC00 <= ch && ch <= 0xDFFF) {
+               if (start - 1 >= 0) {
+                       ch = segmentsText.charAt(start - 1);
+                       if (0xD800 <= ch && ch <= 0xDBFF) {
+                               start--;
+                       }
+               }
+       }
+       ch = segmentsText.charAt(end);
+       if (0xD800 <= ch && ch <= 0xDBFF) {
+               if (end + 1 < length) {
+                       ch = segmentsText.charAt(end + 1);
+                       if (0xDC00 <= ch && ch <= 0xDFFF) {
+                               end++;
+                       }
+               }
+       }
+       int left = 0x7fffffff, right = 0;
+       int top = 0x7fffffff, bottom = 0;
+       boolean isRTL = (orientation & SWT.RIGHT_TO_LEFT) != 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 != null && run.style.metrics != null) {
+                               GlyphMetrics metrics = run.style.metrics;
+                               cx = metrics.getWidthInPixels() * (start - run.start);
+                       } else if (!run.tab) {
+                               int[] piX = new int[1];
+                               long advances = run.justify != 0 ? run.justify : run.advances;
+                               OS.ScriptCPtoX(start - run.start, false, run.length, run.glyphCount, run.clusters, run.visAttrs, advances, run.analysis, piX);
+                               cx = isRTL ? run.width - piX[0] : piX[0];
+                       }
+                       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 != null && run.style.metrics != null) {
+                               GlyphMetrics metrics = run.style.metrics;
+                               cx = metrics.getWidthInPixels() * (end - run.start + 1);
+                       } else if (!run.tab) {
+                               int[] piX = new int[1];
+                               long advances = run.justify != 0 ? run.justify : run.advances;
+                               OS.ScriptCPtoX(end - run.start, true, run.length, run.glyphCount, run.clusters, run.visAttrs, advances, run.analysis, piX);
+                               cx = isRTL ? run.width - piX[0] : piX[0];
+                       }
+                       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, DPIUtil.autoScaleUp(getDevice(), lineY[lineIndex]));
+               bottom = Math.max(bottom, DPIUtil.autoScaleUp(getDevice(), lineY[lineIndex + 1] - lineSpacingInPoints));
+       }
+       return new Rectangle(left, top, right - left, bottom - top + getScaledVerticalIndent());
+}
+
+/**
+ * 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 DPIUtil.autoScaleDown(getDevice(), descentInPixels);
+}
+
+/**
+ * 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 DPIUtil.autoScaleDown(getDevice(), getIndentInPixels());
+}
+
+int getIndentInPixels () {
+       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 boolean getJustify () {
+       checkLayout();
+       return justify;
+}
+
+long getItemFont (StyleItem item) {
+       if (item.fallbackFont != 0) return item.fallbackFont;
+       if (item.style != null && item.style.font != null) {
+               return item.style.font.handle;
+       }
+       if (this.font != 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></ul>
+ */
+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 (resolveTextDirection() & SWT.RIGHT_TO_LEFT) != 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();
+       return DPIUtil.autoScaleDown(getDevice(), getLineBoundsInPixels(lineIndex));
+}
+
+Rectangle getLineBoundsInPixels(int lineIndex) {
+       computeRuns(null);
+       if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+       int x = getLineIndent(lineIndex);
+       int y = DPIUtil.autoScaleUp(getDevice(), lineY[lineIndex]);
+       int width = lineWidth[lineIndex];
+       int height = DPIUtil.autoScaleUp(getDevice(), lineY[lineIndex + 1] - lineY[lineIndex] - lineSpacingInPoints);
+       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 = wrapIndent;
+       if (lineIndex == 0) {
+               lineIndent = indent;
+       } else {
+               StyleItem[] previousLine = runs[lineIndex - 1];
+               StyleItem previousRun = previousLine[previousLine.length - 1];
+               if (previousRun.lineBreak && !previousRun.softBreak) {
+                       lineIndent = indent;
+               }
+       }
+       if (wrapWidth != -1) {
+               boolean 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;
+                       }
+               }
+       }
+       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);
+       long hDC = device.internal_new_GC(null);
+       long srcHdc = OS.CreateCompatibleDC(hDC);
+       TEXTMETRIC lptm = new TEXTMETRIC();
+       OS.SelectObject(srcHdc, font != null ? font.handle : device.systemFont.handle);
+       OS.GetTextMetrics(srcHdc, lptm);
+       OS.DeleteDC(srcHdc);
+       device.internal_dispose_GC(hDC, null);
+
+       int ascentInPoints = DPIUtil.autoScaleDown(getDevice(), Math.max(lptm.tmAscent, this.ascentInPixels));
+       int descentInPoints = DPIUtil.autoScaleDown(getDevice(), Math.max(lptm.tmDescent, this.descentInPixels));
+       int leadingInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmInternalLeading);
+       if (text.length() != 0) {
+               StyleItem[] lineRuns = runs[lineIndex];
+               for (int i = 0; i<lineRuns.length; i++) {
+                       StyleItem run = lineRuns[i];
+                       if (run.ascentInPoints > ascentInPoints) {
+                               ascentInPoints = run.ascentInPoints;
+                               leadingInPoints = run.leadingInPoints;
+                       }
+                       descentInPoints = Math.max(descentInPoints, run.descentInPoints);
+               }
+       }
+       lptm.tmAscent = DPIUtil.autoScaleUp(getDevice(), ascentInPoints);
+       lptm.tmDescent = DPIUtil.autoScaleUp(getDevice(), descentInPoints);
+       lptm.tmHeight = DPIUtil.autoScaleUp(getDevice(), ascentInPoints + descentInPoints);
+       lptm.tmInternalLeading = DPIUtil.autoScaleUp(getDevice(), leadingInPoints);
+       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, boolean trailing) {
+       checkLayout();
+       return DPIUtil.autoScaleDown(getDevice(), getLocationInPixels(offset, trailing));
+}
+
+Point getLocationInPixels (int offset, boolean trailing) {
+       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 == length) {
+               return new Point(getLineIndent(line) + lineWidth[line], DPIUtil.autoScaleUp(getDevice(), lineY[line]));
+       }
+       /* For trailing use the low surrogate and for lead use the high surrogate */
+       char ch = segmentsText.charAt(offset);
+       if (trailing) {
+               if (0xD800 <= ch && ch <= 0xDBFF) {
+                       if (offset + 1 < length) {
+                               ch = segmentsText.charAt(offset + 1);
+                               if (0xDC00 <= ch && ch <= 0xDFFF) {
+                                       offset++;
+                               }
+                       }
+               }
+       } else {
+               if (0xDC00 <= ch && ch <= 0xDFFF) {
+                       if (offset - 1 >= 0) {
+                               ch = segmentsText.charAt(offset - 1);
+                               if (0xD800 <= ch && ch <= 0xDBFF) {
+                                       offset--;
+                               }
+                       }
+               }
+       }
+       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 != null && run.style.metrics != null) {
+                               GlyphMetrics metrics = run.style.metrics;
+                               width = metrics.getWidthInPixels() * (offset - run.start + (trailing ? 1 : 0));
+                       } else if (run.tab) {
+                               width = (trailing || (offset == length)) ? run.width : 0;
+                       } else {
+                               int runOffset = offset - run.start;
+                               int cChars = run.length;
+                               int gGlyphs = run.glyphCount;
+                               int[] piX = new int[1];
+                               long advances = run.justify != 0 ? run.justify : run.advances;
+                               OS.ScriptCPtoX(runOffset, trailing, cChars, gGlyphs, run.clusters, run.visAttrs, advances, run.analysis, piX);
+                               width = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? run.width - piX[0] : piX[0];
+                       }
+                       return new Point(run.x + width, DPIUtil.autoScaleUp(getDevice(), lineY[line]) + getScaledVerticalIndent());
+               }
+       }
+       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, boolean forward) {
+       computeRuns(null);
+       int length = text.length();
+       if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE, null, " [offset value: " + offset + "]");//$NON-NLS-1$ $NON-NLS-2$
+       if (forward && offset == length) return length;
+       if (!forward && offset == 0) return 0;
+       int step = forward ? 1 : -1;
+       if ((movement & SWT.MOVEMENT_CHAR) != 0) return offset + step;
+       length = segmentsText.length();
+       offset = translateOffset(offset);
+       SCRIPT_LOGATTR logAttr = new SCRIPT_LOGATTR();
+       SCRIPT_PROPERTIES properties = new  SCRIPT_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);
+                       OS.MoveMemory(properties, device.scripts[run.analysis.eScript], SCRIPT_PROPERTIES.sizeof);
+                       boolean isComplex = properties.fNeedsCaretInfo || properties.fNeedsWordBreaking;
+                       if (isComplex) breakRun(run);
+                       while (run.start <= offset && offset < run.start + run.length) {
+                               if (isComplex) {
+                                       OS.MoveMemory(logAttr, run.psla + ((offset - run.start) * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                               }
+                               switch (movement) {
+                                       case SWT.MOVEMENT_CLUSTER: {
+                                               if (!properties.fNeedsCaretInfo || (!logAttr.fInvalid && logAttr.fCharStop)) {
+                                                       char ch = segmentsText.charAt(offset);
+                                                       if (0xDC00 <= ch && ch <= 0xDFFF) {
+                                                               if (offset > 0) {
+                                                                       ch = segmentsText.charAt(offset - 1);
+                                                                       if (0xD800 <= ch && ch <= 0xDBFF) {
+                                                                               offset += step;
+                                                                       }
+                                                               }
+                                                       }
+                                                       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) {
+                                                               boolean letterOrDigit = Character.isLetterOrDigit(segmentsText.charAt(offset));
+                                                               boolean previousLetterOrDigit = Character.isLetterOrDigit(segmentsText.charAt(offset - 1));
+                                                               if (letterOrDigit != previousLetterOrDigit || !letterOrDigit) {
+                                                                       if (!Character.isWhitespace(segmentsText.charAt(offset))) {
+                                                                               return untranslateOffset(offset);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               break;
+                                       }
+                                       case SWT.MOVEMENT_WORD_END: {
+                                               if (offset > 0) {
+                                                       boolean isLetterOrDigit = Character.isLetterOrDigit(segmentsText.charAt(offset));
+                                                       boolean previousLetterOrDigit = Character.isLetterOrDigit(segmentsText.charAt(offset - 1));
+                                                       if (!isLetterOrDigit && previousLetterOrDigit) {
+                                                               return untranslateOffset(offset);
+                                                       }
+                                               }
+                                               break;
+                                       }
+                               }
+                               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, boolean)
+ */
+public int getOffset (Point point, int[] trailing) {
+       checkLayout();
+       if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); return getOffsetInPixels(DPIUtil.autoScaleUp(getDevice(), point), trailing);
+}
+
+int getOffsetInPixels (Point point, int[] trailing) {
+       return getOffsetInPixels (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, boolean)
+ */
+public int getOffset (int x, int y, int[] trailing) {
+       checkLayout();
+       return getOffsetInPixels(DPIUtil.autoScaleUp(getDevice(), x), DPIUtil.autoScaleUp(getDevice(), y), trailing);
+}
+
+int getOffsetInPixels (int x, int y, int[] trailing) {
+       computeRuns(null);
+       if (trailing != null && trailing.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       int line;
+       int lineCount = runs.length;
+       for (line=0; line<lineCount; line++) {
+               if (DPIUtil.autoScaleUp(getDevice(), 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 != null && run.style.metrics != null) {
+                               GlyphMetrics metrics = run.style.metrics;
+                               if (metrics.getWidthInPixels() > 0) {
+                                       if (trailing != null) {
+                                               trailing[0] = (xRun % metrics.getWidthInPixels() < metrics.getWidthInPixels() / 2) ? 0 : 1;
+                                       }
+                                       return untranslateOffset(run.start + xRun / metrics.getWidthInPixels());
+                               }
+                       }
+                       if (run.tab) {
+                               if (trailing != null) trailing[0] = x < (run.x + run.width / 2) ? 0 : 1;
+                               return untranslateOffset(run.start);
+                       }
+                       int cChars = run.length;
+                       int cGlyphs = run.glyphCount;
+                       int[] piCP = new int[1];
+                       int[] piTrailing = new int[1];
+                       if ((orientation & SWT.RIGHT_TO_LEFT) != 0) {
+                               xRun = run.width - xRun;
+                       }
+                       long advances = run.justify != 0 ? run.justify : run.advances;
+                       OS.ScriptXtoCP(xRun, cChars, cGlyphs, run.clusters, run.visAttrs, advances, run.analysis, piCP, piTrailing);
+                       int offset = run.start + piCP[0];
+                       int length = segmentsText.length();
+                       char ch = offset < length ? segmentsText.charAt(offset) : 0;
+                       if (0xD800 <= ch && ch <= 0xDBFF && piTrailing[0] <= 1) {
+                               if (offset + 1 < length) {
+                                       ch = segmentsText.charAt(offset + 1);
+                                       if (0xDC00 <= ch && ch <= 0xDFFF) {
+                                               if (trailing != null) trailing[0] = 0;
+                                       }
+                               }
+                       } else if (0xDC00 <= ch && ch <= 0xDFFF && piTrailing[0] <= 1) {
+                               if (offset - 1 >= 0) {
+                                       ch = segmentsText.charAt(offset - 1);
+                                       if (0xD800 <= ch && ch <= 0xDBFF) {
+                                               offset--;
+                                               if (trailing != null) trailing[0] = 2;
+                                       }
+                               }
+                       } else {
+                               if (trailing != null) trailing[0] = piTrailing[0];
+                       }
+                       return untranslateOffset(offset);
+               }
+       }
+       if (trailing != null) trailing[0] = 0;
+       if (lineRuns.length == 1) {
+               StyleItem run = lineRuns[0];
+               if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start);
+       }
+       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;
+}
+
+void getPartialSelection(StyleItem run, int selectionStart, int selectionEnd, RECT rect) {
+       int end = run.start + run.length - 1;
+       int selStart = Math.max(selectionStart, run.start) - run.start;
+       int selEnd = Math.min(selectionEnd, end) - run.start;
+       int cChars = run.length;
+       int gGlyphs = run.glyphCount;
+       int[] piX = new int[1];
+       int x = rect.left;
+       long advances = run.justify != 0 ? 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) != 0 ? run.width - piX[0] : piX[0];
+       rect.left = x + runX;
+       OS.ScriptCPtoX(selEnd, true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, run.analysis, piX);
+       runX = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? run.width - piX[0] : piX[0];
+       rect.right = x + runX;
+}
+
+/**
+ * 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 != null) {
+                       result[count++] = styles[i].start;
+                       result[count++] = styles[i + 1].start - 1;
+               }
+       }
+       if (count != 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;
+}
+
+/**
+ * Returns the segments characters of the receiver.
+ *
+ * @return the segments characters
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.6
+ */
+public char[] getSegmentsChars () {
+       checkLayout();
+       return segmentsChars;
+}
+
+String getSegmentsText() {
+       int length = text.length();
+       if (length == 0) return text;
+       if (segments == null) return text;
+       int nSegments = segments.length;
+       if (nSegments == 0) return text;
+       if (segmentsChars == null) {
+               if (nSegments == 1) return text;
+               if (nSegments == 2) {
+                       if (segments[0] == 0 && segments[1] == length) return text;
+               }
+       }
+       char[] oldChars = new char[length];
+       text.getChars(0, length, oldChars, 0);
+       char[] newChars = new char[length + nSegments];
+       int charCount = 0, segmentCount = 0;
+       char defaultSeparator = (resolveTextDirection() & SWT.RIGHT_TO_LEFT) != 0 ? RTL_MARK : LTR_MARK;
+       while (charCount < length) {
+               if (segmentCount < nSegments && charCount == segments[segmentCount]) {
+                       char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator;
+                       newChars[charCount + segmentCount++] = separator;
+               } else {
+                       newChars[charCount + segmentCount] = oldChars[charCount++];
+               }
+       }
+       while (segmentCount < nSegments) {
+               segments[segmentCount] = charCount;
+               char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator;
+               newChars[charCount + segmentCount++] = separator;
+       }
+       return new String(newChars, 0, newChars.length);
+}
+
+/**
+ * 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 lineSpacingInPoints;
+}
+
+/**
+ * Returns the vertical indent of the receiver.
+ *
+ * @return the vertical indent
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.109
+ */
+public int getVerticalIndent () {
+       checkLayout();
+       return verticalIndentInPoints;
+}
+
+/**
+ * Returns the scaled vertical indent.
+ *
+ * @return the scaled vertical indent.
+ * @since 3.109
+ */
+private int getScaledVerticalIndent() {
+       if (verticalIndentInPoints == 0) {
+               return verticalIndentInPoints;
+       }
+       return DPIUtil.autoScaleUp(getDevice(), verticalIndentInPoints);
+}
+
+/**
+ * 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 != null) {
+                       result[count++] = styles[i].style;
+               }
+       }
+       if (count != 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 DPIUtil.autoScaleDown (getDevice(), getTabsInPixels ());
+}
+
+int[] getTabsInPixels () {
+       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 text direction of the receiver.
+ *
+ * @return the text direction value
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.103
+ */
+public int getTextDirection () {
+       checkLayout();
+       return resolveTextDirection();
+}
+
+/**
+ * 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 DPIUtil.autoScaleDown(getDevice(), getWidthInPixels());
+}
+
+int getWidthInPixels () {
+       return wrapWidth;
+}
+
+/**
+* Returns the receiver's wrap indent.
+*
+* @return the receiver's wrap indent
+*
+* @exception SWTException <ul>
+*    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.6
+*/
+public int getWrapIndent () {
+       checkLayout();
+       return DPIUtil.autoScaleDown(getDevice(), getWrapIndentInPixels());
+}
+
+int getWrapIndentInPixels () {
+       return wrapIndent;
+}
+
+/**
+ * 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 (except {@link #dispose()}) using the text layout.
+ * </p>
+ *
+ * @return <code>true</code> when the text layout is disposed and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed () {
+       return device == null;
+}
+
+/*
+ *  Itemize the receiver text
+ */
+StyleItem[] itemize () {
+       segmentsText = getSegmentsText();
+       int length = segmentsText.length();
+       SCRIPT_CONTROL scriptControl = new SCRIPT_CONTROL();
+       SCRIPT_STATE scriptState = new SCRIPT_STATE();
+       final int MAX_ITEM = length + 1;
+
+       if ((resolveTextDirection() & SWT.RIGHT_TO_LEFT) != 0) {
+               scriptState.uBidiLevel = 1;
+               scriptState.fArabicNumContext = true;
+       }
+
+       /*
+       * In the version of Usp10.h that SWT is compiled the fReserved field is declared
+       * as a bitfield size 8. In newer versions of the Uniscribe, the first bit of fReserved
+       * was used to implement the fMergeNeutralItems feature which can be used to increase
+       * performance by reducing the number of SCRIPT_ITEM returned by ScriptItemize.
+       *
+       * Note: This code is wrong on a big endian machine.
+       *
+       * Note: This code is intentionally commented because it causes bug#377472.
+       */
+//     scriptControl.fReserved = 0x1;
+
+       OS.ScriptApplyDigitSubstitution(null, scriptControl, scriptState);
+
+       long hHeap = OS.GetProcessHeap();
+       long pItems = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, MAX_ITEM * SCRIPT_ITEM.sizeof);
+       if (pItems == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       int[] pcItems = new int[1];
+       char[] chars = new char[length];
+       segmentsText.getChars(0, length, chars, 0);
+       OS.ScriptItemize(chars, length, MAX_ITEM, scriptControl, scriptState, pItems, pcItems);
+//     if (hr == E_OUTOFMEMORY) //TODO handle it
+
+       StyleItem[] runs = merge(pItems, pcItems[0]);
+       OS.HeapFree(hHeap, 0, pItems);
+       return runs;
+}
+
+/*
+ *  Merge styles ranges and script items
+ */
+StyleItem[] merge (long 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 = new SCRIPT_ITEM();
+       int itemLimit = -1;
+       int nextItemIndex = 0;
+       boolean linkBefore = false;
+       boolean merge = itemCount > TOO_MANY_RUNS;
+       SCRIPT_PROPERTIES sp = new SCRIPT_PROPERTIES();
+       while (start < end) {
+               StyleItem item = new StyleItem();
+               item.start = start;
+               item.style = styles[styleIndex].style;
+               runs[count++] = item;
+               OS.MoveMemory(scriptItem, items + itemIndex * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof);
+               item.analysis = scriptItem.a;
+               scriptItem.a = new SCRIPT_ANALYSIS();
+               if (linkBefore) {
+                       item.analysis.fLinkBefore = true;
+                       linkBefore = false;
+               }
+               char ch = segmentsText.charAt(start);
+               switch (ch) {
+                       case '\r':
+                       case '\n':
+                               item.lineBreak = true;
+                               break;
+                       case '\t':
+                               item.tab = true;
+                               break;
+               }
+               if (itemLimit == -1) {
+                       nextItemIndex = itemIndex + 1;
+                       OS.MoveMemory(scriptItem, items + nextItemIndex * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof);
+                       itemLimit = scriptItem.iCharPos;
+                       if (nextItemIndex < itemCount && ch == '\r' && segmentsText.charAt(itemLimit) == '\n') {
+                               nextItemIndex = itemIndex + 2;
+                               OS.MoveMemory(scriptItem, items + nextItemIndex * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof);
+                               itemLimit = scriptItem.iCharPos;
+                       }
+                       if (nextItemIndex < itemCount && merge) {
+                               if (!item.lineBreak) {
+                                       OS.MoveMemory(sp, device.scripts[item.analysis.eScript], SCRIPT_PROPERTIES.sizeof);
+                                       if (!sp.fComplex || item.tab) {
+                                               for (int i = 0; i < MERGE_MAX; i++) {
+                                                       if (nextItemIndex == itemCount) break;
+                                                       char c = segmentsText.charAt(itemLimit);
+                                                       if (c == '\n' || c == '\r') break;
+                                                       if (c == '\t' != item.tab) break;
+                                                       OS.MoveMemory(sp, device.scripts[scriptItem.a.eScript], SCRIPT_PROPERTIES.sizeof);
+                                                       if (!item.tab && sp.fComplex) break;
+                                                       nextItemIndex++;
+                                                       OS.MoveMemory(scriptItem, items + nextItemIndex * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof);
+                                                       itemLimit = scriptItem.iCharPos;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               int styleLimit = translateOffset(styles[styleIndex + 1].start);
+               if (styleLimit <= itemLimit) {
+                       styleIndex++;
+                       start = styleLimit;
+                       if (start < itemLimit && 0 < start && start < end) {
+                               char pChar = segmentsText.charAt(start - 1);
+                               char tChar = segmentsText.charAt(start);
+                               if (Character.isLetter(pChar) && Character.isLetter(tChar)) {
+                                       item.analysis.fLinkAfter = true;
+                                       linkBefore = true;
+                               }
+                       }
+               }
+               if (itemLimit <= styleLimit) {
+                       itemIndex = nextItemIndex;
+                       start = itemLimit;
+                       itemLimit = -1;
+               }
+               item.length = start - item.start;
+       }
+       StyleItem item = new StyleItem();
+       item.start = end;
+       OS.MoveMemory(scriptItem, items + itemCount * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof);
+       item.analysis = scriptItem.a;
+       runs[count++] = item;
+       if (runs.length != count) {
+               StyleItem[] result = new StyleItem[count];
+               System.arraycopy(runs, 0, result, 0, count);
+               return result;
+       }
+       return runs;
+}
+
+/*
+ *  Resolves text direction. If the nominal direction is LTR or RTL, no
+ *  resolution is needed; if the nominal direction is "auto", have BidiUtil
+ *  resolve it according to the first strong bidi character.
+ */
+int resolveTextDirection () {
+       return textDirection == SWT.AUTO_TEXT_DIRECTION ? BidiUtil.resolveTextDirection (text) : textDirection;
+}
+
+/*
+ *  Reorder the run
+ */
+StyleItem[] reorder (StyleItem[] runs, boolean terminate) {
+       int length = runs.length;
+       if (length <= 1) return runs;
+       byte[] bidiLevels = new byte[length];
+       for (int i=0; i<length; i++) {
+               bidiLevels[i] = (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, null, log2vis);
+       StyleItem[] result = new StyleItem[length];
+       for (int i=0; i<length; i++) {
+               result[log2vis[i]] = runs[i];
+       }
+       if ((orientation & SWT.RIGHT_TO_LEFT) != 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 == 0) return;
+       if ((alignment & SWT.LEFT) != 0) alignment = SWT.LEFT;
+       if ((alignment & SWT.RIGHT) != 0) alignment = SWT.RIGHT;
+       if (this.alignment == alignment) return;
+       freeRuns();
+       this.alignment = alignment;
+}
+
+/**
+ * Sets the ascent of the receiver. The ascent is distance in points
+ * 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);
+       ascent = DPIUtil.autoScaleUp(getDevice(), ascent);
+       if (this.ascentInPixels == ascent) return;
+       freeRuns();
+       this.ascentInPixels = ascent;
+}
+
+/**
+ * Sets the descent of the receiver. The descent is distance in points
+ * 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);
+       descent = DPIUtil.autoScaleUp(getDevice(), descent);
+       if (this.descentInPixels == descent) return;
+       freeRuns();
+       this.descentInPixels = 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 != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       Font oldFont = this.font;
+       if (oldFont == font) return;
+       this.font = font;
+       if (oldFont != null && oldFont.equals(font)) return;
+       freeRuns();
+}
+
+/**
+ * Sets the indent of the receiver. This indent is applied to 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>
+ *
+ * @see #setWrapIndent(int)
+ *
+ * @since 3.2
+ */
+public void setIndent (int indent) {
+       checkLayout();
+       setIndentInPixels(DPIUtil.autoScaleUp(getDevice(), indent));
+}
+
+void setIndentInPixels (int indent) {
+       if (indent < 0) return;
+       if (this.indent == 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 (boolean justify) {
+       checkLayout();
+       if (this.justify == 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 == 0) return;
+       if ((orientation & SWT.LEFT_TO_RIGHT) != 0) orientation = SWT.LEFT_TO_RIGHT;
+       if (this.orientation == orientation) return;
+       textDirection = this.orientation = orientation;
+       freeRuns();
+}
+
+/**
+ * Sets the offsets of the receiver's text segments. Text segments are used to
+ * override the default behavior 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>
+ * <p>
+ * When segments characters are set, the segments are the offsets where
+ * the characters are inserted in the text.
+ * <p>
+ *
+ * @param segments the text segments offset
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setSegmentsChars(char[])
+ */
+public void setSegments(int[] segments) {
+       checkLayout();
+       if (this.segments == null && segments == null) return;
+       if (this.segments != null && segments != null) {
+               if (this.segments.length == segments.length) {
+                       int i;
+                       for (i = 0; i <segments.length; i++) {
+                               if (this.segments[i] != segments[i]) break;
+                       }
+                       if (i == segments.length) return;
+               }
+       }
+       freeRuns();
+       this.segments = segments;
+}
+
+/**
+ * Sets the characters to be used in the segments boundaries. The segments
+ * are set by calling <code>setSegments(int[])</code>. The application can
+ * use this API to insert Unicode Control Characters in the text to control
+ * the display of the text and bidi reordering. The characters are not
+ * accessible by any other API in <code>TextLayout</code>.
+ *
+ * @param segmentsChars the segments characters
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setSegments(int[])
+ *
+ * @since 3.6
+ */
+public void setSegmentsChars(char[] segmentsChars) {
+       checkLayout();
+       if (this.segmentsChars == null && segmentsChars == null) return;
+       if (this.segmentsChars != null && segmentsChars != null) {
+               if (this.segmentsChars.length == segmentsChars.length) {
+                       int i;
+                       for (i = 0; i <segmentsChars.length; i++) {
+                               if (this.segmentsChars[i] != segmentsChars[i]) break;
+                       }
+                       if (i == segmentsChars.length) return;
+               }
+       }
+       freeRuns();
+       this.segmentsChars = segmentsChars;
+}
+
+/**
+ * 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.lineSpacingInPoints == spacing) return;
+       freeRuns();
+       this.lineSpacingInPoints = spacing;
+}
+
+/**
+ * Sets the vertical indent of the receiver.  The vertical indent
+ * is the space left before the first line.
+ *
+ * @param verticalIndent the new vertical indent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the vertical indent is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.109
+ */
+public void setVerticalIndent (int verticalIndent) {
+       checkLayout();
+       if (verticalIndent < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (this.verticalIndentInPoints == verticalIndent) return;
+       this.verticalIndentInPoints = verticalIndent;
+}
+
+/**
+ * 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 == 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 == start && styles[high + 1].start - 1 == end) {
+                       if (style == null) {
+                               if (item.style == null) return;
+                       } else {
+                               if (style.equals(item.style)) return;
+                       }
+               }
+       }
+       freeRuns();
+       int modifyStart = high;
+       int modifyEnd = modifyStart;
+       while (modifyEnd < stylesCount) {
+               if (styles[modifyEnd + 1].start > end) break;
+               modifyEnd++;
+       }
+       if (modifyStart == modifyEnd) {
+               int styleStart = styles[modifyStart].start;
+               int styleEnd = styles[modifyEnd + 1].start - 1;
+               if (styleStart == start && styleEnd == end) {
+                       styles[modifyStart].style = style;
+                       return;
+               }
+               if (styleStart != start && styleEnd != 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 == styles[modifyStart].start) modifyStart--;
+       if (end == 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 points 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 == null && tabs == null) return;
+       setTabsInPixels (DPIUtil.autoScaleUp (getDevice(), tabs));
+}
+
+void setTabsInPixels (int[] tabs) {
+       if (Arrays.equals (this.tabs, tabs)) return;
+       freeRuns();
+       this.tabs = tabs;
+}
+
+/**
+ * Sets the receiver's text.
+ *<p>
+ * Note: Setting the text also clears all the styles. This method
+ * returns without doing anything if the new text is the same as
+ * the current text.
+ * </p>
+ *
+ * @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();
+       if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (text.equals(this.text)) return;
+       freeRuns();
+       this.text = text;
+       styles = new StyleItem[2];
+       styles[0] = new StyleItem();
+       styles[1] = new StyleItem();
+       styles[1].start = text.length();
+       stylesCount = 2;
+}
+
+/**
+ * Sets the text direction of the receiver, which must be one
+ * of <code>SWT.LEFT_TO_RIGHT</code>, <code>SWT.RIGHT_TO_LEFT</code>
+ * or <code>SWT.AUTO_TEXT_DIRECTION</code>.
+ *
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows.
+ * It doesn't set the base text direction on GTK and Cocoa.
+ * </p>
+ *
+ * @param textDirection the new text direction
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @since 3.103
+ */
+public void setTextDirection (int textDirection) {
+       checkLayout();
+       int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+       textDirection &= mask;
+       if (textDirection == 0) return;
+       if (textDirection != SWT.AUTO_TEXT_DIRECTION) {
+               if ((textDirection & SWT.LEFT_TO_RIGHT) != 0) textDirection = SWT.LEFT_TO_RIGHT;
+               if (this.textDirection == textDirection) return;
+       }
+       this.textDirection = textDirection;
+       freeRuns();
+}
+
+/**
+ * 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();
+       setWidthInPixels(width != SWT.DEFAULT ? DPIUtil.autoScaleUp(getDevice(), width) : width);
+}
+
+void setWidthInPixels (int width) {
+       if (width < -1 || width == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       if (this.wrapWidth == width) return;
+       freeRuns();
+       this.wrapWidth = width;
+}
+
+/**
+ * Sets the wrap indent of the receiver. This indent is applied to all lines
+ * in the paragraph except the first line.
+ *
+ * @param wrapIndent new wrap indent
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setIndent(int)
+ *
+ * @since 3.6
+ */
+public void setWrapIndent (int wrapIndent) {
+       checkLayout();
+       setWrapIndentInPixels(DPIUtil.autoScaleUp(getDevice(), wrapIndent));
+}
+
+void setWrapIndentInPixels (int wrapIndent) {
+       if (wrapIndent < 0) return;
+       if (this.wrapIndent == wrapIndent) return;
+       freeRuns();
+       this.wrapIndent = wrapIndent;
+}
+
+boolean shape (long hdc, StyleItem run, char[] chars, int[] glyphCount, int maxGlyphs, SCRIPT_PROPERTIES sp) {
+       boolean useCMAPcheck = !sp.fComplex && !run.analysis.fNoGlyphIndex;
+       if (useCMAPcheck) {
+               short[] glyphs = new short[chars.length];
+               if (OS.ScriptGetCMap(hdc, run.psc, chars, chars.length, 0, glyphs) != OS.S_OK) {
+                       if (run.psc != 0) {
+                               OS.ScriptFreeCache(run.psc);
+                               glyphCount[0] = 0;
+                               OS.MoveMemory(run.psc, new long [1], C.PTR_SIZEOF);
+                       }
+                       return false;
+               }
+       }
+       int hr = OS.ScriptShape(hdc, run.psc, chars, chars.length, maxGlyphs, run.analysis, run.glyphs, run.clusters, run.visAttrs, glyphCount);
+       run.glyphCount = glyphCount[0];
+       if (useCMAPcheck) return true;
+
+       if (hr != OS.USP_E_SCRIPT_NOT_IN_FONT) {
+               if (run.analysis.fNoGlyphIndex) return true;
+               SCRIPT_FONTPROPERTIES fp = new SCRIPT_FONTPROPERTIES ();
+               fp.cBytes = SCRIPT_FONTPROPERTIES.sizeof;
+               OS.ScriptGetFontProperties(hdc, run.psc, fp);
+               short[] glyphs = new short[glyphCount[0]];
+               OS.MoveMemory(glyphs, run.glyphs, glyphs.length * 2);
+               int i;
+               for (i = 0; i < glyphs.length; i++) {
+                       if (glyphs[i] == fp.wgDefault) break;
+               }
+               if (i == glyphs.length) return true;
+       }
+       if (run.psc != 0) {
+               OS.ScriptFreeCache(run.psc);
+               glyphCount[0] = 0;
+               OS.MoveMemory(run.psc, new long [1], C.PTR_SIZEOF);
+       }
+       run.glyphCount = 0;
+       return false;
+}
+
+long createMetafileWithChars(long hdc, long hFont, char[] chars, int charCount) {
+       long hHeap = OS.GetProcessHeap();
+
+       /*
+        * The native string must remain unchanged between ScriptStringAnalyse and ScriptStringOut.
+        * According to debugging, ScriptStringAnalyse implicitly saves string to SCRIPT_STRING_ANALYSIS.
+        * Then, ScriptStringOut uses the saved string in internal call to ExtTextOutW.
+        * I believe this is due to OS.SSA_METAFILE, which is documented as follows:
+        *     Write items with ExtTextOutW calls, not with glyphs.
+        * Note: passing Java chars to native function is wrong, because JNI will allocate
+        * temporary native string which will be deallocated upon return from ScriptStringAnalyse.
+        */
+       int nativeStringSize = charCount * Character.BYTES;
+       long nativeString = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, nativeStringSize);
+       OS.MoveMemory (nativeString, chars, nativeStringSize);
+
+       long ssa = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, OS.SCRIPT_STRING_ANALYSIS_sizeof());
+       long metaFileDc = OS.CreateEnhMetaFile(hdc, null, null, null);
+       long oldMetaFont = OS.SelectObject(metaFileDc, hFont);
+       int flags = OS.SSA_METAFILE | OS.SSA_FALLBACK | OS.SSA_GLYPHS | OS.SSA_LINK;
+       if (OS.ScriptStringAnalyse(metaFileDc, nativeString, charCount, 0, -1, flags, 0, null, null, 0, 0, 0, ssa) == OS.S_OK) {
+               OS.ScriptStringOut(ssa, 0, 0, 0, null, 0, 0, false);
+               OS.ScriptStringFree(ssa);
+       }
+       OS.HeapFree(hHeap, 0, nativeString);
+       OS.HeapFree(hHeap, 0, ssa);
+       OS.SelectObject(metaFileDc, oldMetaFont);
+       return OS.CloseEnhMetaFile(metaFileDc);
+}
+
+/*
+ * Generate glyphs for one Run.
+ */
+void shape (final long hdc, final StyleItem run) {
+       if (run.lineBreak) return;
+       if (run.glyphs != 0) return;
+       final int[] buffer = new int[1];
+       final char[] chars = new char[run.length];
+       segmentsText.getChars(run.start, run.start + run.length, chars, 0);
+
+       final int maxGlyphs = (chars.length * 3 / 2) + 16;
+       long hHeap = OS.GetProcessHeap();
+       run.glyphs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * 2);
+       if (run.glyphs == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       run.clusters = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * 2);
+       if (run.clusters == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       run.visAttrs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * SCRIPT_VISATTR_SIZEOF);
+       if (run.visAttrs == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       run.psc = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, C.PTR_SIZEOF);
+       if (run.psc == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       final short script = run.analysis.eScript;
+       final SCRIPT_PROPERTIES sp = new SCRIPT_PROPERTIES();
+       OS.MoveMemory(sp, device.scripts[script], SCRIPT_PROPERTIES.sizeof);
+       boolean shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs, sp);
+       if (!shapeSucceed) {
+               if (sp.fPrivateUseArea) {
+                       run.analysis.fNoGlyphIndex = true;
+                       shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs, sp);
+               }
+       }
+       if (!shapeSucceed) {
+               long hFont = OS.GetCurrentObject(hdc, OS.OBJ_FONT);
+               long newFont = 0;
+               /*
+               * Bug in Uniscribe. In some version of Uniscribe, ScriptStringAnalyse crashes
+               * when the character array is too long. The fix is to limit the size of character
+               * array to two. Note, limiting the array to only one character would cause surrogate
+               * pairs to stop working.
+               */
+               char[] sampleChars = new char[Math.min(chars.length, 2)];
+               SCRIPT_LOGATTR logAttr = new SCRIPT_LOGATTR();
+               breakRun(run);
+               int count = 0;
+               for (int i = 0; i < chars.length; i++) {
+                       OS.MoveMemory(logAttr, run.psla + (i * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                       if (!logAttr.fWhiteSpace) {
+                               sampleChars[count++] = chars[i];
+                               if (count == sampleChars.length) break;
+                       }
+               }
+               if (count > 0) {
+                       long metaFile = createMetafileWithChars(hdc, hFont, sampleChars, count);
+                       final EMREXTCREATEFONTINDIRECTW emr = new EMREXTCREATEFONTINDIRECTW();
+                       class MetaFileEnumProc {
+                               long metaFileEnumProc (long hDC, long table, long record, long nObj, long 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;
+                                       }
+                                       return 1;
+                               }
+                       }
+                       MetaFileEnumProc object = new MetaFileEnumProc();
+                       /* Avoid compiler warnings */
+                       boolean compilerWarningWorkaround = false;
+                       if (compilerWarningWorkaround) object.metaFileEnumProc(0, 0, 0, 0, 0);
+                       Callback callback = new Callback(object, "metaFileEnumProc", 5);
+                       long address = callback.getAddress();
+                       if (address == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+                       OS.EnumEnhMetaFile(0, metaFile, address, 0, null);
+                       OS.DeleteEnhMetaFile(metaFile);
+                       callback.dispose();
+                       newFont = OS.CreateFontIndirect(emr.elfw.elfLogFont);
+               } else {
+                       /*
+                       * The run is composed only by white spaces, this happens when a run is split
+                       * by a visual style. The font fallback for the script can not be determined
+                       * using only white spaces. The solution is to use the font of the previous
+                       * or next run of the same script.
+                       */
+                       int index = 0;
+                       while (index < allRuns.length - 1) {
+                               if (allRuns[index] == run) {
+                                       if (index > 0) {
+                                               StyleItem pRun = allRuns[index - 1];
+                                               if (pRun.analysis.eScript == run.analysis.eScript) {
+                                                       long pFont = getItemFont(pRun);
+                                                       LOGFONT logFont = new LOGFONT ();
+                                                       OS.GetObject(pFont, LOGFONT.sizeof, logFont);
+                                                       newFont = OS.CreateFontIndirect(logFont);
+                                               }
+                                       }
+                                       if (newFont == 0) {
+                                               if (index + 1 < allRuns.length - 1) {
+                                                       StyleItem nRun = allRuns[index + 1];
+                                                       if (nRun.analysis.eScript == run.analysis.eScript) {
+                                                               OS.SelectObject(hdc, getItemFont(nRun));
+                                                               shape(hdc, nRun);
+                                                               long nFont = getItemFont(nRun);
+                                                               LOGFONT logFont = new LOGFONT ();
+                                                               OS.GetObject(nFont, LOGFONT.sizeof, logFont);
+                                                               newFont = OS.CreateFontIndirect(logFont);
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               }
+                               index++;
+                       }
+               }
+               if (newFont != 0) {
+                       OS.SelectObject(hdc, newFont);
+                       if (shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs, sp)) {
+                               run.fallbackFont = newFont;
+                       }
+               }
+               if (!shapeSucceed) {
+                       if (!sp.fComplex) {
+                               run.analysis.fNoGlyphIndex = true;
+                               if (shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs, sp)) {
+                                       run.fallbackFont = newFont;
+                               } else {
+                                       run.analysis.fNoGlyphIndex = false;
+                               }
+                       }
+               }
+               if (!shapeSucceed) {
+                       if (mLangFontLink2 != null) {
+                               long [] hNewFont = new long [1];
+                               int[] dwCodePages = new int[1], cchCodePages = new int[1];
+                               mLangFontLink2.GetStrCodePages(chars, chars.length, 0, dwCodePages, cchCodePages);
+                               if (mLangFontLink2.MapFont(hdc, dwCodePages[0], chars[0], hNewFont) == OS.S_OK) {
+                                       LOGFONT logFont = new LOGFONT ();
+                                       OS.GetObject(hNewFont[0], LOGFONT.sizeof, logFont);
+                                       mLangFontLink2.ReleaseFont(hNewFont[0]);
+                                       long mLangFont = OS.CreateFontIndirect(logFont);
+                                       long oldFont = OS.SelectObject(hdc, mLangFont);
+                                       if (shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs, sp)) {
+                                               run.fallbackFont = mLangFont;
+                                       } else {
+                                               OS.SelectObject(hdc, oldFont);
+                                               OS.DeleteObject(mLangFont);
+                                       }
+                               }
+                       }
+               }
+               if (!shapeSucceed) OS.SelectObject(hdc, hFont);
+               if (newFont != 0 && newFont != 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, chars, chars.length, maxGlyphs, run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer);
+               run.glyphCount = buffer[0];
+       }
+       int[] abc = new int[3];
+       run.advances = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * 4);
+       if (run.advances == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       run.goffsets = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * GOFFSET_SIZEOF);
+       if (run.goffsets == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       OS.ScriptPlace(hdc, run.psc, run.glyphs, run.glyphCount, run.visAttrs, run.analysis, run.advances, run.goffsets, abc);
+       run.width = abc[0] + abc[1] + abc[2];
+       TextStyle style = run.style;
+       if (style != null) {
+               OUTLINETEXTMETRIC lotm = null;
+               if (style.underline || style.strikeout) {
+                       lotm = new OUTLINETEXTMETRIC();
+                       if (OS.GetOutlineTextMetrics(hdc, OUTLINETEXTMETRIC.sizeof, lotm) == 0) {
+                               lotm = null;
+                       }
+               }
+               if (style.metrics != 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.getWidthInPixels() * Math.max (1, run.glyphCount);
+                       run.ascentInPoints = metrics.ascent;
+                       run.descentInPoints = metrics.descent;
+                       run.leadingInPoints = 0;
+               } else {
+                       TEXTMETRIC lptm = null;
+                       if (lotm != null) {
+                               lptm = lotm.otmTextMetrics;
+                       } else {
+                               lptm = new TEXTMETRIC();
+                               OS.GetTextMetrics(hdc, lptm);
+                       }
+                       run.ascentInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmAscent);
+                       run.descentInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmDescent);
+                       run.leadingInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmInternalLeading);
+               }
+               if (lotm != 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 = DPIUtil.autoScaleUp(getDevice(), run.ascentInPoints) / 2;
+                       run.strikeoutThickness = 1;
+               }
+               run.ascentInPoints += style.rise;
+               run.descentInPoints -= style.rise;
+       } else {
+               TEXTMETRIC lptm = new TEXTMETRIC();
+               OS.GetTextMetrics(hdc, lptm);
+               run.ascentInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmAscent);
+               run.descentInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmDescent);
+               run.leadingInPoints = DPIUtil.autoScaleDown(getDevice(), lptm.tmInternalLeading);
+       }
+}
+
+int validadeOffset(int offset, int step) {
+       offset = untranslateOffset(offset);
+       return translateOffset(offset + step);
+}
+
+/**
+ * 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) {
+       int length = text.length();
+       if (length == 0) return offset;
+       if (segments == null) return offset;
+       int nSegments = segments.length;
+       if (nSegments == 0) return offset;
+       if (segmentsChars == null) {
+               if (nSegments == 1) return offset;
+               if (nSegments == 2) {
+                       if (segments[0] == 0 && segments[1] == length) return offset;
+               }
+       }
+       for (int i = 0; i < nSegments && offset - i >= segments[i]; i++) {
+               offset++;
+       }
+       return offset;
+}
+
+int untranslateOffset(int offset) {
+       int length = text.length();
+       if (length == 0) return offset;
+       if (segments == null) return offset;
+       int nSegments = segments.length;
+       if (nSegments == 0) return offset;
+       if (segmentsChars == null) {
+               if (nSegments == 1) return offset;
+               if (nSegments == 2) {
+                       if (segments[0] == 0 && segments[1] == length) return offset;
+               }
+       }
+       for (int i = 0; i < nSegments && offset > segments[i]; i++) {
+               offset--;
+       }
+       return offset;
+}
+
+/**
+ * Sets Default Tab Width in terms if number of space characters.
+ *
+ * @param tabLength in number of characters
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the tabLength is less than <code>0</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * DO NOT USE This might be removed in 4.8
+ * @since 3.107
+ */
+public void setDefaultTabWidth(int tabLength) {
+       // unused in win32
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/TextStyle.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/TextStyle.java
new file mode 100644 (file)
index 0000000..1338f34
--- /dev/null
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+
+/**
+ * <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 boolean 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>,
+        * <code>SWT.UNDERLINE_SQUIGGLE</code>, or <code>SWT.UNDERLINE_LINK</code>.
+        * </p>
+        *
+        * @see SWT#UNDERLINE_SINGLE
+        * @see SWT#UNDERLINE_DOUBLE
+        * @see SWT#UNDERLINE_ERROR
+        * @see SWT#UNDERLINE_SQUIGGLE
+        * @see SWT#UNDERLINE_LINK
+        *
+        * @since 3.4
+        */
+       public int underlineStyle;
+
+       /**
+        * the strikeout flag of the style
+        *
+        * @since 3.1
+        */
+       public boolean 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;
+
+
+       /**
+        * the data. An user data field. It can be used to hold the HREF when the range
+        * is used as a link or the embed object when the range is used with <code>GlyphMetrics</code>.
+        * <p>
+        *
+        * @since 3.5
+        */
+       public Object data;
+
+
+/**
+ * Create an empty text style.
+ *
+ * @since 3.4
+ */
+public TextStyle () {
+}
+
+/**
+ * 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 TextStyle (Font font, Color foreground, Color background) {
+       if (font != null && font.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       if (foreground != null && foreground.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+       if (background != 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 TextStyle (TextStyle style) {
+       if (style == 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;
+       data = style.data;
+}
+
+/**
+ * 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 boolean equals(Object object) {
+       if (object == this) return true;
+       if (object == null) return false;
+       if (!(object instanceof TextStyle)) return false;
+       TextStyle style = (TextStyle)object;
+       if (foreground != null) {
+               if (!foreground.equals(style.foreground)) return false;
+       } else if (style.foreground != null) return false;
+       if (background != null) {
+               if (!background.equals(style.background)) return false;
+       } else if (style.background != null) return false;
+       if (font != null) {
+               if (!font.equals(style.font)) return false;
+       } else if (style.font != null) return false;
+       if (metrics != null) {
+               if (!metrics.equals(style.metrics)) return false;
+       } else if (style.metrics != null) return false;
+       if (underline != style.underline) return false;
+       if (underlineStyle != style.underlineStyle) return false;
+       if (borderStyle != style.borderStyle) return false;
+       if (strikeout != style.strikeout) return false;
+       if (rise != style.rise) return false;
+       if (underlineColor != null) {
+               if (!underlineColor.equals(style.underlineColor)) return false;
+       } else if (style.underlineColor != null) return false;
+       if (strikeoutColor != null) {
+               if (!strikeoutColor.equals(style.strikeoutColor)) return false;
+       } else if (style.strikeoutColor != null) return false;
+       if (underlineStyle != style.underlineStyle) return false;
+       if (borderColor != null) {
+               if (!borderColor.equals(style.borderColor)) return false;
+       } else if (style.borderColor != null) return false;
+       if (data != null) {
+               if (!data.equals(style.data)) return false;
+       } else if (style.data != 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)
+ */
+@Override
+public int hashCode() {
+       int hash = 0;
+       if (foreground != null) hash ^= foreground.hashCode();
+       if (background != null) hash ^= background.hashCode();
+       if (font != null) hash ^= font.hashCode();
+       if (metrics != null) hash ^= metrics.hashCode();
+       if (underline) hash ^= (hash << 1);
+       if (strikeout) hash ^= (hash << 2);
+       hash ^= rise;
+       if (underlineColor != null) hash ^= underlineColor.hashCode();
+       if (strikeoutColor != null) hash ^= strikeoutColor.hashCode();
+       if (borderColor != null) hash ^= borderColor.hashCode();
+       hash ^= underlineStyle;
+       return hash;
+}
+
+boolean isAdherentBorder(TextStyle style) {
+       if (this == style) return true;
+       if (style == null) return false;
+       if (borderStyle != style.borderStyle) return false;
+       if (borderColor != null) {
+               if (!borderColor.equals(style.borderColor)) return false;
+       } else {
+               if (style.borderColor != null) return false;
+               if (foreground != null) {
+                       if (!foreground.equals(style.foreground)) return false;
+               } else if (style.foreground != null) return false;
+       }
+       return true;
+}
+
+boolean isAdherentUnderline(TextStyle style) {
+       if (this == style) return true;
+       if (style == null) return false;
+       if (underline != style.underline) return false;
+       if (underlineStyle != style.underlineStyle) return false;
+       if (underlineColor != null) {
+               if (!underlineColor.equals(style.underlineColor)) return false;
+       } else {
+               if (style.underlineColor != null) return false;
+               if (foreground != null) {
+                       if (!foreground.equals(style.foreground)) return false;
+               } else if (style.foreground != null) return false;
+       }
+       return true;
+}
+
+boolean isAdherentStrikeout(TextStyle style) {
+       if (this == style) return true;
+       if (style == null) return false;
+       if (strikeout != style.strikeout) return false;
+       if (strikeoutColor != null) {
+               if (!strikeoutColor.equals(style.strikeoutColor)) return false;
+       } else {
+               if (style.strikeoutColor != null) return false;
+               if (foreground != null) {
+                       if (!foreground.equals(style.foreground)) return false;
+               } else if (style.foreground != 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 () {
+       StringBuilder buffer = new StringBuilder("TextStyle {"); //$NON-NLS-1$
+       int startLength = buffer.length();
+       if (font != null) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("font="); //$NON-NLS-1$
+               buffer.append(font);
+       }
+       if (foreground != null) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("foreground="); //$NON-NLS-1$
+               buffer.append(foreground);
+       }
+       if (background != null) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("background="); //$NON-NLS-1$
+               buffer.append(background);
+       }
+       if (underline) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("underline="); //$NON-NLS-1$
+               switch (underlineStyle) {
+                       case SWT.UNDERLINE_SINGLE: buffer.append("single"); break; //$NON-NLS-1$
+                       case SWT.UNDERLINE_DOUBLE: buffer.append("double"); break; //$NON-NLS-1$
+                       case SWT.UNDERLINE_SQUIGGLE: buffer.append("squiggle"); break; //$NON-NLS-1$
+                       case SWT.UNDERLINE_ERROR: buffer.append("error"); break; //$NON-NLS-1$
+                       case SWT.UNDERLINE_LINK: buffer.append("link"); break; //$NON-NLS-1$
+               }
+               if (underlineColor != null) {
+                       buffer.append(", underlineColor="); //$NON-NLS-1$
+                       buffer.append(underlineColor);
+               }
+       }
+       if (strikeout) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("striked out"); //$NON-NLS-1$
+               if (strikeoutColor != null) {
+                       buffer.append(", strikeoutColor="); //$NON-NLS-1$
+                       buffer.append(strikeoutColor);
+               }
+       }
+       if (borderStyle != SWT.NONE) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("border="); //$NON-NLS-1$
+               switch (borderStyle) {
+                       case SWT.BORDER_SOLID:  buffer.append("solid"); break; //$NON-NLS-1$
+                       case SWT.BORDER_DOT:    buffer.append("dot"); break; //$NON-NLS-1$
+                       case SWT.BORDER_DASH:   buffer.append("dash"); break; //$NON-NLS-1$
+               }
+               if (borderColor != null) {
+                       buffer.append(", borderColor="); //$NON-NLS-1$
+                       buffer.append(borderColor);
+               }
+       }
+       if (rise != 0) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("rise="); //$NON-NLS-1$
+               buffer.append(rise);
+       }
+       if (metrics != null) {
+               if (buffer.length() > startLength) buffer.append(", "); //$NON-NLS-1$
+               buffer.append("metrics="); //$NON-NLS-1$
+               buffer.append(metrics);
+       }
+       buffer.append("}"); //$NON-NLS-1$
+       return buffer.toString();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Transform.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/Transform.java
new file mode 100644 (file)
index 0000000..6e666ba
--- /dev/null
@@ -0,0 +1,396 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+
+/**
+ * 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 extends Resource {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long 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>
+ * <p>
+ * You must dispose the transform when it is no longer required.
+ * </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 Transform (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>
+ * <p>
+ * You must dispose the transform when it is no longer required.
+ * </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 Transform(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>
+ * <p>
+ * You must dispose the transform when it is no longer required.
+ * </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 Transform (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, DPIUtil.autoScaleUp(dx), DPIUtil.autoScaleUp(dy));
+       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       init();
+}
+
+static float[] checkTransform(float[] elements) {
+       if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       return elements;
+}
+
+@Override
+void destroy() {
+       Gdip.Matrix_delete(handle);
+       handle = 0;
+}
+
+/**
+ * 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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+       Gdip.Matrix_GetElements(handle, elements);
+       elements[4] = DPIUtil.autoScaleDown(elements[4]);
+       elements[5] = DPIUtil.autoScaleDown(elements[5]);
+}
+
+/**
+ * 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) != 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 (except {@link #dispose()}) using the Transform.
+ *
+ * @return <code>true</code> when the Transform is disposed, and <code>false</code> otherwise
+ */
+@Override
+public boolean isDisposed() {
+       return handle == 0;
+}
+
+/**
+ * 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 boolean isIdentity() {
+       if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+       return 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 == 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, DPIUtil.autoScaleUp(dx), DPIUtil.autoScaleUp(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 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+       int length = pointArray.length;
+       for (int i = 0; i < length; i++) {
+               pointArray[i] = DPIUtil.autoScaleUp(pointArray[i]);
+       }
+       Gdip.Matrix_TransformPoints(handle, pointArray, length / 2);
+       for (int i = 0; i < length; i++) {
+               pointArray[i] = DPIUtil.autoScaleDown(pointArray[i]);
+       }
+}
+
+/**
+ * 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, DPIUtil.autoScaleUp(offsetX), DPIUtil.autoScaleUp(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[] elements = new float[6];
+       getElements(elements);
+       return "Transform {" + elements [0] + "," + elements [1] + "," +elements [2] + "," +elements [3] + "," +elements [4] + "," +elements [5] + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/graphics/package.html
new file mode 100644 (file)
index 0000000..d71267a
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT graphics classes.
+<h2>
+Package Specification</h2>
+This package provides the classes which implement points, rectangles,
+regions, colors, cursors, fonts, graphics contexts (that is, <code>GC</code>s)
+where most of the primitive drawing operations are implemented, and 
+images including both the code for displaying them and the public API for
+loading/saving them.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/BidiUtil.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/BidiUtil.java
new file mode 100644 (file)
index 0000000..4cb9407
--- /dev/null
@@ -0,0 +1,688 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+/*
+ * Wraps Win32 API used to bidi enable widgets. Up to 3.104 was used by
+ * StyledText widget exclusively. 3.105 release introduced the method
+ * #resolveTextDirection, which is used by other widgets as well.
+ */
+public class BidiUtil {
+
+       // Keyboard language ids
+       public static final int KEYBOARD_NON_BIDI = 0;
+       public static final int KEYBOARD_BIDI = 1;
+
+       // bidi flag
+       static int isBidiPlatform = -1;
+
+       // getRenderInfo flag values
+       public static final int CLASSIN = 1;
+       public static final int LINKBEFORE = 2;
+       public static final int LINKAFTER = 4;
+
+       // variables used for providing a listener mechanism for keyboard language
+       // switching
+       static Map<LONG, Runnable> languageMap = new HashMap<> ();
+       static Map<LONG, LONG> oldProcMap = new HashMap<> ();
+       /*
+        * 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 final String CLASS_NAME = "org.eclipse.swt.internal.BidiUtil"; //$NON-NLS-1$
+       static Callback callback;
+       static {
+               try {
+                       callback = new Callback (Class.forName (CLASS_NAME), "windowProc", 4); //$NON-NLS-1$
+                       if (callback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+               } catch (ClassNotFoundException e) {}
+       }
+
+       // GetCharacterPlacement constants
+       static final int GCP_REORDER = 0x0002;
+       static final int GCP_GLYPHSHAPE = 0x0010;
+       static final int GCP_LIGATE = 0x0020;
+       static final int GCP_CLASSIN = 0x00080000;
+       static final byte GCPCLASS_ARABIC = 2;
+       static final byte GCPCLASS_HEBREW = 2;
+       static final byte GCPCLASS_LOCALNUMBER = 4;
+       static final byte GCPCLASS_LATINNUMBER = 5;
+       static final int GCPGLYPH_LINKBEFORE = 0x8000;
+       static final int GCPGLYPH_LINKAFTER = 0x4000;
+       // ExtTextOut constants
+       static final int ETO_CLIPPED = 0x4;
+       static final int ETO_GLYPH_INDEX = 0x0010;
+       // Windows primary language identifiers
+       static final int LANG_ARABIC = 0x01;
+       static final int LANG_HEBREW = 0x0d;
+       static final int LANG_FARSI = 0x29;
+       // code page identifiers
+       static final String CD_PG_HEBREW = "1255"; //$NON-NLS-1$
+       static final String CD_PG_ARABIC = "1256"; //$NON-NLS-1$
+       // ActivateKeyboard constants
+       static final int HKL_NEXT = 1;
+       static final 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 final int CLASS_HEBREW = GCPCLASS_ARABIC;
+       public static final int CLASS_ARABIC = GCPCLASS_HEBREW;
+       public static final int CLASS_LOCALNUMBER = GCPCLASS_LOCALNUMBER;
+       public static final int CLASS_LATINNUMBER = GCPCLASS_LATINNUMBER;
+       public static final int REORDER = GCP_REORDER;
+       public static final int LIGATE = GCP_LIGATE;
+       public static final 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 (long hwnd, Runnable runnable) {
+       languageMap.put(new LONG(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 long EnumSystemLanguageGroupsProc(long lpLangGrpId, long lpLangGrpIdString, long lpLangGrpName, long options, long lParam) {
+       if ((int)lpLangGrpId == OS.LGRPID_HEBREW) {
+               isBidiPlatform = 1;
+               return 0;
+       }
+       if ((int)lpLangGrpId == 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, char[] renderBuffer, int[] renderDx, int x, int y) {
+       int length = renderDx.length;
+       if (OS.GetLayout (gc.handle) != 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.ExtTextOut(gc.handle, x, y, ETO_GLYPH_INDEX , null, renderBuffer, renderBuffer.length, renderDx);
+       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) {
+       int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
+       long hHeap = OS.GetProcessHeap();
+       boolean isRightOriented = OS.GetLayout(gc.handle) != 0;
+       char [] textBuffer = text.toCharArray();
+       int byteCount = textBuffer.length;
+       boolean linkBefore = (flags & LINKBEFORE) == LINKBEFORE;
+       boolean linkAfter = (flags & LINKAFTER) == LINKAFTER;
+
+       GCP_RESULTS result = new GCP_RESULTS();
+       result.lStructSize = GCP_RESULTS.sizeof;
+       result.nGlyphs = byteCount;
+       long lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+       long lpDx = result.lpDx = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+       long lpClass = result.lpClass = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       long lpGlyphs = result.lpGlyphs = 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) == GCP_LIGATE) {
+               dwFlags |= GCP_LIGATE;
+               glyphFlags |= 0;
+       }
+       if ((fontLanguageInfo & GCP_GLYPHSHAPE) == 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]=(byte)glyphFlags;
+               lpGlyphs2[1]=(byte)(glyphFlags >> 8);
+       }
+       else {
+               lpGlyphs2 = new byte[] {(byte) glyphFlags};
+       }
+       OS.MoveMemory(result.lpGlyphs, lpGlyphs2, lpGlyphs2.length);
+
+       if ((flags & CLASSIN) == CLASSIN) {
+               // set classification values for the substring
+               dwFlags |= GCP_CLASSIN;
+               OS.MoveMemory(result.lpClass, classBuffer, classBuffer.length);
+       }
+
+       char[] glyphBuffer = new char[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;
+               text.getChars(offset, offset + length, textBuffer, 0);
+               OS.GetCharacterPlacement(gc.handle, textBuffer, length, 0, result, dwFlags);
+
+               if (dx != null) {
+                       int [] dx2 = new int [result.nGlyphs];
+                       OS.MoveMemory(dx2, result.lpDx, dx2.length * 4);
+                       if (isRightOriented) {
+                               reverse(dx2);
+                       }
+                       System.arraycopy (dx2, 0, dx, glyphCount, dx2.length);
+               }
+               if (order != null) {
+                       int [] order2 = new int [length];
+                       OS.MoveMemory(order2, result.lpOrder, order2.length * 4);
+                       translateOrder(order2, glyphCount, isRightOriented);
+                       System.arraycopy (order2, 0, order, offset, length);
+               }
+               if (classBuffer != null) {
+                       byte [] classBuffer2 = new byte [length];
+                       OS.MoveMemory(classBuffer2, result.lpClass, classBuffer2.length);
+                       System.arraycopy (classBuffer2, 0, classBuffer, offset, length);
+               }
+               char[] glyphBuffer2 = new char[result.nGlyphs];
+               OS.MoveMemory(glyphBuffer2, 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 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);
+       long hHeap = OS.GetProcessHeap();
+       char [] textBuffer = text.toCharArray();
+       int byteCount = textBuffer.length;
+       boolean isRightOriented = OS.GetLayout(gc.handle) != 0;
+
+       GCP_RESULTS result = new GCP_RESULTS();
+       result.lStructSize = GCP_RESULTS.sizeof;
+       result.nGlyphs = byteCount;
+       long lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+       long lpClass = result.lpClass = 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) == GCP_LIGATE) {
+               dwFlags |= GCP_LIGATE;
+       }
+       if ((fontLanguageInfo & GCP_GLYPHSHAPE) == GCP_GLYPHSHAPE) {
+               dwFlags |= GCP_GLYPHSHAPE;
+       }
+       if ((flags & CLASSIN) == CLASSIN) {
+               // set classification values for the substring, classification values
+               // can be specified on input
+               dwFlags |= GCP_CLASSIN;
+               OS.MoveMemory(result.lpClass, classBuffer, 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;
+               text.getChars(offset, offset + length, textBuffer, 0);
+               OS.GetCharacterPlacement(gc.handle, textBuffer, length, 0, result, dwFlags);
+
+               if (order != null) {
+                       int [] order2 = new int [length];
+                       OS.MoveMemory(order2, result.lpOrder, order2.length * 4);
+                       translateOrder(order2, glyphCount, isRightOriented);
+                       System.arraycopy (order2, 0, order, offset, length);
+               }
+               if (classBuffer != null) {
+                       byte [] classBuffer2 = new byte [length];
+                       OS.MoveMemory(classBuffer2, 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) != 0)) {
+               fontStyle |= REORDER;
+       }
+       if (((fontLanguageInfo & GCP_LIGATE) != 0)) {
+               fontStyle |= LIGATE;
+       }
+       if (((fontLanguageInfo & GCP_GLYPHSHAPE) != 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() {
+       long layout = OS.GetKeyboardLayout(0);
+       return isBidiLang(layout) ? KEYBOARD_BIDI : KEYBOARD_NON_BIDI;
+}
+/**
+ * Return the languages that are installed for the keyboard.
+ * <p>
+ *
+ * @return integer array with an entry for each installed language
+ */
+static long[] getKeyboardLanguageList() {
+       int maxSize = 10;
+       long[] tempList = new long[maxSize];
+       int size = OS.GetKeyboardLayoutList(maxSize, tempList);
+       long[] list = new long[size];
+       System.arraycopy(tempList, 0, list, 0, size);
+       return list;
+}
+static boolean isBidiLang(long lang) {
+       int id = OS.PRIMARYLANGID(OS.LOWORD(lang));
+       return id == LANG_ARABIC || id == LANG_HEBREW || id == LANG_FARSI;
+}
+/**
+ * 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 boolean isBidiPlatform() {
+       if (isBidiPlatform != -1) return isBidiPlatform == 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$
+               long lpEnumSystemLanguageGroupsProc = callback.getAddress ();
+               if (lpEnumSystemLanguageGroupsProc == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+               OS.EnumSystemLanguageGroups(lpEnumSystemLanguageGroupsProc, OS.LGRPID_INSTALLED, 0);
+               callback.dispose ();
+       } catch (ClassNotFoundException e) {
+               //callback can only be null at this point
+       }
+       if (isBidiPlatform == 1) return true;
+       // need to look at system code page for NT & 98 platforms since EnumSystemLanguageGroups is
+       // not supported for these platforms
+       String codePage = String.valueOf(OS.GetACP());
+       if (CD_PG_ARABIC.equals(codePage) || CD_PG_HEBREW.equals(codePage)) {
+               isBidiPlatform = 1;
+       }
+       return isBidiPlatform == 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 boolean isKeyboardBidi() {
+       long[] list = getKeyboardLanguageList();
+       for (int i=0; i<list.length; i++) {
+               if (isBidiLang(list[i])) {
+                       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 (long hwnd) {
+       languageMap.remove(new LONG(hwnd));
+       unsubclass(hwnd);
+}
+public static void removeLanguageListener (Control control) {
+       removeLanguageListener(control.handle);
+}
+/**
+ * Determine the base direction for the given text. The direction is derived
+ * from that of the first strong bidirectional character. In case the text
+ * doesn't contain any strong characters, the base direction is to be
+ * derived from a higher-level protocol (e.g. the widget orientation).
+ * <p>
+ *
+ * @param text
+ *            Text base direction should be resolved for.
+ * @return SWT#LEFT_RIGHT or SWT#RIGHT_TO_LEFT if the text contains strong
+ *         characters and thus the direction can be resolved, SWT#NONE
+ *         otherwise.
+ * @since 3.105
+ */
+public static int resolveTextDirection (String text) {
+       if (text == null) return SWT.NONE;
+       int length = text.length();
+       if (length == 0) return SWT.NONE;
+       char[] rtlProbe = {' ', ' ', '1'};
+       /*
+        * "Wide" version of win32 API can also run even on non-Unicode Windows,
+        * hence need for OS.IsUnicode check here.
+        */
+       char[] ltrProbe = {'\u202b', 'a', ' '};
+       char[] numberProbe = {'\u05d0', ' ', ' '};
+       GCP_RESULTS result = new GCP_RESULTS();
+       result.lStructSize = GCP_RESULTS.sizeof;
+       int nGlyphs = result.nGlyphs = ltrProbe.length;
+       long hHeap = OS.GetProcessHeap();
+       long lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
+       long hdc = OS.GetDC(0);
+       int[] order = new int[1];
+       int textDirection = SWT.NONE;
+       for (int i = 0; i < length; i++) {
+               char ch = text.charAt(i);
+               rtlProbe[0] = ch;
+               OS.GetCharacterPlacement(hdc, rtlProbe, rtlProbe.length, 0, result, OS.GCP_REORDER);
+               OS.MoveMemory(order, result.lpOrder, 4);
+               if (order[0] == 2) {
+                       textDirection = SWT.RIGHT_TO_LEFT;
+                       break;
+               }
+               ltrProbe[2] = ch;
+               OS.GetCharacterPlacement(hdc, ltrProbe, ltrProbe.length, 0, result, OS.GCP_REORDER);
+               OS.MoveMemory(order, result.lpOrder + 4, 4);
+               if (order[0] == 1) {
+                       numberProbe[2] = ch;
+                       OS.GetCharacterPlacement(hdc, numberProbe, numberProbe.length, 0, result, OS.GCP_REORDER);
+                       OS.MoveMemory(order, result.lpOrder, 4);
+                       if (order[0] == 0) {
+                               textDirection = SWT.LEFT_TO_RIGHT;
+                               break;
+                       }
+               }
+       }
+       OS.ReleaseDC (0, hdc);
+       OS.HeapFree(hHeap, 0, lpOrder);
+       return textDirection;
+
+}
+/**
+ * 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) {
+       if (language == getKeyboardLanguage()) return;
+       boolean bidi = language == KEYBOARD_BIDI;
+       long[] list = getKeyboardLanguageList();
+       for (int i=0; i<list.length; i++) {
+               if (bidi == isBidiLang(list[i])) {
+                       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 boolean setOrientation (long hwnd, int orientation) {
+       int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+       if ((orientation & SWT.RIGHT_TO_LEFT) != 0) {
+               bits |= OS.WS_EX_LAYOUTRTL;
+       } else {
+               bits &= ~OS.WS_EX_LAYOUTRTL;
+       }
+       OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits);
+       return true;
+}
+public static boolean 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(long hwnd) {
+       LONG key = new LONG(hwnd);
+       if (oldProcMap.get(key) == null) {
+               long oldProc = OS.GetWindowLongPtr(hwnd, OS.GWLP_WNDPROC);
+               oldProcMap.put(key, new LONG(oldProc));
+               OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, callback.getAddress());
+       }
+}
+/**
+ *  Reverse the character array.  Used for right orientation.
+ *
+ * @param charArray character array to reverse
+ */
+static void reverse(char[] charArray) {
+       int length = charArray.length;
+       for (int i = 0; i <= (length  - 1) / 2; i++) {
+               char 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, boolean 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(long hwnd) {
+       LONG key = new LONG(hwnd);
+       if (languageMap.get(key) == null) {
+               LONG proc = oldProcMap.remove(key);
+               if (proc == null) return;
+               OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, proc.value);
+       }
+}
+/**
+ * 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 long windowProc (long hwnd, long msg, long wParam, long lParam) {
+       LONG key = new LONG (hwnd);
+       switch ((int)msg) {
+               case OS.WM_INPUTLANGCHANGE:
+                       Runnable runnable = languageMap.get (key);
+                       if (runnable != null) runnable.run ();
+                       break;
+               }
+       LONG oldProc = oldProcMap.get(key);
+       return OS.CallWindowProc (oldProc.value, hwnd, (int)msg, wParam, lParam);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/C.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/C.java
new file mode 100644 (file)
index 0000000..1abd49c
--- /dev/null
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+public class C extends Platform {
+
+       static {
+               Library.loadLibrary ("swt"); //$NON-NLS-1$
+       }
+
+       public static final int PTR_SIZEOF = PTR_sizeof ();
+
+/** @param ptr cast=(void *) */
+public static final native void free (long ptr);
+/** @param env cast=(const char *) */
+public static final native long getenv (byte[] env);
+/**
+ * @param env cast=(const char *)
+ * @param value cast=(const char *)
+ */
+public static final native int setenv (byte[] env, byte[] value, int overwrite);
+public static final native long malloc (long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, byte[] src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, char[] src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, double[] src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, float[] src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, int[] src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, long[] src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, short[] src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *),flags=no_out critical
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (byte[] dest, char[] src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (byte[] dest, long src, long size);
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, long src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (char[] dest, long src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (double[] dest, long src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (float[] dest, long src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (int[] dest, byte[] src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (short[] dest, long src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (int[] dest, long src, long size);
+/**
+ * @param dest cast=(void *),flags=no_in critical
+ * @param src cast=(const void *)
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long[] dest, long src, long size);
+/**
+ * @param buffer cast=(void *),flags=critical
+ * @param num cast=(size_t)
+ */
+public static final native long memset (long buffer, int c, long num);
+public static final native int PTR_sizeof ();
+/** @param s cast=(char *) */
+public static final native int strlen (long s);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Callback.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Callback.java
new file mode 100644 (file)
index 0000000..2248861
--- /dev/null
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+import java.lang.reflect.*;
+import java.util.function.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent entry points into Java
+ * which can be invoked from operating system level callback
+ * routines.
+ * <p>
+ * IMPORTANT: A callback is only valid when invoked on the
+ * thread which created it. The results are undefined (and
+ * typically bad) when a callback is passed out to the
+ * operating system (or other code) in such a way that the
+ * callback is called from a different thread.
+ */
+
+public class Callback {
+
+       Object object;
+       String method, signature;
+       int argCount;
+       long address, errorResult;
+       boolean isStatic, isArrayBased;
+
+       static final boolean is32Bit = C.PTR_SIZEOF == 4 ? true : false;
+       static final String PTR_SIGNATURE = is32Bit ? "I" : "J"; //$NON-NLS-1$  //$NON-NLS-2$
+       static final String SIGNATURE_0 = getSignature(0);
+       static final String SIGNATURE_1 = getSignature(1);
+       static final String SIGNATURE_2 = getSignature(2);
+       static final String SIGNATURE_3 = getSignature(3);
+       static final String SIGNATURE_4 = getSignature(4);
+       static final String SIGNATURE_N = "(["+PTR_SIGNATURE+")"+PTR_SIGNATURE; //$NON-NLS-1$  //$NON-NLS-2$
+
+/**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke and an argument count. Note that, if the object
+ * is an instance of <code>Class</code> it is assumed that
+ * the method is a static method on that class.
+ *
+ * <p>Note, do not use this if the method arguments have a double, as arguments will be
+ * shifted/corrupted. See Bug 510538. Instead use the following constructor: <br>
+ * <code> Callback (Object, String, Type, Type [])</code></p>
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ */
+public Callback (Object object, String method, int argCount) {
+       this (object, method, argCount, false);
+}
+
+/**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke, an argument count and a flag indicating whether
+ * or not the arguments will be passed in an array. Note
+ * that, if the object is an instance of <code>Class</code>
+ * it is assumed that the method is a static method on that
+ * class.
+ *
+ * <p>Note, do not use this if the method arguments have a double, as arguments will be
+ * shifted/corrupted. See Bug 510538. Instead use the following constructor: <br>
+ * <code> Callback (Object, String, Type, Type [])</code></p>
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ * @param isArrayBased <code>true</code> if the arguments should be passed in an array and false otherwise
+ */
+public Callback (Object object, String method, int argCount, boolean isArrayBased) {
+       this (object, method, argCount, isArrayBased, 0);
+}
+
+/**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke, an argument count, a flag indicating whether
+ * or not the arguments will be passed in an array and a value
+ * to return when an exception happens. Note that, if
+ * the object is an instance of <code>Class</code>
+ * it is assumed that the method is a static method on that
+ * class.
+ *
+ * <p>Note, do not use this if the method arguments have a double, as arguments will be
+ * shifted/corrupted. See Bug 510538. Instead use the following constructor: <br>
+ * <code> Callback (Object, String, Type, Type [])</code></p>
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ * @param isArrayBased <code>true</code> if the arguments should be passed in an array and false otherwise
+ * @param errorResult the return value if the java code throws an exception
+ */
+public Callback (Object object, String method, int argCount, boolean isArrayBased, long errorResult) {
+
+       /* Set the callback fields */
+       this.object = object;
+       this.method = method;
+       this.argCount = argCount;
+       this.isStatic = object instanceof Class;
+       this.isArrayBased = isArrayBased;
+       this.errorResult = errorResult;
+
+       /* Inline the common cases */
+       if (isArrayBased) {
+               signature = SIGNATURE_N;
+       } else {
+               switch (argCount) {
+                       case 0: signature = SIGNATURE_0; break; //$NON-NLS-1$
+                       case 1: signature = SIGNATURE_1; break; //$NON-NLS-1$
+                       case 2: signature = SIGNATURE_2; break; //$NON-NLS-1$
+                       case 3: signature = SIGNATURE_3; break; //$NON-NLS-1$
+                       case 4: signature = SIGNATURE_4; break; //$NON-NLS-1$
+                       default:
+                               signature = getSignature(argCount);
+               }
+       }
+
+       /* Bind the address */
+       address = bind (this, object, method, signature, argCount, isStatic, isArrayBased, errorResult);
+}
+
+
+/**
+ * <p>Register the java method to be a C callback.
+ * I.e, C will be able to make a call to this java method directly (through callback.c)</p>
+ *
+ * <p>The other constructors hard-code int/long into the method signature:<br>
+ * <code> long method (long ...) </code><br>
+ * Which is suitable for int/long and pointers.<br>
+ * This constructor is used if you need to use a different return/argument type, e.g double. See Bug 510538 </p>
+ *
+ * <p> Note:
+ * <ul>
+ * <li> Array support is not implemented/supported by this constructor. Use other constructors.</li>
+ * <li> If the object is an instance of <code>Class</code> it is assumed that
+ * the method is a static method on that class. </li>
+ * <li> Note, long types are converted to ints on 32 bit system automatically to account for smaller pointers.
+ * This means if you use 'long', you need to cast int next to it. like: <code> long &#47;*int*&#47;</code> </li>
+ * </ul></p>
+ *
+ * <p>The following types are supported: <br>
+ * <ul>
+ * <li>void (for return values only) </li>
+ * <li>int</li>
+ * <li>long</li>
+ * <li>byte</li>
+ * <li>char</li>
+ * <li>double</li>
+ * <li>float</li>
+ * <li>short</li>
+ * <li>boolean</li>
+ * </ul>
+ *
+ * <p> For example if you want to link the following method: <br>
+ * <code> void myMethod(long &#47;*int*&#47; arg1, double arg2) </code> <br>
+ * Then you would call this callback like:<br>
+ * <code> Callback (this, "myMethod", void.class, new Type []{long.class, double.class}); </code>
+ * </p>
+ *
+ * @param object the object to send the message to
+ * @param method method the name of the method to invoke
+ * @param returnType specify the type like  <code>void.class, long.class, double.class </code>
+ * @param arguments specify the list of arguments like <code> new Type [] {long.class, double.class } </code>
+ */
+public Callback (Object object, String method, Type returnType, Type [] arguments) {
+       /* Set the callback fields */
+       this.object = object;
+       this.method = method;
+       this.argCount = arguments != null ? arguments.length : 0;
+       this.isStatic = object instanceof Class;
+       this.isArrayBased = false;
+       this.errorResult = 0;
+
+       Function <Type, String> getTypeLetter = type -> {
+               // https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2
+               if (int.class.equals(type)) {
+                       return "I";
+               } else if (long.class.equals(type)) {
+                       return "J";
+               } else if (void.class.equals(type)) { // for return type.
+                       return "V";
+               } else if (byte.class.equals(type)) {
+                       return "B";
+               } else if (char.class.equals(type)) {
+                       return "C";
+               } else if (double.class.equals(type)) {
+                       return "D";
+               } else if (float.class.equals(type)) {
+                       return "F";
+               } else if (short.class.equals(type)) {
+                       return "S";
+               } else if (boolean.class.equals(type)) {
+                       return "Z";
+               }
+               SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, type.toString() + "Not supported");
+               return null; // not reachable. Suppress warning.
+       };
+
+       StringBuilder signature = new StringBuilder("(");
+       for (Type t : arguments) {
+               if (t.equals(void.class)) {
+                       SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, "void is not a valid argument");
+               }
+               signature.append(getTypeLetter.apply(t));
+       }
+       signature.append(")");
+       signature.append(getTypeLetter.apply(returnType));
+       this.signature = signature.toString();
+       if (is32Bit) {
+               this.signature = this.signature.replace("J", "I");
+       }
+
+       /* Bind the address */
+       address = bind (this, this.object, this.method, this.signature, this.argCount, this.isStatic, this.isArrayBased, this.errorResult);
+}
+
+
+
+/**
+ * Allocates the native level resources associated with the
+ * callback. This method is only invoked from within the
+ * constructor for the argument.
+ *
+ * @param callback the callback to bind
+ * @param object the callback's object
+ * @param method the callback's method
+ * @param signature the callback's method signature
+ * @param argCount the callback's method argument count
+ * @param isStatic whether the callback's method is static
+ * @param isArrayBased whether the callback's method is array based
+ * @param errorResult the callback's error result
+ */
+static native synchronized long bind (Callback callback, Object object, String method, String signature, int argCount, boolean isStatic, boolean isArrayBased, long errorResult);
+
+/**
+ * Releases the native level resources associated with the callback,
+ * and removes all references between the callback and
+ * other objects. This helps to prevent (bad) application code
+ * from accidentally holding onto extraneous garbage.
+ */
+public void dispose () {
+       if (object == null) return;
+       unbind (this);
+       object = method = signature = null;
+       address = 0;
+}
+
+/**
+ * Returns the address of a block of machine code which will
+ * invoke the callback represented by the receiver.
+ *
+ * @return the callback address
+ */
+public long getAddress () {
+       return address;
+}
+
+/**
+ * Returns the SWT platform name.
+ *
+ * @return the platform name of the currently running SWT
+ */
+public static native String getPlatform ();
+
+/**
+ * Returns the number of times the system has been recursively entered
+ * through a callback.
+ * <p>
+ * Note: This should not be called by application code.
+ * </p>
+ *
+ * @return the entry count
+ *
+ * @since 2.1
+ */
+public static native int getEntryCount ();
+
+static String getSignature(int argCount) {
+       String signature = "("; //$NON-NLS-1$
+       for (int i = 0; i < argCount; i++) signature += PTR_SIGNATURE;
+       signature += ")" + PTR_SIGNATURE; //$NON-NLS-1$
+       return signature;
+}
+
+/**
+ * Indicates whether or not callbacks which are triggered at the
+ * native level should cause the messages described by the matching
+ * <code>Callback</code> objects to be invoked. This method is used
+ * to safely shut down SWT when it is run within environments
+ * which can generate spurious events.
+ * <p>
+ * Note: This should not be called by application code.
+ * </p>
+ *
+ * @param enable true if callbacks should be invoked
+ */
+public static final native synchronized void setEnabled (boolean enable);
+
+/**
+ * Returns whether or not callbacks which are triggered at the
+ * native level should cause the messages described by the matching
+ * <code>Callback</code> objects to be invoked. This method is used
+ * to safely shut down SWT when it is run within environments
+ * which can generate spurious events.
+ * <p>
+ * Note: This should not be called by application code.
+ * </p>
+ *
+ * @return true if callbacks should not be invoked
+ */
+public static final native synchronized boolean getEnabled ();
+
+/**
+ * This might be called directly from native code in environments
+ * which can generate spurious events. Check before removing it.
+ *
+ * @deprecated
+ *
+ * @param ignore true if callbacks should not be invoked
+ */
+@Deprecated
+static final void ignoreCallbacks (boolean ignore) {
+       setEnabled (!ignore);
+}
+
+/**
+ * Immediately wipes out all native level state associated
+ * with <em>all</em> callbacks.
+ * <p>
+ * <b>WARNING:</b> This operation is <em>extremely</em> dangerous,
+ * and should never be performed by application code.
+ * </p>
+ */
+public static final native synchronized void reset ();
+
+/**
+ * Releases the native level resources associated with the callback.
+ *
+ * @see #dispose
+ */
+static final native synchronized void unbind (Callback callback);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Compatibility.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Compatibility.java
new file mode 100644 (file)
index 0000000..4ee7c00
--- /dev/null
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+import org.eclipse.swt.*;
+
+/**
+ * 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 {
+
+/**
+ * Answers the most negative (i.e. closest to negative infinity)
+ * integer value which is greater than or equal to 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 (int)Math.ceil((float)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 Math.round((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;
+}
+
+/**
+ * Execute prog[0] in a separate platform process if the
+ * underlying platform supports this.
+ * <p>
+ * The new process inherits the environment of the caller.
+ * <p>
+ *
+ * @param prog array containing the program to execute and its arguments
+ * @param envp
+ *            array of strings, each element of which has environment
+ *            variable settings in the format name=value
+ * @param workingDir
+ *            the working directory of the new process, or null if the new
+ *            process should inherit the working directory of the caller
+ *
+ * @exception IOException
+ *  if the program cannot be executed
+ * @exception  SecurityException
+ *  if the current SecurityManager disallows program execution
+ *
+ * @since 3.6
+ */
+public static void exec(String[] prog, String[] envp, String workingDir) throws java.io.IOException{
+       Runtime.getRuntime().exec(prog, null, workingDir != null ? new File(workingDir) : null);
+}
+
+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 == null) {
+               SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       }
+       if (msgs == null) {
+               try {
+                       msgs = ResourceBundle.getBundle("org.eclipse.swt.internal.SWTMessages"); //$NON-NLS-1$
+               } catch (MissingResourceException ex) {
+                       answer = key + " (no resource bundle)"; //$NON-NLS-1$
+               }
+       }
+       if (msgs != null) {
+               try {
+                       answer = msgs.getString(key);
+               } catch (MissingResourceException ex2) {}
+       }
+       return answer;
+}
+
+public static String getMessage(String key, Object[] args) {
+       String answer = key;
+
+       if (key == null || args == null) {
+               SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       }
+       if (msgs == null) {
+               try {
+                       msgs = ResourceBundle.getBundle("org.eclipse.swt.internal.SWTMessages"); //$NON-NLS-1$
+               } catch (MissingResourceException ex) {
+                       answer = key + " (no resource bundle)"; //$NON-NLS-1$
+               }
+       }
+       if (msgs != null) {
+               try {
+                       MessageFormat formatter = new MessageFormat("");
+                       formatter.applyPattern(msgs.getString(key));
+                       answer = formatter.format(args);
+               } catch (MissingResourceException ex2) {}
+       }
+       return answer;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/DPIUtil.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/DPIUtil.java
new file mode 100644 (file)
index 0000000..cbfa1c5
--- /dev/null
@@ -0,0 +1,499 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * This class hold common constants and utility functions w.r.t. to SWT high DPI
+ * functionality.
+ * <p>
+ * The {@code autoScaleUp(..)} methods convert from API coordinates (in
+ * SWT points) to internal high DPI coordinates (in pixels) that interface with
+ * native widgets.
+ * </p>
+ * <p>
+ * The {@code autoScaleDown(..)} convert from high DPI pixels to API coordinates
+ * (in SWT points).
+ * </p>
+ *
+ * @since 3.105
+ */
+public class DPIUtil {
+
+       private static final int DPI_ZOOM_100 = 96;
+
+       private static int deviceZoom = 100;
+       private static int nativeDeviceZoom = 100;
+
+       private static enum AutoScaleMethod { AUTO, NEAREST, SMOOTH }
+       private static AutoScaleMethod autoScaleMethodSetting = AutoScaleMethod.AUTO;
+       private static AutoScaleMethod autoScaleMethod = AutoScaleMethod.NEAREST;
+
+       private static String autoScaleValue;
+       private static boolean useCairoAutoScale = false;
+
+       /**
+        * System property that controls the autoScale functionality.
+        * <ul>
+        * <li><b>false</b>: deviceZoom is set to 100%</li>
+        * <li><b>integer</b>: deviceZoom depends on the current display resolution,
+        *     but only uses integer multiples of 100%. The detected native zoom is
+        *     generally rounded down (e.g. at 150%, will use 100%), unless close to
+        *     the next integer multiple (currently at 175%, will use 200%).</li>
+        * <li><b>integer200</b>: like <b>integer</b>, but the maximal zoom level is 200%.</li>
+        * <li><b>quarter</b>: deviceZoom depends on the current display resolution,
+        *     but only uses integer multiples of 25%. The detected native zoom is
+        *     rounded to the closest permissible value.</li>
+        * <li><b>exact</b>: deviceZoom uses the native zoom (with 1% as minimal
+        *     step).</li>
+        * <li><i>&lt;value&gt;</i>: deviceZoom uses the given integer value in
+        *     percent as zoom level.</li>
+        * </ul>
+        * The current default is "integer200".
+        */
+       private static final String SWT_AUTOSCALE = "swt.autoScale";
+
+       /**
+        * System property that controls the method for scaling images:
+        * <ul>
+        * <li>"nearest": nearest-neighbor interpolation, may look jagged</li>
+        * <li>"smooth": smooth edges, may look blurry</li>
+        * </ul>
+        * The current default is to use "nearest", except on
+        * GTK when the deviceZoom is not an integer multiple of 100%.
+        * The smooth strategy currently doesn't work on Win32 and Cocoa, see
+        * <a href="https://bugs.eclipse.org/493455">bug 493455</a>.
+        */
+       private static final String SWT_AUTOSCALE_METHOD = "swt.autoScale.method";
+       static {
+               autoScaleValue = System.getProperty (SWT_AUTOSCALE);
+
+               String value = System.getProperty (SWT_AUTOSCALE_METHOD);
+               if (value != null) {
+                       if (AutoScaleMethod.NEAREST.name().equalsIgnoreCase(value)) {
+                               autoScaleMethod = autoScaleMethodSetting = AutoScaleMethod.NEAREST;
+                       } else if (AutoScaleMethod.SMOOTH.name().equalsIgnoreCase(value)) {
+                               autoScaleMethod = autoScaleMethodSetting = AutoScaleMethod.SMOOTH;
+                       }
+               }
+       }
+
+/**
+ * Auto-scale down ImageData
+ */
+public static ImageData autoScaleDown (Device device, final ImageData imageData) {
+       if (deviceZoom == 100 || imageData == null || (device != null && !device.isAutoScalable())) return imageData;
+       float scaleFactor = 1.0f / getScalingFactor ();
+       return autoScaleImageData(device, imageData, scaleFactor);
+}
+
+public static int[] autoScaleDown(int[] pointArray) {
+       if (deviceZoom == 100 || pointArray == null) return pointArray;
+       float scaleFactor = getScalingFactor ();
+       int [] returnArray = new int[pointArray.length];
+       for (int i = 0; i < pointArray.length; i++) {
+               returnArray [i] =  Math.round (pointArray [i] / scaleFactor);
+       }
+       return returnArray;
+}
+
+public static int[] autoScaleDown(Drawable drawable, int[] pointArray) {
+       if (drawable != null && !drawable.isAutoScalable ()) return pointArray;
+       return autoScaleDown (pointArray);
+}
+
+/**
+ * Auto-scale up float array dimensions.
+ */
+public static float[] autoScaleDown (float size[]) {
+       if (deviceZoom == 100 || size == null) return size;
+       float scaleFactor = getScalingFactor ();
+       float scaledSize[] = new float[size.length];
+       for (int i = 0; i < scaledSize.length; i++) {
+               scaledSize[i] = size[i] / scaleFactor;
+       }
+       return scaledSize;
+}
+
+/**
+ * Auto-scale up float array dimensions if enabled for Drawable class.
+ */
+public static float[] autoScaleDown (Drawable drawable, float size[]) {
+       if (drawable != null && !drawable.isAutoScalable ()) return size;
+       return autoScaleDown (size);
+}
+
+/**
+ * Auto-scale down int dimensions.
+ */
+public static int autoScaleDown (int size) {
+       if (deviceZoom == 100 || size == SWT.DEFAULT) return size;
+       float scaleFactor = getScalingFactor ();
+       return Math.round (size / scaleFactor);
+}
+/**
+ * Auto-scale down int dimensions if enabled for Drawable class.
+ */
+public static int autoScaleDown (Drawable drawable, int size) {
+       if (drawable != null && !drawable.isAutoScalable ()) return size;
+       return autoScaleDown (size);
+}
+
+/**
+ * Auto-scale down float dimensions.
+ */
+public static float autoScaleDown (float size) {
+       if (deviceZoom == 100 || size == SWT.DEFAULT) return size;
+       float scaleFactor = getScalingFactor ();
+       return (size / scaleFactor);
+}
+
+/**
+ * Auto-scale down float dimensions if enabled for Drawable class.
+ */
+public static float autoScaleDown (Drawable drawable, float size) {
+       if (drawable != null && !drawable.isAutoScalable ()) return size;
+       return autoScaleDown (size);
+}
+
+/**
+ * Returns a new scaled down Point.
+ */
+public static Point autoScaleDown (Point point) {
+       if (deviceZoom == 100 || point == null) return point;
+       float scaleFactor = getScalingFactor ();
+       Point scaledPoint = new Point (0,0);
+       scaledPoint.x = Math.round (point.x / scaleFactor);
+       scaledPoint.y = Math.round (point.y / scaleFactor);
+       return scaledPoint;
+}
+
+/**
+ * Returns a new scaled down Point if enabled for Drawable class.
+ */
+public static Point autoScaleDown (Drawable drawable, Point point) {
+       if (drawable != null && !drawable.isAutoScalable ()) return point;
+       return autoScaleDown (point);
+}
+
+/**
+ * Returns a new scaled down Rectangle.
+ */
+public static Rectangle autoScaleDown (Rectangle rect) {
+       if (deviceZoom == 100 || rect == null) return rect;
+       Rectangle scaledRect = new Rectangle (0,0,0,0);
+       Point scaledTopLeft = DPIUtil.autoScaleDown (new Point (rect.x, rect.y));
+       Point scaledBottomRight = DPIUtil.autoScaleDown (new Point (rect.x + rect.width, rect.y + rect.height));
+
+       scaledRect.x = scaledTopLeft.x;
+       scaledRect.y = scaledTopLeft.y;
+       scaledRect.width = scaledBottomRight.x - scaledTopLeft.x;
+       scaledRect.height = scaledBottomRight.y - scaledTopLeft.y;
+       return scaledRect;
+}
+/**
+ * Returns a new scaled down Rectangle if enabled for Drawable class.
+ */
+public static Rectangle autoScaleDown (Drawable drawable, Rectangle rect) {
+       if (drawable != null && !drawable.isAutoScalable ()) return rect;
+       return autoScaleDown (rect);
+}
+
+/**
+ * Auto-scale image with ImageData
+ */
+public static ImageData autoScaleImageData (Device device, final ImageData imageData, int targetZoom, int currentZoom) {
+       if (imageData == null || targetZoom == currentZoom || (device != null && !device.isAutoScalable())) return imageData;
+       float scaleFactor = (float) targetZoom / (float) currentZoom;
+       return autoScaleImageData(device, imageData, scaleFactor);
+}
+
+private static ImageData autoScaleImageData (Device device, final ImageData imageData, float scaleFactor) {
+       // Guards are already implemented in callers: if (deviceZoom == 100 || imageData == null || scaleFactor == 1.0f) return imageData;
+       int width = imageData.width;
+       int height = imageData.height;
+       int scaledWidth = Math.round ((float) width * scaleFactor);
+       int scaledHeight = Math.round ((float) height * scaleFactor);
+       switch (autoScaleMethod) {
+       case SMOOTH:
+               Image original = new Image (device, (ImageDataProvider) zoom -> imageData);
+
+               /* Create a 24 bit image data with alpha channel */
+               final ImageData resultData = new ImageData (scaledWidth, scaledHeight, 24, new PaletteData (0xFF, 0xFF00, 0xFF0000));
+               resultData.alphaData = new byte [scaledWidth * scaledHeight];
+
+               Image resultImage = new Image (device, (ImageDataProvider) zoom -> resultData);
+               GC gc = new GC (resultImage);
+               gc.setAntialias (SWT.ON);
+               gc.drawImage (original, 0, 0, DPIUtil.autoScaleDown (width), DPIUtil.autoScaleDown (height),
+                               /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
+                                * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
+                                */
+                               0, 0, Math.round (DPIUtil.autoScaleDown ((float) width * scaleFactor)), Math.round (DPIUtil.autoScaleDown ((float) height * scaleFactor)));
+               gc.dispose ();
+               original.dispose ();
+               ImageData result = resultImage.getImageData (DPIUtil.getDeviceZoom ());
+               resultImage.dispose ();
+               return result;
+       case NEAREST:
+       default:
+               return imageData.scaledTo (scaledWidth, scaledHeight);
+       }
+}
+
+/**
+ * Returns a new rectangle as per the scaleFactor.
+ */
+public static Rectangle autoScaleBounds (Rectangle rect, int targetZoom, int currentZoom) {
+       if (deviceZoom == 100 || rect == null || targetZoom == currentZoom) return rect;
+       float scaleFactor = ((float)targetZoom) / (float)currentZoom;
+       Rectangle returnRect = new Rectangle (0,0,0,0);
+       returnRect.x = Math.round (rect.x * scaleFactor);
+       returnRect.y = Math.round (rect.y * scaleFactor);
+       returnRect.width = Math.round (rect.width * scaleFactor);
+       returnRect.height = Math.round (rect.height * scaleFactor);
+       return returnRect;
+}
+
+/**
+ * Auto-scale up ImageData
+ */
+public static ImageData autoScaleUp (Device device, final ImageData imageData) {
+       if (deviceZoom == 100 || imageData == null || (device != null && !device.isAutoScalable())) return imageData;
+       float scaleFactor = deviceZoom / 100f;
+       return autoScaleImageData(device, imageData, scaleFactor);
+}
+
+public static int[] autoScaleUp(int[] pointArray) {
+       if (deviceZoom == 100 || pointArray == null) return pointArray;
+       float scaleFactor = getScalingFactor ();
+       int [] returnArray = new int[pointArray.length];
+       for (int i = 0; i < pointArray.length; i++) {
+               returnArray [i] =  Math.round (pointArray [i] * scaleFactor);
+       }
+       return returnArray;
+}
+
+public static int[] autoScaleUp(Drawable drawable, int[] pointArray) {
+       if (drawable != null && !drawable.isAutoScalable ()) return pointArray;
+       return autoScaleUp (pointArray);
+}
+
+/**
+ * Auto-scale up int dimensions.
+ */
+public static int autoScaleUp (int size) {
+       if (deviceZoom == 100 || size == SWT.DEFAULT) return size;
+       float scaleFactor = getScalingFactor ();
+       return Math.round (size * scaleFactor);
+}
+
+/**
+ * Auto-scale up int dimensions using Native DPI
+ */
+public static int autoScaleUpUsingNativeDPI (int size) {
+       if (nativeDeviceZoom == 100 || size == SWT.DEFAULT) return size;
+       float nativeScaleFactor = nativeDeviceZoom / 100f;
+       return Math.round (size * nativeScaleFactor);
+}
+
+/**
+ * Auto-scale up int dimensions if enabled for Drawable class.
+ */
+public static int autoScaleUp (Drawable drawable, int size) {
+       if (drawable != null && !drawable.isAutoScalable ()) return size;
+       return autoScaleUp (size);
+}
+
+public static float autoScaleUp(float size) {
+       if (deviceZoom == 100 || size == SWT.DEFAULT) return size;
+       float scaleFactor = getScalingFactor ();
+       return (size * scaleFactor);
+}
+
+public static float autoScaleUp(Drawable drawable, float size) {
+       if (drawable != null && !drawable.isAutoScalable ()) return size;
+       return autoScaleUp (size);
+}
+
+/**
+ * Returns a new scaled up Point.
+ */
+public static Point autoScaleUp (Point point) {
+       if (deviceZoom == 100 || point == null) return point;
+       float scaleFactor = getScalingFactor ();
+       Point scaledPoint = new Point (0,0);
+       scaledPoint.x = Math.round (point.x * scaleFactor);
+       scaledPoint.y = Math.round (point.y * scaleFactor);
+       return scaledPoint;
+}
+
+/**
+ * Returns a new scaled up Point if enabled for Drawable class.
+ */
+public static Point autoScaleUp (Drawable drawable, Point point) {
+       if (drawable != null && !drawable.isAutoScalable ()) return point;
+       return autoScaleUp (point);
+}
+
+/**
+ * Returns a new scaled up Rectangle.
+ */
+public static Rectangle autoScaleUp (Rectangle rect) {
+       if (deviceZoom == 100 || rect == null) return rect;
+       Rectangle scaledRect = new Rectangle (0,0,0,0);
+       Point scaledTopLeft = DPIUtil.autoScaleUp (new Point (rect.x, rect.y));
+       Point scaledBottomRight = DPIUtil.autoScaleUp (new Point (rect.x + rect.width, rect.y + rect.height));
+
+       scaledRect.x = scaledTopLeft.x;
+       scaledRect.y = scaledTopLeft.y;
+       scaledRect.width = scaledBottomRight.x - scaledTopLeft.x;
+       scaledRect.height = scaledBottomRight.y - scaledTopLeft.y;
+       return scaledRect;
+}
+
+/**
+ * Returns a new scaled up Rectangle if enabled for Drawable class.
+ */
+public static Rectangle autoScaleUp (Drawable drawable, Rectangle rect) {
+       if (drawable != null && !drawable.isAutoScalable ()) return rect;
+       return autoScaleUp (rect);
+}
+
+/**
+ * Returns Scaling factor from the display
+ * @return float scaling factor
+ */
+private static float getScalingFactor () {
+       if (useCairoAutoScale) {
+               return 1;
+       }
+       return deviceZoom / 100f;
+}
+
+/**
+ * Compute the zoom value based on the DPI value.
+ *
+ * @return zoom
+ */
+public static int mapDPIToZoom (int dpi) {
+       double zoom = (double) dpi * 100 / DPI_ZOOM_100;
+       int roundedZoom = (int) Math.round (zoom);
+       return roundedZoom;
+}
+/**
+ * Gets Image data at specified zoom level, if image is missing then
+ * fall-back to 100% image. If provider or fall-back image is not available,
+ * throw error.
+ */
+public static ImageData validateAndGetImageDataAtZoom (ImageDataProvider provider, int zoom, boolean[] found) {
+       if (provider == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       ImageData data = provider.getImageData (zoom);
+       found [0] = (data != null);
+       /* If image is null when (zoom != 100%), fall-back to image at 100% zoom */
+       if (zoom != 100 && !found [0]) data = provider.getImageData (100);
+       if (data == null) SWT.error (SWT.ERROR_INVALID_ARGUMENT, null, ": ImageDataProvider [" + provider + "] returns null ImageData at 100% zoom.");
+       return data;
+}
+
+/**
+ * Gets Image file path at specified zoom level, if image is missing then
+ * fall-back to 100% image. If provider or fall-back image is not available,
+ * throw error.
+ */
+public static String validateAndGetImagePathAtZoom (ImageFileNameProvider provider, int zoom, boolean[] found) {
+       if (provider == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       String filename = provider.getImagePath (zoom);
+       found [0] = (filename != null);
+       /* If image is null when (zoom != 100%), fall-back to image at 100% zoom */
+       if (zoom != 100 && !found [0]) filename = provider.getImagePath (100);
+       if (filename == null) SWT.error (SWT.ERROR_INVALID_ARGUMENT, null, ": ImageFileNameProvider [" + provider + "] returns null filename at 100% zoom.");
+       return filename;
+}
+
+public static int getDeviceZoom() {
+       return deviceZoom;
+}
+
+public static void setDeviceZoom (int nativeDeviceZoom) {
+       DPIUtil.nativeDeviceZoom = nativeDeviceZoom;
+       int deviceZoom = getZoomForAutoscaleProperty (nativeDeviceZoom);
+
+       DPIUtil.deviceZoom = deviceZoom;
+       System.setProperty("org.eclipse.swt.internal.deviceZoom", Integer.toString(deviceZoom));
+       if (deviceZoom != 100 && autoScaleMethodSetting == AutoScaleMethod.AUTO) {
+               if (deviceZoom / 100 * 100 == deviceZoom || !"gtk".equals(SWT.getPlatform())) {
+                       autoScaleMethod = AutoScaleMethod.NEAREST;
+               } else {
+                       autoScaleMethod = AutoScaleMethod.SMOOTH;
+               }
+       }
+}
+
+public static void setUseCairoAutoScale (boolean cairoAutoScale) {
+       useCairoAutoScale = cairoAutoScale;
+}
+
+public static boolean useCairoAutoScale() {
+       return useCairoAutoScale;
+}
+
+public static int getZoomForAutoscaleProperty (int nativeDeviceZoom) {
+       int zoom = 0;
+       if (autoScaleValue != null) {
+               if ("false".equalsIgnoreCase (autoScaleValue)) {
+                       zoom = 100;
+               } else if ("quarter".equalsIgnoreCase (autoScaleValue)) {
+                       zoom = (int) (Math.round (nativeDeviceZoom / 25f) * 25);
+               } else if ("exact".equalsIgnoreCase (autoScaleValue)) {
+                       zoom = nativeDeviceZoom;
+               } else {
+                       try {
+                               int zoomValue = Integer.parseInt (autoScaleValue);
+                               zoom = Math.max (Math.min (zoomValue, 1600), 25);
+                       } catch (NumberFormatException e) {
+                               // unsupported value, use default
+                       }
+               }
+       }
+       if (zoom == 0) { // || "integer".equalsIgnoreCase (value) || "integer200".equalsIgnoreCase (value)
+               zoom = Math.max ((nativeDeviceZoom + 25) / 100 * 100, 100);
+               if (!"integer".equalsIgnoreCase(autoScaleValue)) {
+                       // integer200, or default
+                       zoom = Math.min (zoom, 200);
+               }
+       }
+       return zoom;
+}
+
+/**
+ * AutoScale ImageDataProvider.
+ */
+public static final class AutoScaleImageDataProvider implements ImageDataProvider {
+       Device device;
+       ImageData imageData;
+       int currentZoom;
+       public AutoScaleImageDataProvider(Device device, ImageData data, int zoom){
+               this.device = device;
+               this.imageData = data;
+               this.currentZoom = zoom;
+       }
+       @Override
+       public ImageData getImageData(int zoom) {
+               return DPIUtil.autoScaleImageData(device, imageData, zoom, currentZoom);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/DefaultExceptionHandler.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/DefaultExceptionHandler.java
new file mode 100644 (file)
index 0000000..a30a8e8
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Google Inc and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Stefan Xenos (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+import java.util.function.*;
+
+public class DefaultExceptionHandler {
+
+public static final Consumer<RuntimeException> RUNTIME_EXCEPTION_HANDLER = exception -> {
+       throw exception;
+};
+
+public static final Consumer<Error> RUNTIME_ERROR_HANDLER = error -> {
+       throw error;
+};
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ImageList.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ImageList.java
new file mode 100644 (file)
index 0000000..6b8905b
--- /dev/null
@@ -0,0 +1,439 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+public class ImageList {
+       long handle;
+       int style, refCount;
+       Image [] images;
+
+public ImageList (int style) {
+       this (style, 32, 32);
+}
+
+public ImageList (int style, int width, int height) {
+       this.style = style;
+       int flags = OS.ILC_MASK | OS.ILC_COLOR32;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.ILC_MIRROR;
+       handle = OS.ImageList_Create (width, height, 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] != null) {
+                       if (images [index].isDisposed ()) images [index] = null;
+               }
+               if (images [index] == null) break;
+               index++;
+       }
+       if (count == 0) {
+               Rectangle rect = image.getBoundsInPixels ();
+               OS.ImageList_SetIconSize (handle, rect.width, rect.height);
+       }
+       set (index, image, count);
+       if (index == 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;
+}
+
+long copyBitmap (long hImage, int width, int height) {
+       BITMAP bm = new BITMAP ();
+       OS.GetObject (hImage, BITMAP.sizeof, bm);
+       long hDC = OS.GetDC (0);
+       long hdc1 = OS.CreateCompatibleDC (hDC);
+       OS.SelectObject (hdc1, hImage);
+       long 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.
+       */
+       long hBitmap;
+       if (bm.bmBitsPixel == 32) {
+               BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+               bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+               bmiHeader.biWidth = width;
+               bmiHeader.biHeight = -height;
+               bmiHeader.biPlanes = 1;
+               bmiHeader.biBitCount = (short)24;
+               bmiHeader.biCompression = OS.BI_RGB;
+               byte[] bmi = new byte[BITMAPINFOHEADER.sizeof];
+               OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+               long[] pBits = new long[1];
+               hBitmap = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+       } else {
+               hBitmap = OS.CreateCompatibleBitmap (hDC, width, height);
+       }
+       OS.SelectObject (hdc2, hBitmap);
+       if (width != bm.bmWidth || height != bm.bmHeight) {
+               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 (0, hDC);
+       return hBitmap;
+}
+
+long copyIcon (long hImage, int width, int height) {
+       long hIcon = OS.CopyImage (hImage, OS.IMAGE_ICON, width, height, 0);
+       return hIcon != 0 ? hIcon : hImage;
+}
+
+long copyWithAlpha (long hBitmap, int background, byte[] alphaData, int destWidth, int destHeight) {
+       BITMAP bm = new BITMAP ();
+       OS.GetObject (hBitmap, BITMAP.sizeof, bm);
+       int srcWidth = bm.bmWidth;
+       int srcHeight = bm.bmHeight;
+
+       /* Create resources */
+       long hdc = OS.GetDC (0);
+       long srcHdc = OS.CreateCompatibleDC (hdc);
+       long oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
+       long memHdc = OS.CreateCompatibleDC (hdc);
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+       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];
+       OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+       long [] pBits = new long [1];
+       long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+       if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+       long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+       BITMAP dibBM = new BITMAP ();
+       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);
+
+       /* Merge the alpha channel in place */
+       if (alphaData != 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 = (byte)(background & 0xFF);
+               byte transGreen = (byte)((background >> 8) & 0xFF);
+               byte transBlue = (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] == transRed && srcData[sp-2] == transGreen && srcData[sp-3] == transBlue) ? 0 : (byte)255;
+                               sp += 4;
+                       }
+                       sp += spinc;
+               }
+       }
+       OS.MoveMemory (dibBM.bmBits, srcData, sizeInBytes);
+
+       /* Stretch and free resources */
+       if (srcWidth != destWidth || srcHeight != destHeight) {
+               BITMAPINFOHEADER bmiHeader2 = new BITMAPINFOHEADER ();
+               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];
+               OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof);
+               long [] pBits2 = new long [1];
+               long memDib2 = OS.CreateDIBSection (0, bmi2, OS.DIB_RGB_COLORS, pBits2, 0, 0);
+               long memHdc2 = OS.CreateCompatibleDC (hdc);
+               long oldMemBitmap2 = OS.SelectObject (memHdc2, memDib2);
+               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 (0, hdc);
+       return memDib;
+}
+
+long 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 [] {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);
+               }
+       }
+       long hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data);
+       if (srcWidth != destWidth || srcHeight != destHeight) {
+               long hdc = OS.GetDC (0);
+               long hdc1 = OS.CreateCompatibleDC (hdc);
+               OS.SelectObject (hdc1, hMask);
+               long hdc2 = OS.CreateCompatibleDC (hdc);
+               long hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+               OS.SelectObject (hdc2, hMask2);
+               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 (0, hdc);
+               OS.DeleteObject(hMask);
+               hMask = hMask2;
+       }
+       return hMask;
+}
+
+long createMask (long hBitmap, int destWidth, int destHeight, int background, int transparentPixel) {
+       BITMAP bm = new BITMAP ();
+       OS.GetObject (hBitmap, BITMAP.sizeof, bm);
+       int srcWidth = bm.bmWidth;
+       int srcHeight = bm.bmHeight;
+       long hMask = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+       long hDC = OS.GetDC (0);
+       long hdc1 = OS.CreateCompatibleDC (hDC);
+       if (background != -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.
+               */
+               boolean isDib = bm.bmBits != 0;
+               byte[] originalColors = null;
+               if (transparentPixel != -1 && isDib && bm.bmBitsPixel <= 8) {
+                       int maxColors = 1 << bm.bmBitsPixel;
+                       byte[] oldColors = new byte[maxColors * 4];
+                       OS.GetDIBColorTable(hdc1, 0, maxColors, oldColors);
+                       int offset = transparentPixel * 4;
+                       byte[] newColors = new byte[oldColors.length];
+                       newColors[offset] = (byte)0xFF;
+                       newColors[offset+1] = (byte)0xFF;
+                       newColors[offset+2] = (byte)0xFF;
+                       OS.SetDIBColorTable(hdc1, 0, maxColors, newColors);
+                       originalColors = oldColors;
+                       OS.SetBkColor (hdc1, 0xFFFFFF);
+               } else {
+                       OS.SetBkColor (hdc1, background);
+               }
+
+               long hdc2 = OS.CreateCompatibleDC (hDC);
+               OS.SelectObject (hdc2, hMask);
+               if (destWidth != srcWidth || destHeight != srcHeight) {
+                       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 != null) OS.SetDIBColorTable(hdc1, 0, 1 << bm.bmBitsPixel, originalColors);
+       } else {
+               long hOldBitmap = OS.SelectObject (hdc1, hMask);
+               OS.PatBlt (hdc1, 0, 0, destWidth, destHeight, OS.BLACKNESS);
+               OS.SelectObject (hdc1, hOldBitmap);
+       }
+       OS.ReleaseDC (0, hDC);
+       OS.DeleteDC (hdc1);
+       return hMask;
+}
+
+public void dispose () {
+       if (handle != 0) OS.ImageList_Destroy (handle);
+       handle = 0;
+       images = null;
+}
+
+public Image get (int index) {
+       return images [index];
+}
+
+public int getStyle () {
+       return style;
+}
+
+public long getHandle () {
+       return handle;
+}
+
+public Point getImageSize() {
+       int [] cx = new int [1], cy = new int [1];
+       OS.ImageList_GetIconSize (handle, cx, cy);
+       return new Point (cx [0], cy [0]);
+}
+
+public int indexOf (Image image) {
+       int count = OS.ImageList_GetImageCount (handle);
+       for (int i=0; i<count; i++) {
+               if (images [i] != null) {
+                       if (images [i].isDisposed ()) images [i] = null;
+                       if (images [i] != null && images [i].equals (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 != 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) {
+       long hImage = image.handle;
+       int [] cx = new int [1], cy = new int [1];
+       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.
+                       */
+                       long hBitmap = 0, hMask = 0;
+                       ImageData data = image.getImageData (DPIUtil.getDeviceZoom ());
+                       switch (data.getTransparencyType ()) {
+                               case SWT.TRANSPARENCY_ALPHA:
+                                       /*
+                                        * Fully transparent image is rendered as a black image, so such
+                                        * image needs to be rendered using ImageData mask approach.
+                                        * Refer bug 426247
+                                        *
+                                        * TODO: Explore using createMaskFromAlpha() method even
+                                        * for newer versions of the COMCTL32 library.
+                                        */
+                                       boolean fullyTransparent = true;
+                                       if (data.alphaData == null) {
+                                               fullyTransparent = false;
+                                       }
+                                       else {
+                                               for (byte alphaData : data.alphaData) {
+                                                       if (alphaData != 0) {
+                                                               fullyTransparent = false;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if (!fullyTransparent) {
+                                               hBitmap = copyWithAlpha (hImage, -1, data.alphaData, cx [0], cy [0]);
+                                       } else {
+                                               hBitmap = copyBitmap (hImage, cx [0], cy [0]);
+                                               hMask = createMaskFromAlpha (data, cx [0], cy [0]);
+                                       }
+                                       break;
+                               case SWT.TRANSPARENCY_PIXEL:
+                                       int background = -1;
+                                       Color color = image.getBackground ();
+                                       if (color != null) background = color.handle;
+                                       hBitmap = copyBitmap (hImage, cx [0], cy [0]);
+                                       hMask = createMask (hImage, cx [0], cy [0], background, data.transparentPixel);
+                                       break;
+                               case SWT.TRANSPARENCY_NONE:
+                               default:
+                                       hBitmap = copyBitmap (hImage, cx [0], cy [0]);
+                                       if (index != count) hMask = createMask (hImage, cx [0], cy [0], -1, -1);
+                                       break;
+                       }
+                       if (index == 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 != 0) OS.DeleteObject (hMask);
+                       if (hBitmap != hImage) OS.DeleteObject (hBitmap);
+                       break;
+               }
+               case SWT.ICON: {
+                       long hIcon = copyIcon (hImage, cx [0], cy [0]);
+                       OS.ImageList_ReplaceIcon (handle, index == count ? -1 : index, hIcon);
+                       OS.DestroyIcon (hIcon);
+                       break;
+               }
+       }
+}
+
+public int size () {
+       int result = 0;
+       int count = OS.ImageList_GetImageCount (handle);
+       for (int i=0; i<count; i++) {
+               if (images [i] != null) {
+                       if (images [i].isDisposed ()) images [i] = null;
+                       if (images [i] != null) result++;
+               }
+       }
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/LONG.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/LONG.java
new file mode 100644 (file)
index 0000000..9022c05
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+/** @jniclass flags=no_gen */
+public class LONG {
+       public long value;
+
+       public LONG (long value) {
+               this.value = value;
+       }
+
+       @Override
+       public boolean equals (Object object) {
+               if (object == this) return true;
+               if (!(object instanceof LONG)) return false;
+               LONG obj = (LONG)object;
+               return obj.value == this.value;
+       }
+
+       @Override
+       public int hashCode () {
+               return (int)(value ^ (value >>> 32));
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Library.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Library.java
new file mode 100644 (file)
index 0000000..eab183c
--- /dev/null
@@ -0,0 +1,476 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.function.*;
+import java.util.jar.*;
+
+public class Library {
+
+       /* SWT Version - Mmmm (M=major, mmm=minor) */
+
+       /**
+        * SWT Major version number (must be >= 0)
+        */
+       static int MAJOR_VERSION = 4;
+
+       /**
+        * SWT Minor version number (must be in the range 0..999)
+        */
+       static int MINOR_VERSION = 930;
+
+       /**
+        * SWT revision number (must be >= 0)
+        */
+       static int REVISION = 7;
+
+       /**
+        * The JAVA and SWT versions
+        */
+       public static final int JAVA_VERSION, SWT_VERSION;
+       public static final String USER_HOME;
+
+       static final String SEPARATOR;
+       static final String DELIMITER;
+
+       static final String JAVA_LIB_PATH = "java.library.path";
+       static final String SWT_LIB_PATH = "swt.library.path";
+
+
+       /* 64-bit support */
+       static final boolean IS_64 = longConst() == (long /*int*/)longConst();
+       static final String SUFFIX_64 = "-64";  //$NON-NLS-1$
+       static final String SWT_LIB_DIR;
+
+static {
+       DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$
+       SEPARATOR = File.separator;
+       USER_HOME = System.getProperty ("user.home");
+       SWT_LIB_DIR = ".swt" + SEPARATOR + "lib" + SEPARATOR + os() + SEPARATOR + arch(); //$NON-NLS-1$ $NON-NLS-2$
+       JAVA_VERSION = parseVersion(System.getProperty("java.version")); //$NON-NLS-1$
+       SWT_VERSION = SWT_VERSION(MAJOR_VERSION, MINOR_VERSION);
+}
+
+static String arch() {
+       String osArch = System.getProperty("os.arch"); //$NON-NLS-1$
+       if (osArch.equals ("i386") || osArch.equals ("i686")) return "x86"; //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$
+       if (osArch.equals ("amd64")) return "x86_64"; //$NON-NLS-1$ $NON-NLS-2$
+       return osArch;
+}
+
+static String os() {
+       String osName = System.getProperty("os.name"); //$NON-NLS-1$
+       if (osName.equals ("Linux")) return "linux"; //$NON-NLS-1$ $NON-NLS-2$
+       if (osName.equals ("Mac OS X")) return "macosx"; //$NON-NLS-1$ $NON-NLS-2$
+       if (osName.startsWith ("Win")) return "win32"; //$NON-NLS-1$ $NON-NLS-2$
+       return osName;
+}
+
+static void chmod(String permision, String path) {
+       if (os().equals ("win32")) return; //$NON-NLS-1$
+       try {
+               Runtime.getRuntime ().exec (new String []{"chmod", permision, path}).waitFor(); //$NON-NLS-1$
+       } catch (Throwable e) {}
+}
+
+/* Use method instead of in-lined constants to avoid compiler warnings */
+static long longConst() {
+       return 0x1FFFFFFFFL;
+}
+
+static int parseVersion(String version) {
+       if (version == null) return 0;
+       int major = 0, minor = 0, micro = 0;
+       int length = version.length(), index = 0, start = 0;
+       while (index < length && Character.isDigit(version.charAt(index))) index++;
+       try {
+               if (start < length) major = Integer.parseInt(version.substring(start, index));
+       } catch (NumberFormatException e) {}
+       start = ++index;
+       while (index < length && Character.isDigit(version.charAt(index))) index++;
+       try {
+               if (start < length) minor = Integer.parseInt(version.substring(start, index));
+       } catch (NumberFormatException e) {}
+       start = ++index;
+       while (index < length && Character.isDigit(version.charAt(index))) index++;
+       try {
+               if (start < length) micro = Integer.parseInt(version.substring(start, index));
+       } catch (NumberFormatException e) {}
+       return JAVA_VERSION(major, minor, micro);
+}
+
+/**
+ * Returns the Java version number as an integer.
+ *
+ * @param major
+ * @param minor
+ * @param micro
+ * @return the version
+ */
+public static int JAVA_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 SWT_VERSION (int major, int minor) {
+       return major * 1000 + minor;
+}
+
+private static boolean extractResource(String resourceName, File outFile) {
+       try (InputStream inputStream = Library.class.getResourceAsStream (resourceName)) {
+               if (inputStream == null) return false;
+               Files.copy(inputStream, outFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+       } catch (Throwable e) {
+               return false;
+       }
+
+       return true;
+}
+
+/**
+ * Extract file with 'mappedName' into path 'extractToFilePath'.
+ * Does not overwrite existing file.
+ * Does not leave trash on error.
+ * @param extractToFilePath full path of where the file is to be extacted to, inc name of file,
+ *                          e.g /home/USER/.swt/lib/linux/x86_64/libswt-MYLIB-gtk-4826.so
+ * @param mappedName file to be searched in jar.
+ * @return     true upon success, failure if something went wrong.
+ */
+static boolean extract (String extractToFilePath, String mappedName) {
+       File file = new File(extractToFilePath);
+       if (file.exists ()) return true;
+
+       // Write to temp file first, so that other processes don't see
+       // partially written library on disk
+       File tempFile;
+       try {
+               tempFile = File.createTempFile (file.getName(), ".tmp", file.getParentFile()); //$NON-NLS-1$
+       } catch (Throwable e) {
+               return false;
+                               }
+
+       // Extract resource
+       String resourceName = "/" + mappedName; //$NON-NLS-1$
+       if (!extractResource (resourceName, tempFile)) {
+               tempFile.delete();
+               return false;
+                       }
+
+       // Make it executable
+       chmod ("755", tempFile.getPath()); //$NON-NLS-1$
+
+       // "Publish" file now that it's ready to use.
+       // If there is a file already, then someone published while we were
+       // extracting, just delete our file and consider it a success.
+       try {
+               Files.move (tempFile.toPath(), file.toPath());
+       } catch (Throwable e) {
+               tempFile.delete();
+       }
+
+       return true;
+}
+
+static boolean isLoadable () {
+       URL url = Platform.class.getClassLoader ().getResource ("org/eclipse/swt/internal/Library.class"); //$NON-NLS-1$
+       if (!url.getProtocol ().equals ("jar")) { //$NON-NLS-1$
+               /* SWT is presumably running in a development environment */
+               return true;
+       }
+
+       Attributes attributes = null;
+       try {
+               URLConnection connection = url.openConnection();
+               if (!(connection instanceof JarURLConnection)) {
+                       /* should never happen for a "jar:" url */
+                       return false;
+               }
+               JarURLConnection jc = (JarURLConnection) connection;
+               attributes = jc.getMainAttributes();
+       } catch (IOException e) {
+               /* should never happen for a valid SWT jar with the expected manifest values */
+               return false;
+       }
+
+       String os = os ();
+       String arch = arch ();
+       String manifestOS = attributes.getValue ("SWT-OS"); //$NON-NLS-1$
+       String manifestArch = attributes.getValue ("SWT-Arch"); //$NON-NLS-1$
+       if (arch.equals (manifestArch) && os.equals (manifestOS)) {
+               return true;
+       }
+
+       return false;
+}
+
+static boolean load (String libName, StringBuilder message) {
+       try {
+               if (libName.contains (SEPARATOR)) {
+                       System.load (libName);
+               } else {
+                       System.loadLibrary (libName);
+               }
+               return true;
+       } catch (UnsatisfiedLinkError e) {
+               if (message.length() == 0) message.append(DELIMITER);
+               message.append('\t');
+               message.append(e.getMessage());
+               message.append(DELIMITER);
+       }
+       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 == null) prop = System.getProperty ("com.ibm.vm.bitmode"); //$NON-NLS-1$
+       if (prop != null) {
+               if ("32".equals (prop) && IS_64) { //$NON-NLS-1$
+                       throw new UnsatisfiedLinkError ("Cannot load 64-bit SWT libraries on 32-bit JVM"); //$NON-NLS-1$
+               }
+               if ("64".equals (prop) && !IS_64) { //$NON-NLS-1$
+                       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 = getVersionString ();
+               libName1 = name + "-" + Platform.PLATFORM + "-" + version;  //$NON-NLS-1$ //$NON-NLS-2$
+               libName2 = name + "-" + Platform.PLATFORM;  //$NON-NLS-1$
+               mappedName1 = mapLibraryName (libName1);
+               mappedName2 = mapLibraryName (libName2);
+       } else {
+               libName1 = libName2 = mappedName1 = mappedName2 = name;
+       }
+
+       StringBuilder message = new StringBuilder();
+
+       /* Try loading library from swt library path */
+       String path = System.getProperty (SWT_LIB_PATH); //$NON-NLS-1$
+       if (path != null) {
+               path = new File (path).getAbsolutePath ();
+               if (load (path + SEPARATOR + mappedName1, message)) return;
+               if (mapName && load (path + SEPARATOR + mappedName2, message)) return;
+       }
+
+       /* Try loading library from java library path */
+       if (load (libName1, message)) return;
+       if (mapName && load (libName2, message)) return;
+
+       /* Try loading library from the tmp directory if swt library path is not specified.
+        * Create the tmp folder if it doesn't exist. Tmp folder looks like this:
+        * ~/.swt/lib/<platform>/<arch>/
+        */
+       String fileName1 = mappedName1;
+       String fileName2 = mappedName2;
+       if (path == null) {
+               path = USER_HOME;
+               File dir = new File (path, SWT_LIB_DIR);
+               if ((dir.exists () && dir.isDirectory ()) || dir.mkdirs ()) { // Create if not exist.
+                       path = dir.getAbsolutePath ();
+               } else {
+                       /* fall back to using the home dir directory */
+                       if (IS_64) {
+                               fileName1 = mapLibraryName (libName1 + SUFFIX_64);
+                               fileName2 = mapLibraryName (libName2 + SUFFIX_64);
+                       }
+               }
+               if (load (path + SEPARATOR + fileName1, message)) return;
+               if (mapName && load (path + SEPARATOR + fileName2, message)) return;
+       }
+
+       /* Try extracting and loading library from jar. */
+       if (path != null) {
+               if (extract (path + SEPARATOR + fileName1, mappedName1)) {
+                       load(path + SEPARATOR + fileName1, message);
+                       return;
+               }
+               if (mapName && extract (path + SEPARATOR + fileName2, mappedName2)) {
+                       load(path + SEPARATOR + fileName2, message);
+                       return;
+               }
+       }
+
+       /* Failed to find the library */
+       throw new UnsatisfiedLinkError ("Could not load SWT library. Reasons: " + message.toString()); //$NON-NLS-1$
+}
+
+static String mapLibraryName (String libName) {
+       /* SWT libraries in the Macintosh use the extension .jnilib but the some VMs map to .dylib. */
+       libName = System.mapLibraryName (libName);
+       String ext = ".dylib"; //$NON-NLS-1$
+       if (libName.endsWith(ext)) {
+               libName = libName.substring(0, libName.length() - ext.length()) + ".jnilib"; //$NON-NLS-1$
+       }
+       return libName;
+}
+
+/**
+ * @return String Combined SWT version like 4826
+ */
+public static String getVersionString () {
+       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$
+       }
+       return version;
+}
+
+
+/**
+ * Locates a resource located either in java library path, swt library path, or attempts to extract it from inside swt.jar file.
+ * This function supports a single level subfolder, e.g SubFolder/resource.
+ *
+ * Dev note: (17/12/07) This has been developed and throughly tested on GTK. Designed to work on Cocoa/Win as well, but not tested.
+ *
+ * @param subDir  'null' or a folder name without slashes. E.g Correct: 'mysubdir',  incorrect: '/subdir/'.
+ *                Platform specific Slashes will be added automatically.
+ * @param resourceName e.g swt-webkitgtk
+ * @param mapResourceName  true if you like platform specific mapping applied to resource name. e.g  MyLib -> libMyLib-gtk-4826.so
+ */
+public static File findResource(String subDir, String resourceName, boolean mapResourceName){
+
+       //We construct a 'maybe' subdirectory path. 'Maybe' because if no subDir given, then it's an empty string "".
+                                                                                //       subdir  e.g:  subdir
+       String maybeSubDirPath = subDir != null ? subDir + SEPARATOR : "";       //               e.g:  subdir/  or ""
+       String maybeSubDirPathWithPrefix = subDir != null ? SEPARATOR + maybeSubDirPath : ""; //  e.g: /subdir/  or ""
+       final String finalResourceName = mapResourceName ?
+                       mapLibraryName(resourceName + "-" + Platform.PLATFORM + "-" + getVersionString ()) // e.g libMyLib-gtk-3826.so
+                       : resourceName;
+
+       // 1) Look for the resource in the java/swt library path(s)
+       // This code commonly finds the resource if the swt project is a required project and the swt binary (for your platform)
+       // project is open in your workplace  (found in the JAVA_LIBRARY_PATH) or if you're explicitly specified SWT_LIBRARY_PATH.
+       {
+               Function<String, File> lookForFileInPath = searchPath -> {
+                       String classpath = System.getProperty(searchPath);
+                       if (classpath != null){
+                               String[] paths = classpath.split(":");
+                               for (String path : paths) {
+                               File file = new File(path + SEPARATOR + maybeSubDirPath + finalResourceName);
+                                       if (file.exists()){
+                                               return file;
+                                       }
+                               }
+                       }
+                       return null;
+               };
+               File result = null;
+               for (String path : new String[] {JAVA_LIB_PATH,SWT_LIB_PATH}) {
+                       result = lookForFileInPath.apply(path);
+                       if (result != null)
+                               return result;
+               }
+       }
+
+       // 2) If SWT is ran as OSGI bundle (e.g inside Eclipse), then local resources are extracted to
+       // eclipse/configuration/org.eclipse.osgi/NN/N/.cp/<resource> and we're given a pointer to the file.
+       {
+               // If this is an OSGI bundle look for the resource using getResource
+               URL url = Library.class.getClassLoader().getResource(maybeSubDirPathWithPrefix + finalResourceName);
+               URLConnection connection;
+               try {
+                       connection = url.openConnection();
+                       Method getFileURLMethod = connection.getClass().getMethod("getFileURL");
+                       if (getFileURLMethod != null){
+                               // This method does the actual extraction of file to: ../eclipse/configuration/org.eclipse.osgi/NN/N/.cp/<SubDir>/resource.ext
+                               URL result = (URL) getFileURLMethod.invoke(connection);
+                               return new File(result.toURI());
+                       }
+               } catch (Exception e) {
+                       // If any exceptions are thrown the resource cannot be located this way.
+               }
+       }
+
+       // 3) Need to try to pull the resource out of the swt.jar.
+       // Look for the resource in the user's home directory, (if already extracted in the temp swt folder. (~/.swt/lib...)
+       // Extract from the swt.jar if not there already.
+       {
+               // Developer note:
+               // To test this piece of code, you need to compile SWT into a jar and use it in a test project. E.g
+               //   cd ~/git/eclipse.platform.swt.binaries/bundles/org.eclipse.swt.gtk.linux.x86_64/
+               //   mvn clean verify -Pbuild-individual-bundles -Dnative=gtk.linux.x86_64
+               // then ./target/ will contain org.eclipse.swt.gtk.linux.x86_64-3.106.100-SNAPSHOT.jar (and it's source),
+               //  you can copy those into your test swt project and test that your resource is extracted into something like ~/.swt/...
+               // Lastly, if using subDir, you need to edit the build.properties and specify the folder you wish to have included in your jar in the includes.
+               File file = new File (USER_HOME + SEPARATOR +  SWT_LIB_DIR + maybeSubDirPathWithPrefix, finalResourceName);
+               if (file.exists()){
+                       return file;
+               } else { // Try to extract file from jar if not found.
+
+                       // Create temp directory if it doesn't exist
+                       File tempDir = new File (USER_HOME, SWT_LIB_DIR + maybeSubDirPathWithPrefix);
+                       if ((!tempDir.exists () || tempDir.isDirectory ())) {
+                               tempDir.mkdirs ();
+                       }
+
+                       if (extract(file.getPath(), maybeSubDirPath + finalResourceName)) {
+                               if (file.exists()) {
+                                       return file;
+                               }
+                       }
+               }
+       }
+       throw new UnsatisfiedLinkError("Could not find resource" + resourceName +  (subDir != null ? " (in subdirectory: " + subDir + " )" : ""));
+}
+
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Lock.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Lock.java
new file mode 100644 (file)
index 0000000..971795e
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+/**
+ * Instances of this represent a recursive monitor.  Note that this
+ * is an empty implementation which does not actually perform locking.
+ */
+public class Lock {
+
+/**
+ * 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() {
+       return 0;
+}
+
+/**
+ * Unlocks the monitor. If the current thread is not
+ * the monitor owner, do nothing.
+ */
+public void unlock() {
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Platform.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/Platform.java
new file mode 100644 (file)
index 0000000..3f1d620
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+
+public class Platform {
+       public static final String PLATFORM = "win32"; //$NON-NLS-1$
+       public static final Lock lock = new Lock ();
+
+public static boolean isLoadable () {
+       return Library.isLoadable ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/SWTEventListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/SWTEventListener.java
new file mode 100644 (file)
index 0000000..2622ded
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+
+import java.util.EventListener;
+
+/**
+ * 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>
+ * @noreference This interface is not intended to be referenced by clients.
+ */
+public interface SWTEventListener extends EventListener {
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/SWTMessages.properties b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/SWTMessages.properties
new file mode 100644 (file)
index 0000000..da86f4f
--- /dev/null
@@ -0,0 +1,128 @@
+###############################################################################
+# Copyright (c) 2000, 2013 IBM Corporation and others.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+SWT_Yes=Yes
+SWT_No=No
+SWT_OK=OK
+SWT_Cancel=Cancel
+SWT_Help=Help
+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_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_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_Page_Mnemonic=Alt+{0}
+SWT_SwitchPage_Shortcut=Ctrl+PageDown
+SWT_FileDownload=File Download
+SWT_Download_Error=Error occurred, download not completed
+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}
+SWT_Page_Load_Failed=Page load failed with error: {0}
+SWT_InvalidCert_Title=Invalid Certificate
+SWT_InvalidCert_Message=The security certificate presented by "{0}" has problem(s).
+SWT_InvalidCert_InvalidName=Certificate name is invalid or does not match site name.  Certificate issued to: "{0}". 
+SWT_InvalidCert_NotValid=Certificate is not currently valid.  Valid date range: "{0}".  
+SWT_InvalidCert_NotTrusted=Certificate is not from a trusted certifying authority.  Certificate issuer: "{0}".
+SWT_InvalidCert_UnknownCA=The signing certificate authority is not known.
+SWT_InvalidCert_BadIdentity=The certificate does not match the expected identity of the site that it was retrieved from.
+SWT_InvalidCert_NotActivated=The certificate's activation time is still in the future.
+SWT_InvalidCert_Expired=The certificate has expired.
+SWT_InvalidCert_Revoked=The certificate has been revoked.
+SWT_InvalidCert_Insecure=The certificate's algorithm is considered insecure.
+SWT_InvalidCert_GenericError=Some other error occurred validating the certificate.
+SWT_InvalidCert_ValidateAll=This certificate has many errors.
+SWT_InvalidCert_Connect=Would you like to connect to this site anyways?
+SWT_OnBeforeUnload_Message1=Are you sure you want to leave this page?
+SWT_OnBeforeUnload_Message2=Click OK to continue, or Cancel to stay on this page.
+SWT_ViewCertificate=View Certificate
+SWT_Certificate=Certificate
+SWT_Controlled_By=controlled by
+SWT_Controller_For=controller for
+SWT_Described_By=described by
+SWT_Description_For=description for
+SWT_Embedded_By=embedded by
+SWT_Embeds=embeds
+SWT_Flows_From=flows from
+SWT_Flows_To=flows to
+SWT_Label_For=label for
+SWT_Labelled_By=labelled by
+SWT_Member_Of=member of
+SWT_Node_Child_Of=node child of
+SWT_Parent_Window_Of=parent window of
+SWT_Popup_For=popup for
+SWT_Subwindow_Of=subwindow of
+SWT_Continue=Continue
+SWT_IssuedTo=Issued to:\t{0}
+SWT_IssuedFrom=Issued from:\t{0}
+SWT_Issuer=Issuer
+SWT_General=General
+SWT_Details=Details
+SWT_Field=Field
+SWT_Value=Value
+SWT_Version=Version
+SWT_ValidFrom=Valid From
+SWT_ValidTo=Valid To
+SWT_ValidFromTo=Valid from: {0} to: {1}
+SWT_Subject=Subject
+SWT_SerialNumber=Serial Number
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/BitmapData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/BitmapData.java
new file mode 100644 (file)
index 0000000..457100c
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+public class BitmapData {
+       public int Width;
+       public int Height;
+       public int Stride;
+       /** @field cast=(PixelFormat) */
+       public int PixelFormat;
+       /** @field cast=(void*) */
+       public long Scan0;
+       /** @field cast=(UINT_PTR) */
+       public long Reserved;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/ColorPalette.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/ColorPalette.java
new file mode 100644 (file)
index 0000000..fe85c74
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+public class ColorPalette {
+       public int Flags;
+       public int Count;
+       public int[] Entries = new int[1];
+       public static final int sizeof = Gdip.ColorPalette_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/Gdip.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/Gdip.java
new file mode 100644 (file)
index 0000000..375544e
--- /dev/null
@@ -0,0 +1,1215 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+import org.eclipse.swt.internal.*;
+
+/** @jniclass flags=cpp */
+public class Gdip extends Platform {
+       static {
+               Library.loadLibrary ("swt-gdip"); //$NON-NLS-1$
+       }
+
+       /** GdiPlus constants */
+       public static final float FlatnessDefault = 0.25f;
+       public static final int BrushTypeSolidColor = 0;
+       public static final int BrushTypeHatchFill = 1;
+       public static final int BrushTypeTextureFill = 2;
+       public static final int BrushTypePathGradient = 3;
+       public static final int BrushTypeLinearGradient = 4;
+       public static final int ColorAdjustTypeBitmap = 1;
+       public static final int ColorMatrixFlagsDefault = 0;
+       public static final int CombineModeReplace = 0;
+       public static final int CombineModeIntersect = 1;
+       public static final int CombineModeUnion = 2;
+       public static final int CombineModeXor = 3;
+       public static final int CombineModeExclude = 4;
+       public static final int CombineModeComplement = 5;
+       public static final int FillModeAlternate = 0;
+       public static final int FillModeWinding = 1;
+       public static final int DashCapFlat = 0;
+       public static final int DashCapRound = 2;
+       public static final int DashCapTriangle = 3;
+       public static final int DashStyleSolid = 0;
+       public static final int DashStyleDash = 1;
+       public static final int DashStyleDot = 2;
+       public static final int DashStyleDashDot = 3;
+       public static final int DashStyleDashDotDot = 4;
+       public static final int DashStyleCustom = 5;
+       public static final int DriverStringOptionsRealizedAdvance = 4;
+       public static final int FontStyleRegular = 0;
+       public static final int FontStyleBold = 1;
+       public static final int FontStyleItalic = 2;
+       public static final int FontStyleBoldItalic = 3;
+       public static final int FontStyleUnderline = 4;
+       public static final int FontStyleStrikeout = 8;
+       public static final int PaletteFlagsHasAlpha = 0x0001;
+       public static final int FlushIntentionFlush = 0;
+       public static final int FlushIntentionSync = 1;
+       public static final int HotkeyPrefixNone = 0;
+       public static final int HotkeyPrefixShow = 1;
+       public static final int HotkeyPrefixHide = 2;
+       public static final int LineJoinMiter = 0;
+       public static final int LineJoinBevel = 1;
+       public static final int LineJoinRound = 2;
+       public static final int LineCapFlat = 0;
+       public static final int LineCapSquare = 1;
+       public static final int LineCapRound = 2;
+       public static final int MatrixOrderPrepend = 0;
+       public static final int MatrixOrderAppend = 1;
+       public static final int QualityModeDefault = 0;
+       public static final int QualityModeLow = 1;
+       public static final int QualityModeHigh = 2;
+       public static final int InterpolationModeDefault = QualityModeDefault;
+       public static final int InterpolationModeLowQuality = QualityModeLow;
+       public static final int InterpolationModeHighQuality = QualityModeHigh;
+       public static final int InterpolationModeBilinear = QualityModeHigh + 1;
+       public static final int InterpolationModeBicubic = QualityModeHigh + 2;
+       public static final int InterpolationModeNearestNeighbor = QualityModeHigh + 3;
+       public static final int InterpolationModeHighQualityBilinear = QualityModeHigh + 4;
+       public static final int InterpolationModeHighQualityBicubic = QualityModeHigh + 5;
+       public static final int PathPointTypeStart = 0;
+       public static final int PathPointTypeLine = 1;
+       public static final int PathPointTypeBezier = 3;
+       public static final int PathPointTypePathTypeMask = 0x7;
+       public static final int PathPointTypePathDashMode = 0x10;
+       public static final int PathPointTypePathMarker = 0x20;
+       public static final int PathPointTypeCloseSubpath = 0x80;
+       public static final int PathPointTypeBezier3 = 3;
+       public static final int PixelFormatIndexed = 0x00010000;
+       public static final int PixelFormatGDI = 0x00020000;
+       public static final int PixelFormatAlpha = 0x00040000;
+       public static final int PixelFormatPAlpha = 0x00080000;
+       public static final int PixelFormatExtended = 0x00100000;
+       public static final int PixelFormatCanonical = 0x00200000;
+       public static final int PixelFormat1bppIndexed = (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI);
+       public static final int PixelFormat4bppIndexed = (2 | ( 4 << 8) | PixelFormatIndexed | PixelFormatGDI);
+       public static final int PixelFormat8bppIndexed = (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI);
+       public static final int PixelFormat16bppGrayScale = (4 | (16 << 8) | PixelFormatExtended);
+       public static final int PixelFormat16bppRGB555 = (5 | (16 << 8) | PixelFormatGDI);
+       public static final int PixelFormat16bppRGB565 = (6 | (16 << 8) | PixelFormatGDI);
+       public static final int PixelFormat16bppARGB1555 = (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI);
+       public static final int PixelFormat24bppRGB = (8 | (24 << 8) | PixelFormatGDI);
+       public static final int PixelFormat32bppRGB = (9 | (32 << 8) | PixelFormatGDI);
+       public static final int PixelFormat32bppARGB = (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical);
+       public static final int PixelFormat32bppPARGB = (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI);
+       public static final int PixelFormat48bppRGB = (12 | (48 << 8) | PixelFormatExtended);
+       public static final int PixelFormat64bppARGB = (13 | (64 << 8) | PixelFormatAlpha  | PixelFormatCanonical | PixelFormatExtended);
+       public static final int PixelFormat64bppPARGB = (14 | (64 << 8) | PixelFormatAlpha  | PixelFormatPAlpha | PixelFormatExtended);
+       public static final int PixelFormat32bppCMYK = (15 | (32 << 8));
+       public static final int PixelFormatMax = 16;
+       public static final int PixelOffsetModeNone = QualityModeHigh + 1;
+       public static final int PixelOffsetModeHalf = QualityModeHigh + 2;
+       public static final int SmoothingModeDefault = QualityModeDefault;
+       public static final int SmoothingModeHighSpeed = QualityModeLow;
+       public static final int SmoothingModeHighQuality = QualityModeHigh;
+       public static final int SmoothingModeNone = 3;
+       public static final int SmoothingModeAntiAlias8x4 = 4;
+       public static final int SmoothingModeAntiAlias = SmoothingModeAntiAlias8x4;
+       public static final int SmoothingModeAntiAlias8x8 = 5;
+       public static final int StringFormatFlagsDirectionRightToLeft = 0x00000001;
+       public static final int StringFormatFlagsDirectionVertical = 0x00000002;
+       public static final int StringFormatFlagsNoFitBlackBox = 0x00000004;
+       public static final int StringFormatFlagsDisplayFormatControl = 0x00000020;
+       public static final int StringFormatFlagsNoFontFallback = 0x00000400;
+       public static final int StringFormatFlagsMeasureTrailingSpaces = 0x00000800;
+       public static final int StringFormatFlagsNoWrap = 0x00001000;
+       public static final int StringFormatFlagsLineLimit = 0x00002000;
+       public static final int StringFormatFlagsNoClip = 0x00004000;
+       public static final int TextRenderingHintSystemDefault = 0;
+       public static final int TextRenderingHintSingleBitPerPixelGridFit = 1;
+       public static final int TextRenderingHintSingleBitPerPixel = 2;
+       public static final int TextRenderingHintAntiAliasGridFit = 3;
+       public static final int TextRenderingHintAntiAlias = 4;
+       public static final int TextRenderingHintClearTypeGridFit = 5;
+       public static final int UnitPixel = 2;
+       public static final int WrapModeTile = 0;
+       public static final int WrapModeTileFlipX = 1;
+       public static final int WrapModeTileFlipY = 2;
+       public static final int WrapModeTileFlipXY = 3;
+       public static final int WrapModeClamp = 4;
+
+/** 64 bit */
+public static final native int ColorPalette_sizeof();
+public static final native int GdiplusStartupInput_sizeof();
+
+/** GdiPlus natives */
+
+/**
+ * @param token cast=(ULONG_PTR *)
+ * @param input cast=(const GdiplusStartupInput *)
+ * @param output cast=(GdiplusStartupOutput *)
+ */
+public static final native int GdiplusStartup(long[] token, GdiplusStartupInput input, long output);
+/** @param token cast=(ULONG_PTR) */
+public static final native void GdiplusShutdown(long token);
+/**
+ * @method flags=new
+ * @param hbm cast=(HBITMAP)
+ * @param hpal cast=(HPALETTE)
+ */
+public static final native long Bitmap_new(long hbm, long hpal);
+/**
+ * @method flags=new
+ * @param hicon cast=(HICON)
+ */
+public static final native long Bitmap_new(long hicon);
+/**
+ * @method flags=new
+ * @param format cast=(PixelFormat)
+ * @param scan0 cast=(BYTE *)
+ */
+public static final native long Bitmap_new(int width, int height, int stride, int format, long scan0);
+/**
+ * @method flags=new
+ * @param filename cast=(WCHAR*)
+ */
+public static final native long Bitmap_new(char[] filename, boolean useIcm);
+/** @method flags=delete */
+public static final native void Bitmap_delete(long bitmap);
+/**
+ * @method flags=cpp
+ * @param bitmap cast=(Bitmap*)
+ * @param colorBackground cast=(Color)
+ * @param hbmReturn cast=(HBITMAP*)
+ */
+public static final native int Bitmap_GetHBITMAP(long bitmap, int colorBackground, long[] hbmReturn);
+/**
+ * @method flags=cpp
+ * @param bitmap cast=(Bitmap*)
+ * @param hicon cast=(HICON*)
+ */
+public static final native int Bitmap_GetHICON(long bitmap, long[] hicon);
+/** @method flags=new */
+public static final native long BitmapData_new();
+/** @method flags=delete */
+public static final native void BitmapData_delete(long bitmapData);
+/**
+ * @method flags=cpp
+ * @param bitmap cast=(Bitmap*)
+ * @param rect cast=(Rect*)
+ * @param pixelFormat cast=(PixelFormat)
+ * @param lockedBitmapData cast=(BitmapData*)
+ */
+public static final native int Bitmap_LockBits(long bitmap, long rect, int flags, int pixelFormat, long lockedBitmapData);
+/**
+ * @method flags=cpp
+ * @param bitmap cast=(Bitmap*)
+ * @param lockedBitmapData cast=(BitmapData*)
+ */
+public static final native int Bitmap_UnlockBits(long bitmap, long lockedBitmapData);
+/**
+ * @method flags=cpp
+ * @param brush cast=(Brush *)
+ */
+public static final native long Brush_Clone(long brush);
+/**
+ * @method flags=cpp
+ * @param brush cast=(Brush *)
+ */
+public static final native int Brush_GetType(long brush);
+/** @method flags=new */
+public static final native long PrivateFontCollection_new();
+/** @method flags=delete */
+public static final native void PrivateFontCollection_delete(long collection);
+/**
+ * @method flags=cpp
+ * @param collection cast=(PrivateFontCollection *)
+ * @param filename cast=(const WCHAR *)
+ */
+public static final native int PrivateFontCollection_AddFontFile(long collection, char[] filename);
+/**
+ * @method flags=new
+ * @param hdc cast=(HDC)
+ * @param hfont cast=(HFONT)
+ */
+public static final native long Font_new(long hdc, long hfont);
+/**
+ * @method flags=new
+ * @param family cast=(const FontFamily *)
+ * @param emSize cast=(REAL)
+ * @param style cast=(INT)
+ * @param unit cast=(Unit)
+ */
+public static final native long Font_new(long family, float emSize, int style, int unit);
+/**
+ * @method flags=new
+ * @param familyName cast=(const WCHAR *)
+ * @param emSize cast=(REAL)
+ * @param style cast=(INT)
+ * @param unit cast=(Unit)
+ * @param fontCollection cast=(const FontCollection *)
+ */
+public static final native long Font_new(char[] familyName, float emSize, int style, int unit, long fontCollection);
+/** @method flags=delete */
+public static final native void Font_delete(long font);
+/**
+ * @method flags=cpp
+ * @param font cast=(Font *)
+ * @param family cast=(FontFamily *)
+ */
+public static final native int Font_GetFamily(long font, long family);
+/**
+ * @method flags=cpp
+ * @param font cast=(Font *)
+ */
+public static final native float Font_GetSize(long font);
+/**
+ * @method flags=cpp
+ * @param font cast=(Font *)
+ */
+public static final native int Font_GetStyle(long font);
+/**
+ * @method flags=cpp
+ * @param font cast=(Font *)
+ * @param g cast=(const Graphics *)
+ * @param logfontW cast=(LOGFONTW *)
+ */
+public static final native int Font_GetLogFontW (long font, long g, long  logfontW);
+/**
+ * @method flags=cpp
+ * @param font cast=(Font *)
+ */
+public static final native boolean Font_IsAvailable(long font);
+/** @method flags=new */
+public static final native long FontFamily_new();
+/**
+ * @method flags=new
+ * @param name cast=(const WCHAR *)
+ * @param fontCollection cast=(const FontCollection *)
+ */
+public static final native long FontFamily_new(char[] name, long fontCollection);
+/** @method flags=delete */
+public static final native void FontFamily_delete(long family);
+/**
+ * @method flags=cpp
+ * @param family cast=(FontFamily *)
+ * @param name cast=(WCHAR *)
+ * @param language cast=(WCHAR)
+ */
+public static final native int FontFamily_GetFamilyName(long family, char[] name, char language);
+/**
+ * @method flags=cpp
+ * @param family cast=(FontFamily *)
+ */
+public static final native boolean FontFamily_IsAvailable(long family);
+/**
+ * @method flags=new
+ * @param hdc cast=(HDC)
+ */
+public static final native long Graphics_new(long hdc);
+/** @method flags=delete */
+public static final native void Graphics_delete(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ */
+public static final native int Graphics_DrawArc(long graphics, long pen, int x, int y, int width, int height, float startAngle, float sweepAngle);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param text cast=(const UINT16 *)
+ * @param font cast=(const Font *)
+ * @param brush cast=(const Brush *)
+ * @param positions cast=(const PointF *)
+ * @param matrix cast=(const Matrix *)
+ */
+public static final native int Graphics_DrawDriverString(long graphics, long text, int length, long font, long brush, PointF /*long*/ positions, int flags, long matrix);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param text cast=(const UINT16 *)
+ * @param font cast=(const Font *)
+ * @param brush cast=(const Brush *)
+ * @param positions cast=(const PointF *),flags=no_out
+ * @param matrix cast=(const Matrix *)
+ */
+public static final native int Graphics_DrawDriverString(long graphics, long text, int length, long font, long brush, float[] positions, int flags, long matrix);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ */
+public static final native int Graphics_DrawEllipse(long graphics, long pen, int x, int y, int width, int height);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param image cast=(Image *)
+ * @param x cast=(INT)
+ * @param y cast=(INT)
+ */
+public static final native int Graphics_DrawImage(long graphics, long image, int x, int y);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param image cast=(Image *)
+ * @param destRect cast=(const Rect *),flags=struct
+ * @param srcx cast=(INT)
+ * @param srcy cast=(INT)
+ * @param srcwidth cast=(INT)
+ * @param srcheight cast=(INT)
+ * @param srcUnit cast=(Unit)
+ * @param imageAttributes cast=(ImageAttributes *)
+ * @param callback cast=(DrawImageAbort)
+ * @param callbackData cast=(VOID *)
+ */
+public static final native int Graphics_DrawImage(long graphics, long image, Rect destRect, int srcx, int srcy, int srcwidth, int srcheight, int srcUnit, long imageAttributes, long callback, long callbackData);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ */
+public static final native int Graphics_DrawLine(long graphics, long pen, int x1, int y1, int x2, int y2);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ * @param points cast=(const Point *),flags=no_out
+ * @param count cast=(INT)
+ */
+public static final native int Graphics_DrawLines(long graphics, long pen, int[] points, int count);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int Graphics_DrawPath(long graphics, long pen, long path);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ * @param points cast=(Point *)
+ * @param count cast=(INT)
+ */
+public static final native int Graphics_DrawPolygon(long graphics, long pen, int[] points, int count);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pen cast=(Pen *)
+ */
+public static final native int Graphics_DrawRectangle(long graphics, long pen, int x, int y, int width, int height);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param string cast=(WCHAR *)
+ * @param length cast=(int)
+ * @param font cast=(Font *)
+ * @param origin flags=struct
+ * @param brush cast=(Brush *)
+ */
+public static final native int Graphics_DrawString(long graphics, char[] string, int length, long font, PointF origin, long brush);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param string cast=(WCHAR *)
+ * @param length cast=(int)
+ * @param font cast=(Font *)
+ * @param origin flags=struct
+ * @param format cast=(StringFormat *)
+ * @param brush cast=(Brush *)
+ */
+public static final native int Graphics_DrawString(long graphics, char[] string, int length, long font, PointF origin, long format, long brush);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param brush cast=(Brush *)
+ * @param x cast=(INT)
+ * @param y cast=(INT)
+ * @param width cast=(INT)
+ * @param height cast=(INT)
+ */
+public static final native int Graphics_FillEllipse(long graphics, long brush, int x, int y, int width, int height);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param brush cast=(Brush *)
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int Graphics_FillPath(long graphics, long brush, long path);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param intention cast=(FlushIntention)
+ */
+public static final native void Graphics_Flush(long graphics, int intention);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param brush cast=(Brush *)
+ * @param x cast=(INT)
+ * @param y cast=(INT)
+ * @param width cast=(INT)
+ * @param height cast=(INT)
+ * @param startAngle cast=(REAL)
+ * @param sweepAngle cast=(REAL)
+ */
+public static final native int Graphics_FillPie(long graphics, long brush, int x, int y, int width, int height, float startAngle, float sweepAngle);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param brush cast=(Brush *)
+ * @param points cast=(const Point *),flags=no_out
+ * @param count cast=(INT)
+ * @param fillMode cast=(FillMode)
+ */
+public static final native int Graphics_FillPolygon(long graphics, long brush, int[] points, int count, int fillMode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param brush cast=(Brush *)
+ * @param x cast=(INT)
+ * @param y cast=(INT)
+ * @param width cast=(INT)
+ * @param height cast=(INT)
+ */
+public static final native int Graphics_FillRectangle(long graphics, long brush, int x, int y, int width, int height);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_GetClipBounds(long graphics, RectF rect);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_GetClipBounds(long graphics, Rect rect);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param region cast=(Region *)
+ */
+public static final native int Graphics_GetClip(long graphics, long region);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native long Graphics_GetHDC(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param hdc cast=(HDC)
+ */
+public static final native void Graphics_ReleaseHDC(long graphics, long hdc);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_GetInterpolationMode(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_GetSmoothingMode(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_GetTextRenderingHint(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int Graphics_GetTransform(long graphics, long matrix);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_GetVisibleClipBounds(long graphics, Rect rect);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param text cast=(const UINT16 *)
+ * @param font cast=(Font *)
+ * @param positions cast=(const PointF *),flags=no_out
+ * @param matrix cast=(const Matrix *)
+ */
+public static final native int Graphics_MeasureDriverString(long graphics, long text, int length, long font, float[] positions, int flags, long matrix, RectF boundingBox);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param string cast=(const WCHAR *)
+ * @param length cast=(INT)
+ * @param font cast=(const Font *)
+ * @param origin cast=(const PointF *),flags=struct
+ * @param boundingBox cast=(RectF *)
+ */
+public static final native int Graphics_MeasureString(long graphics, char[] string, int length, long font, PointF origin, RectF boundingBox);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param string cast=(const WCHAR *)
+ * @param length cast=(INT)
+ * @param font cast=(const Font *)
+ * @param origin cast=(const PointF *),flags=struct
+ * @param format cast=(StringFormat *)
+ */
+public static final native int Graphics_MeasureString(long graphics, char[] string, int length, long font, PointF origin, long format, RectF boundingBox);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_ResetClip(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param gstate cast=(GraphicsState)
+ */
+public static final native int Graphics_Restore(long graphics, int gstate);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ */
+public static final native int Graphics_Save(long graphics);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Graphics_ScaleTransform(long graphics, float sx, float sy, int order);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param hrgn cast=(Region *)
+ * @param combineMode cast=(CombineMode)
+ */
+public static final native int Graphics_SetClip(long graphics, long hrgn, int combineMode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param rect cast=(Rect *),flags=struct
+ * @param combineMode cast=(CombineMode)
+ */
+public static final native int Graphics_SetClip(long graphics, Rect rect, int combineMode);
+/**
+ * @method accessor=SetClip,flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int Graphics_SetClipPath(long graphics, long path);
+/**
+ * @method accessor=SetClip,flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param path cast=(GraphicsPath *)
+ * @param combineMode cast=(CombineMode)
+ */
+public static final native int Graphics_SetClipPath(long graphics, long path, int combineMode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param compositingQuality cast=(CompositingQuality)
+ */
+public static final native int Graphics_SetCompositingQuality(long graphics, int compositingQuality);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param unit cast=(Unit)
+ */
+public static final native int Graphics_SetPageUnit(long graphics, int unit);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param pixelOffsetMode cast=(PixelOffsetMode)
+ */
+public static final native int Graphics_SetPixelOffsetMode(long graphics, int pixelOffsetMode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param smoothingMode cast=(SmoothingMode)
+ */
+public static final native int Graphics_SetSmoothingMode(long graphics, int smoothingMode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int Graphics_SetTransform(long graphics, long matrix);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param mode cast=(InterpolationMode)
+ */
+public static final native int Graphics_SetInterpolationMode(long graphics, int mode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param mode cast=(TextRenderingHint)
+ */
+public static final native int Graphics_SetTextRenderingHint(long graphics, int mode);
+/**
+ * @method flags=cpp
+ * @param graphics cast=(Graphics *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Graphics_TranslateTransform(long graphics, float dx, float dy, int order);
+/**
+ * @method flags=new
+ * @param fillMode cast=(FillMode)
+ */
+public static final native long GraphicsPath_new(int fillMode);
+/**
+ * @method flags=new
+ * @param points cast=(const Point *),flags=no_out
+ * @param types cast=(const BYTE *),flags=no_out
+ * @param fillMode cast=(FillMode)
+ */
+public static final native long GraphicsPath_new(int[] points, byte[] types, int count, int fillMode);
+/** @method flags=delete */
+public static final native void GraphicsPath_delete(long path);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param x cast=(REAL)
+ * @param y cast=(REAL)
+ * @param width cast=(REAL)
+ * @param height cast=(REAL)
+ * @param startAngle cast=(REAL)
+ * @param sweepAngle cast=(REAL)
+ */
+public static final native int GraphicsPath_AddArc(long path, float x, float y, float width, float height, float startAngle, float sweepAngle);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param x1 cast=(REAL)
+ * @param y1 cast=(REAL)
+ * @param x2 cast=(REAL)
+ * @param y2 cast=(REAL)
+ * @param x3 cast=(REAL)
+ * @param y3 cast=(REAL)
+ * @param x4 cast=(REAL)
+ * @param y4 cast=(REAL)
+ */
+public static final native int GraphicsPath_AddBezier(long path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param x1 cast=(REAL)
+ * @param y1 cast=(REAL)
+ * @param x2 cast=(REAL)
+ * @param y2 cast=(REAL)
+ */
+public static final native int GraphicsPath_AddLine(long path, float x1, float y1, float x2, float y2);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param addingPath cast=(GraphicsPath *)
+ * @param connect cast=(BOOL)
+ */
+public static final native int GraphicsPath_AddPath(long path, long addingPath, boolean connect);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param rect flags=struct
+ */
+public static final native int GraphicsPath_AddRectangle(long path, RectF rect);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param string cast=(const WCHAR *)
+ * @param length cast=(INT)
+ * @param family cast=(const FontFamily *)
+ * @param style cast=(INT)
+ * @param emSize cast=(REAL)
+ * @param origin cast=(const PointF *),flags=struct
+ * @param format cast=(const StringFormat *)
+ */
+public static final native int GraphicsPath_AddString(long path, char[] string, int length, long family, int style, float emSize, PointF origin, long format);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int GraphicsPath_CloseFigure(long path);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native long GraphicsPath_Clone(long path);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int GraphicsPath_Flatten(long path, long matrix, float flatness);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param matrix cast=(Matrix *)
+ * @param pen cast=(Pen *)
+ */
+public static final native int GraphicsPath_GetBounds(long path, RectF bounds, long matrix, long pen);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param lastPoint cast=(PointF *)
+ */
+public static final native int GraphicsPath_GetLastPoint(long path, PointF lastPoint);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param points cast=(PointF *)
+ */
+public static final native int GraphicsPath_GetPathPoints(long path, float[] points, int count);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param types cast=(BYTE *)
+ */
+public static final native int GraphicsPath_GetPathTypes(long path, byte[] types, int count);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int GraphicsPath_GetPointCount(long path);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param pen cast=(const Pen *)
+ * @param g cast=(const Graphics *)
+ */
+public static final native boolean GraphicsPath_IsOutlineVisible(long path, float x, float y, long pen, long g);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param g cast=(const Graphics *)
+ */
+public static final native boolean GraphicsPath_IsVisible(long path, float x, float y, long g);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param fillmode cast=(FillMode)
+ */
+public static final native int GraphicsPath_SetFillMode(long path, int fillmode);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int GraphicsPath_StartFigure(long path);
+/**
+ * @method flags=cpp
+ * @param path cast=(GraphicsPath *)
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int GraphicsPath_Transform(long path, long matrix);
+/**
+ * @method flags=new
+ * @param hatchStyle cast=(HatchStyle)
+ * @param foreColor cast=(Color)
+ * @param backColor cast=(Color)
+ */
+public static final native long HatchBrush_new(int hatchStyle, int foreColor, int backColor);
+/**
+ * @method flags=cpp
+ * @param image cast=(Image*)
+ */
+public static final native int Image_GetLastStatus(long image);
+/**
+ * @method flags=cpp
+ * @param image cast=(Image*)
+ */
+public static final native int Image_GetPixelFormat(long image);
+/**
+ * @method flags=cpp
+ * @param image cast=(Image *)
+ */
+public static final native int Image_GetWidth(long image);
+/**
+ * @method flags=cpp
+ * @param image cast=(Image *)
+ */
+public static final native int Image_GetHeight(long image);
+/**
+ * @method flags=cpp
+ * @param image cast=(Image*)
+ * @param palette cast=(ColorPalette*)
+ */
+public static final native int Image_GetPalette(long image, long palette, int size);
+/**
+ * @method flags=cpp
+ * @param image cast=(Image*)
+ */
+public static final native int Image_GetPaletteSize(long image);
+/** @method flags=new */
+public static final native long ImageAttributes_new();
+/** @method flags=delete */
+public static final native void ImageAttributes_delete(long attrib);
+/**
+ * @method flags=cpp
+ * @param attrib cast=(ImageAttributes *)
+ * @param wrap cast=(WrapMode)
+ */
+public static final native int ImageAttributes_SetWrapMode(long attrib, int wrap);
+/**
+ * @method flags=cpp
+ * @param attrib cast=(ImageAttributes *)
+ * @param matrix cast=(ColorMatrix *)
+ * @param mode cast=(ColorMatrixFlags)
+ * @param type cast=(ColorAdjustType)
+ */
+public static final native int ImageAttributes_SetColorMatrix(long attrib, float[] matrix, int mode, int type);
+/** @method flags=delete */
+public static final native void HatchBrush_delete(long brush);
+/**
+ * @method flags=new
+ * @param point1 flags=struct
+ * @param point2 flags=struct
+ * @param color1 cast=(Color)
+ * @param color2 cast=(Color)
+ */
+public static final native long LinearGradientBrush_new(PointF point1, PointF point2, int color1, int color2);
+/** @method flags=delete */
+public static final native void LinearGradientBrush_delete(long brush);
+/**
+ * @method flags=cpp
+ * @param brush cast=(LinearGradientBrush *)
+ * @param presetColors cast=(const Color *),flags=no_out
+ * @param blendPositions cast=(const REAL *),flags=no_out
+ */
+public static final native int LinearGradientBrush_SetInterpolationColors(long brush, int [] presetColors, float[] blendPositions, int count);
+/**
+ * @method flags=cpp
+ * @param brush cast=(LinearGradientBrush *)
+ * @param wrapMode cast=(WrapMode)
+ */
+public static final native int LinearGradientBrush_SetWrapMode(long brush, int wrapMode);
+/**
+ * @method flags=cpp
+ * @param brush cast=(LinearGradientBrush *)
+ */
+public static final native int LinearGradientBrush_ResetTransform(long brush);
+/**
+ * @method flags=cpp
+ * @param brush cast=(LinearGradientBrush *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int LinearGradientBrush_ScaleTransform(long brush, float sx, float sy, int order);
+/**
+ * @method flags=cpp
+ * @param brush cast=(LinearGradientBrush *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int LinearGradientBrush_TranslateTransform(long brush, float dx, float dy, int order);
+/**
+ * @method flags=new
+ * @param m11 cast=(REAL)
+ * @param m12 cast=(REAL)
+ * @param m21 cast=(REAL)
+ * @param m22 cast=(REAL)
+ * @param dx cast=(REAL)
+ * @param dy cast=(REAL)
+ */
+public static final native long Matrix_new(float m11, float m12, float m21, float m22, float dx, float dy);
+/** @method flags=delete */
+public static final native void Matrix_delete(long matrix);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param m cast=(REAL *)
+ */
+public static final native int Matrix_GetElements(long matrix, float[] m);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int Matrix_Invert(long matrix);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ */
+public static final native boolean Matrix_IsIdentity(long matrix);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param matrix1 cast=(Matrix *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Matrix_Multiply(long matrix, long matrix1, int order);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param angle cast=(REAL)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Matrix_Rotate(long matrix, float angle, int order);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param scaleX cast=(REAL)
+ * @param scaleY cast=(REAL)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Matrix_Scale(long matrix, float scaleX, float scaleY, int order);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param shearX cast=(REAL)
+ * @param shearY cast=(REAL)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Matrix_Shear(long matrix, float shearX, float shearY, int order);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int Matrix_TransformPoints(long matrix, PointF pts, int count);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param pts cast=(PointF *)
+ */
+public static final native int Matrix_TransformPoints(long matrix, float[] pts, int count);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int Matrix_TransformVectors(long matrix, PointF pts, int count);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param offsetX cast=(REAL)
+ * @param offsetY cast=(REAL)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int Matrix_Translate(long matrix, float offsetX, float offsetY, int order);
+/**
+ * @method flags=cpp
+ * @param matrix cast=(Matrix *)
+ * @param m11 cast=(REAL)
+ * @param m12 cast=(REAL)
+ * @param m21 cast=(REAL)
+ * @param m22 cast=(REAL)
+ * @param dx cast=(REAL)
+ * @param dy cast=(REAL)
+ */
+public static final native int Matrix_SetElements(long matrix, float m11, float m12, float m21, float m22, float dx, float dy);
+/**
+ * @param Destination cast=(PVOID)
+ * @param SourcePtr cast=(CONST VOID*)
+ */
+public static final native void MoveMemory(ColorPalette Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param SourcePtr cast=(CONST VOID*)
+ */
+public static final native void MoveMemory(BitmapData Destination, long SourcePtr);
+/**
+ * @method flags=new
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native long PathGradientBrush_new(long path);
+/** @method flags=delete */
+public static final native void PathGradientBrush_delete(long brush);
+/**
+ * @method flags=cpp
+ * @param brush cast=(PathGradientBrush *)
+ * @param color cast=(Color)
+ */
+public static final native int PathGradientBrush_SetCenterColor(long brush, int color);
+/**
+ * @method flags=cpp
+ * @param brush cast=(PathGradientBrush *)
+ * @param pt flags=struct
+ */
+public static final native int PathGradientBrush_SetCenterPoint(long brush, PointF pt);
+/**
+ * @method flags=cpp
+ * @param brush cast=(PathGradientBrush *)
+ * @param presetColors cast=(const Color *),flags=no_out
+ * @param blendPositions cast=(const REAL *),flags=no_out
+ */
+public static final native int PathGradientBrush_SetInterpolationColors(long brush, int [] presetColors, float[] blendPositions, int count);
+/**
+ * @method flags=cpp
+ * @param brush cast=(PathGradientBrush *)
+ * @param colors cast=(const Color *),flags=no_out
+ * @param count cast=(INT *)
+ */
+public static final native int PathGradientBrush_SetSurroundColors(long brush, int [] colors, int[] count);
+/**
+ * @method flags=cpp
+ * @param brush cast=(PathGradientBrush *)
+ * @param path cast=(GraphicsPath *)
+ */
+public static final native int PathGradientBrush_SetGraphicsPath(long brush, long path);
+/**
+ * @method flags=cpp
+ * @param brush cast=(PathGradientBrush *)
+ * @param wrapMode cast=(WrapMode)
+ */
+public static final native int PathGradientBrush_SetWrapMode(long brush, int wrapMode);
+/**
+ * @method flags=new
+ * @param brush cast=(Brush *)
+ * @param width cast=(REAL)
+ */
+public static final native long Pen_new(long brush, float width);
+/** @method flags=delete */
+public static final native void Pen_delete(long pen);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ */
+public static final native long Pen_GetBrush(long pen);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ * @param brush cast=(Brush *)
+ */
+public static final native int Pen_SetBrush(long pen, long brush);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ */
+public static final native int Pen_SetDashOffset(long pen, float dashOffset);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ * @param dashArray cast=(REAL *)
+ * @param count cast=(int)
+ */
+public static final native int Pen_SetDashPattern(long pen, float[] dashArray, int count);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ * @param dashStyle cast=(DashStyle)
+ */
+public static final native int Pen_SetDashStyle(long pen, int dashStyle);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ * @param startCap cast=(LineCap)
+ * @param endCap cast=(LineCap)
+ * @param dashCap cast=(DashCap)
+ */
+public static final native int Pen_SetLineCap(long pen, int startCap, int endCap, int dashCap);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ * @param lineJoin cast=(LineJoin)
+ */
+public static final native int Pen_SetLineJoin(long pen, int lineJoin);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ */
+public static final native int Pen_SetMiterLimit(long pen, float miterLimit);
+/**
+ * @method flags=cpp
+ * @param pen cast=(Pen *)
+ * @param width cast=(REAL)
+ */
+public static final native int Pen_SetWidth(long pen, float width);
+/** @method flags=new */
+public static final native long Point_new(int x, int y);
+/** @method flags=delete */
+public static final native void Point_delete(long point);
+/**
+ * @method flags=new
+ * @param hRgn cast=(HRGN)
+ */
+public static final native long Region_new(long hRgn);
+/**
+ * @method flags=new
+ * @param path cast=(GraphicsPath*)
+ */
+public static final native long Region_newGraphicsPath(long path);
+/** @method flags=new */
+public static final native long Region_new();
+/** @method flags=delete */
+public static final native void Region_delete(long region);
+/**
+ * @method flags=cpp
+ * @param region cast=(Region *)
+ * @param graphics cast=(Graphics *)
+ */
+public static final native long Region_GetHRGN(long region, long graphics);
+/**
+ * @method flags=cpp
+ * @param region cast=(Region *)
+ * @param graphics cast=(Graphics *)
+ */
+public static final native boolean Region_IsInfinite(long region, long graphics);
+/**
+ * @method flags=new
+ * @param color cast=(Color)
+ */
+public static final native long SolidBrush_new(int color);
+/** @method flags=delete */
+public static final native void SolidBrush_delete(long brush);
+/** @method flags=delete */
+public static final native void StringFormat_delete(long format);
+/**
+ * @method flags=cpp
+ * @param format cast=(StringFormat *)
+ */
+public static final native long StringFormat_Clone(long format);
+/** @method accessor=StringFormat::GenericDefault */
+public static final native long StringFormat_GenericDefault();
+/** @method accessor=StringFormat::GenericTypographic */
+public static final native long StringFormat_GenericTypographic();
+/**
+ * @method flags=cpp
+ * @param format cast=(StringFormat *)
+ */
+public static final native int StringFormat_GetFormatFlags(long format);
+/**
+ * @method flags=cpp
+ * @param format cast=(StringFormat *)
+ * @param hotkeyPrefix cast=(HotkeyPrefix)
+ */
+public static final native int StringFormat_SetHotkeyPrefix(long format, int hotkeyPrefix);
+/**
+ * @method flags=cpp
+ * @param format cast=(StringFormat *)
+ * @param flags cast=(StringFormatFlags)
+ */
+public static final native int StringFormat_SetFormatFlags(long format, int flags);
+/**
+ * @method flags=cpp
+ * @param format cast=(StringFormat *)
+ */
+public static final native int StringFormat_SetTabStops(long format, float firstTabOffset, int count, float[] tabStops);
+/**
+ * @method flags=new
+ * @param image cast=(Image *)
+ * @param wrapMode cast=(WrapMode)
+ */
+public static final native long TextureBrush_new(long image, int wrapMode, float dstX, float dstY, float dstWidth, float dstHeight);
+/** @method flags=delete */
+public static final native void TextureBrush_delete(long brush);
+/**
+ * @method flags=cpp
+ * @param brush cast=(TextureBrush *)
+ * @param matrix cast=(Matrix *)
+ */
+public static final native int TextureBrush_SetTransform(long brush, long matrix);
+/**
+ * @method flags=cpp
+ * @param brush cast=(TextureBrush *)
+ */
+public static final native int TextureBrush_ResetTransform(long brush);
+/**
+ * @method flags=cpp
+ * @param brush cast=(TextureBrush *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int TextureBrush_ScaleTransform(long brush, float sx, float sy, int order);
+/**
+ * @method flags=cpp
+ * @param brush cast=(TextureBrush *)
+ * @param order cast=(MatrixOrder)
+ */
+public static final native int TextureBrush_TranslateTransform(long brush, float dx, float dy, int order);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/GdiplusStartupInput.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/GdiplusStartupInput.java
new file mode 100644 (file)
index 0000000..e9c782a
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+/** @jniclass flags=cpp */
+public class GdiplusStartupInput {
+       public int GdiplusVersion;
+       /** @field cast=(DebugEventProc) */
+       public long DebugEventCallback;
+       /** @field cast=(BOOL) */
+       public boolean SuppressBackgroundThread;
+       /** @field cast=(BOOL) */
+       public boolean SuppressExternalCodecs;
+       public static final int sizeof = Gdip.GdiplusStartupInput_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/PointF.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/PointF.java
new file mode 100644 (file)
index 0000000..d08b0a6
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+public class PointF {
+       /** @field cast=(REAL) */
+       public float X;
+       /** @field cast=(REAL) */
+       public float Y;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/Rect.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/Rect.java
new file mode 100644 (file)
index 0000000..10fd7ae
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+public class Rect {
+       public int X;
+       public int Y;
+       public int Width;
+       public int Height;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/RectF.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/gdip/RectF.java
new file mode 100644 (file)
index 0000000..c2dcf0d
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.gdip;
+
+public class RectF {
+       public float X;
+       public float Y;
+       public float Width;
+       public float Height;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/FileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/FileFormat.java
new file mode 100644 (file)
index 0000000..4ac32ac
--- /dev/null
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Abstract factory class for loading/unloading images from files or streams
+ * in various image file formats.
+ *
+ */
+public abstract class FileFormat {
+       static final String FORMAT_PACKAGE = "org.eclipse.swt.internal.image"; //$NON-NLS-1$
+       static final String FORMAT_SUFFIX = "FileFormat"; //$NON-NLS-1$
+       static final 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$
+
+       LEDataInputStream inputStream;
+       LEDataOutputStream outputStream;
+       ImageLoader loader;
+       int compression;
+
+static FileFormat getFileFormat (LEDataInputStream stream, String format) throws Exception {
+       Class<?> clazz = Class.forName(FORMAT_PACKAGE + '.' + format + FORMAT_SUFFIX);
+       FileFormat fileFormat = (FileFormat) clazz.getDeclaredConstructor().newInstance();
+       if (fileFormat.isFileFormat(stream)) return fileFormat;
+       return null;
+}
+
+/**
+ * Return whether or not the specified input stream
+ * represents a supported file format.
+ */
+abstract boolean 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 (Exception e) {
+               if (e instanceof IOException) {
+                       SWT.error(SWT.ERROR_IO, e);
+               } else {
+                       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 is, ImageLoader loader) {
+       FileFormat fileFormat = null;
+       LEDataInputStream stream = new LEDataInputStream(is);
+       for (int i = 1; i < FORMATS.length; i++) {
+               if (FORMATS[i] != null) {
+                       try {
+                               fileFormat = getFileFormat (stream, FORMATS[i]);
+                               if (fileFormat != null) break;
+                       } catch (ClassNotFoundException e) {
+                               FORMATS[i] = null;
+                       } catch (Exception e) {
+                       }
+               }
+       }
+       if (fileFormat == null) 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] == null) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+       if (loader.data == null || loader.data.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+       LEDataOutputStream stream = new LEDataOutputStream(os);
+       FileFormat fileFormat = null;
+       try {
+               Class<?> clazz = Class.forName(FORMAT_PACKAGE + '.' + FORMATS[format] + FORMAT_SUFFIX);
+               fileFormat = (FileFormat) clazz.getDeclaredConstructor().newInstance();
+       } catch (Exception e) {
+               SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+       }
+       if (format == SWT.IMAGE_BMP_RLE) {
+               switch (loader.data[0].depth) {
+                       case 8: fileFormat.compression = 1; break;
+                       case 4: fileFormat.compression = 2; break;
+               }
+       }
+       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);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/GIFFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/GIFFileFormat.java
new file mode 100644 (file)
index 0000000..09050a3
--- /dev/null
@@ -0,0 +1,593 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+public final class GIFFileFormat extends 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 = new byte[] { (byte)'G', (byte)'I', (byte)'F', (byte)'8', (byte)'9', (byte)'a' };
+       static final byte [] NETSCAPE2_0 = new byte[] { (byte)'N', (byte)'E', (byte)'T', (byte)'S', (byte)'C', (byte)'A', (byte)'P', (byte)'E', (byte)'2', (byte)'.', (byte)'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 = (byte)((i * 3) * 256 / n);
+                       colors[i] = new RGB(intensity, intensity, intensity);
+               }
+               return new PaletteData(colors);
+       }
+
+       @Override
+       boolean isFileFormat(LEDataInputStream stream) {
+               try {
+                       byte[] signature = new byte[3];
+                       stream.read(signature);
+                       stream.unread(signature);
+                       return signature[0] == 'G' && signature[1] == 'I' && signature[2] == '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[] signature = new byte[3];
+               byte[] versionBytes = new byte[3];
+               byte[] block = new byte[7];
+               try {
+                       inputStream.read(signature);
+                       if (!(signature[0] == 'G' && signature[1] == 'I' && signature[2] == '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) != 0) {
+                       // Global palette.
+                       //sorted = (bitField & 0x8) != 0;
+                       palette = readPalette(1 << defaultDepth);
+               } else {
+                       // No global palette.
+                       //sorted = false;
+                       backgroundPixel = -1;
+                       defaultDepth = bitsPerPixel;
+               }
+               loader.backgroundPixel = backgroundPixel;
+
+               ImageData[] images = new ImageData[0];
+               int id = readID();
+               while (id != GIF_TRAILER_ID && id != -1) {
+                       if (id == 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;
+                       } else if (id == GIF_EXTENSION_BLOCK_ID) {
+                               /* Read the extension block. Currently, only the
+                                * interesting parts of certain extensions are kept,
+                                * and the rest is discarded. In future, if we want
+                                * to keep extensions, they should be grouped with
+                                * the image data before which they appear.
+                                */
+                               readExtension();
+                       } else {
+                               /* The GIF is not to spec, but try to salvage it
+                                * if we read at least one image. */
+                               if (images.length > 0) break;
+                               SWT.error(SWT.ERROR_INVALID_IMAGE);
+                       }
+                       id = readID(); // block terminator (0)
+                       if (id == 0) id = readID(); // next block ID (unless we just read it)
+               }
+               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 a control extension.
+        * Return the extension block data.
+        */
+       byte[] readExtension() {
+               int extensionID = readID();
+               if (extensionID == GIF_COMMENT_BLOCK_ID)
+                       return readCommentExtension();
+               if (extensionID == GIF_PLAIN_TEXT_BLOCK_ID)
+                       return readPlainTextExtension();
+               if (extensionID == GIF_GRAPHICS_CONTROL_BLOCK_ID)
+                       return readGraphicsControlExtension();
+               if (extensionID == 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) != -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);
+                               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) != -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);
+                               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) != 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) != 0) {
+                               transparentPixel = controlBlock[3] & 0xFF;
+                       } else {
+                               transparentPixel = -1;
+                       }
+                       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 block data.
+                       int blockSize = inputStream.read();
+                       byte[] blockData = new byte[blockSize];
+                       inputStream.read(blockData);
+                       // 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) != -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);
+                               size = inputStream.read();
+                       }
+                       // Look for the NETSCAPE 'repeat count' field for an animated GIF.
+                       boolean netscape =
+                               blockSize > 7 &&
+                               blockData[0] == 'N' &&
+                               blockData[1] == 'E' &&
+                               blockData[2] == 'T' &&
+                               blockData[3] == 'S' &&
+                               blockData[4] == 'C' &&
+                               blockData[5] == 'A' &&
+                               blockData[6] == 'P' &&
+                               blockData[7] == 'E';
+                       boolean authentic =
+                               blockSize > 10 &&
+                               blockData[8] == '2' &&
+                               blockData[9] == '.' &&
+                               blockData[10] == '0';
+                       if (netscape && authentic && data[0] == 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];
+               boolean interlaced = (bitField & 0x40) != 0;
+               //boolean sorted = (bitField & 0x20) != 0;
+               if ((bitField & 0x80) != 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 == 1 || depth == 4 || depth == 8)) {
+                       if (depth < 4)
+                               depth = 4;
+                       else
+                               depth = 8;
+               }
+               if (palette == 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) != 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;
+               boolean 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 == 1 || depth == 4 || depth == 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 == depth)) {
+                                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+                               }
+                               if (globalTable == 1) {
+                                       RGB rgbs[] = data[i].palette.getRGBs();
+                                       if (rgbs.length != colors.length) {
+                                               globalTable = 0;
+                                       } else {
+                                               for (int j=0; j<colors.length; j++) {
+                                                       if (!(rgbs[j].red == colors[j].red &&
+                                                               rgbs[j].green == colors[j].green &&
+                                                               rgbs[j].blue == 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((short)logicalScreenWidth);
+                       outputStream.writeShort((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 == 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((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 != -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] = (byte)(x & 0xFF);
+                               block[1] = (byte)((x >> 8) & 0xFF);
+                               block[2] = (byte)(y & 0xFF);
+                               block[3] = (byte)((y >> 8) & 0xFF);
+                               block[4] = (byte)(width & 0xFF);
+                               block[5] = (byte)((width >> 8) & 0xFF);
+                               block[6] = (byte)(height & 0xFF);
+                               block[7] = (byte)((height >> 8) & 0xFF);
+                               block[8] = (byte)(globalTable == 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 == 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 != -1) {
+                               gcBlock[0] = (byte)0x01;
+                               gcBlock[3] = (byte)image.transparentPixel;
+                       }
+                       if (image.disposalMethod != 0) {
+                               gcBlock[0] |= (byte)((image.disposalMethod & 0x07) << 2);
+                       }
+                       if (image.delayTime != 0) {
+                               gcBlock[1] = (byte)(image.delayTime & 0xFF);
+                               gcBlock[2] = (byte)((image.delayTime >> 8) & 0xFF);
+                       }
+                       outputStream.write((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] = (byte)color.red;
+                       bytes[offset + 1] = (byte)color.green;
+                       bytes[offset + 2] = (byte)color.blue;
+                       offset += 3;
+               }
+               try {
+                       outputStream.write(bytes);
+               } catch (IOException e) {
+                       SWT.error(SWT.ERROR_IO, e);
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGAppn.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGAppn.java
new file mode 100644 (file)
index 0000000..bf43e6e
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGAppn extends JPEGVariableSizeSegment {
+
+       public JPEGAppn(byte[] reference) {
+               super(reference);
+       }
+
+       public JPEGAppn(LEDataInputStream byteStream) {
+               super(byteStream);
+       }
+
+       @Override
+       public boolean verify() {
+               int marker = getSegmentMarker();
+               return marker >= JPEGFileFormat.APP0 && marker <= JPEGFileFormat.APP15;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java
new file mode 100644 (file)
index 0000000..e6c6790
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGArithmeticConditioningTable extends JPEGVariableSizeSegment {
+
+       public JPEGArithmeticConditioningTable(LEDataInputStream byteStream) {
+               super(byteStream);
+       }
+
+       @Override
+       public int signature() {
+               return JPEGFileFormat.DAC;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGComment.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGComment.java
new file mode 100644 (file)
index 0000000..9effada
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGComment extends JPEGVariableSizeSegment {
+
+       public JPEGComment(byte[] reference) {
+               super(reference);
+       }
+
+       public JPEGComment(LEDataInputStream byteStream) {
+               super(byteStream);
+       }
+
+       @Override
+       public int signature() {
+               return JPEGFileFormat.COM;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGDecoder.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGDecoder.java
new file mode 100644 (file)
index 0000000..40d5c98
--- /dev/null
@@ -0,0 +1,6366 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * This source file is based in part on the work of the Independent JPEG Group (IJG)
+ * and is made available under the terms contained in the about_files/IJG_README
+ * file accompanying this program.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+public class JPEGDecoder {
+
+       static final int DCTSIZE = 8;
+       static final int DCTSIZE2 = 64;
+       static final int NUM_QUANT_TBLS = 4;
+       static final int NUM_HUFF_TBLS = 4;
+       static final int NUM_ARITH_TBLS = 16;
+       static final int MAX_COMPS_IN_SCAN = 4;
+       static final int MAX_COMPONENTS = 10;
+       static final int MAX_SAMP_FACTOR = 4;
+       static final int D_MAX_BLOCKS_IN_MCU = 10;
+       static final int HUFF_LOOKAHEAD = 8;
+       static final int MAX_Q_COMPS = 4;
+       static final int IFAST_SCALE_BITS = 2;
+       static final int MAXJSAMPLE = 255;
+       static final int CENTERJSAMPLE = 128;
+       static final int MIN_GET_BITS = 32-7;
+       static final int INPUT_BUFFER_SIZE = 4096;
+
+       static final int SCALEBITS = 16;        /* speediest right-shift on some machines */
+       static final int ONE_HALF = 1 << (SCALEBITS-1);
+
+       static final int RGB_RED = 2;   /* Offset of Red in an RGB scanline element */
+       static final int RGB_GREEN = 1; /* Offset of Green */
+       static final int RGB_BLUE = 0;  /* Offset of Blue */
+       static final int RGB_PIXELSIZE = 3;
+
+       static final int JBUF_PASS_THRU = 0;
+       static final int JBUF_SAVE_SOURCE = 1;  /* Run source subobject only, save output */
+       static final int JBUF_CRANK_DEST = 2;   /* Run dest subobject only, using saved data */
+       static final int JBUF_SAVE_AND_PASS = 3;
+
+       static final int JPEG_MAX_DIMENSION = 65500;
+       static final int BITS_IN_JSAMPLE = 8;
+
+       static final int JDITHER_NONE = 0;              /* no dithering */
+       static final int JDITHER_ORDERED = 1;   /* simple ordered dither */
+       static final int JDITHER_FS = 2;
+
+       static final int JDCT_ISLOW = 0;        /* slow but accurate integer algorithm */
+       static final int JDCT_IFAST = 1;        /* faster, less accurate integer method */
+       static final int JDCT_FLOAT = 2;        /* floating-point: accurate, fast on fast HW */
+       static final int JDCT_DEFAULT = JDCT_ISLOW;
+
+       static final int JCS_UNKNOWN = 0;               /* error/unspecified */
+       static final int JCS_GRAYSCALE = 1;             /* monochrome */
+       static final int JCS_RGB = 2;           /* red/green/blue */
+       static final int JCS_YCbCr = 3;         /* Y/Cb/Cr (also known as YUV) */
+       static final int JCS_CMYK = 4;          /* C/M/Y/K */
+       static final int JCS_YCCK = 5;          /* Y/Cb/Cr/K */
+
+       static final int SAVED_COEFS = 6;
+       static final int Q01_POS = 1;
+       static final int Q10_POS = 8;
+       static final int Q20_POS = 16;
+       static final int Q11_POS = 9;
+       static final int Q02_POS = 2;
+
+       static final int CTX_PREPARE_FOR_IMCU = 0;      /* need to prepare for MCU row */
+       static final int CTX_PROCESS_IMCU = 1;  /* feeding iMCU to postprocessor */
+       static final int CTX_POSTPONED_ROW = 2; /* feeding postponed row group */
+
+       static final int APP0_DATA_LEN = 14;    /* Length of interesting data in APP0 */
+       static final int APP14_DATA_LEN = 12;   /* Length of interesting data in APP14 */
+       static final int APPN_DATA_LEN = 14;    /* Must be the largest of the above!! */
+
+       /* markers */
+       static final int M_SOF0 = 0xc0;
+       static final int M_SOF1 = 0xc1;
+       static final int M_SOF2 = 0xc2;
+       static final int M_SOF3 = 0xc3;
+       static final int M_SOF5 = 0xc5;
+       static final int M_SOF6 = 0xc6;
+       static final int M_SOF7 = 0xc7;
+       static final int M_JPG = 0xc8;
+       static final int M_SOF9 = 0xc9;
+       static final int M_SOF10 = 0xca;
+       static final int M_SOF11 = 0xcb;
+       static final int M_SOF13 = 0xcd;
+       static final int M_SOF14 = 0xce;
+       static final int M_SOF15 = 0xcf;
+       static final int M_DHT = 0xc4;
+       static final int M_DAC = 0xcc;
+       static final int M_RST0 = 0xd0;
+       static final int M_RST1 = 0xd1;
+       static final int M_RST2 = 0xd2;
+       static final int M_RST3 = 0xd3;
+       static final int M_RST4 = 0xd4;
+       static final int M_RST5 = 0xd5;
+       static final int M_RST6 = 0xd6;
+       static final int M_RST7 = 0xd7;
+       static final int M_SOI = 0xd8;
+       static final int M_EOI = 0xd9;
+       static final int M_SOS = 0xda;
+       static final int M_DQT = 0xdb;
+       static final int M_DNL = 0xdc;
+       static final int M_DRI = 0xdd;
+       static final int M_DHP = 0xde;
+       static final int M_EXP = 0xdf;
+       static final int M_APP0 = 0xe0;
+       static final int M_APP1 = 0xe1;
+       static final int M_APP2 = 0xe2;
+       static final int M_APP3 = 0xe3;
+       static final int M_APP4 = 0xe4;
+       static final int M_APP5 = 0xe5;
+       static final int M_APP6 = 0xe6;
+       static final int M_APP7 = 0xe7;
+       static final int M_APP8 = 0xe8;
+       static final int M_APP9 = 0xe9;
+       static final int M_APP10 = 0xea;
+       static final int M_APP11 = 0xeb;
+       static final int M_APP12 = 0xec;
+       static final int M_APP13 = 0xed;
+       static final int M_APP14 = 0xee;
+       static final int M_APP15 = 0xef;
+       static final int M_JPG0 = 0xf0;
+       static final int M_JPG13 = 0xfd;
+       static final int M_COM = 0xfe;
+       static final int M_TEM = 0x01;
+       static final int M_ERROR = 0x100;
+
+       /* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+       static final int CSTATE_START = 100;    /* after create_compress */
+       static final int CSTATE_SCANNING = 101; /* start_compress done, write_scanlines OK */
+       static final int CSTATE_RAW_OK = 102;   /* start_compress done, write_raw_data OK */
+       static final int CSTATE_WRCOEFS = 103;  /* jpeg_write_coefficients done */
+       static final int DSTATE_START = 200;    /* after create_decompress */
+       static final int DSTATE_INHEADER = 201; /* reading header markers, no SOS yet */
+       static final int DSTATE_READY = 202;    /* found SOS, ready for start_decompress */
+       static final int DSTATE_PRELOAD = 203;  /* reading multiscan file in start_decompress*/
+       static final int DSTATE_PRESCAN = 204;  /* performing dummy pass for 2-pass quant */
+       static final int DSTATE_SCANNING = 205; /* start_decompress done, read_scanlines OK */
+       static final int DSTATE_RAW_OK = 206;   /* start_decompress done, read_raw_data OK */
+       static final int DSTATE_BUFIMAGE = 207; /* expecting jpeg_start_output */
+       static final int DSTATE_BUFPOST = 208;  /* looking for SOS/EOI in jpeg_finish_output */
+       static final int DSTATE_RDCOEFS = 209;  /* reading file in jpeg_read_coefficients */
+       static final int DSTATE_STOPPING = 210; /* looking for EOI in jpeg_finish_decompress */
+
+       static final int JPEG_REACHED_SOS = 1; /* Reached start of new scan */
+       static final int JPEG_REACHED_EOI = 2; /* Reached end of image */
+       static final int JPEG_ROW_COMPLETED = 3; /* Completed one iMCU row */
+       static final int JPEG_SCAN_COMPLETED = 4; /* Completed last iMCU row of a scan */
+
+       static final int JPEG_SUSPENDED = 0; /* Suspended due to lack of input data */
+       static final int JPEG_HEADER_OK = 1; /* Found valid image datastream */
+       static final int JPEG_HEADER_TABLES_ONLY = 2; /* Found valid table-specs-only datastream */
+
+       /* Function pointers */
+       static final int DECOMPRESS_DATA = 0;
+       static final int DECOMPRESS_SMOOTH_DATA = 1;
+       static final int DECOMPRESS_ONEPASS = 2;
+
+       static final int CONSUME_DATA = 0;
+       static final int DUMMY_CONSUME_DATA = 1;
+
+       static final int PROCESS_DATA_SIMPLE_MAIN = 0;
+       static final int PROCESS_DATA_CONTEXT_MAIN = 1;
+       static final int PROCESS_DATA_CRANK_POST = 2;
+
+       static final int POST_PROCESS_1PASS = 0;
+       static final int POST_PROCESS_DATA_UPSAMPLE = 1;
+
+       static final int NULL_CONVERT = 0;
+       static final int GRAYSCALE_CONVERT = 1;
+       static final int YCC_RGB_CONVERT = 2;
+       static final int GRAY_RGB_CONVERT = 3;
+       static final int YCCK_CMYK_CONVERT = 4;
+
+       static final int NOOP_UPSAMPLE = 0;
+       static final int FULLSIZE_UPSAMPLE = 1;
+       static final int H2V1_FANCY_UPSAMPLE = 2;
+       static final int H2V1_UPSAMPLE = 3;
+       static final int H2V2_FANCY_UPSAMPLE = 4;
+       static final int H2V2_UPSAMPLE = 5;
+       static final int INT_UPSAMPLE = 6;
+
+       static final int INPUT_CONSUME_INPUT = 0;
+       static final 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[] 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.)
+                */
+               boolean 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[] bits = new byte[17]; /* bits[k] = # of symbols with codes of */
+                                                                       /* length k bits; bits[0] is unused */
+               byte[] 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.)
+                */
+               boolean 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[] 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[] maxcode = new int[18];            /* largest code of length k (-1 if none) */
+               /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
+               int[] 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[] look_nbits = new int[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
+               byte[] 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[][] MCU_buffer = new short[D_MAX_BLOCKS_IN_MCU][];
+
+               /* In multi-pass modes, we need a virtual block array for each component. */
+               short[][][][] 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 boolean 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 */
+               boolean insufficient_data;      /* set true after emitting warning */
+
+               bitread_working_state br_state_local = new bitread_working_state();
+               savable_state state_local = new savable_state();
+       }
+
+       static final class huff_entropy_decoder extends 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[] dc_derived_tbls = new d_derived_tbl[NUM_HUFF_TBLS];
+               d_derived_tbl[] 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[] dc_cur_tbls = new d_derived_tbl[D_MAX_BLOCKS_IN_MCU];
+               d_derived_tbl[] 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 */
+               boolean[] dc_needed = new boolean[D_MAX_BLOCKS_IN_MCU];
+               boolean[] ac_needed = new boolean[D_MAX_BLOCKS_IN_MCU];
+
+               @Override
+               void start_pass (jpeg_decompress_struct cinfo) {
+                       start_pass_huff_decoder(cinfo);
+               }
+
+               @Override
+               boolean 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 != 0) {
+                               if (entropy.restarts_to_go == 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 != 1) {
+                                               look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                                               if ((nb = dctbl.look_nbits[look]) != 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 != 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] = (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 != 1) {
+//                                                             look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                                               look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                                                               if ((nb = actbl.look_nbits[look]) != 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 != 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]] = (short) s;
+                                                       } else {
+                                                               if (r != 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 != 1) {
+//                                                             look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                                               look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                                                               if ((nb = actbl.look_nbits[look]) != 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 != 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 != 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 != 0 || cinfo.Se != DCTSIZE2-1 || cinfo.Ah != 0 || cinfo.Al != 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;
+               }
+
+               boolean 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 == 0)
+                               entropy.insufficient_data = false;
+
+                       return true;
+               }
+       }
+
+       static final class phuff_entropy_decoder extends 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[] derived_tbls = new d_derived_tbl[NUM_HUFF_TBLS];
+
+               d_derived_tbl ac_derived_tbl; /* active table during an AC scan */
+
+               int[] newnz_pos = new int[DCTSIZE2];
+
+               @Override
+               void start_pass (jpeg_decompress_struct cinfo) {
+                       start_pass_phuff_decoder(cinfo);
+               }
+
+               @Override
+               boolean decode_mcu (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+                       boolean is_DC_band = (cinfo.Ss == 0);
+                       if (cinfo.Ah == 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);
+                       }
+               }
+
+               boolean 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 != 0) {
+                               if (entropy.restarts_to_go == 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)) != 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;
+
+               }
+
+               boolean 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 != 0) {
+                               if (entropy.restarts_to_go == 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 == 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 != 1) {
+//                                                     look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                                       look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                                                       if ((nb = tbl.look_nbits[look]) != 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 != 0) {
+                                                       if (s != 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)) != 0)
+                                                               s = p1;         /* newly nonzero coef is positive */
+                                                       else
+                                                               s = m1;         /* newly nonzero coef is negative */
+                                               } else {
+                                                       if (r != 15) {
+                                                               EOBRUN = 1 << r;        /* EOBr, run length is 2^r + appended bits */
+                                                               if (r != 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] != 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)) != 0) {
+                                                                       if ((thiscoef[thiscoef_offset] & p1) == 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 != 0) {
+                                                       int pos = jpeg_natural_order[k];
+                                                       /* Output newly nonzero coefficient */
+                                                       block[pos] = (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] != 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)) != 0) {
+                                                               if ((thiscoef[thiscoef_offset] & p1) == 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;
+
+               }
+
+               boolean 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 != 0) {
+                               if (entropy.restarts_to_go == 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 != 1) {
+//                                                     look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                                       look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+
+                                                       if ((nb = tbl.look_nbits[look]) != 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 != 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]] = (short) (s << Al);
+                                               } else {
+                                                       if (r == 15) {  /* ZRL */
+                                                               k += 15;                /* skip 15 zeroes in band */
+                                                       } else {                /* EOBr, run length is 2^r + appended bits */
+                                                               EOBRUN = 1 << r;
+                                                               if (r != 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;
+               }
+
+               boolean 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 != 0) {
+                               if (entropy.restarts_to_go == 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 != 1) {
+//                                             look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                               look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+
+                                               if ((nb = tbl.look_nbits[look]) != 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 != 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] = (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;
+               }
+
+               boolean 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 == 0)
+                               entropy.insufficient_data = false;
+
+                       return true;
+               }
+
+               void start_pass_phuff_decoder (jpeg_decompress_struct cinfo) {
+                       phuff_entropy_decoder entropy = this;
+                       boolean is_DC_band, bad;
+                       int ci, coefi, tbl;
+                       int[] coef_bit_ptr;
+                       jpeg_component_info compptr;
+
+                       is_DC_band = (cinfo.Ss == 0);
+
+                       /* Validate scan parameters */
+                       bad = false;
+                       if (is_DC_band) {
+                               if (cinfo.Se != 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 != 1)
+                                       bad = true;
+                       }
+                       if (cinfo.Ah != 0) {
+                               /* Successive approximation refinement scan: must have Al = Ah-1. */
+                               if (cinfo.Al != 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 != expected) {
+//                                             WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+                                       }
+                                       coef_bit_ptr[coefi] = cinfo.Al;
+                               }
+                       }
+
+                       /* Select MCU decoding routine */
+//                     if (cinfo.Ah == 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 == 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.
+                */
+               boolean 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, boolean 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.
+                */
+               boolean is_padded;              /* is the colorindex padded for odither? */
+
+               int[] 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 */
+               boolean on_odd_row;
+
+               void start_pass (jpeg_decompress_struct cinfo, boolean 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));
+
+               boolean 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[][][] color_buf = new byte[MAX_COMPONENTS][][];
+               int[] color_buf_offset = new int[MAX_COMPONENTS];
+
+               /* Per-component upsampling method pointers */
+               int[] 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[] 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[] h_expand = new byte[MAX_COMPONENTS];
+               byte[] 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.
+                */
+               boolean saw_SOI;                /* found SOI? */
+               boolean 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[] 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[][][] buffer = new byte[MAX_COMPONENTS][][];
+               int[] buffer_offset = new int[MAX_COMPONENTS];
+
+               boolean buffer_full;            /* Have we gotten an iMCU row from decoder? */
+               int[] 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[][][][] xbuffer = new byte[2][][][];       /* pointers to weird pointer lists */
+               int[][] 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 */
+               boolean is_dummy_pass;
+
+               int pass_number;                /* # of passes completed */
+
+               boolean 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[] 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] == method)
+                                               continue;
+                                       qtbl = compptr.quant_table;
+                                       if (qtbl == 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;
+               boolean has_multiple_scans;     /* True if file has multiple scans */
+               boolean eoi_reached;
+
+               boolean 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 == 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 == 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 == 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 */\
+               boolean 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;
+               boolean 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 */
+
+               boolean buffered_image; /* true=multiple output passes */
+               boolean raw_data_out;           /* true=downsampled data wanted */
+
+               int dct_method; /* IDCT algorithm selector */
+               boolean do_fancy_upsampling;    /* true=apply fancy upsampling */
+               boolean do_block_smoothing;     /* true=apply interblock smoothing */
+
+               boolean quantize_colors;        /* true=colormapped output wanted */
+               /* the following are ignored if not quantize_colors: */
+               int dither_mode;        /* type of color dithering to use */
+               boolean 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: */
+               boolean enable_1pass_quant;     /* enable future use of 1-pass quantizer */
+               boolean enable_external_quant;/* enable future use of external colormap */
+               boolean 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[] quant_tbl_ptrs = new JQUANT_TBL[NUM_QUANT_TBLS];
+               /* ptrs to coefficient quantization tables, or null if not defined */
+
+               JHUFF_TBL[] dc_huff_tbl_ptrs = new JHUFF_TBL[NUM_HUFF_TBLS];
+               JHUFF_TBL[] 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 */
+
+               boolean progressive_mode;       /* true if SOFn specifies progressive mode */
+               boolean arith_code;             /* true=arithmetic coding, false=Huffman */
+
+               byte[] arith_dc_L = new byte[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+               byte[] arith_dc_U = new byte[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+               byte[] 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.
+                */
+               boolean 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 */
+               boolean saw_Adobe_marker;       /* true iff an Adobe APP14 marker was found */
+               byte Adobe_transform;   /* Color transform code from Adobe marker */
+
+               boolean 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[] 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[] 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[] workspace = new int[DCTSIZE2];
+               int[] 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, boolean 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
+                                       [(int)jround_up( compptr.height_in_blocks, compptr.v_samp_factor)]
+                                       [(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. */
+               coef.MCU_buffer = new short[D_MAX_BLOCKS_IN_MCU][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 != 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 != 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 = (int)
+//                     jdiv_round_up(cinfo.image_width, 8L);
+//             cinfo.output_height = (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 = (int)
+//                     jdiv_round_up(cinfo.image_width, 4L);
+//             cinfo.output_height = (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 = (int)
+//                     jdiv_round_up(cinfo.image_width, 2L);
+//             cinfo.output_height = (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 = (int)
+//                     jdiv_round_up((long) cinfo.image_width * (long) (compptr.h_samp_factor * compptr.DCT_scaled_size),
+//                             (cinfo.max_h_samp_factor * DCTSIZE));
+//             compptr.downsampled_height = (int)
+//                     jdiv_round_up((long) cinfo.image_height * (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:
+               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 boolean 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 != JCS_YCbCr || cinfo.num_components != 3 ||
+                       cinfo.out_color_space != JCS_RGB ||
+                       cinfo.out_color_components != RGB_PIXELSIZE)
+               return false;
+       /* and it only handles 2h1v or 2h2v sampling ratios */
+       if (cinfo.comp_info[0].h_samp_factor != 2 ||
+                       cinfo.comp_info[1].h_samp_factor != 1 ||
+                       cinfo.comp_info[2].h_samp_factor != 1 ||
+                       cinfo.comp_info[0].v_samp_factor >      2 ||
+                       cinfo.comp_info[1].v_samp_factor != 1 ||
+                       cinfo.comp_info[2].v_samp_factor != 1)
+               return false;
+       /* furthermore, it doesn't work if we've scaled the IDCTs differently */
+       if (cinfo.comp_info[0].DCT_scaled_size != cinfo.min_DCT_scaled_size ||
+                       cinfo.comp_info[1].DCT_scaled_size != cinfo.min_DCT_scaled_size ||
+                       cinfo.comp_info[2].DCT_scaled_size != 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] = (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] = (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] = ((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] = ((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] = ((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] = ((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 != 1)
+                               error();
+//                             ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+                       break;
+
+               case JCS_RGB:
+               case JCS_YCbCr:
+                       if (cinfo.num_components != 3)
+                               error();
+//                             ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+                       break;
+
+               case JCS_CMYK:
+               case JCS_YCCK:
+                       if (cinfo.num_components != 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 == JCS_GRAYSCALE || cinfo.jpeg_color_space == 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 == JCS_YCbCr) {
+                               cconvert.color_convert = YCC_RGB_CONVERT;
+                               build_ycc_rgb_table(cinfo);
+                       } else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) {
+                               cconvert.color_convert = GRAY_RGB_CONVERT;
+                       } else if (cinfo.jpeg_color_space == JCS_RGB) {
+                               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 == JCS_YCCK) {
+                               cconvert.color_convert = YCCK_CMYK_CONVERT;
+                               build_ycc_rgb_table(cinfo);
+                       } else if (cinfo.jpeg_color_space == 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 == 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, boolean 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((long) cinfo.output_height,
+//                             (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, boolean 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;
+       boolean 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 == h_out_group && v_in_group == 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 == h_out_group && v_in_group == 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 == h_out_group && v_in_group * 2 == 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) == 0 && (v_out_group % v_in_group) == 0) {
+                       /* Generic integral-factors upsampling method */
+                       upsample.methods[ci] = INT_UPSAMPLE;
+                       upsample.h_expand[ci] = (byte) (h_out_group / h_in_group);
+                       upsample.v_expand[ci] = (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]
+                                                [(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] == 0 && inptr[DCTSIZE*2+inptr_offset] == 0 &&
+                       inptr[DCTSIZE*3+inptr_offset] == 0 && inptr[DCTSIZE*4+inptr_offset] == 0 &&
+                       inptr[DCTSIZE*5+inptr_offset] == 0 && inptr[DCTSIZE*6+inptr_offset] == 0 &&
+                       inptr[DCTSIZE*7+inptr_offset] == 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 == 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] == 0 && wsptr[2+wsptr_offset] == 0 && wsptr[3+wsptr_offset] == 0 && wsptr[4+wsptr_offset] == 0 &&
+                       wsptr[5+wsptr_offset] == 0 && wsptr[6+wsptr_offset] == 0 && wsptr[7+wsptr_offset] == 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 boolean smoothing_ok (jpeg_decompress_struct cinfo) {
+       jpeg_d_coef_controller coef = cinfo.coef;
+       boolean 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 == null)
+               return false;
+
+       /* Allocate latch area if not already done */
+       if (coef.coef_bits_latch == 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) == null)
+                       return false;
+               /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
+               if (qtable.quantval[0] == 0 ||
+                       qtable.quantval[Q01_POS] == 0 ||
+                       qtable.quantval[Q10_POS] == 0 ||
+                       qtable.quantval[Q20_POS] == 0 ||
+                       qtable.quantval[Q11_POS] == 0 ||
+                       qtable.quantval[Q02_POS] == 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] != 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;
+       boolean 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 = (long) cinfo.output_width * (long) cinfo.out_color_components;
+       jd_samplesperrow = (int) samplesperrow;
+       if ( jd_samplesperrow != 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 != 3) {
+//                     cinfo.enable_1pass_quant = true;
+//                     cinfo.enable_external_quant = false;
+//                     cinfo.enable_2pass_quant = false;
+//                     cinfo.colormap = null;
+//             } else if (cinfo.colormap != 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 != 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 = (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 boolean jpeg_start_decompress (jpeg_decompress_struct cinfo) {
+       if (cinfo.global_state == 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 == 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 != null)
+//                                     (*cinfo.progress.progress_monitor) ((j_common_ptr) cinfo);
+                               /* Absorb some more input */
+                               retcode = consume_input (cinfo);
+                               if (retcode == JPEG_SUSPENDED)
+                                       return false;
+                               if (retcode == JPEG_REACHED_EOI)
+                                       break;
+                               /* Advance progress counter if appropriate */
+//                             if (cinfo.progress != null && (retcode == JPEG_ROW_COMPLETED || retcode == 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 += (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 != 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 == 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 != 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 boolean 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 == (M_RST0 + ((desired+1) & 7)) || marker == ( M_RST0 + ((desired+2) & 7)))
+                               action = 3;             /* one of the next two expected restarts */
+                       else if (marker == (M_RST0 + ((desired-1) & 7)) || marker == ( 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;
+               }
+       } /* end loop */
+}
+
+static boolean 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 == 0) {
+               if (! next_marker(cinfo))
+                       return false;
+       }
+
+       if (cinfo.unread_marker == (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 boolean 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 == 0) { /* cannot advance past a marker */
+               while (bits_left < MIN_GET_BITS) {
+                       int c;
+
+                       /* Attempt to read a byte */
+                       if (bytes_offset == 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 == 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 == 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 == 0xFF);
+
+                               if (c == 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;
+       boolean first_row, last_row;
+       short[] workspace = coef.workspace;
+       if (workspace == 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 == 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 == 0) ? 1 : 0;
+                       if (cinfo.input_iMCU_row > cinfo.output_iMCU_row+delta)
+                               break;
+               }
+               if (consume_input(cinfo) == 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 == 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 == 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 == 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]) != 0 && workspace[1] == 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] = (short) pred;
+                               }
+                               /* AC10 */
+                               if ((Al=coef_bits[2+coef_offset]) != 0 && workspace[8] == 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] = (short) pred;
+                               }
+                               /* AC20 */
+                               if ((Al=coef_bits[3+coef_offset]) != 0 && workspace[16] == 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] = (short) pred;
+                               }
+                               /* AC11 */
+                               if ((Al=coef_bits[4+coef_offset]) != 0 && workspace[9] == 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] = (short) pred;
+                               }
+                               /* AC02 */
+                               if ((Al=coef_bits[5+coef_offset]) != 0 && workspace[2] == 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] = (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 == cinfo.output_scan_number &&
+               cinfo.input_iMCU_row <= cinfo.output_iMCU_row))
+       {
+               if (consume_input(cinfo) == 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 == 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 == 0) rows_left = iMCUheight;
+               /* Count nondummy row groups.   Should get same answer for each component,
+                * so we need only do it once.
+                */
+               if (ci == 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 == 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 == 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 == 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;
+       }
+}
+
+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 == 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 != 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 != NULL) {
+//             cinfo.progress.pass_counter = (long) cinfo.output_scanline;
+//             cinfo.progress.pass_limit = (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 boolean output_pass_setup (jpeg_decompress_struct cinfo) {
+       if (cinfo.global_state != 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 != NULL) {
+//     cinfo.progress.pass_counter = (long) cinfo.output_scanline;
+//     cinfo.progress.pass_limit = (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 == 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 boolean 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       length -= 2;
+
+       while (length > 16) {
+               if (cinfo.bytes_offset == 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 == 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                       huffval[i] = cinfo.buffer[cinfo.bytes_offset++];
+               }
+
+               length -= count;
+
+               if ((index & 0x10) != 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 != 0)
+               error();
+//             ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+       return true;
+}
+
+
+static boolean 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       length -= 2;
+
+       while (length > 0) {
+               if (cinfo.bytes_offset == 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] == null)
+                       cinfo.quant_tbl_ptrs[n] = new JQUANT_TBL();
+               quant_ptr = cinfo.quant_tbl_ptrs[n];
+
+               for (i = 0; i < DCTSIZE2; i++) {
+                       if (prec != 0) {
+                               if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                               tmp = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+                               if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                               tmp |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+                       } else {
+                                       if (cinfo.bytes_offset == 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]] = (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 != 0) length -= DCTSIZE2;
+       }
+
+       if (length != 0)
+               error();
+//             ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+       return true;
+}
+
+static boolean get_dri (jpeg_decompress_struct cinfo)
+/* Process a DRI marker */
+{
+       int length;
+       int tmp;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+       if (length != 4)
+       error();
+//             ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       tmp = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == 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 boolean get_dac (jpeg_decompress_struct cinfo)
+/* Process a DAC marker */
+{
+       int length;
+       int index, val;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       length -= 2;
+
+       while (length > 0) {
+               if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+               index = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+               if (cinfo.bytes_offset == 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] = (byte) val;
+               } else {                        /* define DC table */
+                       cinfo.arith_dc_L[index] = (byte) (val & 0x0F);
+                       cinfo.arith_dc_U[index] = (byte) (val >> 4);
+                       if (cinfo.arith_dc_L[index] > cinfo.arith_dc_U[index])
+                               error();
+//     ERREXIT1(cinfo, JERR_DAC_VALUE, val);
+               }
+       }
+
+       if (length != 0)
+               error();
+//             ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+       return true;
+}
+
+
+static boolean 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       n = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+//     TRACEMS1(cinfo, 1, JTRC_SOS, n);
+
+       if (length != (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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+               cc = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+               if (cinfo.bytes_offset == 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 == compptr.component_id)
+                               break;
+               }
+
+               if (ci == 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       cinfo.Ss = c;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       cinfo.Se = c;
+       if (cinfo.bytes_offset == 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 boolean get_sof (jpeg_decompress_struct cinfo, boolean is_prog, boolean is_arith) {
+       int length;
+       int c, ci;
+
+       cinfo.progressive_mode = is_prog;
+       cinfo.arith_code = is_arith;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       cinfo.data_precision = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       cinfo.image_height = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       cinfo.image_height |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       cinfo.image_width = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       cinfo.image_width |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+       if (cinfo.bytes_offset == 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,
+//              (int) cinfo.image_width, (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 != (cinfo.num_components * 3))
+               error();
+//             ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+       if (cinfo.comp_info == 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+               compptr.component_id = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+               if (cinfo.bytes_offset == 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 == 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;
+                       }
+               }
+               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;
+       }
+
+       /* 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++] = (byte) invalue;
+               outptr[outptr_offset++] = (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++] = (byte) ((invalue + (inptr[inptr_offset-2] & 0xFF) + 1) >> 2);
+                       outptr[outptr_offset++] = (byte) ((invalue + (inptr[inptr_offset] & 0xFF) + 2) >> 2);
+               }
+
+               /* Special case for last column */
+               invalue = (inptr[inptr_offset] & 0xFF);
+               outptr[outptr_offset++] = (byte) ((invalue * 3 + (inptr[inptr_offset-1] & 0xFF) + 1) >> 2);
+               outptr[outptr_offset++] = (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 == 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++] = (byte) ((thiscolsum * 4 + 8) >> 4);
+                       outptr[outptr_offset++] = (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++] = (byte) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+                               outptr[outptr_offset++] = (byte) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+                               lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+                       }
+
+                       /* Special case for last column */
+                       outptr[outptr_offset++] = (byte) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+                       outptr[outptr_offset++] = (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;
+                       }
+                       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 boolean process_APPn(int n, jpeg_decompress_struct cinfo) {
+       if (n == 0 || n == 14) {
+               return get_interesting_appn(cinfo);
+       }
+       return skip_variable(cinfo);
+}
+
+static boolean 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 boolean skip_variable (jpeg_decompress_struct cinfo)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+       int length;
+
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == 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, (int) length);
+
+       if (length > 0) {
+               skip_input_data (cinfo, length);
+       }
+
+       return true;
+}
+
+static boolean 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+       if (cinfo.bytes_offset == 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 == 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) == 0x4A &&
+                       (data[1] & 0xFF) == 0x46 &&
+                       (data[2] & 0xFF) == 0x49 &&
+                       (data[3] & 0xFF) == 0x46 &&
+                       (data[4] & 0xFF) == 0)
+       {
+               /* Found JFIF APP0 marker: save info */
+               cinfo.saw_JFIF_marker = true;
+               cinfo.JFIF_major_version = (data[5]);
+               cinfo.JFIF_minor_version = (byte)(data[6] & 0xFF);
+               cinfo.density_unit = (byte)(data[7] & 0xFF);
+               cinfo.X_density = (short)(((data[8] & 0xFF) << 8) + (data[9] & 0xFF));
+               cinfo.Y_density = (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 != 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) != 0) {
+//                     TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
+//                              GETJOCTET(data[12]), GETJOCTET(data[13]));
+               }
+               totallen -= APP0_DATA_LEN;
+               if (totallen != ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) {
+//                     TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+               }
+       } else if (datalen >= 6 &&
+                       (data[0] & 0xFF) == 0x4A &&
+                       (data[1] & 0xFF) == 0x46 &&
+                       (data[2] & 0xFF) == 0x58 &&
+                       (data[3] & 0xFF) == 0x58 &&
+                       (data[4] & 0xFF) == 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, (int) totallen);
+                               break;
+                       case 0x11:
+//                             TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+                               break;
+                       case 0x13:
+//                             TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+                               break;
+                       default:
+//                             TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, GETJOCTET(data[5]), (int) totallen);
+                       break;
+               }
+       } else {
+               /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
+//             TRACEMS1(cinfo, 1, JTRC_APP0, (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) == 0x41 &&
+                       (data[1] & 0xFF) == 0x64 &&
+                       (data[2] & 0xFF) == 0x6F &&
+                       (data[3] & 0xFF) == 0x62 &&
+                       (data[4] & 0xFF) == 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 = (byte) transform;
+       } else {
+               /* Start of APP14 does not match "Adobe", or too short */
+//             TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+       }
+}
+
+static boolean 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 != 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 boolean 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 boolean jpeg_start_output (jpeg_decompress_struct cinfo, int scan_number) {
+       if (cinfo.global_state != DSTATE_BUFIMAGE && cinfo.global_state != 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 boolean jpeg_finish_output (jpeg_decompress_struct cinfo) {
+       if ((cinfo.global_state == DSTATE_SCANNING || cinfo.global_state == 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 != 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) == JPEG_SUSPENDED)
+                       return false;           /* Suspend, come back later */
+       }
+       cinfo.global_state = DSTATE_BUFIMAGE;
+       return true;
+}
+
+static boolean jpeg_finish_decompress (jpeg_decompress_struct cinfo) {
+       if ((cinfo.global_state == DSTATE_SCANNING || cinfo.global_state == 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 == DSTATE_BUFIMAGE) {
+               /* Finishing after a buffered-image operation */
+               cinfo.global_state = DSTATE_STOPPING;
+       } else if (cinfo.global_state != 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) == 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, boolean require_image) {
+       int retcode;
+
+       if (cinfo.global_state != DSTATE_START && cinfo.global_state != 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;
+       }
+
+       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 boolean 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] = (byte)0xFF;
+                       cinfo.buffer[1] = (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 boolean 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       if (cinfo.bytes_offset == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+       c2 = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+       if (c != 0xFF || c2 != M_SOI)
+               error();
+//             ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
+
+       cinfo.unread_marker = c2;
+
+       return true;
+}
+
+static boolean next_marker (jpeg_decompress_struct cinfo) {
+       int c;
+
+       for (;;) {
+               if (cinfo.bytes_offset == 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 != 0xFF) {
+                       cinfo.marker.discarded_bytes++;
+                       if (cinfo.bytes_offset == 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 == cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                               c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+               } while (c == 0xFF);
+               if (c != 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 != 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 == 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 != BITS_IN_JSAMPLE)
+               error(" [data precision=" + 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 = (int)jdiv_round_up((long) cinfo.image_width * (long) compptr.h_samp_factor, (cinfo.max_h_samp_factor * DCTSIZE));
+               compptr.height_in_blocks = (int)jdiv_round_up((long) cinfo.image_height * (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 = (int)jdiv_round_up((long) cinfo.image_width * (long) compptr.h_samp_factor, cinfo.max_h_samp_factor);
+               compptr.downsampled_height = (int)jdiv_round_up((long) cinfo.image_height * (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 = (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 == 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 == 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 = (int)jdiv_round_up( cinfo.image_width, (cinfo.max_h_samp_factor*DCTSIZE));
+               cinfo.MCU_rows_in_scan = (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 == 0) tmp = compptr.MCU_width;
+                       compptr.last_col_width = tmp;
+                       tmp = (compptr.height_in_blocks % compptr.MCU_height);
+                       if (tmp == 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 != 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] == 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, boolean 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 == 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-- != 0)
+                       huffsize[p++] = (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]) != 0) {
+               while (( huffsize[p]) == 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) != 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;
+       }
+
+       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 == 1 && cid1 == 2 && cid2 == 3)
+                                       cinfo.jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
+                               else if (cid0 == 82 && cid1 == 71 && cid2 == 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 == 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 boolean isFileFormat(LEDataInputStream stream) {
+       try {
+               byte[] buffer = new byte[2];
+               stream.read(buffer);
+               stream.unread(buffer);
+               return (buffer[0] & 0xFF) == 0xFF && (buffer[1] & 0xFF) == 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) {
+               boolean 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, (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 new ImageData[]{imageData};
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGEndOfImage.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGEndOfImage.java
new file mode 100644 (file)
index 0000000..40e33fd
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGEndOfImage extends JPEGFixedSizeSegment {
+
+       public JPEGEndOfImage() {
+               super();
+       }
+
+       public JPEGEndOfImage(byte[] reference) {
+               super(reference);
+       }
+
+       @Override
+       public int signature() {
+               return JPEGFileFormat.EOI;
+       }
+
+       @Override
+       public int fixedSize() {
+               return 2;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFileFormat.java
new file mode 100644 (file)
index 0000000..0f5c6f8
--- /dev/null
@@ -0,0 +1,1894 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * This source file is based in part on the work of the Independent JPEG Group (IJG)
+ * and is made available under the terms contained in the about_files/IJG_README
+ * file accompanying this program.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+public final class JPEGFileFormat extends FileFormat {
+       int restartInterval;
+       JPEGFrameHeader frameHeader;
+       int imageWidth, imageHeight;
+       int interleavedMcuCols, interleavedMcuRows;
+       int maxV, maxH;
+       boolean 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 final int DCTSIZE = 8;
+       public static final int DCTSIZESQR = 64;
+       /* JPEGFixedPointConstants */
+       public static final int FIX_0_899976223 = 7373;
+       public static final int FIX_1_961570560 = 16069;
+       public static final int FIX_2_053119869 = 16819;
+       public static final int FIX_0_298631336 = 2446;
+       public static final int FIX_1_847759065 = 15137;
+       public static final int FIX_1_175875602 = 9633;
+       public static final int FIX_3_072711026 = 25172;
+       public static final int FIX_0_765366865 = 6270;
+       public static final int FIX_2_562915447 = 20995;
+       public static final int FIX_0_541196100 = 4433;
+       public static final int FIX_0_390180644 = 3196;
+       public static final int FIX_1_501321110 = 12299;
+       /* JPEGMarkerCodes */
+       public static final int APP0  = 0xFFE0;
+       public static final int APP15 = 0xFFEF;
+       public static final int COM   = 0xFFFE;
+       public static final int DAC   = 0xFFCC;
+       public static final int DHP   = 0xFFDE;
+       public static final int DHT   = 0xFFC4;
+       public static final int DNL   = 0xFFDC;
+       public static final int DRI   = 0xFFDD;
+       public static final int DQT   = 0xFFDB;
+       public static final int EOI   = 0xFFD9;
+       public static final int EXP   = 0xFFDF;
+       public static final int JPG   = 0xFFC8;
+       public static final int JPG0  = 0xFFF0;
+       public static final int JPG13 = 0xFFFD;
+       public static final int RST0  = 0xFFD0;
+       public static final int RST1  = 0xFFD1;
+       public static final int RST2  = 0xFFD2;
+       public static final int RST3  = 0xFFD3;
+       public static final int RST4  = 0xFFD4;
+       public static final int RST5  = 0xFFD5;
+       public static final int RST6  = 0xFFD6;
+       public static final int RST7  = 0xFFD7;
+       public static final int SOF0  = 0xFFC0;
+       public static final int SOF1  = 0xFFC1;
+       public static final int SOF2  = 0xFFC2;
+       public static final int SOF3  = 0xFFC3;
+       public static final int SOF5  = 0xFFC5;
+       public static final int SOF6  = 0xFFC6;
+       public static final int SOF7  = 0xFFC7;
+       public static final int SOF9  = 0xFFC9;
+       public static final int SOF10 = 0xFFCA;
+       public static final int SOF11 = 0xFFCB;
+       public static final int SOF13 = 0xFFCD;
+       public static final int SOF14 = 0xFFCE;
+       public static final int SOF15 = 0xFFCF;
+       public static final int SOI   = 0xFFD8;
+       public static final int SOS   = 0xFFDA;
+       public static final int TEM   = 0xFF01;
+       /* JPEGFrameComponentParameterConstants */
+       public static final int TQI     = 0;
+       public static final int HI      = 1;
+       public static final int VI      = 2;
+       public static final int CW      = 3;
+       public static final int CH      = 4;
+       /* JPEGScanComponentParameterConstants */
+       public static final int DC      = 0;
+       public static final int AC      = 1;
+       /* JFIF Component Constants */
+       public static final int ID_Y            = 1 - 1;
+       public static final int ID_CB   = 2 - 1;
+       public static final int ID_CR   = 3 - 1;
+       public static final RGB[] RGB16 = new RGB[] {
+               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),
+       };
+       public static final int[] ExtendTest = {
+               0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
+               4096, 8192, 16384, 32768, 65536, 131072, 262144
+       };
+       public static final int[] ExtendOffset = new int[] {
+               0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047,
+               -4095, -8191, -16383, -32767, -65535, -131071, -262143
+       };
+       public static final 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 final int[] CrRTable, CbBTable, CrGTable, CbGTable;
+       public static final int[] RYTable, GYTable, BYTable,
+               RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable;
+       static {
+               /* Initialize RGB-YCbCr Tables */
+               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 [] 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] = (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] = (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] = (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] = (byte)(n >> 16);
+               if ((n < 0) && ((n & 0xFFFF) != 0)) yComp[i]--;
+               n = RCbTable[r] + GCbTable[g] + BCbTable[b];
+               cbComp[i] = (byte)(n >> 16);
+               if ((n < 0) && ((n & 0xFFFF) != 0)) cbComp[i]--;
+               n = RCrTable[r] + GCrTable[g] + BCrTable[b];
+               crComp[i] = (byte)(n >> 16);
+               if ((n < 0) && ((n & 0xFFFF) != 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] = (byte)(n >> 16);
+               if ((n < 0) && ((n & 0xFFFF) != 0)) yComp[i]--;
+               n = RCbTable[r] + GCbTable[g] + BCbTable[b];
+               cbComp[i] = (byte)(n >> 16);
+               if ((n < 0) && ((n & 0xFFFF) != 0)) cbComp[i]--;
+               n = RCrTable[r] + GCrTable[g] + BCrTable[b];
+               crComp[i] = (byte)(n >> 16);
+               if ((n < 0) && ((n & 0xFFFF) != 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] = (byte)((RYTable[r] + GYTable[g] + BYTable[b]) >> 16);
+                               dataCbComp[dstDataIndex] = (byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) >> 16);
+                               dataCrComp[dstDataIndex] = (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] = (byte)((RYTable[r] + GYTable[g] + BYTable[b]) >> 16);
+                               dataCbComp[dstDataIndex] = (byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) >> 16);
+                               dataCrComp[dstDataIndex] = (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] = (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] = (byte)b;
+                       rgbData[destIndex + 1] = (byte)g;
+                       rgbData[destIndex + 2] = (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 == 0) {
+                       if (r == 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 == 0) {
+                       if (r == 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] != 0) {
+                                       dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+                               }
+                               k++;
+                       }
+                       eobrun--;
+               } else {
+                       int rs = decodeUsingTable(acTable);
+                       int r = rs >> 4;
+                       int s = rs & 0xF;
+                       if (s == 0) {
+                               if (r == 15) {
+                                       int zeros = 0;
+                                       while (zeros < 16 && k <= end) {
+                                               int zzIndex = ZigZag8x8[k];
+                                               if (dataUnit[zzIndex] != 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] != 0) && k <= end) {
+                                       if (dataUnit[zzIndex] != 0) {
+                                               dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+                                       } else {
+                                               zeros++;
+                                       }
+                                       k++;
+                                       zzIndex = ZigZag8x8[k];
+                               }
+                               if (bit != 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 != 0) {
+                       ac += 1 << approxBit;
+               }
+       } else if (ac < 0) {
+               int bit = nextBit();
+               if (bit != 0) {
+                       ac += -1 << approxBit;
+               }
+       }
+       return ac;
+}
+void decodeDCCoefficient(int[] dataUnit, int iComp, boolean 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 != 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 == 3) { // compIds 1, 2, 3
+               return convertYCbCrToRGB();
+       }
+//     if (nComponents == 3) { // compIds 1, 4, 5
+//             Unsupported CMYK format.
+//             return convertYIQToRGB();
+//     }
+       if (nComponents == 4) {
+               return convertCMYKToRGB();
+       }
+       return convertYToRGB();
+}
+void decodeMCUAtXAndY(int xmcu, int ymcu, int nComponentsInScan, boolean first, int start, int end, int approxBit) {
+       for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
+               int scanComponent = iComp;
+               while (scanHeader.componentParameters[componentIds[scanComponent]] == null) {
+                       scanComponent++;
+               }
+               int[] frameComponent = frameComponents[componentIds[scanComponent]];
+               int hi = frameComponent[HI];
+               int vi = frameComponent[VI];
+               if (nComponentsInScan == 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 == 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 == 1) {
+               // Non-interleaved.
+               int scanComponent = 0;
+               while (scanHeader.componentParameters[componentIds[scanComponent]] == 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;
+       }
+       boolean 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 != 0) {
+                               if (restartsToGo == 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 == 0) {
+               SWT.error(SWT.ERROR_INVALID_IMAGE);
+       }
+       int[] power2m1 = new int[] {
+               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] = (byte)(code & 0xFF);
+       codeBuffer[1] = (byte)((code >> 8) & 0xFF);
+       codeBuffer[2] = (byte)((code >> 16) & 0xFF);
+       codeBuffer[3] = (byte)((code >> 24) & 0xFF);
+       int abs = nBits - (8 - currentBitCount);
+       if (abs < 0) abs = -abs;
+       if ((abs >> 3) > 0) {
+               currentByte += codeBuffer[2];
+               emitByte((byte)currentByte);
+               emitByte(codeBuffer[1]);
+               currentByte = codeBuffer[0];
+               currentBitCount += nBits - 16;
+       } else {
+               currentBitCount += nBits;
+               if (currentBitCount >= 8) {
+                       currentByte += codeBuffer[2];
+                       emitByte((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 == -1) {
+               emitByte((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 == 0) {
+                       if (k == 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 != 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 != 0) {
+               emitByte((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) != 0)) dataUnit[rIndex + 2]--;
+               n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 1024;
+               dataUnit[rIndex + 6] = n >> 11;
+               if ((n < 0) && ((n & 0x07FF) != 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) != 0)) dataUnit[rIndex + 7]--;
+               n = tmp5 + z2 + z4 + 1024;
+               dataUnit[rIndex + 5] = n >> 11;
+               if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 5]--;
+               n = tmp6 + z2 + z3 + 1024;
+               dataUnit[rIndex + 3] = n >> 11;
+               if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 3]--;
+               n = tmp7 + z1 + z4 + 1024;
+               dataUnit[rIndex + 1] = n >> 11;
+               if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 1]--;
+       }
+
+       /**
+        * Pass 2: process columns.
+        * Note that we must descale the results by a factor of 8 == 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) != 0)) dataUnit[c0]--;
+               n = tmp10 - tmp11 + 16;
+               dataUnit[c4] = n >> 5;
+               if ((n < 0) && ((n & 0x1F) != 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) != 0)) dataUnit[c2]--;
+               n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 131072;
+               dataUnit[c6] = n >> 18;
+               if ((n < 0) && ((n & 0x3FFFF) != 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) != 0)) dataUnit[c7]--;
+               n = tmp5 + z2 + z4 + 131072;
+               dataUnit[c5] = n >> 18;
+               if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c5]--;
+               n = tmp6 + z2 + z3 + 131072;
+               dataUnit[c3] = n >> 18;
+               if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c3]--;
+               n = tmp7 + z1 + z4 + 131072;
+               dataUnit[c1] = n >> 18;
+               if ((n < 0) && ((n & 0x3FFFF) != 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 == null) {
+               acHuffmanTables = new JPEGHuffmanTable[4];
+       }
+       if (dcHuffmanTables == null) {
+               dcHuffmanTables = new JPEGHuffmanTable[4];
+       }
+       JPEGHuffmanTable[] dhtTables = dht.getAllTables();
+       for (int i = 0; i < dhtTables.length; i++) {
+               JPEGHuffmanTable dhtTable = dhtTables[i];
+               if (dhtTable.getTableClass() == 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 == 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 == 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
+boolean 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;
+       }
+}
+boolean isZeroInColumn(int[] dataUnit, int col) {
+       return dataUnit[col + 8] == 0 && dataUnit[col + 16] == 0
+                       && dataUnit[col + 24] == 0 && dataUnit[col + 32] == 0
+                       && dataUnit[col + 40] == 0 && dataUnit[col + 48] == 0
+                       && dataUnit[col + 56] == 0;
+}
+boolean isZeroInRow(int[] dataUnit, int rIndex) {
+       return dataUnit[rIndex + 1] == 0 && dataUnit[rIndex + 2] == 0
+                       && dataUnit[rIndex + 3] == 0 && dataUnit[rIndex + 4] == 0
+                       && dataUnit[rIndex + 5] == 0 && dataUnit[rIndex + 6] == 0
+                       && dataUnit[rIndex + 7] == 0;
+}
+@Override
+ImageData[] loadFromByteStream() {
+       //TEMPORARY CODE
+       if (System.getProperty("org.eclipse.swt.internal.image.JPEGFileFormat_3.2") == null) {
+               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;
+       boolean 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 == null || jpegSegment.getSegmentMarker() == 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 new ImageData[] {imageData};
+}
+ImageData createImageData() {
+       return ImageData.internal_new(
+               imageWidth,
+               imageHeight,
+               nComponents * samplePrecision,
+               setUpPalette(),
+               nComponents == 1 ? 4 : 1,
+               decodeImageComponents(),
+               0,
+               null,
+               null,
+               -1,
+               -1,
+               SWT.IMAGE_JPEG,
+               0,
+               0,
+               0,
+               0);
+}
+int nextBit() {
+       if (currentBitCount != 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 == 511) {
+               resetInputBuffer();
+               currentBitCount = 8;
+               nextByte = dataBuffer[0];
+       } else {
+               nextByte = dataBuffer[bufferCurrentPosition + 1];
+       }
+       if (currentByte == 0xFF) {
+               if (nextByte == 0) {
+                       bufferCurrentPosition ++;
+                       currentBitCount--;
+                       currentByte *= 2;
+                       if (currentByte > 255) {
+                               currentByte -= 256;
+                               return 1;
+                       } else {
+                               return 0;
+                       }
+               } else {
+                       if ((nextByte & 0xFF) + 0xFF00 == 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 != 0xFF);
+       while (currentByte == 0xFF) {
+               bufferCurrentPosition++;
+               if (bufferCurrentPosition > 511) {
+                       resetInputBuffer();
+                       bufferCurrentPosition = 0;
+               }
+               currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+       }
+       if (currentByte != ((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 == 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 == 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 == 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) != 1) return null;
+                       if (byteArray[0] == (byte) 0xFF) {
+                               if (byteStream.read(byteArray, 1, 1) != 1) return null;
+                               if (byteArray[1] != (byte) 0xFF && byteArray[1] != 0) {
+                                       byteStream.unread(byteArray);
+                                       return new JPEGSegment(byteArray);
+                               }
+                       }
+               }
+       } catch (IOException e) {
+               SWT.error(SWT.ERROR_IO, e);
+       }
+       return null;
+}
+PaletteData setUpPalette() {
+       if (nComponents == 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) != byteArray.length) {
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+               }
+               if (!(byteArray[0] == -1 && byteArray[1] != 0 && byteArray[1] != -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] = (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(new byte[] {(byte)0xFF, (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();
+       int encoderQFactor = loader.compression >= 1 && loader.compression <= 100 ? loader.compression : 75;
+       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 == 1) {
+               frameLength = 11;
+               frameParams = new int[1][];
+               frameParams[0] = new int[] {1, 1, 1, 0, 0};
+               scanParams = new int[1][];
+               scanParams[0] = new int[] {0, 0};
+               scanLength = 8;
+               nComponents = 1;
+               precision = 1;
+       } else {
+               frameLength = 17;
+               frameParams = new int[3][];
+               frameParams[0] = new int[] {0, 2, 2, 0, 0};
+               frameParams[1] = new int[] {1, 1, 1, 0, 0};
+               frameParams[2] = new int[] {1, 1, 1, 0, 0};
+               scanParams = new int[3][];
+               scanParams[0] = new int[] {0, 0};
+               scanParams[1] = new int[] {1, 1};
+               scanParams[2] = new int[] {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 = new int[] {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 = new JPEGHuffmanTable[] {
+               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() == 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);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java
new file mode 100644 (file)
index 0000000..ef9e6e2
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+abstract class JPEGFixedSizeSegment extends JPEGSegment {
+
+       public JPEGFixedSizeSegment() {
+               reference = new byte[fixedSize()];
+               setSegmentMarker(signature());
+       }
+
+       public JPEGFixedSizeSegment(byte[] reference) {
+               super(reference);
+       }
+
+       public JPEGFixedSizeSegment(LEDataInputStream byteStream) {
+               reference = new byte[fixedSize()];
+               try {
+                       byteStream.read(reference);
+               } catch (Exception e) {
+                       SWT.error(SWT.ERROR_IO, e);
+               }
+       }
+
+       abstract public int fixedSize();
+
+       @Override
+       public int getSegmentLength() {
+               return fixedSize() - 2;
+       }
+
+       @Override
+       public void setSegmentLength(int length) {
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFrameHeader.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGFrameHeader.java
new file mode 100644 (file)
index 0000000..c52aca8
--- /dev/null
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+final class JPEGFrameHeader extends JPEGVariableSizeSegment {
+       int maxVFactor;
+       int maxHFactor;
+       public int[] componentIdentifiers;
+       public int[][] componentParameters;
+
+       public JPEGFrameHeader(byte[] reference) {
+               super(reference);
+       }
+
+       public JPEGFrameHeader(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] = (byte)(precision & 0xFF);
+       }
+
+       public void setNumberOfLines(int anInteger) {
+               reference[5] = (byte)((anInteger & 0xFF00) >> 8);
+               reference[6] = (byte)(anInteger & 0xFF);
+       }
+
+       public void setSamplesPerLine(int samples) {
+               reference[7] = (byte)((samples & 0xFF00) >> 8);
+               reference[8] = (byte)(samples & 0xFF);
+       }
+
+       public void setNumberOfImageComponents(int anInteger) {
+               reference[9] = (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 = new int[0][];
+               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 = new int[] { 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 == 0 || nf != 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] = (byte)(i + 1);
+                       reference[ofs + 1] = (byte)(hi * 16 + vi);
+                       reference[ofs + 2] = (byte)(compParam[0]);
+                       if (hi > hmax) hmax = hi;
+                       if (vi > vmax) vmax = vi;
+               }
+               int x = getSamplesPerLine();
+               int y = getNumberOfLines();
+               int[] multiples = new int[] {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
+        */
+       @Override
+       public boolean 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 boolean isProgressive() {
+               int marker = getSegmentMarker();
+               return marker == JPEGFileFormat.SOF2
+                       || marker == JPEGFileFormat.SOF6
+                       || marker == JPEGFileFormat.SOF10
+                       || marker == JPEGFileFormat.SOF14;
+       }
+
+       public boolean isArithmeticCoding() {
+               return getSegmentMarker() >= JPEGFileFormat.SOF9;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGHuffmanTable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGHuffmanTable.java
new file mode 100644 (file)
index 0000000..63bd2b0
--- /dev/null
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+/**
+ * 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 extends JPEGVariableSizeSegment {
+       JPEGHuffmanTable[] allTables;
+       int tableClass;
+       int tableIdentifier;
+       int[] dhMaxCodes;
+       int[] dhMinCodes;
+       int[] dhValPtrs;
+       int[] dhValues;
+       int[] ehCodes;
+       byte[] ehCodeLengths;
+       static byte[] DCLuminanceTable = {
+               (byte)255, (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 = {
+               (byte)255, (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 = {
+               (byte)255, (byte)196, 0, (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, (byte)129, (byte)145, (byte)161, 8, 35, 66, (byte)177, (byte)193, 21, 82, (byte)209, (byte)240, 36, 51, 98,
+               114, (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, (byte)131, (byte)132, (byte)133, (byte)134, (byte)135, (byte)136, (byte)137, (byte)138, (byte)146, (byte)147, (byte)148,
+               (byte)149, (byte)150, (byte)151, (byte)152, (byte)153, (byte)154, (byte)162, (byte)163, (byte)164, (byte)165, (byte)166, (byte)167, (byte)168, (byte)169, (byte)170,
+               (byte)178, (byte)179, (byte)180, (byte)181, (byte)182, (byte)183, (byte)184, (byte)185, (byte)186, (byte)194, (byte)195, (byte)196, (byte)197, (byte)198, (byte)199,
+               (byte)200, (byte)201, (byte)202, (byte)210, (byte)211, (byte)212, (byte)213, (byte)214, (byte)215, (byte)216, (byte)217, (byte)218, (byte)225, (byte)226, (byte)227,
+               (byte)228, (byte)229, (byte)230, (byte)231, (byte)232, (byte)233, (byte)234, (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248,
+               (byte)249, (byte)250
+       };
+       static byte[] ACChrominanceTable = {
+               (byte)255, (byte)196, 0, (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, (byte)129, 8, 20, 66, (byte)145, (byte)161, (byte)177, (byte)193, 9, 35,
+               51, 82, (byte)240, 21, 98, 114, (byte)209, 10, 22, 36, 52, (byte)225, 37,
+               (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, (byte)130,
+               (byte)131, (byte)132, (byte)133, (byte)134, (byte)135, (byte)136, (byte)137,
+               (byte)138, (byte)146, (byte)147, (byte)148, (byte)149, (byte)150, (byte)151,
+               (byte)152, (byte)153, (byte)154, (byte)162, (byte)163, (byte)164, (byte)165,
+               (byte)166, (byte)167, (byte)168, (byte)169, (byte)170, (byte)178, (byte)179,
+               (byte)180, (byte)181, (byte)182, (byte)183, (byte)184, (byte)185, (byte)186,
+               (byte)194, (byte)195, (byte)196, (byte)197, (byte)198, (byte)199, (byte)200,
+               (byte)201, (byte)202, (byte)210, (byte)211, (byte)212, (byte)213, (byte)214,
+               (byte)215, (byte)216, (byte)217, (byte)218, (byte)226, (byte)227, (byte)228,
+               (byte)229, (byte)230, (byte)231, (byte)232, (byte)233, (byte)234, (byte)242,
+               (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248, (byte)249,
+               (byte)250
+       };
+
+public JPEGHuffmanTable(byte[] reference) {
+       super(reference);
+}
+
+public JPEGHuffmanTable(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] == 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 == 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]] = (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);
+}
+
+@Override
+public int signature() {
+       return JPEGFileFormat.DHT;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGQuantizationTable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGQuantizationTable.java
new file mode 100644 (file)
index 0000000..39db187
--- /dev/null
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGQuantizationTable extends JPEGVariableSizeSegment {
+       public static byte[] DefaultLuminanceQTable = {
+               (byte)255, (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 = {
+               (byte)255, (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 JPEGQuantizationTable(byte[] reference) {
+       super(reference);
+}
+
+public JPEGQuantizationTable(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 == 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 == 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 == 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] = (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] = (byte)(temp >> 8);
+                               reference[i + 1] = (byte)(temp & 0xFF);
+                       }
+                       ofs += 129;
+                       totalLength -= 129;
+               }
+       }
+}
+
+@Override
+public int signature() {
+       return JPEGFileFormat.DQT;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGRestartInterval.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGRestartInterval.java
new file mode 100644 (file)
index 0000000..ac81d1f
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGRestartInterval extends JPEGFixedSizeSegment {
+
+       public JPEGRestartInterval(LEDataInputStream byteStream) {
+               super(byteStream);
+       }
+
+       @Override
+       public int signature() {
+               return JPEGFileFormat.DRI;
+       }
+
+       public int getRestartInterval() {
+               return ((reference[4] & 0xFF) << 8 | (reference[5] & 0xFF));
+       }
+
+       @Override
+       public int fixedSize() {
+               return 6;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGScanHeader.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGScanHeader.java
new file mode 100644 (file)
index 0000000..578a27f
--- /dev/null
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+final class JPEGScanHeader extends JPEGVariableSizeSegment {
+       public int[][] componentParameters;
+
+public JPEGScanHeader(byte[] reference) {
+       super(reference);
+}
+
+public JPEGScanHeader(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 = new int[0][];
+       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] = new int[] { dc, ac };
+       }
+}
+
+/* Used when encoding. */
+public void initializeContents() {
+       int compCount = getNumberOfImageComponents();
+       int[][] compSpecParams = componentParameters;
+       if (compCount == 0 || compCount != 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] = (byte)(i + 1);
+               reference[ofs + 1] = (byte)(compParams[0] * 16 + compParams[1]);
+       }
+}
+
+public void setEndOfSpectralSelection(int anInteger) {
+       reference[(2 * getNumberOfImageComponents()) + 6] = (byte)anInteger;
+}
+
+public void setNumberOfImageComponents(int anInteger) {
+       reference[4] = (byte)(anInteger & 0xFF);
+}
+
+public void setStartOfSpectralSelection(int anInteger) {
+       reference[(2 * getNumberOfImageComponents()) + 5] = (byte)anInteger;
+}
+
+@Override
+public int signature() {
+       return JPEGFileFormat.SOS;
+}
+
+public boolean verifyProgressiveScan() {
+       int start = getStartOfSpectralSelection();
+       int end = getEndOfSpectralSelection();
+       int low = getApproxBitPositionLow();
+       int high = getApproxBitPositionHigh();
+       int count = getNumberOfImageComponents();
+       if ((start == 0 && end == 00) || (start <= end && end <= 63)) {
+               if (low <= 13 && high <= 13 && (high == 0 || high == low + 1)) {
+                       return start == 0 || (start > 0 && count == 1);
+               }
+       }
+       return false;
+}
+
+public boolean isACProgressiveScan() {
+       return getStartOfSpectralSelection() != 0 && getEndOfSpectralSelection() != 0;
+}
+
+public boolean isDCProgressiveScan() {
+       return getStartOfSpectralSelection() == 0 && getEndOfSpectralSelection() == 0;
+}
+
+public boolean isFirstScan() {
+       return getApproxBitPositionHigh() == 0;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGSegment.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGSegment.java
new file mode 100644 (file)
index 0000000..5fd3246
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+class JPEGSegment {
+       public byte[] reference;
+
+       JPEGSegment() {
+       }
+
+       public JPEGSegment(byte[] reference) {
+               this.reference = reference;
+       }
+
+       public int signature() {
+               return 0;
+       }
+
+       public boolean verify() {
+               return getSegmentMarker() == signature();
+       }
+
+       public int getSegmentMarker() {
+               return ((reference[0] & 0xFF) << 8 | (reference[1] & 0xFF));
+       }
+
+       public void setSegmentMarker(int marker) {
+               reference[0] = (byte)((marker & 0xFF00) >> 8);
+               reference[1] = (byte)(marker & 0xFF);
+       }
+
+       public int getSegmentLength() {
+               return ((reference[2] & 0xFF) << 8 | (reference[3] & 0xFF));
+       }
+
+       public void setSegmentLength(int length) {
+               reference[2] = (byte)((length & 0xFF00) >> 8);
+               reference[3] = (byte)(length & 0xFF);
+       }
+
+       public boolean writeToStream(LEDataOutputStream byteStream) {
+               try {
+                       byteStream.write(reference);
+                       return true;
+               } catch (Exception e) {
+                       return false;
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGStartOfImage.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGStartOfImage.java
new file mode 100644 (file)
index 0000000..5df7802
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class JPEGStartOfImage extends JPEGFixedSizeSegment {
+
+       public JPEGStartOfImage() {
+               super();
+       }
+
+       public JPEGStartOfImage(byte[] reference) {
+               super(reference);
+       }
+
+       public JPEGStartOfImage(LEDataInputStream byteStream) {
+               super(byteStream);
+       }
+
+       @Override
+       public int signature() {
+               return JPEGFileFormat.SOI;
+       }
+
+       @Override
+       public int fixedSize() {
+               return 2;
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java
new file mode 100644 (file)
index 0000000..0c83d55
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+abstract class JPEGVariableSizeSegment extends JPEGSegment {
+
+       public JPEGVariableSizeSegment(byte[] reference) {
+               super(reference);
+       }
+
+       public JPEGVariableSizeSegment(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);
+               }
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LEDataInputStream.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LEDataInputStream.java
new file mode 100644 (file)
index 0000000..54e5bbd
--- /dev/null
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import java.io.*;
+
+final class LEDataInputStream extends InputStream {
+       int position;
+       InputStream in;
+
+       /**
+        * 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 LEDataInputStream(InputStream input) {
+               this(input, 512);
+       }
+
+       public LEDataInputStream(InputStream input, int bufferSize) {
+               this.in = input;
+               if (bufferSize > 0) {
+                       buf = new byte[bufferSize];
+                       pos = bufferSize;
+               }
+               else throw new IllegalArgumentException();
+       }
+
+       @Override
+       public void close() throws IOException {
+               buf = null;
+               if (in != null) {
+                       in.close();
+                       in = null;
+               }
+       }
+
+       /**
+        * Answer how many bytes were read.
+        */
+       public int getPosition() {
+               return position;
+       }
+
+       /**
+        * Answers how many bytes are available for reading without blocking
+        */
+       @Override
+       public int available() throws IOException {
+               if (buf == null) throw new IOException();
+               return (buf.length - pos) + in.available();
+       }
+
+       /**
+        * Answer the next byte of the input stream.
+        */
+       @Override
+       public int read() throws IOException {
+               if (buf == null) throw new IOException();
+               if (pos < buf.length) {
+                       position++;
+                       return (buf[pos++] & 0xFF);
+               }
+               int c = in.read();
+               if (c != -1) position++;
+               return c;
+       }
+
+       /**
+        * Don't imitate the JDK behaviour of reading a random number
+        * of bytes when you can actually read them all.
+        */
+       @Override
+       public int read(byte b[], int off, int len) throws IOException {
+               int read = 0, count;
+               while (read != len && (count = readData(b, off, len - read)) != -1) {
+                       off += count;
+                       read += count;
+               }
+               position += read;
+               if (read == 0 && read != 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 length) throws IOException {
+               if (buf == null) throw new IOException();
+               if (offset < 0 || offset > buffer.length ||
+                       length < 0 || (length > buffer.length - offset)) {
+                       throw new ArrayIndexOutOfBoundsException();
+                       }
+
+               int cacheCopied = 0;
+               int newOffset = offset;
+
+               // Are there pushback bytes available?
+               int available = buf.length - pos;
+               if (available > 0) {
+                       cacheCopied = (available >= length) ? length : available;
+                       System.arraycopy(buf, pos, buffer, newOffset, cacheCopied);
+                       newOffset += cacheCopied;
+                       pos += cacheCopied;
+               }
+
+               // Have we copied enough?
+               if (cacheCopied == length) return length;
+
+               int inCopied = in.read(buffer, newOffset, length - cacheCopied);
+
+               if (inCopied > 0) return inCopied + cacheCopied;
+               if (cacheCopied == 0) return inCopied;
+               return cacheCopied;
+       }
+
+       /**
+        * Answer an integer comprised of the next
+        * four bytes of the input stream.
+        */
+       public int readInt() throws IOException {
+               byte[] buf = new byte[4];
+               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() throws IOException {
+               byte[] buf = new byte[2];
+               read(buf);
+               return (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) throws IOException {
+               int length = b.length;
+               if (length > pos) throw new IOException();
+               position -= length;
+               pos -= length;
+               System.arraycopy(b, 0, buf, pos, length);
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LEDataOutputStream.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LEDataOutputStream.java
new file mode 100644 (file)
index 0000000..da938a0
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import java.io.*;
+
+final class LEDataOutputStream extends OutputStream {
+       OutputStream out;
+public LEDataOutputStream(OutputStream output) {
+       this.out = output;
+}
+/**
+ * Write the specified number of bytes of the given byte array,
+ * starting at the specified offset, to the output stream.
+ */
+@Override
+public void write(byte b[], int off, int len) throws IOException {
+       out.write(b, off, len);
+}
+/**
+ * Write the given byte to the output stream.
+ */
+@Override
+public void write(int b) throws IOException {
+       out.write(b);
+}
+/**
+ * Write the given byte to the output stream.
+ */
+public void writeByte(byte b) throws IOException {
+       out.write(b & 0xFF);
+}
+/**
+ * Write the four bytes of the given integer
+ * to the output stream.
+ */
+public void writeInt(int theInt) throws IOException {
+       out.write(theInt & 0xFF);
+       out.write((theInt >> 8) & 0xFF);
+       out.write((theInt >> 16) & 0xFF);
+       out.write((theInt >> 24) & 0xFF);
+}
+/**
+ * Write the two bytes of the given short
+ * to the output stream.
+ */
+public void writeShort(int theShort) throws IOException {
+       out.write(theShort & 0xFF);
+       out.write((theShort >> 8) & 0xFF);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LZWCodec.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LZWCodec.java
new file mode 100644 (file)
index 0000000..025ce9d
--- /dev/null
@@ -0,0 +1,480 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+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;
+       boolean interlaced;
+       static final int[] MASK_TABLE = new int[] {
+               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()) != endCode) {
+               if (c == clearCode) {
+                       codeSize = bitsPerPixel + 1;
+                       codeMask = MASK_TABLE[bitsPerPixel];
+                       currentSlot = newCodes;
+                       topSlot = 1 << codeSize;
+                       while ((c = nextCode()) == clearCode) {}
+                       if (c != endCode) {
+                               oc = fc = c;
+                               buf[bufIndex] = (byte)c;
+                               bufIndex++;
+                               if (bufIndex == 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] = (byte)stack[stackIndex];
+                               bufIndex++;
+                               if (bufIndex == imageWidth) {
+                                       nextPutPixels(buf);
+                                       bufIndex = 0;
+                               }
+                       }
+               }
+       }
+       if (bufIndex != 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, boolean 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 == 8) {
+               block[0] = (byte)(blockIndex - 1); // Nothing in last byte
+       } else {
+               block[0] = (byte)(blockIndex); // Last byte has data
+       }
+       writeBlock();
+
+       // Write out empty block to indicate the end (if needed)
+       if (block[0] != 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();
+       boolean found;
+       LZWNode node;
+       while (true) {
+               int currentPrefix = pixel;
+               node = nodeStack[currentPrefix];
+               found = true;
+               pixel = nextPixel();
+               if (pixel < 0)
+                       return currentPrefix;
+               while (found && (node.children != null)) {
+                       node = node.children;
+                       while (found && (node.suffix != pixel)) {
+                               if (pixel < node.suffix) {
+                                       if (node.left == null) {
+                                               node.left = new LZWNode();
+                                               found = false;
+                                       }
+                                       node = node.left;
+                               } else {
+                                       if (node.right == 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] = (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 == 0) {
+               if (blockIndex >= blockSize) {
+                       blockSize = readBlock();
+                       blockIndex = 0;
+                       if (blockSize == 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 == 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 == 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] = (byte)currentByte;
+       codeBitsToDo -= bitsLeft;
+       if (codeBitsToDo < 1) {
+               // The whole code fit in the first byte, so we are done.
+               bitsLeft -= codeSize;
+               if (bitsLeft == 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] = (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] = (byte)currentByte;
+}
+/**
+ * Copy a row of pixel values to the image.
+ */
+void nextPutPixels(byte[] buf) {
+       if (image.depth == 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 == 1) {
+                       copyRow(buf, 7);
+                       line += 8;
+               } else if (pass == 2) {
+                       copyRow(buf, 3);
+                       line += 8;
+               } else if (pass == 3) {
+                       copyRow(buf, 1);
+                       line += 4;
+               } else if (pass == 4) {
+                       line += 2;
+               } else if (pass == 5) {
+                       line += 0;
+               }
+               if (line >= imageHeight) {
+                       pass++;
+                       if (pass == 2) line = 4;
+                       else if (pass == 3) line = 2;
+                       else if (pass == 4) line = 1;
+                       else if (pass == 5) line = 0;
+                       if (pass < 5) {
+                               if (loader.hasListeners()) {
+                                       ImageData imageCopy = (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 == -1) {
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+               }
+               block[0] = (byte)size;
+               size = inputStream.read(block, 1, size);
+               if (size == -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);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LZWNode.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/LZWNode.java
new file mode 100644 (file)
index 0000000..653f829
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+final class LZWNode {
+       public LZWNode left, right, children;
+       public int code, prefix, suffix;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/OS2BMPFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/OS2BMPFileFormat.java
new file mode 100644 (file)
index 0000000..130484a
--- /dev/null
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+public final class OS2BMPFileFormat extends FileFormat {
+       static final int BMPFileHeaderSize = 14;
+       static final int BMPHeaderFixedSize = 12;
+       int width, height, bitCount;
+
+@Override
+boolean 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] == 0x42 && header[1] == 0x4D && infoHeaderSize == 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) != 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] != 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 new ImageData[] {
+               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) != buf.length)
+                               SWT.error(SWT.ERROR_INVALID_IMAGE);
+               } catch (IOException e) {
+                       SWT.error(SWT.ERROR_IO, e);
+               }
+               return paletteFromBytes(buf, numColors);
+       }
+       if (bitCount == 16) return new PaletteData(0x7C00, 0x3E0, 0x1F);
+       if (bitCount == 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 == 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] = (byte)col.blue;
+               bytes[offset + 1] = (byte)col.green;
+               bytes[offset + 2] = (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 out) {
+       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 == 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;
+                               }
+                               out.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;
+                               }
+                               out.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 == 1) || (image.depth == 4) || (image.depth == 8) ||
+                 (image.depth == 16) || (image.depth == 24) || (image.depth == 32)))
+                       SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+       PaletteData pal = image.palette;
+       if ((image.depth == 16) || (image.depth == 24) || (image.depth == 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 != 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 out = new ByteArrayOutputStream();
+       unloadData(image, out);
+       byte[] data = out.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((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;
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PNGFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PNGFileFormat.java
new file mode 100644 (file)
index 0000000..fbf2720
--- /dev/null
@@ -0,0 +1,594 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import java.io.*;
+import java.util.zip.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+public final class PNGFileFormat extends 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() throws IOException {
+       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 new ImageData[] {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) throws IOException {
+       PngChunk chunk = chunkReader.readNextChunk();
+       switch (chunk.getChunkType()) {
+               case PngChunk.CHUNK_IEND:
+                       break;
+               case PngChunk.CHUNK_PLTE:
+                       if (!headerChunk.usesDirectColor()) {
+                               paletteChunk = (PngPlteChunk) chunk;
+                               imageData.palette = paletteChunk.getPaletteData();
+                       }
+                       break;
+               case PngChunk.CHUNK_tRNS:
+                       PngTrnsChunk trnsChunk = (PngTrnsChunk) chunk;
+                       if (trnsChunk.getTransparencyType(headerChunk) ==
+                               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) != 255) {
+                                               transparentCount++;
+                                               transparentPixel = i;
+                                       }
+                               }
+                               if (transparentCount == 0) {
+                                       alphaPalette = null;
+                               } else if (transparentCount == 1 && alphaPalette[transparentPixel] == 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 = (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
+boolean isFileFormat(LEDataInputStream stream) {
+       try {
+               byte[] signature = new byte[SIGNATURE_LENGTH];
+               stream.read(signature);
+               stream.unread(signature);
+               if ((signature[0] & 0xFF) != 137) return false; //137
+               if ((signature[1] & 0xFF) != 80) return false; //P
+               if ((signature[2] & 0xFF) != 78) return false; //N
+               if ((signature[3] & 0xFF) != 71) return false; //G
+               if ((signature[4] & 0xFF) != 13) return false; //<RETURN>
+               if ((signature[5] & 0xFF) != 10) return false; //<LINEFEED>
+               if ((signature[6] & 0xFF) != 26) return false; //<CTRL/Z>
+               if ((signature[7] & 0xFF) != 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_PALETTE:
+                       imageData.data = data;
+                       if (alphaPalette != 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;
+               case PngIhdrChunk.COLOR_TYPE_RGB:
+               default:
+                       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;
+                       if (destBytesPerLine != srcBytesPerLine) {
+                               for (int y = 0; y < height; y++) {
+                                       System.arraycopy(data, y * srcBytesPerLine, imageData.data, y * destBytesPerLine, srcBytesPerLine);
+                               }
+                       } else {
+                               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.
+ */
+@SuppressWarnings("resource")
+void readPixelData(PngIdatChunk chunk, PngChunkReader chunkReader) throws IOException {
+       InputStream stream = new PngInputStream(chunk, chunkReader);
+       //TEMPORARY CODE
+       boolean use3_2 = System.getProperty("org.eclipse.swt.internal.image.PNGFileFormat_3.2") != null;
+       InputStream inflaterStream = use3_2 ? null : new BufferedInputStream(new InflaterInputStream(stream));
+       if (inflaterStream != null) {
+               stream = inflaterStream;
+       } else {
+               stream = new PngDecodingDataStream(stream);
+       }
+       int interlaceMethod = headerChunk.getInterlaceMethod();
+       if (interlaceMethod == 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) throws IOException
+{
+       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 = (byte)inputStream.read();
+               int read = 0;
+               while (read != 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 == row1) ? row2 : row1;
+               lastRow = (lastRow == row1) ? row2 : row1;
+       }
+       setImageDataValues(data, imageData);
+       fireInterlacedFrameEvent(frameCount);
+}
+/**
+ * Read the pixel data for an interlaced image from the
+ * data stream.
+ */
+void readInterlacedImage(InputStream inputStream) throws IOException {
+       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 = (ImageData) imageData.clone();
+               boolean finalFrame = frameCount == 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) throws IOException {
+       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 = (byte)inputStream.read();
+               int read = 0;
+               while (read != bytesPerRow) {
+                       read += inputStream.read(currentRow, read, bytesPerRow - read);
+               }
+               filterRow(currentRow, lastRow, filterType);
+               System.arraycopy(currentRow, 0, data, dataOffset, bytesPerRow);
+               dataOffset += alignedBytesPerRow;
+               currentRow = (currentRow == row1) ? row2 : row1;
+               lastRow = (lastRow == 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] = (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] = (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] = (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] = (byte) ((currentValue + preductor) & 0xFF);
+                       }
+                       break;
+       }
+}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngChunk.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngChunk.java
new file mode 100644 (file)
index 0000000..200cb30
--- /dev/null
@@ -0,0 +1,386 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+
+class PngChunk extends Object {
+       byte[] reference;
+
+       static final int LENGTH_OFFSET = 0;
+       static final int TYPE_OFFSET = 4;
+       static final int DATA_OFFSET = 8;
+
+       static final int TYPE_FIELD_LENGTH = 4;
+       static final int LENGTH_FIELD_LENGTH = 4;
+       static final int MIN_LENGTH = 12;
+
+       static final int CHUNK_UNKNOWN = -1;
+       // Critical chunks.
+       static final int CHUNK_IHDR = 0;
+       static final int CHUNK_PLTE = 1;
+       static final int CHUNK_IDAT = 2;
+       static final int CHUNK_IEND = 3;
+       // Non-critical chunks.
+       static final int CHUNK_tRNS = 5;
+
+       static final byte[] TYPE_IHDR = {(byte) 'I', (byte) 'H', (byte) 'D', (byte) 'R'};
+       static final byte[] TYPE_PLTE = {(byte) 'P', (byte) 'L', (byte) 'T', (byte) 'E'};
+       static final byte[] TYPE_IDAT = {(byte) 'I', (byte) 'D', (byte) 'A', (byte) 'T'};
+       static final byte[] TYPE_IEND = {(byte) 'I', (byte) 'E', (byte) 'N', (byte) 'D'};
+       static final byte[] TYPE_tRNS = {(byte) 't', (byte) 'R', (byte) 'N', (byte) 'S'};
+
+       static final int[] CRC_TABLE;
+       static {
+               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) == 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.
+ */
+PngChunk(byte[] reference) {
+       super();
+       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.
+ */
+PngChunk(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] = (byte) ((value >> 8) & 0xFF);
+       reference[offset + 1] = (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] = (byte) ((value >> 24) & 0xFF);
+       reference[offset + 1] = (byte) ((value >> 16) & 0xFF);
+       reference[offset + 2] = (byte) ((value >> 8) & 0xFF);
+       reference[offset + 3] = (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 != 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.
+ */
+boolean checkCRC() {
+       int crc = computeCRC();
+       int storedCRC = getCRC();
+       return crc == 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;
+}
+
+boolean typeMatchesArray(byte[] array) {
+       for (int i = 0; i < TYPE_FIELD_LENGTH; i++) {
+               if (reference[TYPE_OFFSET + i] != array[i]){
+                       return false;
+               }
+       }
+       return true;
+}
+
+boolean isCritical() {
+       char c = (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 != 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 != 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 = (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 = (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.
+ */
+void contributeToString(StringBuilder buffer) {}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       StringBuilder buffer = new StringBuilder();
+       buffer.append("{");
+       buffer.append("\n\tLength: ");
+       buffer.append(getLength());
+       buffer.append("\n\tType: ");
+       byte[] type = getTypeBytes();
+       for(int i = 0; i < type.length; i++) {
+               buffer.append((char) type[i]);
+       }
+
+       contributeToString(buffer);
+
+       buffer.append("\n\tCRC: ");
+       buffer.append(Integer.toHexString(getCRC()));
+       buffer.append("\n}");
+       return buffer.toString();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngChunkReader.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngChunkReader.java
new file mode 100644 (file)
index 0000000..211f1e8
--- /dev/null
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+public class PngChunkReader {
+       LEDataInputStream inputStream;
+       PngFileReadState readState;
+       PngIhdrChunk headerChunk;
+       PngPlteChunk paletteChunk;
+
+PngChunkReader(LEDataInputStream inputStream) {
+       this.inputStream = inputStream;
+       readState = new PngFileReadState();
+       headerChunk = null;
+}
+
+PngIhdrChunk getIhdrChunk() {
+       if (headerChunk == null) {
+               try {
+                       PngChunk chunk = PngChunk.readNextFromStream(inputStream);
+                       if (chunk == null) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                       headerChunk = (PngIhdrChunk) chunk;
+                       headerChunk.validate(readState, null);
+               } catch (ClassCastException e) {
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+               }
+       }
+       return headerChunk;
+}
+
+PngChunk readNextChunk() {
+       if (headerChunk == null) return getIhdrChunk();
+
+       PngChunk chunk = PngChunk.readNextFromStream(inputStream);
+       if (chunk == null) SWT.error(SWT.ERROR_INVALID_IMAGE);
+       switch (chunk.getChunkType()) {
+               case PngChunk.CHUNK_tRNS:
+                       ((PngTrnsChunk) chunk).validate(readState, headerChunk, paletteChunk);
+                       break;
+               case PngChunk.CHUNK_PLTE:
+                       chunk.validate(readState, headerChunk);
+                       paletteChunk = (PngPlteChunk) chunk;
+                       break;
+               default:
+                       chunk.validate(readState, headerChunk);
+       }
+       if (readState.readIDAT && !(chunk.getChunkType() == PngChunk.CHUNK_IDAT)) {
+               readState.readPixelData = true;
+       }
+       return chunk;
+}
+
+boolean readPixelData() {
+       return readState.readPixelData;
+}
+
+boolean hasMoreChunks() {
+       return !readState.readIEND;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngDecodingDataStream.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngDecodingDataStream.java
new file mode 100644 (file)
index 0000000..a884f93
--- /dev/null
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+
+public class PngDecodingDataStream extends InputStream {
+       InputStream stream;
+       byte currentByte;
+       int nextBitIndex;
+
+       PngLzBlockReader lzBlockReader;
+       int adlerValue;
+
+       static final int PRIME = 65521;
+       static final int MAX_BIT = 7;
+
+PngDecodingDataStream(InputStream stream) throws IOException {
+       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() throws IOException {
+       lzBlockReader.assertCompressedDataAtEnd();
+}
+
+@Override
+public void close() throws IOException {
+       assertImageDataAtEnd();
+       checkAdler();
+}
+
+int getNextIdatBits(int length) throws IOException {
+       int value = 0;
+       for (int i = 0; i < length; i++) {
+               value |= (getNextIdatBit() << i);
+       }
+       return value;
+}
+
+int getNextIdatBit() throws IOException {
+       if (nextBitIndex > MAX_BIT) {
+               currentByte = getNextIdatByte();
+               nextBitIndex = 0;
+       }
+       return (currentByte & (1 << nextBitIndex)) >> nextBitIndex++;
+}
+
+byte getNextIdatByte() throws IOException {
+       byte nextByte = (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;
+}
+
+@Override
+public int read() throws IOException {
+       byte nextDecodedByte = lzBlockReader.getNextByte();
+       updateAdler(nextDecodedByte);
+       return nextDecodedByte & 0xFF;
+}
+
+@Override
+public int read(byte[] buffer, int off, int len) throws IOException {
+       for (int i = 0; i < len; i++) {
+               int b = read();
+               if (b == -1) return i;
+               buffer[off + i] = (byte)b;
+       }
+       return len;
+}
+
+void error() {
+       SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+private void readCompressedDataHeader() throws IOException {
+       byte headerByte1 = getNextIdatByte();
+       byte headerByte2 = getNextIdatByte();
+
+       int number = ((headerByte1 & 0xFF) << 8) | (headerByte2 & 0xFF);
+       if (number % 31 != 0) error();
+
+       int compressionMethod = headerByte1 & 0x0F;
+       if (compressionMethod != 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 != 0) error();
+
+//     int compressionLevel = (headerByte2 & 0xC0) >> 6;
+}
+
+void checkAdler() throws IOException {
+       int storedAdler = ((getNextIdatByte() & 0xFF) << 24)
+               | ((getNextIdatByte() & 0xFF) << 16)
+               | ((getNextIdatByte() & 0xFF) << 8)
+               | (getNextIdatByte() & 0xFF);
+       if (storedAdler != adlerValue) error();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngDeflater.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngDeflater.java
new file mode 100644 (file)
index 0000000..695c683
--- /dev/null
@@ -0,0 +1,621 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.ByteArrayOutputStream;
+
+public class PngDeflater {
+
+       static final int BASE = 65521;
+       static final int WINDOW = 32768;
+       static final int MIN_LENGTH = 3;
+       static final int MAX_MATCHES = 32;
+       static final int HASH = 8209;
+
+       byte[] in;
+       int inLength;
+
+       ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
+
+       int adler32 = 1;
+
+       int buffer, bitCount;
+
+       Link[] hashtable = new Link[HASH];
+       Link[] window = new Link[WINDOW];
+       int nextWindow;
+
+static class Link {
+
+       int hash, value;
+       Link previous, next;
+
+       Link() {
+
+               this.hash = 0;
+               this.value = 0;
+               this.previous = null;
+               this.next = null;
+
+       }
+
+}
+
+static class Match {
+
+       int length, distance;
+
+       Match(int length, int distance) {
+
+               this.length = length;
+               this.distance = distance;
+
+       }
+
+}
+
+static final short mirrorBytes[] = {
+
+       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;
+
+       Code(int code, int extraBits, int min, int max) {
+
+               this.code = code;
+               this.extraBits = extraBits;
+               this.min = min;
+               this.max = max;
+
+       }
+
+}
+
+static final Code lengthCodes[] = {
+
+       new Code(257, 0, 3, 3),
+       new Code(258, 0, 4, 4),
+       new Code(259, 0, 5, 5),
+       new Code(260, 0, 6, 6),
+       new Code(261, 0, 7, 7),
+       new Code(262, 0, 8, 8),
+       new Code(263, 0, 9, 9),
+       new Code(264, 0, 10, 10),
+       new Code(265, 1, 11, 12),
+       new Code(266, 1, 13, 14),
+       new Code(267, 1, 15, 16),
+       new Code(268, 1, 17, 18),
+       new Code(269, 2, 19, 22),
+       new Code(270, 2, 23, 26),
+       new Code(271, 2, 27, 30),
+       new Code(272, 2, 31, 34),
+       new Code(273, 3, 35, 42),
+       new Code(274, 3, 43, 50),
+       new Code(275, 3, 51, 58),
+       new Code(276, 3, 59, 66),
+       new Code(277, 4, 67, 82),
+       new Code(278, 4, 83, 98),
+       new Code(279, 4, 99, 114),
+       new Code(280, 4, 115, 130),
+       new Code(281, 5, 131, 162),
+       new Code(282, 5, 163, 194),
+       new Code(283, 5, 195, 226),
+       new Code(284, 5, 227, 257),
+       new Code(285, 0, 258, 258)
+
+};
+
+static final Code 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 = (byte) (theShort & 0xff);
+       byte byte2 = (byte) ((theShort >> 8) & 0xff);
+       byte[] temp = {byte1, byte2};
+       baos.write(temp, 0, 2);
+
+}
+
+void writeInt(ByteArrayOutputStream baos, int theInt) {
+
+       byte byte1 = (byte) ((theInt >> 24) & 0xff);
+       byte byte2 = (byte) ((theInt >> 16) & 0xff);
+       byte byte3 = (byte) ((theInt >> 8) & 0xff);
+       byte byte4 = (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((byte) buffer);
+               bytes.write((byte) (buffer >>> 8));
+               buffer >>>= 16;
+               bitCount -= 16;
+       }
+
+}
+
+void alignToByte() {
+
+       if (bitCount > 0) {
+               bytes.write((byte) buffer);
+               if (bitCount > 8) bytes.write((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 != 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 != 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 != 0) {
+
+                       int i;
+
+                       for (i = 1; position + i < inLength; i++) {
+                               if (in[position + i] != in[matchPosition + i]) {
+                                       break;
+                               }
+                       }
+
+                       if (i >= MIN_LENGTH) {
+
+                               if (i > bestMatch.length) {
+                                       bestMatch.length = i;
+                                       bestMatch.distance = position - matchPosition;
+                               }
+
+                               numberOfMatches = numberOfMatches + 1;
+
+                               if (numberOfMatches == MAX_MATCHES) {
+                                       break;
+                               }
+
+                       }
+
+               }
+
+               link = link.next;
+               if (link == 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 hash;
+       Link temp;
+
+       for (int i = to; i < from; i++) {
+
+               if (i + MIN_LENGTH > inLength) {
+                       break;
+               }
+
+               data[0] = in[i];
+               data[1] = in[i + 1];
+               data[2] = in[i + 2];
+
+               hash = hash(data);
+
+               if (window[nextWindow].previous != null) {
+                       window[nextWindow].previous.next = null;
+               }
+               else if (window[nextWindow].hash != 0) {
+                       hashtable[window[nextWindow].hash].next = null;
+               }
+
+               window[nextWindow].hash = hash;
+               window[nextWindow].value = i;
+               window[nextWindow].previous = null;
+               temp = window[nextWindow].next = hashtable[hash].next;
+               hashtable[hash].next = window[nextWindow];
+               if (temp != null) {
+                       temp.previous = window[nextWindow];
+               }
+
+               nextWindow = nextWindow + 1;
+               if (nextWindow == WINDOW) {
+                       nextWindow = 0;
+               }
+
+       }
+
+}
+
+void compress() {
+
+       int position, newPosition;
+       byte[] data = new byte[3];
+       int hash;
+       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(in[0]);
+       position = 1;
+
+       while (position < inLength) {
+
+               if (inLength - position < MIN_LENGTH) {
+                       outputLiteral(in[position]);
+                       position = position + 1;
+                       continue;
+               }
+
+               data[0] = in[position];
+               data[1] = in[position + 1];
+               data[2] = in[position + 2];
+
+               hash = hash(data);
+               firstPosition = hashtable[hash];
+
+               match = findLongestMatch(position, firstPosition);
+
+               updateHashtable(position, position + 1);
+
+               if (match != null) {
+
+                       if (deferredMatch != null) {
+                               if (match.length > deferredMatch.length + 1) {
+                                       // output literal at deferredPosition
+                                       outputLiteral(in[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 != null) {
+                               outputMatch(deferredMatch.length, deferredMatch.distance);
+                               newPosition = deferredPosition + deferredMatch.length;
+                               deferredPosition = -1;
+                               deferredMatch = null;
+                               updateHashtable(position + 1, newPosition);
+                               position = newPosition;
+                       }
+                       else {
+                               outputLiteral(in[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(in[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((byte) BFINAL);
+               writeShortLSB(bytes, blockLength); // LEN
+               writeShortLSB(bytes, blockLength ^ 0xffff); // NLEN (one's complement of LEN)
+
+               // write actual data
+               bytes.write(in, start, blockLength);
+
+               length = length - blockLength;
+               start = start + blockLength;
+
+       }
+
+}
+
+public byte[] deflate(byte[] input) {
+
+       in = input;
+       inLength = input.length;
+
+       // write zlib header
+       bytes.write((byte) 0x78); // window size = 0x70 (32768), compression method = 0x08
+       bytes.write((byte) 0x9C); // compression level = 0x80 (default), check bits = 0x1C
+
+       // compute checksum
+       for (int i = 0; i < inLength; i++) {
+               updateAdler(in[i]);
+       }
+
+       //store();
+
+       //compressHuffmanOnly();
+
+       compress();
+
+       // write checksum
+       writeInt(bytes, adler32);
+
+       return bytes.toByteArray();
+
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java
new file mode 100644 (file)
index 0000000..b00aa65
--- /dev/null
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+import java.util.zip.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+final class PngEncoder extends Object {
+
+       static final byte SIGNATURE[] = {(byte) '\211', (byte) 'P', (byte) 'N', (byte) 'G', (byte) '\r', (byte) '\n', (byte) '\032', (byte) '\n'};
+       static final byte TAG_IHDR[] = {(byte) 'I', (byte) 'H', (byte) 'D', (byte) 'R'};
+       static final byte TAG_PLTE[] = {(byte) 'P', (byte) 'L', (byte) 'T', (byte) 'E'};
+       static final byte TAG_TRNS[] = {(byte) 't', (byte) 'R', (byte) 'N', (byte) 'S'};
+       static final byte TAG_IDAT[] = {(byte) 'I', (byte) 'D', (byte) 'A', (byte) 'T'};
+       static final byte TAG_IEND[] = {(byte) 'I', (byte) 'E', (byte) 'N', (byte) 'D'};
+
+       static final int NO_COMPRESSION = 0;
+       static final int BEST_SPEED = 1;
+       static final int BEST_COMPRESSION = 9;
+       static final int DEFAULT_COMPRESSION = -1;
+
+       ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
+       PngChunk chunk;
+
+       ImageLoader loader;
+       ImageData data;
+       int transparencyType;
+
+       int width, height, bitDepth, colorType;
+
+       int compressionMethod = 0;
+       int filterMethod = 0;
+       int interlaceMethod = 0;
+
+public PngEncoder(ImageLoader loader) {
+
+       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 == SWT.TRANSPARENCY_ALPHA) {
+                       this.colorType = 6;
+               }
+       }
+       else {
+               this.colorType = 3;
+       }
+
+       if (!(colorType == 2 || colorType == 3 || colorType == 6)) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+}
+
+void writeShort(ByteArrayOutputStream baos, int theShort) {
+
+       byte byte1 = (byte) ((theShort >> 8) & 0xff);
+       byte byte2 = (byte) (theShort & 0xff);
+       byte[] temp = {byte1, byte2};
+       baos.write(temp, 0, 2);
+
+}
+
+void writeInt(ByteArrayOutputStream baos, int theInt) {
+
+       byte byte1 = (byte) ((theInt >> 24) & 0xff);
+       byte byte2 = (byte) ((theInt >> 16) & 0xff);
+       byte byte3 = (byte) ((theInt >> 8) & 0xff);
+       byte byte4 = (byte) (theInt & 0xff);
+       byte[] temp = {byte1, byte2, byte3, byte4};
+       baos.write(temp, 0, 4);
+
+}
+
+void writeChunk(byte[] tag, byte[] buffer) {
+
+       int bufferLength = (buffer != null) ? buffer.length : 0;
+
+       chunk = new PngChunk(bufferLength);
+
+       writeInt(bytes, bufferLength);
+       bytes.write(tag, 0, 4);
+       chunk.setType(tag);
+       if (bufferLength != 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((byte) RGBs[i].red);
+               baos.write((byte) RGBs[i].green);
+               baos.write((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] = (byte) alphaValue;
+
+                               }
+
+                       }
+
+                       baos.write(alphas, 0, alphas.length);
+
+                       break;
+
+               case SWT.TRANSPARENCY_PIXEL:
+
+                       int pixel = data.transparentPixel;
+
+                       if (colorType == 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 == 3) {
+
+                               byte[] padding = new byte[pixel + 1];
+
+                               for (int i = 0; i < pixel; i++) {
+
+                                       padding[i] = (byte) 255;
+
+                               }
+
+                               padding[pixel] = (byte) 0;
+
+                               baos.write(padding, 0, padding.length);
+
+                       }
+
+                       break;
+
+       }
+
+       writeChunk(TAG_TRNS, baos.toByteArray());
+
+}
+
+void writeImageData() throws IOException {
+
+       ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+       OutputStream os = null;
+       switch (loader.compression) {
+       case 0:
+               os = new DeflaterOutputStream(baos, new Deflater(NO_COMPRESSION));
+               break;
+       case 1:
+               os = new DeflaterOutputStream(baos, new Deflater(BEST_SPEED));
+               break;
+       case 3:
+               os = new DeflaterOutputStream(baos, new Deflater(BEST_COMPRESSION));
+               break;
+       default:
+               os = new DeflaterOutputStream(baos, new Deflater(DEFAULT_COMPRESSION));
+               break;
+       }
+
+       if (colorType == 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);
+
+                       os.write(lineData);
+
+               }
+
+       }
+
+       else {
+
+               int[] lineData = new int[width];
+               byte[] alphaData = null;
+               if (colorType == 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;
+
+               byte[] lineBytes = new byte[width * (colorType == 6 ? 4 : 3)];
+
+               for (int y = 0; y < height; y++) {
+
+                       int filter = 0;
+                       os.write(filter);
+
+                       data.getPixels(0, y, width, lineData, 0);
+
+                       if (colorType == 6) {
+                               data.getAlphas(0, y, width, alphaData, 0);
+                       }
+
+                       int offset = 0;
+                       for (int x = 0; x < lineData.length; x++) {
+
+                               int pixel = lineData[x];
+
+                               int r = pixel & redMask;
+                               lineBytes[offset++] = (byte) ((redShift < 0) ? r >>> -redShift
+                                               : r << redShift);
+                               int g = pixel & greenMask;
+                               lineBytes[offset++] = (byte) ((greenShift < 0) ? g >>> -greenShift
+                                               : g << greenShift);
+                               int b = pixel & blueMask;
+                               lineBytes[offset++] = (byte) ((blueShift < 0) ? b >>> -blueShift
+                                               : b << blueShift);
+
+                               if (colorType == 6) {
+                                       lineBytes[offset++] = alphaData[x];
+                               }
+
+                       }
+
+                       os.write(lineBytes);
+
+               }
+
+       }
+
+       os.flush();
+       os.close();
+
+       byte[] compressed = baos.toByteArray();
+       if (os == baos) {
+               /* Use PngDeflater for J2ME. */
+               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 == 3) {
+                       writePalette();
+               }
+
+               boolean transparencyAlpha = (transparencyType == SWT.TRANSPARENCY_ALPHA);
+               boolean transparencyPixel = (transparencyType == SWT.TRANSPARENCY_PIXEL);
+               boolean type2Transparency = (colorType == 2 && transparencyPixel);
+               boolean type3Transparency = (colorType == 3 && (transparencyAlpha || transparencyPixel));
+
+               if (type2Transparency || type3Transparency) {
+                       writeTransparency();
+               }
+
+               writeImageData();
+               writeEnd();
+
+               outputStream.write(bytes.toByteArray());
+
+       }
+
+       catch (IOException e) {
+
+               SWT.error(SWT.ERROR_IO, e);
+
+       }
+
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngFileReadState.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngFileReadState.java
new file mode 100644 (file)
index 0000000..1faab9b
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+class PngFileReadState extends Object {
+       boolean readIHDR;
+       boolean readPLTE;
+       boolean readIDAT;
+       boolean readIEND;
+
+       // Non - critical chunks
+       boolean readTRNS;
+
+       // Set to true after IDATs have been read.
+       boolean readPixelData;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTable.java
new file mode 100644 (file)
index 0000000..ca7aef4
--- /dev/null
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+
+public class PngHuffmanTable {
+       CodeLengthInfo[] codeLengthInfo;
+       int[] codeValues;
+
+       static final int MAX_CODE_LENGTH = 15;
+       static final int BAD_CODE = 0xFFFFFFF;
+       static final int incs[] = {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1};
+
+PngHuffmanTable (int[] lengths) {
+       super();
+       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] == 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 != lengths[i]) {
+                       lastLength++;
+                       code <<= 1;
+               }
+               if (lastLength != 0) {
+                       codes[i] = code;
+                       code++;
+               }
+       }
+
+       int last = 0;
+       for (int i = 0; i < lengths.length; i++) {
+               if (last != lengths[i]) {
+                       last = lengths[i];
+                       codeLengthInfo[last - 1].baseIndex = i;
+                       codeLengthInfo[last - 1].min = codes[i];
+               }
+               if (last != 0) codeLengthInfo[last - 1].max = codes[i];
+       }
+}
+
+int getNextValue(PngDecodingDataStream stream) throws IOException {
+       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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTables.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTables.java
new file mode 100644 (file)
index 0000000..9f60c6c
--- /dev/null
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+
+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) throws IOException {
+       return new PngHuffmanTables(stream);
+}
+static PngHuffmanTables getFixedTables() {
+       return new PngHuffmanTables();
+}
+
+private PngHuffmanTable getFixedLiteralTable() {
+       if (FixedLiteralTable == null) {
+               FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
+       }
+       return FixedLiteralTable;
+}
+
+private PngHuffmanTable getFixedDistanceTable() {
+       if (FixedDistanceTable == null) {
+               FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
+       }
+       return FixedDistanceTable;
+}
+
+private PngHuffmanTables () {
+       literalTable = getFixedLiteralTable();
+       distanceTable = getFixedDistanceTable();
+}
+
+private PngHuffmanTables (PngDecodingDataStream stream) throws IOException {
+       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) throws IOException
+{
+       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 == 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 == 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 == 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) throws IOException {
+       return literalTable.getNextValue(stream);
+}
+
+int getNextDistanceValue(PngDecodingDataStream stream) throws IOException {
+       return distanceTable.getNextValue(stream);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIdatChunk.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIdatChunk.java
new file mode 100644 (file)
index 0000000..b1a884d
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+class PngIdatChunk extends PngChunk {
+
+       static final int HEADER_BYTES_LENGTH = 2;
+       static final int ADLER_FIELD_LENGTH = 4;
+       static final int HEADER_BYTE1_DATA_OFFSET = DATA_OFFSET + 0;
+       static final int HEADER_BYTE2_DATA_OFFSET = DATA_OFFSET + 1;
+       static final int ADLER_DATA_OFFSET = DATA_OFFSET + 2; // plus variable compressed data length
+
+PngIdatChunk(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());
+}
+
+PngIdatChunk(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];
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIendChunk.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIendChunk.java
new file mode 100644 (file)
index 0000000..fa9992b
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+
+class PngIendChunk extends PngChunk {
+
+PngIendChunk() {
+       super(0);
+       setType(TYPE_IEND);
+       setCRC(computeCRC());
+}
+
+PngIendChunk(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);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIhdrChunk.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngIhdrChunk.java
new file mode 100644 (file)
index 0000000..b71bc8f
--- /dev/null
@@ -0,0 +1,414 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+class PngIhdrChunk extends PngChunk {
+       static final int IHDR_DATA_LENGTH = 13;
+
+       static final int WIDTH_DATA_OFFSET = DATA_OFFSET + 0;
+       static final int HEIGHT_DATA_OFFSET = DATA_OFFSET + 4;
+       static final int BIT_DEPTH_OFFSET = DATA_OFFSET + 8;
+       static final int COLOR_TYPE_OFFSET = DATA_OFFSET + 9;
+       static final int COMPRESSION_METHOD_OFFSET = DATA_OFFSET + 10;
+       static final int FILTER_METHOD_OFFSET = DATA_OFFSET + 11;
+       static final int INTERLACE_METHOD_OFFSET = DATA_OFFSET + 12;
+
+       static final byte COLOR_TYPE_GRAYSCALE = 0;
+       static final byte COLOR_TYPE_RGB = 2;
+       static final byte COLOR_TYPE_PALETTE = 3;
+       static final byte COLOR_TYPE_GRAYSCALE_WITH_ALPHA = 4;
+       static final byte COLOR_TYPE_RGB_WITH_ALPHA = 6;
+
+       static final int INTERLACE_METHOD_NONE = 0;
+       static final int INTERLACE_METHOD_ADAM7 = 1;
+
+       static final int FILTER_NONE = 0;
+       static final int FILTER_SUB = 1;
+       static final int FILTER_UP = 2;
+       static final int FILTER_AVERAGE = 3;
+       static final int FILTER_PAETH = 4;
+
+       static final byte[] ValidBitDepths = {1, 2, 4, 8, 16};
+       static final byte[] ValidColorTypes = {0, 2, 3, 4, 6};
+
+       int width, height;
+       byte bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod;
+
+PngIhdrChunk(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.
+ */
+PngIhdrChunk(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 != IHDR_DATA_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+       if (compressionMethod != 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+       if (interlaceMethod != INTERLACE_METHOD_NONE &&
+               interlaceMethod != INTERLACE_METHOD_ADAM7) {
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+       }
+
+       boolean colorTypeIsValid = false;
+       for (int i = 0; i < ValidColorTypes.length; i++) {
+               if (ValidColorTypes[i] == colorType) {
+                       colorTypeIsValid = true;
+                       break;
+               }
+       }
+       if (!colorTypeIsValid) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+       boolean bitDepthIsValid = false;
+       for (int i = 0; i < ValidBitDepths.length; i++) {
+               if (ValidBitDepths[i] == bitDepth) {
+                       bitDepthIsValid = true;
+                       break;
+               }
+       }
+       if (!bitDepthIsValid) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+       if ((colorType == COLOR_TYPE_RGB
+               || colorType == COLOR_TYPE_RGB_WITH_ALPHA
+               || colorType == COLOR_TYPE_GRAYSCALE_WITH_ALPHA)
+               && bitDepth < 8)
+       {
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+       }
+
+       if (colorType == 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 - " + 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
+void contributeToString(StringBuilder buffer) {
+       buffer.append("\n\tWidth: ");
+       buffer.append(width);
+       buffer.append("\n\tHeight: ");
+       buffer.append(height);
+       buffer.append("\n\tBit Depth: ");
+       buffer.append(bitDepth);
+       buffer.append("\n\tColor Type: ");
+       buffer.append(getColorTypeString());
+       buffer.append("\n\tCompression Method: ");
+       buffer.append(compressionMethod);
+       buffer.append("\n\tFilter Method: ");
+       buffer.append(getFilterMethodString());
+       buffer.append("\n\tInterlace Method: ");
+       buffer.append(getInterlaceMethodString());
+}
+
+boolean getMustHavePalette() {
+       return colorType == COLOR_TYPE_PALETTE;
+}
+
+boolean getCanHavePalette() {
+       return colorType != COLOR_TYPE_GRAYSCALE &&
+               colorType != 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;
+}
+
+boolean 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;
+       }
+}
+
+
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngInputStream.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngInputStream.java
new file mode 100644 (file)
index 0000000..ec4aac6
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+
+public class PngInputStream extends InputStream {
+       PngChunkReader reader;
+       PngChunk chunk;
+       int offset, length;
+
+       final static int DATA_OFFSET = 8;
+
+public PngInputStream(PngIdatChunk chunk, PngChunkReader reader) {
+       this.chunk = chunk;
+       this.reader = reader;
+       length = chunk.getLength();
+       offset = 0;
+}
+
+private boolean checkChunk() throws IOException {
+       while (offset == length) {
+               chunk = reader.readNextChunk();
+               if (chunk == null) throw new IOException();
+               if (chunk.getChunkType() == PngChunk.CHUNK_IEND) return false;
+               if (chunk.getChunkType() != PngChunk.CHUNK_IDAT) throw new IOException();
+               length = chunk.getLength();
+               offset = 0;
+       }
+       return true;
+}
+
+@Override
+public void close() throws IOException {
+       chunk = null;
+}
+
+@Override
+public int read() throws IOException {
+       if (chunk == null) throw new IOException();
+       if (offset == length && !checkChunk()) return -1;
+       int b = chunk.reference[DATA_OFFSET + offset] & 0xFF;
+       offset++;
+       return b;
+}
+
+@Override
+public int read(byte[] b, int off, int len) throws IOException {
+       if (chunk == null) throw new IOException();
+       if (offset == length && !checkChunk()) return -1;
+       len = Math.min(len, length - offset);
+       System.arraycopy(chunk.reference, DATA_OFFSET + offset, b, off, len);
+       offset += len;
+       return len;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngLzBlockReader.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngLzBlockReader.java
new file mode 100644 (file)
index 0000000..71673cd
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+
+public class PngLzBlockReader {
+       boolean isLastBlock;
+       byte compressionType;
+       int uncompressedBytesRemaining;
+       PngDecodingDataStream stream;
+       PngHuffmanTables huffmanTables;
+
+       byte[] window;
+       int windowIndex;
+       int copyIndex;
+       int copyBytesRemaining;
+
+       static final int UNCOMPRESSED = 0;
+       static final int COMPRESSED_FIXED = 1;
+       static final int COMPRESSED_DYNAMIC = 2;
+
+       static final int END_OF_COMPRESSED_BLOCK = 256;
+       static final int FIRST_LENGTH_CODE = 257;
+       static final int LAST_LENGTH_CODE = 285;
+       static final int FIRST_DISTANCE_CODE = 1;
+       static final int LAST_DISTANCE_CODE = 29;
+       static final int FIRST_CODE_LENGTH_CODE = 4;
+       static final int LAST_CODE_LENGTH_CODE = 19;
+
+       static final 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 final 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 final 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 final 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,
+       };
+
+
+PngLzBlockReader(PngDecodingDataStream stream) {
+       this.stream = stream;
+       isLastBlock = false;
+}
+
+void setWindowSize(int windowSize) {
+       window = new byte[windowSize];
+}
+
+void readNextBlockHeader() throws IOException {
+       isLastBlock = stream.getNextIdatBit() != 0;
+       compressionType = (byte) stream.getNextIdatBits(2);
+       if (compressionType > 2) stream.error();
+
+       if (compressionType == UNCOMPRESSED) {
+               byte b1 = stream.getNextIdatByte();
+               byte b2 = stream.getNextIdatByte();
+               byte b3 = stream.getNextIdatByte();
+               byte b4 = stream.getNextIdatByte();
+               if (b1 != ~b3 || b2 != ~b4) stream.error();
+               uncompressedBytesRemaining = (b1 & 0xFF) | ((b2 & 0xFF) << 8);
+       } else if (compressionType == COMPRESSED_DYNAMIC) {
+               huffmanTables = PngHuffmanTables.getDynamicTables(stream);
+       } else {
+               huffmanTables = PngHuffmanTables.getFixedTables();
+       }
+}
+
+byte getNextByte() throws IOException {
+       if (compressionType == UNCOMPRESSED) {
+               if (uncompressedBytesRemaining == 0) {
+                       readNextBlockHeader();
+                       return getNextByte();
+               }
+               uncompressedBytesRemaining--;
+               return stream.getNextIdatByte();
+       } else {
+               return getNextCompressedByte();
+       }
+}
+
+private void assertBlockAtEnd() throws IOException {
+       if (compressionType == UNCOMPRESSED) {
+               if (uncompressedBytesRemaining > 0) stream.error();
+       } else if (copyBytesRemaining > 0 ||
+               (huffmanTables.getNextLiteralValue(stream) != END_OF_COMPRESSED_BLOCK))
+       {
+               stream.error();
+       }
+}
+void assertCompressedDataAtEnd() throws IOException {
+       assertBlockAtEnd();
+       while (!isLastBlock) {
+               readNextBlockHeader();
+               assertBlockAtEnd();
+       }
+}
+
+private byte getNextCompressedByte() throws IOException {
+       if (copyBytesRemaining > 0) {
+               byte value = window[copyIndex];
+               window[windowIndex] = value;
+               copyBytesRemaining--;
+
+               copyIndex++;
+               windowIndex++;
+               if (copyIndex == window.length) copyIndex = 0;
+               if (windowIndex == window.length) windowIndex = 0;
+
+               return value;
+       }
+
+       int value = huffmanTables.getNextLiteralValue(stream);
+       if (value < END_OF_COMPRESSED_BLOCK) {
+               window[windowIndex] = (byte) value;
+               windowIndex++;
+               if (windowIndex >= window.length) windowIndex = 0;
+               return (byte) value;
+       } else if (value == 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;
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngPlteChunk.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngPlteChunk.java
new file mode 100644 (file)
index 0000000..f0d1f6d
--- /dev/null
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+class PngPlteChunk extends PngChunk {
+
+       int paletteSize;
+
+PngPlteChunk(PaletteData palette) {
+       super(palette.getRGBs().length * 3);
+       paletteSize = length / 3;
+       setType(TYPE_PLTE);
+       setPaletteData(palette);
+       setCRC(computeCRC());
+}
+
+PngPlteChunk(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] = (byte) rgbs[i].red;
+               reference[offset + 1] = (byte) rgbs[i].green;
+               reference[offset + 2] = (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 != 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
+void contributeToString(StringBuilder buffer) {
+       buffer.append("\n\tPalette size:");
+       buffer.append(paletteSize);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngTrnsChunk.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngTrnsChunk.java
new file mode 100644 (file)
index 0000000..9df7d9d
--- /dev/null
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+public class PngTrnsChunk extends PngChunk {
+       static final int TRANSPARENCY_TYPE_PIXEL = 0;
+       static final int TRANSPARENCY_TYPE_ALPHAS = 1;
+       static final int RGB_DATA_LENGTH = 6;
+
+PngTrnsChunk(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());
+}
+
+PngTrnsChunk(byte[] reference){
+       super(reference);
+}
+
+@Override
+int getChunkType() {
+       return CHUNK_tRNS;
+}
+
+void validateLength(PngIhdrChunk header, PngPlteChunk paletteChunk) {
+       boolean valid;
+       switch (header.getColorType()) {
+               case PngIhdrChunk.COLOR_TYPE_RGB:
+                       // Three 2-byte values (RGB)
+                       valid = getLength() == 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() == 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() == 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() != 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] = (byte) 255;
+       }
+       return alphas;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFDirectory.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFDirectory.java
new file mode 100644 (file)
index 0000000..0be7e94
--- /dev/null
@@ -0,0 +1,680 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+final class TIFFDirectory {
+
+       TIFFRandomFileAccess file;
+       boolean isLittleEndian;
+       ImageLoader loader;
+       int depth;
+
+       /* Directory fields */
+       int subfileType;
+       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 out;
+
+       static final int NO_VALUE = -1;
+
+       static final short TAG_NewSubfileType = 254;
+       static final short TAG_SubfileType = 255;
+       static final short TAG_ImageWidth = 256;
+       static final short TAG_ImageLength = 257;
+       static final short TAG_BitsPerSample = 258;
+       static final short TAG_Compression = 259;
+       static final short TAG_PhotometricInterpretation = 262;
+       static final short TAG_FillOrder = 266;
+       static final short TAG_ImageDescription = 270;
+       static final short TAG_StripOffsets = 273;
+       static final short TAG_Orientation = 274;
+       static final short TAG_SamplesPerPixel = 277;
+       static final short TAG_RowsPerStrip = 278;
+       static final short TAG_StripByteCounts = 279;
+       static final short TAG_XResolution = 282;
+       static final short TAG_YResolution = 283;
+       static final short TAG_PlanarConfiguration = 284;
+       static final short TAG_T4Options = 292;
+       static final short TAG_ResolutionUnit = 296;
+       static final short TAG_Software = 305;
+       static final short TAG_DateTime = 306;
+       static final short TAG_ColorMap = 320;
+
+       static final int TYPE_BYTE = 1;
+       static final int TYPE_ASCII = 2;
+       static final int TYPE_SHORT = 3;
+       static final int TYPE_LONG = 4;
+       static final int TYPE_RATIONAL = 5;
+
+       static final int FILETYPE_REDUCEDIMAGE = 1;
+       static final int FILETYPE_PAGE = 2;
+       static final int FILETYPE_MASK = 4;
+       static final int OFILETYPE_IMAGE = 1;
+       static final int OFILETYPE_REDUCEDIMAGE = 2;
+       static final int OFILETYPE_PAGE = 3;
+
+       /* Different compression schemes */
+       static final int COMPRESSION_NONE = 1;
+       static final int COMPRESSION_CCITT_3_1 = 2;
+       static final int COMPRESSION_PACKBITS = 32773;
+
+       static final int IFD_ENTRY_SIZE = 12;
+
+public TIFFDirectory(TIFFRandomFileAccess file, boolean isLittleEndian, ImageLoader loader) {
+       this.file = file;
+       this.isLittleEndian = isLittleEndian;
+       this.loader = loader;
+}
+
+public TIFFDirectory(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 (n >= 0) {
+                       /* Copy next n+1 bytes literally */
+                       System.arraycopy(src, ++srcIndex, dest, destIndex, n + 1);
+                       srcIndex += n + 1;
+                       destIndex += n + 1;
+               } else if (n >= -127) {
+                       /* 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 == -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) throws IOException {
+       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) throws IOException {
+       /* 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 == COMPRESSION_NONE) {
+                       System.arraycopy(data, 0, imageData, destIndex, data.length);
+                       destIndex += data.length;
+               } else if (compression == COMPRESSION_PACKBITS) {
+                       destIndex += decodePackBits(data, imageData, destIndex);
+               } else if (compression == COMPRESSION_CCITT_3_1 || compression == 3) {
+                       TIFFModifiedHuffmanCodec codec = new TIFFModifiedHuffmanCodec();
+                       int nRows = rowsPerStrip;
+                       if (i == length -1) {
+                               int n = imageLength % rowsPerStrip;
+                               if (n != 0) nRows = n;
+                       }
+                       destIndex += codec.decode(data, imageData, destIndex, imageWidth, nRows);
+               }
+               if (loader.hasListeners()) {
+                       loader.notifyListeners(new ImageLoaderEvent(loader, image, i, i == length - 1));
+               }
+       }
+}
+
+PaletteData getColorMap() throws IOException {
+       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 == 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 == 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 != 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) throws IOException {
+       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_NewSubfileType: {
+                               subfileType = getEntryValue(type, buffer, offset);
+                               break;
+                       }
+                       case TAG_SubfileType: {
+                               int oldSubfileType = getEntryValue(type, buffer, offset);
+                               subfileType = oldSubfileType == OFILETYPE_REDUCEDIMAGE ? FILETYPE_REDUCEDIMAGE : oldSubfileType == OFILETYPE_PAGE ? FILETYPE_PAGE : 0;
+                               break;
+                       }
+                       case TAG_ImageWidth: {
+                               imageWidth = getEntryValue(type, buffer, offset);
+                               break;
+                       }
+                       case TAG_ImageLength: {
+                               imageLength = getEntryValue(type, buffer, offset);
+                               break;
+                       }
+                       case TAG_BitsPerSample: {
+                               if (type != 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_FillOrder: {
+                               /* Ignored: baseline only requires default fill order. */
+                               break;
+                       }
+                       case TAG_ImageDescription: {
+                               /* Ignored */
+                               break;
+                       }
+                       case TAG_PhotometricInterpretation: {
+                               photometricInterpretation = getEntryValue(type, buffer, offset);
+                               break;
+                       }
+                       case TAG_StripOffsets: {
+                               if (type != TYPE_LONG && type != TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                               stripOffsets = new int[count];
+                               getEntryValue(type, buffer, offset, stripOffsets);
+                               break;
+                       }
+                       case TAG_Orientation: {
+                               /* Ignored: baseline only requires top left orientation. */
+                               break;
+                       }
+                       case TAG_SamplesPerPixel: {
+                               if (type != TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                               samplesPerPixel = getEntryValue(type, buffer, offset);
+                               /* Only the basic 1 and 3 values are supported */
+                               if (samplesPerPixel != 1 && samplesPerPixel != 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_PlanarConfiguration: {
+                               /* Ignored: baseline only requires default planar configuration. */
+                               break;
+                       }
+                       case TAG_T4Options: {
+                               if (type != TYPE_LONG) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                               t4Options = getEntryValue(type, buffer, offset);
+                               if ((t4Options & 0x1) == 1) {
+                                       /* 2-dimensional coding is not supported */
+                                       SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+                               }
+                               break;
+                       }
+                       case TAG_ResolutionUnit: {
+                               /* Ignored */
+                               break;
+                       }
+                       case TAG_Software: {
+                               /* Ignored */
+                               break;
+                       }
+                       case TAG_DateTime: {
+                               /* Ignored */
+                               break;
+                       }
+                       case TAG_ColorMap: {
+                               if (type != TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                               /* Get the offset of the colorMap (use TYPE_LONG) */
+                               colorMapOffset = getEntryValue(TYPE_LONG, buffer, offset);
+                               break;
+                       }
+               }
+       }
+}
+
+public ImageData read(int [] nextIFDOffset) throws IOException {
+       /* Set TIFF default values */
+       bitsPerSample = new int[] {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);
+       byte buffer2[] = new byte[4];
+       file.read(buffer2);
+       nextIFDOffset[0] = toInt(buffer2, 0, TYPE_LONG);
+       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 != 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 == 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 == 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 == 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) throws IOException {
+       boolean isRGB = photometricInterpretation == 2;
+       boolean isColorMap = photometricInterpretation == 3;
+       boolean isBiLevel = photometricInterpretation == 0 || photometricInterpretation == 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 != 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 */
+       out.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) */
+       out.writeInt(0);
+
+       /* Values longer than 4 bytes Section */
+
+       /* BitsPerSample 8,8,8 */
+       if (isRGB) for (int i = 0; i < 3; i++) out.writeShort(8);
+       if (cnt > 1) {
+               for (int i = 0; i < cnt; i++) out.writeInt(stripOffsets[i]);
+               for (int i = 0; i < cnt; i++) out.writeInt(stripByteCounts[i]);
+       }
+       /* XResolution and YResolution set to 300 dpi */
+       for (int i = 0; i < 2; i++) {
+               out.writeInt(300);
+               out.writeInt(1);
+       }
+       /* ColorMap */
+       if (isColorMap) for (int i = 0; i < colorMap.length; i++) out.writeShort(colorMap[i]);
+
+       /* Image Data */
+       out.write(data);
+}
+
+void writeEntry(short tag, int type, int count, int value) throws IOException {
+       out.writeShort(tag);
+       out.writeShort(type);
+       out.writeInt(count);
+       out.writeInt(value);
+}
+
+void writeHeader() throws IOException {
+       /* little endian */
+       out.write(0x49);
+       out.write(0x49);
+
+       /* TIFF identifier */
+       out.writeShort(42);
+       /*
+       * Offset of the first IFD is chosen to be 8.
+       * It is word aligned and immediately after this header.
+       */
+       out.writeInt(8);
+}
+
+void writeToStream(LEDataOutputStream byteStream) throws IOException {
+       out = byteStream;
+       int photometricInterpretation = -1;
+
+       /* Scanline pad must be 1 */
+       if (image.scanlinePad != 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 == null || rgbs.length != 2) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+                       RGB rgb0 = rgbs[0];
+                       RGB rgb1 = rgbs[1];
+                       if (!(rgb0.red == rgb0.green && rgb0.green == rgb0.blue &&
+                               rgb1.red == rgb1.green && rgb1.green == rgb1.blue &&
+                               ((rgb0.red == 0x0 && rgb1.red == 0xFF) || (rgb0.red == 0xFF && rgb1.red == 0x0)))) {
+                               SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+                       }
+                       /* 0 means a color index of 0 is imaged as white */
+                       photometricInterpretation = image.palette.colors[0].red == 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);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFFileFormat.java
new file mode 100644 (file)
index 0000000..56112ba
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+/**
+ * Baseline TIFF decoder revision 6.0
+ * Extension T4-encoding CCITT T.4 1D
+ */
+public final class TIFFFileFormat extends FileFormat {
+
+@Override
+boolean isFileFormat(LEDataInputStream stream) {
+       try {
+               byte[] header = new byte[4];
+               stream.read(header);
+               stream.unread(header);
+               if (header[0] != header[1]) return false;
+               if (!(header[0] == 0x49 && header[2] == 42 && header[3] == 0) &&
+                       !(header[0] == 0x4d && header[2] == 0 && header[3] == 42)) {
+                       return false;
+               }
+               return true;
+       } catch (Exception e) {
+               return false;
+       }
+}
+
+@Override
+ImageData[] loadFromByteStream() {
+       byte[] header = new byte[8];
+       boolean isLittleEndian;
+       ImageData[] images = new ImageData[0];
+       TIFFRandomFileAccess file = new TIFFRandomFileAccess(inputStream);
+       try {
+               file.read(header);
+               if (header[0] != header[1]) SWT.error(SWT.ERROR_INVALID_IMAGE);
+               if (!(header[0] == 0x49 && header[2] == 42 && header[3] == 0) &&
+                       !(header[0] == 0x4d && header[2] == 0 && header[3] == 42)) {
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+               }
+               isLittleEndian = header[0] == 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);
+               while (offset != 0) {
+                       file.seek(offset);
+                       TIFFDirectory directory = new TIFFDirectory(file, isLittleEndian, loader);
+                       int [] nextIFDOffset = new int[1];
+                       ImageData image = directory.read(nextIFDOffset);
+                       offset = nextIFDOffset[0];
+                       ImageData[] oldImages = images;
+                       images = new ImageData[oldImages.length + 1];
+                       System.arraycopy(oldImages, 0, images, 0, oldImages.length);
+                       images[images.length - 1] = 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);
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFModifiedHuffmanCodec.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFModifiedHuffmanCodec.java
new file mode 100644 (file)
index 0000000..03e887e
--- /dev/null
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.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  */
+               {{2, 3}, {3, 2}},
+               /* 3 bits  */
+               {{2, 1}, {3, 4}},
+               /* 4 bits  */
+               {{2, 6}, {3, 5}},
+               /* 5 bits  */
+               {{3, 7}},
+               /* 6 bits  */
+               {{4, 9}, {5, 8}},
+               /* 7 bits  */
+               {{4, 10}, {5, 11}, {7, 12}},
+               /* 8 bits  */
+               {{4, 13}, {7, 14}},
+               /* 9 bits  */
+               {{24, 15}},
+               /* 10 bits */
+               {{8, 18}, {15, 64}, {23, 16}, {24, 17}, {55, 0}},
+               /* 11 bits */
+               {/* EOL */{0, -1}, {8, 1792}, {23, 24}, {24, 25}, {40, 23}, {55, 22}, {103, 19},
+               {104, 20}, {108, 21}, {12, 1856}, {13, 1920}},
+               /* 12 bits */
+               {{18, 1984}, {19, 2048}, {20, 2112}, {21, 2176}, {22, 2240}, {23, 2304},
+               {28, 2368}, {29, 2432}, {30, 2496}, {31, 2560}, {36, 52}, {39, 55}, {40, 56},
+               {43, 59}, {44, 60}, {51, 320}, {52, 384}, {53, 448}, {55, 53}, {56, 54}, {82, 50},
+               {83, 51}, {84, 44}, {85, 45}, {86, 46}, {87, 47}, {88, 57}, {89, 58}, {90, 61},
+               {91, 256}, {100, 48}, {101, 49}, {102, 62}, {103, 63}, {104, 30}, {105, 31},
+               {106, 32}, {107, 33}, {108, 40}, {109, 41}, {200, 128}, {201, 192}, {202, 26},
+               {203, 27}, {204, 28}, {205, 29}, {210, 34}, {211, 35}, {212, 36}, {213, 37},
+               {214, 38}, {215, 39}, {218, 42}, {219, 43}},
+               /* 13 bits */
+               {{74, 640}, {75, 704}, {76, 768}, {77, 832}, {82, 1280}, {83, 1344}, {84, 1408},
+               {85, 1472}, {90, 1536}, {91, 1600}, {100, 1664}, {101, 1728}, {108, 512},
+               {109, 576}, {114, 896}, {115, 960}, {116, 1024}, {117, 1088}, {118, 1152},
+               {119, 1216}}
+       };
+
+       static final short[][][] WHITE_CODE = {
+               /* 4 bits */
+               {{7, 2}, {8, 3}, {11, 4}, {12, 5}, {14, 6}, {15, 7}},
+               /* 5 bits */
+               {{7, 10}, {8, 11}, {18, 128}, {19, 8}, {20, 9}, {27, 64}},
+               /* 6 bits */
+               {{3, 13}, {7, 1}, {8, 12}, {23, 192}, {24, 1664}, {42, 16}, {43, 17}, {52, 14},
+               {53, 15}},
+               /* 7 bits */
+               {{3, 22}, {4, 23}, {8, 20}, {12, 19}, {19, 26}, {23, 21}, {24, 28}, {36, 27},
+               {39, 18}, {40, 24}, {43, 25}, {55, 256}},
+               /* 8 bits */
+               {{2, 29}, {3, 30}, {4, 45}, {5, 46}, {10, 47}, {11, 48}, {18, 33}, {19, 34},
+               {20, 35}, {21, 36}, {22, 37}, {23, 38}, {26, 31}, {27, 32}, {36, 53}, {37, 54},
+               {40, 39}, {41, 40}, {42, 41}, {43, 42}, {44, 43}, {45, 44}, {50, 61}, {51, 62},
+               {52, 63}, {53, 0}, {54, 320}, {55, 384}, {74, 59}, {75, 60}, {82, 49}, {83, 50},
+               {84, 51}, {85, 52}, {88, 55}, {89, 56}, {90, 57}, {91, 58}, {100, 448},
+               {101, 512}, {103, 640}, {104, 576}},
+               /* 9 bits */
+               {{152, 1472}, {153, 1536}, {154, 1600}, {155, 1728}, {204, 704}, {205, 768},
+               {210, 832}, {211, 896}, {212, 960}, {213, 1024}, {214, 1088}, {215, 1152},
+               {216, 1216}, {217, 1280}, {218, 1344}, {219, 1408}},
+               /* 10 bits */
+               {},
+               /* 11 bits */
+               {{8, 1792}, {12, 1856}, {13, 1920}},
+               /* 12 bits */
+               {/* EOL */{1, -1}, {18, 1984}, {19, 2048}, {20, 2112}, {21, 2176}, {22, 2240}, {23, 2304},
+               {28, 2368}, {29, 2432}, {30, 2496}, {31, 2560}}
+       };
+
+       static final int BLACK_MIN_BITS = 2;
+       static final int WHITE_MIN_BITS = 4;
+
+       boolean 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;
+}
+
+boolean 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) {
+               boolean 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] == code) {
+                                       found = true;
+                                       partialRun = huffmanCode[i][j][1];
+                                       if (partialRun == -1) {
+                                               /* Stop when reaching final EOL on last byte */
+                                               if (byteOffsetSrc == 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 == 1 ?
+                       (byte)(dest[byteOffsetDest] | (1 << (7 - bitOffsetDest))) :
+                       (byte)(dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest)));
+               n--;
+               bitOffsetDest++;
+       }
+       if (bitOffsetDest == 8) {
+               byteOffsetDest++;
+               bitOffsetDest = 0;
+       }
+       while (n >= 8) {
+               dest[byteOffsetDest++] = (byte) (value == 1 ? 0xFF : 0);
+               n -= 8;
+       }
+       while (n > 0) {
+               dest[byteOffsetDest] = value == 1 ?
+                       (byte)(dest[byteOffsetDest] | (1 << (7 - bitOffsetDest))) :
+                       (byte)(dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest)));
+               n--;
+               bitOffsetDest++;
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFRandomFileAccess.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/TIFFRandomFileAccess.java
new file mode 100644 (file)
index 0000000..a06a3ef
--- /dev/null
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+
+final class TIFFRandomFileAccess {
+
+       LEDataInputStream inputStream;
+       int start, current, next;
+       byte[][] buffers;
+
+       static final int CHUNK_SIZE = 8192;
+       static final int LIST_SIZE = 128;
+
+public TIFFRandomFileAccess(LEDataInputStream stream) {
+       inputStream = stream;
+       start = current = next = inputStream.getPosition();
+       buffers = new byte[LIST_SIZE][];
+}
+
+void seek(int pos) throws IOException {
+       if (pos == current) return;
+       if (pos < start) throw new IOException();
+       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] == 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[]) throws IOException {
+       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] == 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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/WinBMPFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/WinBMPFileFormat.java
new file mode 100644 (file)
index 0000000..a20b883
--- /dev/null
@@ -0,0 +1,807 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+public final class WinBMPFileFormat extends FileFormat {
+       static final int BMPFileHeaderSize = 14;
+       static final int BMPHeaderFixedSize = 40;
+       int importantColors;
+       Point 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, boolean last) {
+       if (comp == 1) { // BMP_RLE8_COMPRESSION
+               return compressRLE8Data(src, srcOffset, numBytes, dest, last);
+       }
+       if (comp == 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, boolean 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] == src[sp + n + 1])
+                               break;
+               }
+               /* if there is only one more byte in the scan line, include it */
+               if (n < 127 && n == 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 == 2 pixels */
+                               dest[dp] = src[sp];
+                               dp++; sp++;
+                               size += 2;
+                               break;
+                       default:
+                               dest[dp] = 0; dp++;
+                               dest[dp] = (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) != 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] != theByte)
+                                       break;
+                       }
+                       dest[dp] = (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, boolean 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] == src[sp + n + 1])
+                               break;
+               }
+               /* if there is only one more byte in the scan line, include it */
+               if (n == 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] = (byte)n; dp++;
+                               for (i = n; i > 0; i--) {
+                                       dest[dp] = src[sp];
+                                       dp++; sp++;
+                               }
+                               size += 2 + n;
+                               if ((n & 1) != 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] != theByte)
+                                       break;
+                       }
+                       dest[dp] = (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 convertPixelsToBGR(ImageData image, byte[] dest) {
+       /*
+        * For direct palette, uncompressed image, BMP encoders expect the
+        * pixels to be in BGR format for 24 & 32 bit and RGB 1555 for 16 bit
+        * On Linux and MacOS, the pixels are in RGB format. Also, in
+        * MacOS, the alpha byte may be first.
+        * Hence, we use the palette information of the image and convert
+        * the pixels to the required format. Converted pixels are stored
+        * in dest byte array.
+        */
+       byte[] data = image.data;
+       PaletteData palette = image.palette;
+       for (int y = 0; y < image.height; y++) {
+               int index;
+               int srcX = 0, srcY = y;
+               int numOfBytes = image.depth / 8;
+               index = (y * image.bytesPerLine);
+
+               for (int i = 0; i < image.width; i++) {
+                       int pixel = 0;
+                       switch (image.depth) {
+                               case 32:
+                                       pixel = ((data[index] & 0xFF) << 24)
+                                                       | ((data[index + 1] & 0xFF) << 16)
+                                                       | ((data[index + 2] & 0xFF) << 8)
+                                                       | (data[index + 3] & 0xFF);
+                                       break;
+                               case 24:
+                                       pixel = ((data[index] & 0xFF) << 16)
+                                                       | ((data[index + 1] & 0xFF) << 8)
+                                                       | (data[index + 2] & 0xFF);
+                                       break;
+                               case 16:
+                                       pixel = ((data[index + 1] & 0xFF) << 8)
+                                                       | (data[index] & 0xFF);
+                                       break;
+                               default:
+                                       SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+                       }
+
+                       if (image.depth == 16) {
+                               /* convert to RGB 555 format */
+                               int r = pixel & palette.redMask;
+                               r = ((palette.redShift < 0) ? r >>> -palette.redShift
+                                               : r << palette.redShift);
+
+                               int g = pixel & palette.greenMask;
+                               g = ((palette.greenShift < 0) ? g >>> -palette.greenShift
+                                               : g << palette.greenShift);
+                               g = (g & 0xF8); /* In 565 format, G is 6 bit, mask it to 5 bit */
+
+                               int b = pixel & palette.blueMask;
+                               b = ((palette.blueShift < 0) ? b >>> -palette.blueShift
+                                               : b << palette.blueShift);
+
+                               int modPixel = (r << 7) | (g << 2) | (b >> 3);
+                               dest[index] = (byte) (modPixel & 0xFF);
+                               dest[index + 1] = (byte) ((modPixel >> 8) & 0xFF);
+                       } else {
+                               /* convert to BGR format */
+                               int b = pixel & palette.blueMask;
+                               dest[index] = (byte) ((palette.blueShift < 0) ? b >>> -palette.blueShift
+                                               : b << palette.blueShift);
+
+                               int g = pixel & palette.greenMask;
+                               dest[index + 1] = (byte) ((palette.greenShift < 0) ? g >>> -palette.greenShift
+                                               : g << palette.greenShift);
+
+                               int r = pixel & palette.redMask;
+                               dest[index + 2] = (byte) ((palette.redShift < 0) ? r >>> -palette.redShift
+                                               : r << palette.redShift);
+
+                               if (numOfBytes == 4) dest[index + 3] = 0;
+                       }
+
+                       srcX++;
+                       if (srcX >= image.width) {
+                               srcY++;
+                               index = srcY * image.bytesPerLine;
+                               srcX = 0;
+                       } else {
+                               index += numOfBytes;
+                       }
+               }
+       }
+}
+void decompressData(byte[] src, byte[] dest, int stride, int cmp) {
+       if (cmp == 1) { // BMP_RLE8_COMPRESSION
+               if (decompressRLE8Data(src, src.length, stride, dest, dest.length) <= 0)
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+               return;
+       }
+       if (cmp == 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 == 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) != 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) != 0)
+                                               sp++; /* word align sp? */
+                                       break;
+                       }
+               } else {
+                       if ((len & 1) != 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 == 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) != 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
+boolean 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] == 0x42 && header[1] == 0x4D && infoHeaderSize >= BMPHeaderFixedSize;
+       } catch (Exception e) {
+               return false;
+       }
+}
+boolean isPaletteBMP(PaletteData pal, int depth) {
+       switch(depth) {
+               case 32:
+                       if ((pal.redMask == 0xFF00) && (pal.greenMask == 0xFF0000) && (pal.blueMask == 0xFF000000)) return true;
+                       return false;
+               case 24:
+                       if ((pal.redMask == 0xFF) && (pal.greenMask == 0xFF00) && (pal.blueMask == 0xFF0000)) return true;
+                       return false;
+               case 16:
+                       if ((pal.redMask == 0x7C00) && (pal.greenMask == 0x3E0) && (pal.blueMask == 0x1F)) return true;
+                       return false;
+               default:
+                       return true;
+       }
+}
+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 == 0 || cmp == 3) { // BMP_NO_COMPRESSION
+               try {
+                       if (inputStream.read(data) != 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) != 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] != 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 == 1 /*BMP_RLE8_COMPRESSION*/) || (this.compression == 2 /*BMP_RLE4_COMPRESSION*/) ? SWT.IMAGE_BMP_RLE : SWT.IMAGE_BMP;
+       return new ImageData[] {
+               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 == 0) {
+                       numColors = 1 << depth;
+               } else {
+                       if (numColors > 256)
+                               numColors = 256;
+               }
+               byte[] buf = new byte[numColors * 4];
+               try {
+                       if (inputStream.read(buf) != buf.length)
+                               SWT.error(SWT.ERROR_INVALID_IMAGE);
+               } catch (IOException e) {
+                       SWT.error(SWT.ERROR_IO, e);
+               }
+               return paletteFromBytes(buf, numColors);
+       }
+       if (depth == 16) {
+               if (this.compression == 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 == 24) return new PaletteData(0xFF, 0xFF00, 0xFF0000);
+       if (this.compression == 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 == 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] = (byte)col.blue;
+               bytes[offset + 1] = (byte)col.green;
+               bytes[offset + 2] = (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.
+ * Method modified to use the passed data if it is not null.
+ */
+int unloadData(ImageData image, byte[] data, OutputStream out, int comp) {
+       int totalSize = 0;
+       try {
+               if (comp == 0)
+                       return unloadDataNoCompression(image, data, out);
+               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
+               if (data == null) 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 == 0);
+                       if (buf2Offset + lineSize > buf2.length) {
+                               out.write(buf2, 0, buf2Offset);
+                               buf2Offset = 0;
+                       }
+                       System.arraycopy(buf, 0, buf2, buf2Offset, lineSize);
+                       buf2Offset += lineSize;
+                       totalSize += lineSize;
+                       srcOffset -= imageBpl;
+               }
+               if (buf2Offset > 0)
+                       out.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.
+ * Method modified to use the passed data if it is not null.
+ */
+int unloadDataNoCompression(ImageData image, byte[] data, OutputStream out) {
+       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];
+               if (data == null) data = image.data;
+               int imageBpl = image.bytesPerLine;
+               int dataIndex = imageBpl * (image.height - 1); // Start at last line
+               if (image.depth == 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;
+                               }
+                               out.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;
+                               }
+                               out.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 == 1) || (image.depth == 4) || (image.depth == 8) ||
+                 (image.depth == 16) || (image.depth == 24) || (image.depth == 32)))
+                       SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+       int comp = this.compression;
+       if (!((comp == 0) || ((comp == 1) && (image.depth == 8)) ||
+                 ((comp == 2) && (image.depth == 4))))
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+       PaletteData pal = image.palette;
+       if ((image.depth == 16) || (image.depth == 24) || (image.depth == 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 != null) {
+               fileHeader[4] += rgbs.length;
+       }
+
+       byte iData[] = null;
+       // If the pixels are not in the expected BMP format, convert them.
+       if (pal.isDirect && !isPaletteBMP(pal, image.depth)) {
+               // array to store the converted pixels
+               iData = new byte[image.data.length];
+               convertPixelsToBGR(image, iData);
+       }
+
+       // Prepare data. This is done first so we don't have to try to rewind
+       // the stream and fill in the details later.
+       ByteArrayOutputStream out = new ByteArrayOutputStream();
+       unloadData(image, iData, out, comp);
+       byte[] data = out.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((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;
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/WinICOFileFormat.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/WinICOFileFormat.java
new file mode 100644 (file)
index 0000000..f06baa3
--- /dev/null
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.image;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+public final class WinICOFileFormat extends 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] = (byte)(255 - data[i - startIndex]);
+       }
+       return data;
+}
+
+static byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
+       if (pad == 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 != null ? i.palette.colors.length * 4 : 0;
+       return WinBMPFileFormat.BMPHeaderFixedSize + paletteSize + dataSize;
+}
+@Override
+boolean isFileFormat(LEDataInputStream stream) {
+       try {
+               byte[] header = new byte[4];
+               stream.read(header);
+               stream.unread(header);
+               return header[0] == 0 && header[1] == 0 && header[2] == 1 && header[3] == 0;
+       } catch (Exception e) {
+               return false;
+       }
+}
+boolean 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 == 2 || size == 16 || size == 32 || size == 256;
+               case 24:
+               case 32:
+                       return i.palette.isDirect;
+       }
+       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] != 0) || (fileHeader[1] != 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, boolean 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] != 0) || (fileHeader[1] != 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) {
+       try {
+               FileFormat png = getFileFormat(inputStream, "PNG");
+               if (png != null) {
+                       png.loader = this.loader;
+                       return png.loadFromStream(inputStream)[0];
+               }
+       } catch (Exception e) {
+       }
+       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 == 0) numColors = 256; // this is specified: '00' represents '256' (0x100) colors
+       if ((numColors != 2) && (numColors != 8) && (numColors != 16) &&
+               (numColors != 32) && (numColors != 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)) != 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);
+       /*
+        * Feature in the ico spec. The spec says that a width/height of 0 represents 256, however, newer images can be created with even larger sizes.
+        * Images with a width/height >= 256 will have their width/height set to 0 in the icon header; the fix for this case is to read the width/height
+        * directly from the image header.
+        */
+       if (width == 0) width = infoWidth;
+       if (height == 0) height = infoHeight / 2;
+       if (height == infoHeight && bitCount == 1) height /= 2;
+       if (!((width == infoWidth) && (height * 2 == infoHeight) &&
+               (bitCount == 1 || bitCount == 4 || bitCount == 8 || bitCount == 24 || bitCount == 32)))
+                       SWT.error(SWT.ERROR_INVALID_IMAGE);
+       infoHeader[8] = (byte)(height & 0xFF);
+       infoHeader[9] = (byte)((height >> 8) & 0xFF);
+       infoHeader[10] = (byte)((height >> 16) & 0xFF);
+       infoHeader[11] = (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((short)icon.depth);
+               outputStream.writeInt(0);
+               outputStream.writeInt(sizeImage);
+               outputStream.writeInt(0);
+               outputStream.writeInt(0);
+               outputStream.writeInt(icon.palette.colors != 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 != 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);
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/package.html
new file mode 100644 (file)
index 0000000..ab7efd4
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT internal image loading/saving support classes.
+<h2>
+Package Specification</h2>
+This package contains the classes used by SWT to load and save images
+in the various formats we support, including GIF, JPEG, PNG, BMP, and ICO.
+<p>
+Applications should not need to reference the classes in this package
+directly.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/CAUUID.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/CAUUID.java
new file mode 100644 (file)
index 0000000..11b9645
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class CAUUID {
+       public int cElems;
+       /** @field cast=(GUID FAR *) */
+       public long pElems;
+       public static final int sizeof = COM.CAUUID_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/COM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/COM.java
new file mode 100644 (file)
index 0000000..9a67d30
--- /dev/null
@@ -0,0 +1,706 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class COM extends OS {
+       /** GUID Constants */
+       public static final GUID CLSID_CMultiLanguage = IIDFromString("{275c23e2-3747-11d0-9fea-00aa003f8646}");
+       public static final GUID CLSID_DestinationList = IIDFromString ("{77f10cf0-3db5-4966-b520-b7c54fd35ed6}"); //$NON-NLS-1$
+       public static final GUID CLSID_DragDropHelper = COM.IIDFromString("{4657278A-411B-11d2-839A-00C04FD918D0}"); //$NON-NLS-1$
+       public static final GUID CLSID_EnumerableObjectCollection = IIDFromString ("{2d3468c1-36a7-43b6-ac24-d3f02fd9607a}"); //$NON-NLS-1$
+       public static final GUID CLSID_FileOpenDialog = IIDFromString("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}"); //$NON-NLS-1$
+       public static final GUID CLSID_FileSaveDialog = IIDFromString("{84bccd23-5fde-4cdb-aea4-af64b83d78ab}"); //$NON-NLS-1$
+       public static final GUID CLSID_ShellLink = IIDFromString ("{00021401-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID CLSID_TaskbarList = IIDFromString ("{56FDF344-FD6D-11d0-958A-006097C9A090}"); //$NON-NLS-1$
+       public static final GUID CLSID_TF_InputProcessorProfiles = IIDFromString("{33C53A50-F456-4884-B049-85FD643ECFED}"); //$NON-NLS-1$
+       public static final GUID GUID_TFCAT_TIP_KEYBOARD = IIDFromString("{34745C63-B2F0-4784-8B67-5E12C8701A31}"); //$NON-NLS-1$
+       public static final GUID IID_ICustomDestinationList = IIDFromString ("{6332debf-87b5-4670-90c0-5e57b408a49e}"); //$NON-NLS-1$
+       public static final GUID IID_IDropTargetHelper = COM.IIDFromString("{4657278B-411B-11D2-839A-00C04FD918D0}"); //$NON-NLS-1$
+       public static final GUID IID_IFileOpenDialog = IIDFromString("{d57c7288-d4ad-4768-be02-9d969532d960}"); //$NON-NLS-1$
+       public static final GUID IID_IFileSaveDialog = IIDFromString("{84bccd23-5fde-4cdb-aea4-af64b83d78ab}"); //$NON-NLS-1$
+       public static final GUID IID_IMLangFontLink2 = IIDFromString("{DCCFC162-2B38-11d2-B7EC-00C04F8F5D9A}");
+       public static final GUID IID_IObjectArray = IIDFromString ("{92CA9DCD-5622-4bba-A805-5E9F541BD8C9}"); //$NON-NLS-1$
+       public static final GUID IID_IObjectCollection = IIDFromString ("{5632b1a4-e38a-400a-928a-d4cd63230295}"); //$NON-NLS-1$
+       public static final GUID IID_IPropertyStore = IIDFromString ("{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}"); //$NON-NLS-1$
+       public static final GUID IID_IShellItem = IIDFromString("{43826d1e-e718-42ee-bc55-a1e261c37bfe}"); //$NON-NLS-1$
+       public static final GUID IID_IShellLinkW = IIDFromString ("{000214F9-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IID_ITaskbarList3 = IIDFromString ("{ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}"); //$NON-NLS-1$
+       public static final GUID IID_ITfDisplayAttributeProvider = IIDFromString("{fee47777-163c-4769-996a-6e9c50ad8f54}"); //$NON-NLS-1$
+       public static final GUID IID_ITfInputProcessorProfiles = IIDFromString("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}"); //$NON-NLS-1$
+       public static final GUID IIDJavaBeansBridge = COM.IIDFromString("{8AD9C840-044E-11D1-B3E9-00805F499D93}"); //$NON-NLS-1$
+       public static final GUID IIDShockwaveActiveXControl = COM.IIDFromString("{166B1BCA-3F9C-11CF-8075-444553540000}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessible = IIDFromString("{618736E0-3C3D-11CF-810C-00AA00389B71}"); //$NON-NLS-1$
+       public static final GUID IIDIAdviseSink = IIDFromString("{0000010F-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIClassFactory = IIDFromString("{00000001-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIClassFactory2 = IIDFromString("{B196B28F-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIConnectionPointContainer = IIDFromString("{B196B284-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIDataObject = IIDFromString("{0000010E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIDispatch = IIDFromString("{00020400-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIDispatchEx = IIDFromString("{A6EF9860-C720-11D0-9337-00A0C90DCAA9}"); //$NON-NLS-1$
+       public static final GUID IIDIDocHostUIHandler = IIDFromString("{BD3F23C0-D43E-11CF-893B-00AA00BDCE1A}"); //$NON-NLS-1$
+       public static final GUID IIDIDocHostShowUI = IIDFromString("{C4D244B0-D43E-11CF-893B-00AA00BDCE1A}"); //$NON-NLS-1$
+       public static final GUID IIDIDropSource = IIDFromString("{00000121-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIDropTarget = IIDFromString("{00000122-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIEnumFORMATETC = IIDFromString("{00000103-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIEnumVARIANT = IIDFromString("{00020404-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final /*GUID*/ String IIDIHTMLDocumentEvents2 = /*IIDFromString(*/"{3050F613-98B5-11CF-BB82-00AA00BDCE0B}"/*)*/;
+       public static final GUID IIDIInternetSecurityManager = IIDFromString("{79eac9ee-baf9-11ce-8c82-00aa004ba90b}"); //$NON-NLS-1$
+       public static final GUID IIDIAuthenticate = IIDFromString("{79eac9d0-baf9-11ce-8c82-00aa004ba90b}"); //$NON-NLS-1$
+       public static final GUID IIDIJScriptTypeInfo = IIDFromString("{C59C6B12-F6C1-11CF-8835-00A0C911E8B2}"); //$NON-NLS-1$
+       public static final GUID IIDIOleClientSite = IIDFromString("{00000118-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIOleCommandTarget = IIDFromString("{B722BCCB-4E68-101B-A2BC-00AA00404770}"); //$NON-NLS-1$
+       public static final GUID IIDIOleControl = IIDFromString("{B196B288-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIOleControlSite = IIDFromString("{B196B289-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIOleDocument = IIDFromString("{B722BCC5-4E68-101B-A2BC-00AA00404770}"); //$NON-NLS-1$
+       public static final GUID IIDIOleDocumentSite = IIDFromString("{B722BCC7-4E68-101B-A2BC-00AA00404770}"); //$NON-NLS-1$
+       public static final GUID IIDIOleInPlaceFrame = IIDFromString("{00000116-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIOleInPlaceObject = IIDFromString("{00000113-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIOleInPlaceSite = IIDFromString("{00000119-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIOleLink = IIDFromString("{0000011D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIOleObject = IIDFromString("{00000112-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIPersist = IIDFromString("{0000010C-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIPersistFile = IIDFromString("{0000010B-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIPersistStorage = IIDFromString("{0000010A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIPersistStreamInit = IIDFromString("{7FD52380-4E07-101B-AE2D-08002B2EC713}"); //$NON-NLS-1$
+       public static final GUID IIDIPropertyNotifySink = IIDFromString("{9BFBBC02-EFF1-101A-84ED-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIProvideClassInfo = IIDFromString("{B196B283-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIProvideClassInfo2 = IIDFromString("{A6BC3AC0-DBAA-11CE-9DE3-00AA004BB851}"); //$NON-NLS-1$
+       public static final GUID IIDIServiceProvider = IIDFromString("{6d5140c1-7436-11ce-8034-00aa006009fa}"); //$NON-NLS-1$
+       public static final GUID IIDISpecifyPropertyPages = IIDFromString("{B196B28B-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+       public static final GUID IIDIUnknown = IIDFromString("{00000000-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID IIDIViewObject2 = IIDFromString("{00000127-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+       public static final GUID CGID_DocHostCommandHandler = IIDFromString("{f38bc242-b950-11d1-8918-00c04fc2c836}"); //$NON-NLS-1$
+       public static final GUID CGID_Explorer = IIDFromString("{000214D0-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+
+       // IA2 related GUIDS
+       public static final GUID IIDIAccessible2 = IIDFromString("{E89F726E-C4F4-4c19-BB19-B647D7FA8478}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleRelation = IIDFromString("{7CDF86EE-C3DA-496a-BDA4-281B336E1FDC}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleAction = IIDFromString("{B70D9F59-3B5A-4dba-AB9E-22012F607DF5}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleComponent = IIDFromString("{1546D4B0-4C98-4bda-89AE-9A64748BDDE4}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleValue = IIDFromString("{35855B5B-C566-4fd0-A7B1-E65465600394}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleText = IIDFromString("{24FD2FFB-3AAD-4a08-8335-A3AD89C0FB4B}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleEditableText = IIDFromString("{A59AA09A-7011-4b65-939D-32B1FB5547E3}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleHyperlink = IIDFromString("{01C20F2B-3DD2-400f-949F-AD00BDAB1D41}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleHypertext = IIDFromString("{6B4F8BBF-F1F2-418a-B35E-A195BC4103B9}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleTable = IIDFromString("{35AD8070-C20C-4fb4-B094-F4F7275DD469}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleTable2 = IIDFromString("{6167f295-06f0-4cdd-a1fa-02e25153d869}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleTableCell = IIDFromString("{594116B1-C99F-4847-AD06-0A7A86ECE645}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleImage = IIDFromString("{FE5ABB3D-615E-4f7b-909F-5F0EDA9E8DDE}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleApplication = IIDFromString("{D49DED83-5B25-43F4-9B95-93B44595979E}"); //$NON-NLS-1$
+       public static final GUID IIDIAccessibleContext = IIDFromString("{77A123E4-5794-44e0-B8BF-DE600C9D29BD}"); //$NON-NLS-1$
+
+       /** Constants */
+       public static final int CF_TEXT = 1;
+       public static final int CF_BITMAP = 2;
+       public static final int CF_METAFILEPICT = 3;
+       public static final int CF_SYLK = 4;
+       public static final int CF_DIF = 5;
+       public static final int CF_TIFF = 6;
+       public static final int CF_OEMTEXT = 7;
+       public static final int CF_DIB = 8;
+       public static final int CF_PALETTE = 9;
+       public static final int CF_PENDATA = 10;
+       public static final int CF_RIFF = 11;
+       public static final int CF_WAVE = 12;
+       public static final int CF_UNICODETEXT = 13;
+       public static final int CF_ENHMETAFILE = 14;
+       public static final int CF_HDROP = 15;
+       public static final int CF_LOCALE = 16;
+       public static final int CF_MAX = 17;
+       public static final int CLSCTX_INPROC_HANDLER = 2;
+       public static final int CLSCTX_INPROC_SERVER = 1;
+       public static final int CLSCTX_LOCAL_SERVER = 4;
+       public static final int DATADIR_GET = 1;
+       public static final int DATADIR_SET = 2;
+       public static final int DISPATCH_CONSTRUCT = 0x4000;
+       public static final int DISP_E_EXCEPTION = 0x80020009;
+       public static final int DISP_E_MEMBERNOTFOUND = -2147352573;
+       public static final int DISP_E_UNKNOWNINTERFACE = 0x80020001;
+       public static final int DISP_E_UNKNOWNNAME = 0x80020006;
+       public static final int DISPID_AMBIENT_BACKCOLOR = -701;
+       public static final int DISPID_AMBIENT_FONT = -703;
+       public static final int DISPID_AMBIENT_FORECOLOR = -704;
+       public static final int DISPID_AMBIENT_LOCALEID = -705;
+       public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706;
+       public static final int DISPID_AMBIENT_OFFLINEIFNOTCONNECTED = -5501;
+       public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711;
+       public static final int DISPID_AMBIENT_SHOWHATCHING = -712;
+       public static final int DISPID_AMBIENT_SILENT = -5502;
+       public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714;
+       public static final int DISPID_AMBIENT_UIDEAD = -710;
+       public static final int DISPID_AMBIENT_USERMODE = -709;
+       public static final int DISPID_BACKCOLOR = -501;
+       public static final int DISPID_FONT = -512;
+       public static final int DISPID_FONT_BOLD = 3;
+       public static final int DISPID_FONT_CHARSET = 8;
+       public static final int DISPID_FONT_ITALIC = 4;
+       public static final int DISPID_FONT_NAME = 0;
+       public static final int DISPID_FONT_SIZE = 2;
+       public static final int DISPID_FONT_STRIKE = 6;
+       public static final int DISPID_FONT_UNDER = 5;
+       public static final int DISPID_FONT_WEIGHT = 7;
+       public static final int DISPID_FORECOLOR = -513;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK = 0xFFFFFDA7;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND = 0x80010015;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART = 0x8001000B;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN = 0xFFFFFDA6;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS = 0xFFFFFDA5;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONKEYUP = 0xFFFFFDA4;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT = 0x80010009;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER = 0x80010008;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE = 0xFFFFFDA2;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN = 0xFFFFFDA3;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP = 0xFFFFFDA1;
+       public static final int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL = 1033;
+
+       public static final int DRAGDROP_S_DROP = 0x00040100;
+       public static final int DRAGDROP_S_CANCEL = 0x00040101;
+       public static final int DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102;
+       public static final int DROPEFFECT_NONE = 0;
+       public static final int DROPEFFECT_COPY = 1;
+       public static final int DROPEFFECT_MOVE = 2;
+       public static final int DROPEFFECT_LINK = 4;
+       public static final int DV_E_FORMATETC = -2147221404;
+       public static final int DV_E_STGMEDIUM = -2147221402;
+       public static final int DV_E_TYMED = -2147221399;
+       public static final int DVASPECT_CONTENT = 1;
+       public static final int E_ACCESSDENIED = 0x80070005;
+       public static final int E_FAIL = -2147467259;
+       public static final int E_INVALIDARG = -2147024809;
+       public static final int E_NOINTERFACE = -2147467262;
+       public static final int E_NOTIMPL = -2147467263;
+       public static final int E_NOTSUPPORTED = 0x80040100;
+       public static final int E_OUTOFMEMORY = -2147024882;
+       public static final int GMEM_FIXED = 0;
+       public static final int GMEM_ZEROINIT = 64;
+       public static final int GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1;
+       public static final int IMPLTYPEFLAG_FDEFAULT = 1;
+       public static final int IMPLTYPEFLAG_FRESTRICTED = 4;
+       public static final int IMPLTYPEFLAG_FSOURCE = 2;
+       public static final int LOCALE_USER_DEFAULT = 2048;
+       public static final int OLECLOSE_NOSAVE = 1;
+       public static final int OLECLOSE_SAVEIFDIRTY = 0;
+       public static final int OLEEMBEDDED = 1;
+       public static final int OLELINKED = 0;
+       public static final int OLERENDER_DRAW = 1;
+       public static final int S_FALSE = 1;
+       public static final int S_OK = 0;
+       public static final int STGC_DEFAULT = 0;
+       public static final int STGM_CREATE = 0x00001000;
+       public static final int STGM_DELETEONRELEASE = 0x04000000;
+       public static final int STGM_DIRECT = 0x00000000;
+       public static final int STGM_READ = 0x00000000;
+       public static final int STGM_READWRITE = 0x00000002;
+       public static final int STGM_SHARE_EXCLUSIVE = 0x00000010;
+       public static final int STGM_TRANSACTED = 0x00010000;
+       public static final int TYMED_HGLOBAL = 1;
+       public static final short DISPATCH_METHOD = 0x1;
+       public static final short DISPATCH_PROPERTYGET = 0x2;
+       public static final short DISPATCH_PROPERTYPUT = 0x4;
+       public static final short DISPATCH_PROPERTYPUTREF = 0x8;
+       public static final short DISPID_PROPERTYPUT = -3;
+       public static final short DISPID_UNKNOWN = -1;
+       public static final short DISPID_VALUE = 0;
+       public static final short VT_BOOL = 11;
+       public static final short VT_BSTR = 8;
+       public static final short VT_BYREF = 16384;
+       public static final short VT_DATE = 7;
+       public static final short VT_DISPATCH = 9;
+       public static final short VT_EMPTY = 0;
+       public static final short VT_I1 = 16;
+       public static final short VT_I2 = 2;
+       public static final short VT_I4 = 3;
+       public static final short VT_I8 = 20;
+       public static final short VT_NULL = 1;
+       public static final short VT_R4 = 4;
+       public static final short VT_R8 = 5;
+       public static final short VT_UI1 = 17;
+       public static final short VT_UI2 = 18;
+       public static final short VT_UI4 = 19;
+       public static final short VT_UNKNOWN = 13;
+       public static final short VT_VARIANT = 12;
+
+       public static boolean FreeUnusedLibraries = true;
+
+private static GUID IIDFromString(String lpsz) {
+       int length = lpsz.length();
+       char[] buffer = new char[length + 1];
+       lpsz.getChars(0, length, buffer, 0);
+       GUID lpiid = new GUID();
+       if (COM.IIDFromString(buffer, lpiid) == COM.S_OK) return lpiid;
+       return null;
+}
+
+/** Natives */
+
+/** @param lpszProgID cast=(LPCOLESTR) */
+public static final native int CLSIDFromProgID(char[] lpszProgID, GUID pclsid);
+/** @param lpsz cast=(LPOLESTR) */
+public static final native int CLSIDFromString(char[] lpsz, GUID pclsid);
+/**
+ * @param pUnkOuter cast=(LPUNKNOWN)
+ * @param ppv cast=(LPVOID *)
+ */
+public static final native int CoCreateInstance(GUID rclsid, long pUnkOuter, int dwClsContext, GUID riid, long[] ppv);
+public static final native void CoFreeUnusedLibraries();
+/**
+ * @param pServerInfo cast=(COSERVERINFO *)
+ * @param ppv cast=(LPVOID *)
+ */
+public static final native int CoGetClassObject(GUID rclsid, int dwClsContext, long pServerInfo, GUID riid, long[] ppv);
+/**
+ * @param pUnk cast=(IUnknown *)
+ * @param fLock cast=(BOOL)
+ * @param fLastUnlockReleases cast=(BOOL)
+ */
+public static final native int CoLockObjectExternal(long pUnk, boolean fLock, boolean fLastUnlockReleases);
+/**
+ * @param pDataObject cast=(IDataObject *)
+ * @param pDropSource cast=(IDropSource *)
+ * @param pdwEffect cast=(LPDWORD)
+ */
+public static final native int DoDragDrop(long pDataObject, long pDropSource, int dwOKEffect, int[] pdwEffect);
+/** @param szFileName cast=(LPCWSTR) */
+public static final native int GetClassFile(char[] szFileName, GUID clsid);
+/** @param lpsz cast=(LPOLESTR) */
+public static final native int IIDFromString(char[] lpsz, GUID lpiid);
+public static final native boolean IsEqualGUID(GUID rguid1, GUID rguid2);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory(long Destination, FORMATETC Source, int Length);
+/**
+ * @param DestinationPtr cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory(long DestinationPtr, OLEINPLACEFRAMEINFO Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory(long Destination, STGMEDIUM Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(STGMEDIUM Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(DISPPARAMS Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(FORMATETC Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(GUID Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(TYPEATTR Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(RECT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(FUNCDESC Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(VARDESC Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory(VARIANT Destination, long Source, int Length);
+/**
+ * @param pClientSite cast=(IOleClientSite *)
+ * @param pStg cast=(IStorage *)
+ * @param ppvObject cast=(void **)
+ */
+public static final native int OleCreate(GUID rclsid, GUID riid, int renderopt, FORMATETC pFormatEtc, long pClientSite, long pStg, long[] ppvObject);
+/**
+ * @param lpszFileName cast=(LPCOLESTR)
+ * @param pClientSite cast=(LPOLECLIENTSITE)
+ * @param pStg cast=(LPSTORAGE)
+ * @param ppvObj cast=(LPVOID *)
+ */
+public static final native int OleCreateFromFile(GUID rclsid, char[] lpszFileName, GUID riid, int renderopt, FORMATETC pFormatEtc, long pClientSite, long pStg, long[] ppvObj);
+/**
+ * @param hwndOwner cast=(HWND)
+ * @param lpszCaption cast=(LPCOLESTR)
+ * @param lplpUnk cast=(LPUNKNOWN FAR*)
+ * @param lpPageClsID cast=(LPCLSID)
+ * @param lcid cast=(LCID)
+ * @param lpvReserved cast=(LPVOID)
+ */
+public static final native int OleCreatePropertyFrame(long hwndOwner,int x, int y, char[] lpszCaption, int cObjects, long[] lplpUnk, int cPages, long lpPageClsID, int lcid, int dwReserved, long lpvReserved);
+/**
+ * @param pUnk cast=(LPUNKNOWN)
+ * @param dwAspect cast=(DWORD)
+ * @param hdcDraw cast=(HDC)
+ * @param lprcBounds cast=(LPRECT)
+ */
+public static final native int OleDraw(long pUnk, int dwAspect, long hdcDraw, long lprcBounds);
+public static final native int OleFlushClipboard();
+/** @param ppDataObject cast=(IDataObject **) */
+public static final native int OleGetClipboard(long[] ppDataObject);
+/** @param pDataObject cast=(IDataObject *) */
+public static final native int OleIsCurrentClipboard(long pDataObject);
+/** @param pObject cast=(LPOLEOBJECT) */
+public static final native boolean OleIsRunning(long pObject);
+/** @param pUnknown cast=(LPUNKNOWN) */
+public static final native int OleRun(long pUnknown);
+/**
+ * @param pPS cast=(IPersistStorage *)
+ * @param pStg cast=(IStorage *)
+ */
+public static final native int OleSave(long pPS, long pStg, boolean fSameAsLoad);
+/** @param pDataObject cast=(IDataObject *) */
+public static final native int OleSetClipboard(long pDataObject);
+/** @param pUnk cast=(LPUNKNOWN) */
+public static final native int OleSetContainedObject(long pUnk, boolean fContained);
+/**
+ * @method flags=trycatch
+ * @param holemenu cast=(HOLEMENU)
+ * @param hwndFrame cast=(HWND)
+ * @param hwndActiveObject cast=(HWND)
+ * @param lpFrame cast=(LPOLEINPLACEFRAME)
+ * @param lpActiveObj cast=(LPOLEINPLACEACTIVEOBJECT)
+ */
+public static final native int OleSetMenuDescriptor(long holemenu, long hwndFrame, long hwndActiveObject, long lpFrame, long lpActiveObj);
+/**
+ * @param clr cast=(OLE_COLOR)
+ * @param hpal cast=(HPALETTE)
+ * @param pcolorref cast=(COLORREF *)
+ */
+public static final native int OleTranslateColor(int clr, long hpal, int[] pcolorref);
+/**
+ * Custom native function.
+ * @param pszName cast=(PCWSTR)
+ * @param ppidl cast=(PIDLIST_ABSOLUTE)
+ */
+public static final native int PathToPIDL (char [] pszName, long [] ppidl);
+/** @param lplpszProgID cast=(LPOLESTR *) */
+public static final native int ProgIDFromCLSID(GUID clsid, long[] lplpszProgID);
+/**
+ * @param hwnd cast=(HWND)
+ * @param pDropTarget cast=(IDropTarget *)
+ */
+public static final native int RegisterDragDrop(long hwnd, long pDropTarget);
+/** @param pmedium cast=(STGMEDIUM *) */
+public static final native void ReleaseStgMedium(long pmedium);
+/** @param hwnd cast=(HWND) */
+public static final native int RevokeDragDrop(long hwnd);
+/**
+ * @param pszName cast=(PCWSTR)
+ * @param pbc cast=(IBindCtx *)
+ * @param riid cast=(REFIID)
+ * @param ppv cast=(void **)
+ */
+public static final native int SHCreateItemFromParsingName (char [] pszName, long pbc, GUID riid, long [] ppv);
+/** @param ppstgOpen cast=(IStorage **) */
+public static final native int StgCreateDocfile(char[] pwcsName, int grfMode, int reserved, long[] ppstgOpen);
+/** @param pwcsName cast=(const WCHAR *) */
+public static final native int StgIsStorageFile(char[] pwcsName);
+/**
+ * @param pwcsName cast=(const WCHAR *)
+ * @param pstgPriority cast=(IStorage *)
+ * @param snbExclude cast=(SNB)
+ * @param ppstgOpen cast=(IStorage **)
+ */
+public static final native int StgOpenStorage(char[] pwcsName, long pstgPriority, int grfMode, long snbExclude, int reserved, long[] ppstgOpen);
+/** @param sz cast=(OLECHAR *) */
+public static final native long SysAllocString(char [] sz);
+/** @param bstr cast=(BSTR) */
+public static final native void SysFreeString(long bstr);
+/** @param bstr cast=(BSTR) */
+public static final native int SysStringByteLen(long bstr);
+/** @param bstr cast=(BSTR) */
+public static final native int SysStringLen(long bstr);
+/**
+ * @param pvargDest cast=(VARIANTARG FAR* )
+ * @param pvarSrc cast=(VARIANTARG FAR* )
+ * @param vt cast=(VARTYPE)
+ */
+public static final native int VariantChangeType(long pvargDest, long pvarSrc, short wFlags, short vt);
+/** @param pvarg cast=(VARIANTARG FAR* ) */
+public static final native int VariantClear(long pvarg);
+/** @param pvarg cast=(VARIANTARG FAR* ) */
+public static final native void VariantInit(long pvarg);
+/** @param pStg cast=(IStorage *) */
+public static final native int WriteClassStg(long pStg, GUID rclsid);
+
+/** @method flags=trycatch */
+public static final native int VtblCall(int fnNumber, long ppVtbl);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1, int arg2, long[] arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long arg1, int arg2, long[] arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, int arg1, int arg2, long[] arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, int arg1, int arg2, int[] arg3, int[] arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int[] arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long[] arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long[] arg1, int[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, TF_DISPLAYATTRIBUTE arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long arg1, long arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1, long arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, int arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, long arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, PROPERTYKEY arg0, long arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, int[] arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, int[] arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long[] arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, char[] arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1, POINT arg2, int arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int[] arg0, GUID arg1, long[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, POINT arg1, long arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, POINT arg0, int arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, int arg1, int arg2, int arg3, long[] arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, long arg1, int arg2, int arg3, long[] arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, char[] arg0, long arg1, int arg2, int arg3, int arg4, long[] arg5);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long[] arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, int arg1, long[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1, long[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long arg1, int[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, int arg1, int[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, int arg1, long arg2, SIZE arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1, GUID arg2, long arg3, long [] arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, GUID arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, GUID arg1, long arg2, long arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, GUID arg1, int arg2, int arg3, DISPPARAMS arg4, long arg5, EXCEPINFO arg6, int[] arg7);
+public static final native int VtblCall(int fnNumber, long ppVtbl, MSG arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, MSG arg1, long arg2, int arg3, long arg4, RECT arg5);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, SIZE arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, int arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, CAUUID arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, CONTROLINFO arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, FORMATETC arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, FORMATETC arg0, STGMEDIUM arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, GUID arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, GUID arg0, long[] arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, GUID arg0, GUID arg1, long[] arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, GUID arg0, long arg1, int arg2, int arg3, int[] arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, GUID arg0, int arg1, int arg2, long arg3, long arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, GUID arg0, int arg1, OLECMD arg2, long arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, GUID arg1, GUID arg2, GUID arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, LICINFO arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, RECT arg0, long arg1, int arg2);
+public static final native int VtblCall(int fnNumber, long ppVtbl, long arg0, long arg1, long arg2, long arg3, long arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, RECT arg0, RECT arg1);
+public static final native int VtblCall(int fnNumber, long ppVtbl, RECT arg0);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long[] arg1, long[] arg2, int[] arg3, long[] arg4);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, long[] arg1, int arg2, int[] arg3);
+public static final native int VtblCall(int fnNumber, long ppVtbl, int arg0, int arg1, int arg2, DISPPARAMS arg3, long arg4, EXCEPINFO arg5, long arg6);
+/**
+ * @param arg0 flags=struct
+ */
+public static final native int VtblCall(int fnNumber, long ppVtbl, RECT arg0, long arg1, long arg2);
+
+/** Accessibility constants */
+public static final int CHILDID_SELF = 0;
+public static final int CO_E_OBJNOTCONNECTED = 0x800401FD;
+public static final int ROLE_SYSTEM_MENUBAR = 0x2;
+public static final int ROLE_SYSTEM_SCROLLBAR = 0x3;
+public static final int ROLE_SYSTEM_ALERT = 0x8;
+public static final int ROLE_SYSTEM_WINDOW = 0x9;
+public static final int ROLE_SYSTEM_CLIENT = 0xa;
+public static final int ROLE_SYSTEM_MENUPOPUP = 0xb;
+public static final int ROLE_SYSTEM_MENUITEM = 0xc;
+public static final int ROLE_SYSTEM_TOOLTIP = 0xd;
+public static final int ROLE_SYSTEM_DOCUMENT = 0xf;
+public static final int ROLE_SYSTEM_DIALOG = 0x12;
+public static final int ROLE_SYSTEM_GROUPING = 0x14;
+public static final int ROLE_SYSTEM_SEPARATOR = 0x15;
+public static final int ROLE_SYSTEM_TOOLBAR = 0x16;
+public static final int ROLE_SYSTEM_STATUSBAR = 0x17;
+public static final int ROLE_SYSTEM_TABLE = 0x18;
+public static final int ROLE_SYSTEM_COLUMNHEADER = 0x19;
+public static final int ROLE_SYSTEM_ROWHEADER = 0x1a;
+public static final int ROLE_SYSTEM_COLUMN = 0x1b;
+public static final int ROLE_SYSTEM_ROW = 0x1c;
+public static final int ROLE_SYSTEM_CELL = 0x1d;
+public static final int ROLE_SYSTEM_LINK = 0x1e;
+public static final int ROLE_SYSTEM_LIST = 0x21;
+public static final int ROLE_SYSTEM_LISTITEM = 0x22;
+public static final int ROLE_SYSTEM_OUTLINE = 0x23;
+public static final int ROLE_SYSTEM_OUTLINEITEM = 0x24;
+public static final int ROLE_SYSTEM_PAGETAB = 0x25;
+public static final int ROLE_SYSTEM_GRAPHIC = 0x28;
+public static final int ROLE_SYSTEM_STATICTEXT = 0x29;
+public static final int ROLE_SYSTEM_TEXT = 0x2a;
+public static final int ROLE_SYSTEM_PUSHBUTTON = 0x2b;
+public static final int ROLE_SYSTEM_CHECKBUTTON = 0x2c;
+public static final int ROLE_SYSTEM_RADIOBUTTON = 0x2d;
+public static final int ROLE_SYSTEM_COMBOBOX = 0x2e;
+public static final int ROLE_SYSTEM_DROPLIST = 0x2f;
+public static final int ROLE_SYSTEM_PROGRESSBAR = 0x30;
+public static final int ROLE_SYSTEM_SLIDER = 0x33;
+public static final int ROLE_SYSTEM_SPINBUTTON = 0x34;
+public static final int ROLE_SYSTEM_ANIMATION = 0x36;
+public static final int ROLE_SYSTEM_PAGETABLIST = 0x3c;
+public static final int ROLE_SYSTEM_CLOCK = 0x3d;
+public static final int ROLE_SYSTEM_SPLITBUTTON = 0x3e;
+
+public static final int STATE_SYSTEM_NORMAL = 0;
+public static final int STATE_SYSTEM_UNAVAILABLE = 0x1;
+public static final int STATE_SYSTEM_SELECTED = 0x2;
+public static final int STATE_SYSTEM_FOCUSED = 0x4;
+public static final int STATE_SYSTEM_PRESSED = 0x8;
+public static final int STATE_SYSTEM_CHECKED = 0x10;
+public static final int STATE_SYSTEM_MIXED = 0x20;
+public static final int STATE_SYSTEM_READONLY = 0x40;
+public static final int STATE_SYSTEM_HOTTRACKED = 0x80;
+public static final int STATE_SYSTEM_EXPANDED = 0x200;
+public static final int STATE_SYSTEM_COLLAPSED = 0x400;
+public static final int STATE_SYSTEM_BUSY = 0x800;
+public static final int STATE_SYSTEM_INVISIBLE = 0x8000;
+public static final int STATE_SYSTEM_OFFSCREEN = 0x10000;
+public static final int STATE_SYSTEM_SIZEABLE = 0x20000;
+public static final int STATE_SYSTEM_FOCUSABLE = 0x100000;
+public static final int STATE_SYSTEM_SELECTABLE = 0x200000;
+public static final int STATE_SYSTEM_LINKED = 0x400000;
+public static final int STATE_SYSTEM_MULTISELECTABLE = 0x1000000;
+
+public static final int EVENT_OBJECT_SELECTIONWITHIN = 0x8009;
+public static final int EVENT_OBJECT_STATECHANGE = 0x800A;
+public static final int EVENT_OBJECT_LOCATIONCHANGE = 0x800B;
+public static final int EVENT_OBJECT_NAMECHANGE = 0x800C;
+public static final int EVENT_OBJECT_DESCRIPTIONCHANGE = 0x800D;
+public static final int EVENT_OBJECT_VALUECHANGE = 0x800E;
+public static final int EVENT_OBJECT_TEXTSELECTIONCHANGED = 0x8014;
+
+/* IA2 additional constants */
+public static final int IA2_COORDTYPE_SCREEN_RELATIVE = 0;
+public static final int IA2_COORDTYPE_PARENT_RELATIVE = 1;
+
+public static final int IA2_STATE_ACTIVE = 0x00000001;
+public static final int IA2_STATE_SINGLE_LINE = 0x00002000;
+public static final int IA2_STATE_MULTI_LINE = 0x00000200;
+public static final int IA2_STATE_REQUIRED = 0x00000800;
+public static final int IA2_STATE_INVALID_ENTRY = 0x00000040;
+public static final int IA2_STATE_SUPPORTS_AUTOCOMPLETION = 0x00008000;
+public static final int IA2_STATE_EDITABLE = 0x00000008;
+
+public static final int IA2_EVENT_DOCUMENT_LOAD_COMPLETE = 0x00000105;
+public static final int IA2_EVENT_DOCUMENT_LOAD_STOPPED = 0x00000106;
+public static final int IA2_EVENT_DOCUMENT_RELOAD = 0x00000107;
+public static final int IA2_EVENT_PAGE_CHANGED = 0x00000111;
+public static final int IA2_EVENT_SECTION_CHANGED = 0x00000112;
+public static final int IA2_EVENT_ACTION_CHANGED = 0x00000101;
+public static final int IA2_EVENT_HYPERLINK_START_INDEX_CHANGED = 0x0000010d;
+public static final int IA2_EVENT_HYPERLINK_END_INDEX_CHANGED = 0x00000108;
+public static final int IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED = 0x00000109;
+public static final int IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED = 0x0000010a;
+public static final int IA2_EVENT_HYPERLINK_ACTIVATED = 0x0000010b;
+public static final int IA2_EVENT_HYPERTEXT_LINK_SELECTED = 0x0000010c;
+public static final int IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED = 0x0000010f;
+public static final int IA2_EVENT_ATTRIBUTE_CHANGED = 0x00000110;
+public static final int IA2_EVENT_TABLE_CAPTION_CHANGED = 0x00000113;
+public static final int IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED = 0x00000114;
+public static final int IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED = 0x00000115;
+public static final int IA2_EVENT_TABLE_CHANGED = 0x00000116;
+public static final int IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED = 0x00000117;
+public static final int IA2_EVENT_TABLE_ROW_HEADER_CHANGED = 0x00000118;
+public static final int IA2_EVENT_TABLE_SUMMARY_CHANGED = 0x00000119;
+public static final int IA2_EVENT_TEXT_ATTRIBUTE_CHANGED = 0x0000011a;
+public static final int IA2_EVENT_TEXT_CARET_MOVED = 0x0000011b;
+public static final int IA2_EVENT_TEXT_COLUMN_CHANGED = 0x0000011d;
+public static final int IA2_EVENT_TEXT_INSERTED = 0x0000011e;
+public static final int IA2_EVENT_TEXT_REMOVED = 0x0000011f;
+
+public static final int IA2_TEXT_BOUNDARY_CHAR = 0;
+public static final int IA2_TEXT_BOUNDARY_WORD = 1;
+public static final int IA2_TEXT_BOUNDARY_SENTENCE = 2;
+public static final int IA2_TEXT_BOUNDARY_PARAGRAPH = 3;
+public static final int IA2_TEXT_BOUNDARY_LINE = 4;
+public static final int IA2_TEXT_BOUNDARY_ALL = 5;
+
+public static final int IA2_TEXT_OFFSET_LENGTH = -1;
+public static final int IA2_TEXT_OFFSET_CARET =  -2;
+
+public static final int IA2_SCROLL_TYPE_TOP_LEFT = 0;
+public static final int IA2_SCROLL_TYPE_BOTTOM_RIGHT = 1;
+public static final int IA2_SCROLL_TYPE_TOP_EDGE = 2;
+public static final int IA2_SCROLL_TYPE_BOTTOM_EDGE = 3;
+public static final int IA2_SCROLL_TYPE_LEFT_EDGE = 4;
+public static final int IA2_SCROLL_TYPE_RIGHT_EDGE = 5;
+public static final int IA2_SCROLL_TYPE_ANYWHERE = 6;
+
+/** Accessibility natives */
+
+/**
+ * @method flags=dynamic
+ * @param hwnd cast=(HWND)
+ * @param dwObjectID cast=(DWORD)
+ * @param ppvObject cast=(LPVOID *)
+ */
+public static final native int AccessibleObjectFromWindow (long hwnd, int dwObjectID, GUID riid, long[] ppvObject);
+/**
+ * @method flags=dynamic
+ * @param hwnd cast=(HWND)
+ * @param ppvObject cast=(LPVOID *)
+ */
+public static final native int CreateStdAccessibleObject (long hwnd, int idObject, GUID riidInterface, long[] ppvObject);
+/**
+ * @method flags=dynamic
+ * @param pAcc cast=(LPUNKNOWN)
+ */
+public static final native long LresultFromObject (GUID riid, long wParam, long pAcc);
+/**
+ * @method flags=dynamic
+ * @param paccContainer cast=(IAccessible *)
+ * @param iChildStart cast=(LONG)
+ * @param cChildren cast=(LONG)
+ * @param rgvarChildren cast=(VARIANT *)
+ * @param pcObtained cast=(LONG *)
+ */
+public static final native int AccessibleChildren(long paccContainer, int iChildStart, int cChildren, long rgvarChildren, int [] pcObtained);
+
+/* sizeof's */
+public static final native int CAUUID_sizeof();
+public static final native int CONTROLINFO_sizeof();
+public static final native int DISPPARAMS_sizeof();
+public static final native int ELEMDESC_sizeof();
+public static final native int EXCEPINFO_sizeof();
+public static final native int FORMATETC_sizeof();
+public static final native int FUNCDESC_sizeof();
+public static final native int GUID_sizeof();
+public static final native int LICINFO_sizeof();
+public static final native int OLECMD_sizeof();
+public static final native int OLEINPLACEFRAMEINFO_sizeof();
+public static final native int STGMEDIUM_sizeof();
+public static final native int TYPEATTR_sizeof();
+public static final native int TYPEDESC_sizeof();
+public static final native int VARDESC_sizeof();
+public static final native int VARIANT_sizeof();
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/COMObject.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/COMObject.java
new file mode 100644 (file)
index 0000000..e6a810a
--- /dev/null
@@ -0,0 +1,1037 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+public class COMObject {
+
+       public long ppVtable;
+
+       static private final int MAX_ARG_COUNT = 12;
+       static private final int MAX_VTABLE_LENGTH = 80;
+       static private Callback[][] Callbacks = new Callback[MAX_VTABLE_LENGTH][MAX_ARG_COUNT];
+       static private Map<LONG, COMObject> ObjectMap = new HashMap<>();
+
+public COMObject(int[] argCounts) {
+       long[] callbackAddresses = new long[argCounts.length];
+       synchronized (Callbacks) {
+               for (int i = 0, length = argCounts.length; i < length; i++){
+                       if ((Callbacks[i][argCounts[i]]) == null) {
+                               Callbacks[i][argCounts[i]] = new Callback(this.getClass(), "callback"+i, argCounts[i] + 1, true, COM.E_FAIL); //$NON-NLS-1$
+                               if (Callbacks[i][argCounts[i]].getAddress() == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+                       }
+                       callbackAddresses[i] = Callbacks[i][argCounts[i]].getAddress();
+               }
+       }
+
+       long pVtable = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, C.PTR_SIZEOF * argCounts.length);
+       OS.MoveMemory(pVtable, callbackAddresses, C.PTR_SIZEOF * argCounts.length);
+       ppVtable = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, C.PTR_SIZEOF);
+       OS.MoveMemory(ppVtable, new long[] {pVtable}, C.PTR_SIZEOF);
+       ObjectMap.put(new LONG(ppVtable), this);
+}
+
+public static GUID IIDFromString(String lpsz) {
+       // create a null terminated array of char
+       char[] buffer = (lpsz +"\0").toCharArray();
+
+       // invoke system method
+       GUID lpiid = new GUID();
+       if (COM.IIDFromString(buffer, lpiid) == COM.S_OK)
+               return lpiid;
+       return null;
+}
+
+static long callback0(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method0(args);
+}
+static long callback1(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method1(args);
+}
+static long callback2(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method2(args);
+}
+static long callback3(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method3(args);
+}
+static long callback4(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method4(args);
+}
+static long callback5(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method5(args);
+}
+static long callback6(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method6(args);
+}
+static long callback7(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method7(args);
+}
+static long callback8(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method8(args);
+}
+static long callback9(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method9(args);
+}
+static long callback10(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method10(args);
+}
+static long callback11(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method11(args);
+}
+static long callback12(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method12(args);
+}
+static long callback13(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method13(args);
+}
+static long callback14(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method14(args);
+}
+static long callback15(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method15(args);
+}
+static long callback16(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method16(args);
+}
+static long callback17(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method17(args);
+}
+static long callback18(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method18(args);
+}
+static long callback19(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method19(args);
+}
+static long callback20(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method20(args);
+}
+static long callback21(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method21(args);
+}
+static long callback22(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method22(args);
+}
+static long callback23(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method23(args);
+}
+static long callback24(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method24(args);
+}
+static long callback25(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method25(args);
+}
+static long callback26(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method26(args);
+}
+static long callback27(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method27(args);
+}
+static long callback28(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method28(args);
+}
+static long callback29(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method29(args);
+}
+static long callback30(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method30(args);
+}
+static long callback31(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method31(args);
+}
+static long callback32(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method32(args);
+}
+static long callback33(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method33(args);
+}
+static long callback34(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method34(args);
+}
+static long callback35(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method35(args);
+}
+static long callback36(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method36(args);
+}
+static long callback37(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method37(args);
+}
+static long callback38(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method38(args);
+}
+static long callback39(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method39(args);
+}
+static long callback40(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method40(args);
+}
+static long callback41(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method41(args);
+}
+static long callback42(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method42(args);
+}
+static long callback43(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method43(args);
+}
+static long callback44(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method44(args);
+}
+static long callback45(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method45(args);
+}
+static long callback46(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method46(args);
+}
+static long callback47(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method47(args);
+}
+static long callback48(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method48(args);
+}
+static long callback49(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method49(args);
+}
+static long callback50(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method50(args);
+}
+static long callback51(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method51(args);
+}
+static long callback52(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method52(args);
+}
+static long callback53(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method53(args);
+}
+static long callback54(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method54(args);
+}
+static long callback55(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method55(args);
+}
+static long callback56(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method56(args);
+}
+static long callback57(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method57(args);
+}
+static long callback58(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method58(args);
+}
+static long callback59(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method59(args);
+}
+static long callback60(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method60(args);
+}
+static long callback61(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method61(args);
+}
+static long callback62(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method62(args);
+}
+static long callback63(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method63(args);
+}
+static long callback64(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method64(args);
+}
+static long callback65(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method65(args);
+}
+static long callback66(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method66(args);
+}
+static long callback67(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method67(args);
+}
+static long callback68(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method68(args);
+}
+static long callback69(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method69(args);
+}
+static long callback70(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method70(args);
+}
+static long callback71(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method71(args);
+}
+static long callback72(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method72(args);
+}
+static long callback73(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method73(args);
+}
+static long callback74(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method74(args);
+}
+static long callback75(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method75(args);
+}
+static long callback76(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method76(args);
+}
+static long callback77(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method77(args);
+}
+static long callback78(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method78(args);
+}
+static long callback79(long[] callbackArgs) {
+       // find the object on which this call was invoked
+       long address = callbackArgs[0];
+       COMObject object = ObjectMap.get(new LONG(address));
+       if (object == null) return COM.E_FAIL;
+       long[] args = new long[callbackArgs.length - 1];
+       System.arraycopy(callbackArgs, 1, args, 0, args.length);
+       return object.method79(args);
+}
+public void dispose() {
+       // free the memory for this reference
+       long[] pVtable = new long[1];
+       OS.MoveMemory(pVtable, ppVtable, C.PTR_SIZEOF);
+       OS.GlobalFree(pVtable[0]);
+       OS.GlobalFree(ppVtable);
+
+       // remove this ppVtable from the list
+       ObjectMap.remove(new LONG(ppVtable));
+
+       ppVtable = 0;
+}
+public long getAddress () {
+       return ppVtable;
+}
+public long method0(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method1(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method2(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method3(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method4(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method5(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method6(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method7(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method8(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method9(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method10(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method11(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method12(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method13(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method14(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method15(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method16(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method17(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method18(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method19(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method20(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method21(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method22(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method23(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method24(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method25(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method26(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method27(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method28(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method29(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method30(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method31(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method32(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method33(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method34(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method35(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method36(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method37(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method38(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method39(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method40(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method41(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method42(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method43(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method44(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method45(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method46(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method47(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method48(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method49(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method50(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method51(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method52(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method53(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method54(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method55(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method56(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method57(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method58(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method59(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method60(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method61(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method62(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method63(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method64(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method65(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method66(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method67(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method68(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method69(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method70(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method71(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method72(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method73(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method74(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method75(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method76(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method77(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method78(long[] args) {
+       return COM.E_NOTIMPL;
+}
+public long method79(long[] args) {
+       return COM.E_NOTIMPL;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/CONTROLINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/CONTROLINFO.java
new file mode 100644 (file)
index 0000000..3e9db86
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class CONTROLINFO {
+       public int cb;
+       /** @field cast=(HACCEL) */
+       public long hAccel;
+       public short cAccel;
+       public int dwFlags;
+       public static final int sizeof = COM.CONTROLINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/DISPPARAMS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/DISPPARAMS.java
new file mode 100644 (file)
index 0000000..6d4dd05
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class DISPPARAMS {
+       /** @field cast=(VARIANTARG FAR *) */
+       public long rgvarg;
+       /** @field cast=(DISPID FAR *) */
+       public long rgdispidNamedArgs;
+       public int cArgs;
+       public int cNamedArgs;
+       public static final int sizeof = COM.DISPPARAMS_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/EXCEPINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/EXCEPINFO.java
new file mode 100644 (file)
index 0000000..0a48daa
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class EXCEPINFO {
+       public short wCode;
+       public short wReserved;
+       /** @field cast=(BSTR) */
+       public long bstrSource;
+       /** @field cast=(BSTR) */
+       public long bstrDescription;
+       /** @field cast=(BSTR) */
+       public long bstrHelpFile;
+       public int dwHelpContext;
+       /** @field cast=(void FAR *) */
+       public long pvReserved;
+       /** @field cast=(HRESULT (STDAPICALLTYPE FAR* )(struct tagEXCEPINFO FAR*)) */
+       public long pfnDeferredFillIn;
+       public int scode;
+       public static final int sizeof = COM.EXCEPINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/FORMATETC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/FORMATETC.java
new file mode 100644 (file)
index 0000000..4796c7f
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class FORMATETC {
+       /** @field cast=(CLIPFORMAT) */
+       public int cfFormat;
+       /** @field cast=(DVTARGETDEVICE *) */
+       public long ptd;
+       public int dwAspect;
+       public int lindex;
+       public int tymed;
+       public static final int sizeof = COM.FORMATETC_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/FUNCDESC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/FUNCDESC.java
new file mode 100644 (file)
index 0000000..3cd2aec
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class FUNCDESC {
+       /** @field cast=(MEMBERID) */
+       public int memid;
+       /** @field cast=(SCODE FAR *) */
+       public long lprgscode;
+       /** @field cast=(ELEMDESC FAR *) */
+       public long lprgelemdescParam;
+       /** @field cast=(FUNCKIND) */
+       public int funckind;
+       /** @field cast=(INVOKEKIND) */
+       public int invkind;
+       /** @field cast=(CALLCONV) */
+       public int callconv;
+       public short cParams;
+       public short cParamsOpt;
+       public short oVft;
+       public short cScodes;
+//     ELEMDESC elemdescFunc;
+//     TYPEDESC elemdescFunc.tdesc
+       /** @field accessor=elemdescFunc.tdesc.lptdesc,cast=(struct FARSTRUCT tagTYPEDESC FAR* ) */
+       public long elemdescFunc_tdesc_union;
+       /** @field accessor=elemdescFunc.tdesc.vt */
+       public short elemdescFunc_tdesc_vt;
+//     PARAMDESC elemdescFunc.paramdesc
+       /** @field accessor=elemdescFunc.paramdesc.pparamdescex,cast=(LPPARAMDESCEX) */
+       public long elemdescFunc_paramdesc_pparamdescex;
+       /** @field accessor=elemdescFunc.paramdesc.wParamFlags */
+       public short elemdescFunc_paramdesc_wParamFlags;
+       public short wFuncFlags;
+       public static final int sizeof = COM.FUNCDESC_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/GUID.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/GUID.java
new file mode 100644 (file)
index 0000000..ee1a6b8
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class GUID {
+       public int Data1;
+       public short Data2;
+       public short Data3;
+       public byte[] Data4 = new byte[8];
+       public static final int sizeof = COM.GUID_sizeof ();
+
+       static final String zeros = "00000000"; //$NON-NLS-1$
+
+static String toHex (int v, int length) {
+       String t = Integer.toHexString (v).toUpperCase ();
+       int tlen = t.length ();
+       if (tlen > length) {
+               t = t.substring (tlen - length);
+       }
+       return zeros.substring (0, Math.max (0, length - tlen)) + t;
+}
+
+@Override
+public String toString () {
+       return '{' + toHex (Data1, 8) + '-' +
+               toHex (Data2, 4) + '-' +
+               toHex (Data3, 4) + '-' +
+               toHex (Data4[0], 2) + toHex (Data4[1], 2) + '-' +
+               toHex (Data4[2], 2) + toHex (Data4[3], 2) + toHex (Data4[4], 2) + toHex (Data4[5], 2) + toHex (Data4[6], 2) + toHex (Data4[7], 2) + '}';
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IAccessible.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IAccessible.java
new file mode 100644 (file)
index 0000000..7bb82c3
--- /dev/null
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IAccessible extends IDispatch {
+
+public IAccessible(long address) {
+       super(address);
+}
+
+public int get_accParent(long ppdispParent) {
+       return COM.VtblCall(7, address, ppdispParent);
+}
+public int get_accChildCount(long pcountChildren) {
+       return COM.VtblCall(8, address, pcountChildren);
+}
+public int get_accChild(long variant, long ppdispChild) {
+       return COM.VtblCall(9, address, variant, ppdispChild);
+}
+public int get_accName(long variant, long pszName) {
+       return COM.VtblCall(10, address, variant, pszName);
+}
+public int get_accValue(long variant, long pszValue) {
+       return COM.VtblCall(11, address, variant, pszValue);
+}
+public int get_accDescription(long variant, long pszDescription) {
+       return COM.VtblCall(12, address, variant, pszDescription);
+}
+public int get_accRole(long variant, long pvarRole) {
+       return COM.VtblCall(13, address, variant, pvarRole);
+}
+public int get_accState(long variant, long pvarState) {
+       return COM.VtblCall(14, address, variant, pvarState);
+}
+public int get_accHelp(long variant, long pszHelp) {
+       return COM.VtblCall(15, address, variant, pszHelp);
+}
+public int get_accHelpTopic(long pszHelpFile, long variant, long pidTopic) {
+       return COM.VtblCall(16, address, pszHelpFile, variant, pidTopic);
+}
+public int get_accKeyboardShortcut(long variant, long pszKeyboardShortcut) {
+       return COM.VtblCall(17, address, variant, pszKeyboardShortcut);
+}
+public int get_accFocus(long pvarChild) {
+       return COM.VtblCall(18, address, pvarChild);
+}
+public int get_accSelection(long pvarChildren) {
+       return COM.VtblCall(19, address, pvarChildren);
+}
+public int get_accDefaultAction(long variant, long pszDefaultAction) {
+       return COM.VtblCall(20, address, variant, pszDefaultAction);
+}
+public int accSelect(int flagsSelect, long variant) {
+       return COM.VtblCall(21, address, flagsSelect, variant);
+}
+public int accLocation(long pxLeft, long pyTop, long pcxWidth, long pcyHeight, long variant) {
+       return COM.VtblCall(22, address, pxLeft, pyTop, pcxWidth, pcyHeight, variant);
+}
+public int accNavigate(int navDir, long variant, long pvarEndUpAt) {
+       return COM.VtblCall(23, address, navDir, variant, pvarEndUpAt);
+}
+public int accHitTest(int xLeft, int yTop, long pvarChild) {
+       return COM.VtblCall(24, address, xLeft, yTop, pvarChild);
+}
+public int accDoDefaultAction(long variant) {
+       return COM.VtblCall(25, address, variant);
+}
+public int put_accName(long variant, long szName) {
+       return COM.VtblCall(26, address, variant, szName);
+}
+public int put_accValue(long variant, long szValue) {
+       return COM.VtblCall(27, address, variant, szValue);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IClassFactory2.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IClassFactory2.java
new file mode 100644 (file)
index 0000000..4a98133
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IClassFactory2 extends IUnknown
+{
+public IClassFactory2(long address) {
+       super(address);
+}
+public int CreateInstanceLic(long pUnkOuter, long pUnkReserved, GUID riid, long bstrKey, long ppvObject[]) {
+       return COM.VtblCall(7, address, pUnkOuter, pUnkReserved, riid, bstrKey, ppvObject);
+}
+public int GetLicInfo(LICINFO licInfo) {
+       return COM.VtblCall(5, address, licInfo);
+}
+public int RequestLicKey(int dwReserved, long[] pBstrKey) {
+       return COM.VtblCall(6, address, dwReserved, pBstrKey);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IConnectionPoint.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IConnectionPoint.java
new file mode 100644 (file)
index 0000000..2ccfb8e
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IConnectionPoint extends IUnknown
+{
+public IConnectionPoint(long address) {
+       super(address);
+}
+public int Advise(long pUnk, int[] pdwCookie) {
+       return COM.VtblCall(5, address, pUnk, pdwCookie);
+}
+public int Unadvise(int dwCookie) {
+       return COM.VtblCall(6, address, dwCookie);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IConnectionPointContainer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IConnectionPointContainer.java
new file mode 100644 (file)
index 0000000..66eb771
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IConnectionPointContainer extends IUnknown
+{
+public IConnectionPointContainer(long address) {
+       super(address);
+}
+public int FindConnectionPoint(GUID riid, long[] ppCP) {
+       return COM.VtblCall(4, address, riid, ppCP);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ICustomDestinationList.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ICustomDestinationList.java
new file mode 100644 (file)
index 0000000..c5f09a8
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class ICustomDestinationList extends IUnknown {
+
+public ICustomDestinationList(long address) {
+       super(address);
+}
+
+public int SetAppID(char[] pszAppID) {
+       return COM.VtblCall(3, address, pszAppID);
+}
+
+public int BeginList(int[] pcMinSlots, GUID riid, long[] ppv) {
+       return COM.VtblCall(4, address, pcMinSlots, riid, ppv);
+}
+
+public int AppendCategory(char[] pszCategory, IObjectArray poa) {
+       return COM.VtblCall(5, address, pszCategory, poa.address);
+}
+
+public int AddUserTasks(IUnknown poa) {
+       return COM.VtblCall(7, address, poa.address);
+}
+
+public int CommitList() {
+       return COM.VtblCall(8, address);
+}
+
+public int DeleteList(char[] pszAppID) {
+       return COM.VtblCall(10, address, pszAppID);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDataObject.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDataObject.java
new file mode 100644 (file)
index 0000000..1f8214e
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IDataObject extends IUnknown {
+public IDataObject(long address) {
+       super(address);
+}
+public int EnumFormatEtc(int dwDirection, long[] ppenumFormatetc) {
+       return COM.VtblCall(8, address, dwDirection, ppenumFormatetc);
+}
+public int 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.
+       return COM.VtblCall(3, address, pFormatetc, pmedium);
+}
+public int QueryGetData(FORMATETC pFormatetc) {
+       return COM.VtblCall(5, address, pFormatetc);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDispatch.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDispatch.java
new file mode 100644 (file)
index 0000000..a93811e
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+public class IDispatch extends IUnknown {
+
+public IDispatch(long address) {
+       super(address);
+}
+public int GetIDsOfNames(GUID riid, String[] rgszNames, int cNames, int lcid, int[] rgDispId) {
+
+       char[] buffer;
+       int size = rgszNames.length;
+
+       // create an array to hold the addresses
+       long hHeap = OS.GetProcessHeap();
+       long ppNames = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size * C.PTR_SIZEOF);
+       long[] memTracker = new long[size];
+
+       try {
+               // add the address of each string to the array
+
+               for (int i=0; i<size; i++){
+                       // create a null terminated array of char for each String
+                       int nameSize = rgszNames[i].length();
+                       buffer = new char[nameSize +1];
+                       rgszNames[i].getChars(0, nameSize, buffer, 0);
+                       // get the address of the start of the array of char
+                       long pName = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length * 2);
+                       OS.MoveMemory(pName, buffer, buffer.length * 2);
+                       // copy the address to the array of addresses
+                       OS.MoveMemory(ppNames + C.PTR_SIZEOF * i, new long[]{pName}, C.PTR_SIZEOF);
+                       // keep track of the Global Memory so we can free it
+                       memTracker[i] = pName;
+               }
+
+               return COM.VtblCall(5, address, new GUID(), ppNames, cNames, lcid, rgDispId);
+
+       } finally {
+               // free the memory
+               for (int i=0; i<memTracker.length; i++){
+                       OS.HeapFree(hHeap, 0, memTracker[i]);
+               }
+               OS.HeapFree(hHeap, 0, ppNames);
+       }
+}
+public int GetTypeInfo(int iTInfo, int lcid, long[] ppTInfo ){
+       return COM.VtblCall(4, address, iTInfo, lcid, ppTInfo);
+}
+public int Invoke(int dispIdMember, GUID riid, int lcid, int dwFlags, DISPPARAMS pDispParams, long pVarResult, EXCEPINFO pExcepInfo, int[] pArgErr) {
+       return COM.VtblCall(6, address, dispIdMember, riid, lcid, dwFlags, pDispParams, pVarResult, pExcepInfo, pArgErr);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDispatchEx.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IDispatchEx.java
new file mode 100644 (file)
index 0000000..08f5f1c
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IDispatchEx extends IDispatch {
+
+public IDispatchEx (long address) {
+       super (address);
+}
+
+public int InvokeEx (int id, int lcid, int wFlags, DISPPARAMS pdp, long pvarRes, EXCEPINFO pei, long pspCaller) {
+       return COM.VtblCall (8, address, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnum.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnum.java
new file mode 100644 (file)
index 0000000..793703e
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IEnum extends IUnknown
+{
+public IEnum(long address) {
+       super(address);
+}
+public int Clone( long[] ppenum  ){
+       return COM.VtblCall(6, address, ppenum);
+}
+public int Next(int celt, long rgelt, int[] pceltFetched  ){
+       return COM.VtblCall(3, address, celt, rgelt, pceltFetched);
+}
+public int Reset() {
+       return COM.VtblCall(5, address);
+}
+public int Skip(int celt){
+       return COM.VtblCall(4, address, celt);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumFORMATETC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumFORMATETC.java
new file mode 100644 (file)
index 0000000..664fe05
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IEnumFORMATETC extends IEnum {
+public IEnumFORMATETC(long address) {
+       super(address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumTfDisplayAttributeInfo.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumTfDisplayAttributeInfo.java
new file mode 100644 (file)
index 0000000..f8365b6
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IEnumTfDisplayAttributeInfo extends IUnknown {
+
+public IEnumTfDisplayAttributeInfo(long address) {
+       super(address);
+}
+
+public int Next(int celt, long[] rgelt, int[] pceltFetched) {
+       return COM.VtblCall(4, address, celt, rgelt, pceltFetched);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumVARIANT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IEnumVARIANT.java
new file mode 100644 (file)
index 0000000..0efbf37
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IEnumVARIANT extends IEnum {
+public IEnumVARIANT(long address) {
+       super(address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IFileDialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IFileDialog.java
new file mode 100644 (file)
index 0000000..cb21697
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IFileDialog extends IUnknown {
+
+public IFileDialog(long address) {
+       super(address);
+}
+
+// IModalWindow
+
+public int Show(long hwndOwner) {
+       return COM.VtblCall(3, address, hwndOwner);
+}
+
+// IFileDialog
+
+public int SetOptions(int fos) {
+       return COM.VtblCall(9, address, fos);
+}
+
+public int GetOptions(int[] pfos) {
+       return COM.VtblCall(10, address, pfos);
+}
+
+public int SetDefaultFolder(IShellItem psi) {
+       return COM.VtblCall(11, address, psi.address);
+}
+
+public int SetFolder(IShellItem psi) {
+       return COM.VtblCall(12, address, psi.address);
+}
+
+public int SetTitle(char[] pszTitle) {
+       return COM.VtblCall(17, address, pszTitle);
+}
+
+public int GetResult(long[] ppsi) {
+       return COM.VtblCall(20, address, ppsi);
+}
+
+public int ClearClientData() {
+       return COM.VtblCall(25, address);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IMLangFontLink2.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IMLangFontLink2.java
new file mode 100644 (file)
index 0000000..9f6f4fc
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IMLangFontLink2 extends IUnknown {
+
+public IMLangFontLink2(long address) {
+       super(address);
+}
+
+// IMLangCodePages
+
+public int GetStrCodePages(char[] pszSrc, int cchSrc, int dwPriorityCodePages, int[] pdwCodePages, int[] pcchCodePages) {
+       return COM.VtblCall(4, address, pszSrc, cchSrc, dwPriorityCodePages, pdwCodePages, pcchCodePages);
+}
+
+// IMLangFontLink2
+
+public int ReleaseFont(long hFont) {
+       return COM.VtblCall(8, address, hFont);
+}
+
+public int MapFont(long hDC, int dwCodePages, char chSrc, long[] phDestFont) {
+       return COM.VtblCall(10, address, hDC, dwCodePages, chSrc, phDestFont);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IObjectArray.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IObjectArray.java
new file mode 100644 (file)
index 0000000..a9883ce
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IObjectArray extends IUnknown {
+
+public IObjectArray(long address) {
+       super(address);
+}
+
+public int GetCount(int[] count) {
+       return COM.VtblCall(3, address, count);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IObjectCollection.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IObjectCollection.java
new file mode 100644 (file)
index 0000000..55844f7
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IObjectCollection extends IObjectArray {
+
+public IObjectCollection(long address) {
+       super(address);
+}
+
+public int AddObject(IUnknown punk) {
+       return COM.VtblCall(5, address, punk.address);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleCommandTarget.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleCommandTarget.java
new file mode 100644 (file)
index 0000000..d710395
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IOleCommandTarget extends IUnknown {
+public IOleCommandTarget(long address) {
+       super(address);
+}
+public int Exec(
+       GUID pguidCmdGroup,  // Pointer to command group
+       int  nCmdID,         // Identifier of command to execute
+       int  nCmdExecOpt,    // Options for executing the command
+       long  pvaIn,        // Pointer to input arguments
+       long  pvaOut        // Pointer to command output
+){
+       return COM.VtblCall(4, address, pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut);
+}
+public int QueryStatus(
+       GUID       pguidCmdGroup, // Pointer to command group
+       int        cCmds,         // Number of commands in prgCmds array
+       OLECMD     prgCmds,       // Array of commands
+       long       pCmdText       // Pointer to name or status of command
+){
+       // we only support querying for one command at a time
+       if (cCmds > 1) return COM.E_INVALIDARG;
+       return COM.VtblCall(3, address, pguidCmdGroup, cCmds, prgCmds, pCmdText);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleControl.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleControl.java
new file mode 100644 (file)
index 0000000..a2a80c5
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IOleControl extends IUnknown
+{
+public IOleControl(long address) {
+       super(address);
+}
+public int GetControlInfo(CONTROLINFO pCI) {
+       return COM.VtblCall(3, address, pCI);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleDocument.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleDocument.java
new file mode 100644 (file)
index 0000000..fca3f30
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IOleDocument extends IUnknown
+{
+public IOleDocument(long address) {
+       super(address);
+}
+public int CreateView(long pIPSite,long pstm, int dwReserved, long[] ppView) {
+       return COM.VtblCall(3, address, pIPSite, pstm, dwReserved, ppView);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleDocumentView.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleDocumentView.java
new file mode 100644 (file)
index 0000000..ffe055d
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+
+import org.eclipse.swt.internal.win32.*;
+
+public class IOleDocumentView extends IUnknown
+{
+public IOleDocumentView(long address) {
+       super(address);
+}
+public int SetInPlaceSite(long pIPSite) {
+       return COM.VtblCall(3, address, pIPSite);
+}
+public int SetRect(RECT prcView) {
+       return COM.VtblCall(6, address, prcView);
+}
+public int Show(int fShow) {
+       return COM.VtblCall(9, address, fShow);
+}
+public int UIActivate(int fUIActivate) {
+       return COM.VtblCall(10, address, fUIActivate);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleInPlaceActiveObject.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleInPlaceActiveObject.java
new file mode 100644 (file)
index 0000000..059a3a9
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class IOleInPlaceActiveObject extends IOleWindow
+{
+public IOleInPlaceActiveObject(long address) {
+       super(address);
+}
+public int TranslateAccelerator(MSG lpmsg) {
+       //lpmsg - Pointer to message that may need translating
+       return COM.VtblCall(5, address, lpmsg);
+}
+public void OnFrameWindowActivate(boolean fActivate) {
+       COM.VtblCall(6, address, fActivate ? 1 : 0);
+}
+public int ResizeBorder(RECT prcBorder, long pUIWindow, boolean fFrameWindow) {
+       return COM.VtblCall(8, address, prcBorder, pUIWindow, fFrameWindow ? 1 : 0);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleInPlaceObject.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleInPlaceObject.java
new file mode 100644 (file)
index 0000000..3ba5c50
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class IOleInPlaceObject extends IOleWindow
+{
+public IOleInPlaceObject(long address) {
+       super(address);
+}
+public int InPlaceDeactivate() {
+       return COM.VtblCall(5, address);
+}
+public int UIDeactivate() {
+       return COM.VtblCall(6, address);
+}
+public int SetObjectRects(RECT lprcPosRect, RECT lprcClipRect) {
+       return COM.VtblCall(7, address, lprcPosRect, lprcClipRect);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleLink.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleLink.java
new file mode 100644 (file)
index 0000000..7b364ae
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IOleLink extends IUnknown
+{
+public IOleLink(long address) {
+       super(address);
+}
+public int BindIfRunning() {
+       return COM.VtblCall(10, address);
+}
+public int GetSourceMoniker(long[] ppmk) {
+       return COM.VtblCall(6, address, ppmk);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleObject.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleObject.java
new file mode 100644 (file)
index 0000000..ca4abce
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class IOleObject extends IUnknown
+{
+public IOleObject(long address) {
+       super(address);
+}
+public int Advise(long pAdvSink, int[] pdwConnection) {
+       return COM.VtblCall(19, address, pAdvSink, pdwConnection);
+}
+public int Close(int dwSaveOption) {
+       return COM.VtblCall(6, address, dwSaveOption);
+}
+public int DoVerb(int iVerb, MSG lpmsg, long pActiveSite, int lindex, long hwndParent, RECT lprcPosRect) {
+       return COM.VtblCall(11, address, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
+}
+public int GetClientSite(long[] ppvClientSite) {
+       return COM.VtblCall(4, address, ppvClientSite);
+}
+public int GetExtent(int dwDrawAspect, SIZE pSizel) {
+       return COM.VtblCall(18, address, dwDrawAspect, pSizel);
+}
+public int SetClientSite(long pClientSite) {
+       return COM.VtblCall(3, address, pClientSite);
+}
+public int SetExtent(int dwDrawAspect, SIZE pSizel) {
+       return COM.VtblCall(17, address, dwDrawAspect, pSizel);
+}
+public int SetHostNames(String szContainerApp, String szContainerObj) {
+
+       // create a null terminated array of char
+       char[] buffer1 = null;
+       if (szContainerApp != null) {
+               int count1 = szContainerApp.length();
+               buffer1 = new char[count1 + 1];
+               szContainerApp.getChars(0, count1, buffer1, 0);
+       }
+
+       // create a null terminated array of char
+       char[] buffer2 = null;
+       if (szContainerObj != null) {
+               int count2 = szContainerObj.length();
+               buffer2 = new char[count2 + 1];
+               szContainerObj.getChars(0, count2, buffer2, 0);
+       }
+       return COM.VtblCall(5, address, buffer1, buffer2);
+}
+public int Unadvise(int token) {
+       return COM.VtblCall(20, address, token);
+}
+public int Update() {
+       return COM.VtblCall(13, address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleWindow.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IOleWindow.java
new file mode 100644 (file)
index 0000000..7a9c254
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IOleWindow extends IUnknown {
+public IOleWindow(long address) {
+       super(address);
+}
+public int GetWindow(long[] phwnd) {
+       return COM.VtblCall(3, address, phwnd);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersist.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersist.java
new file mode 100644 (file)
index 0000000..fdede1c
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IPersist extends IUnknown
+{
+public IPersist(long address) {
+       super(address);
+}
+public int GetClassID(GUID pClassID) {
+       return COM.VtblCall(3, address, pClassID);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistFile.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistFile.java
new file mode 100644 (file)
index 0000000..52f2797
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IPersistFile extends IPersist
+{
+public IPersistFile(long address) {
+       super(address);
+}
+public int IsDirty() {
+       return COM.VtblCall(4, address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistStorage.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistStorage.java
new file mode 100644 (file)
index 0000000..5e6f2aa
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IPersistStorage extends IPersist
+{
+public IPersistStorage(long address) {
+       super(address);
+}
+public int InitNew(long pStg) {
+       return COM.VtblCall(5, address, pStg);
+}
+public int Load(long pStg) {
+       return COM.VtblCall(6, address, pStg);
+}
+public int Save(long pStgSave, boolean fSameAsLoad) {
+       return COM.VtblCall(7, address, pStgSave, fSameAsLoad ? 1 : 0);
+}
+public int SaveCompleted(long pStgNew) {
+       return COM.VtblCall(8, address, pStgNew);
+}
+public int HandsOffStorage(){
+       return COM.VtblCall(9, address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistStreamInit.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPersistStreamInit.java
new file mode 100644 (file)
index 0000000..4253622
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IPersistStreamInit extends IPersist
+{
+public IPersistStreamInit(long address) {
+       super(address);
+}
+
+public int Load(long pStm) {
+       return COM.VtblCall(5, address, pStm);
+}
+
+public int InitNew() {
+       return COM.VtblCall(8, address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPropertyBag.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPropertyBag.java
new file mode 100644 (file)
index 0000000..f234be6
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+
+public class IPropertyBag extends IUnknown {
+
+public IPropertyBag (long address) {
+       super (address);
+}
+
+public int Read (long pszPropName, long pVar, long[] pErrorLog) {
+       return COM.VtblCall (3, getAddress(), pszPropName, pVar, pErrorLog);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPropertyStore.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IPropertyStore.java
new file mode 100644 (file)
index 0000000..c946313
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class IPropertyStore extends IUnknown {
+
+public IPropertyStore(long address) {
+       super(address);
+}
+
+public int SetValue(PROPERTYKEY key, long propvar) {
+       return COM.VtblCall(6, address, key, propvar);
+}
+
+public int Commit() {
+       return COM.VtblCall(7, address);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IProvideClassInfo.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IProvideClassInfo.java
new file mode 100644 (file)
index 0000000..b08d77c
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IProvideClassInfo extends IUnknown
+{
+public IProvideClassInfo(long address) {
+       super(address);
+}
+public int GetClassInfo(long[] ppTI) {
+       return COM.VtblCall(3, address, ppTI);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IProvideClassInfo2.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IProvideClassInfo2.java
new file mode 100644 (file)
index 0000000..61f7fbb
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IProvideClassInfo2 extends IProvideClassInfo
+{
+public IProvideClassInfo2(long address) {
+       super(address);
+}
+public int GetGUID(int dwGuidKind, GUID pGUID) {
+       return COM.VtblCall(4, address, dwGuidKind, pGUID);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IServiceProvider.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IServiceProvider.java
new file mode 100644 (file)
index 0000000..0ac2256
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IServiceProvider extends IUnknown
+{
+public IServiceProvider(long address) {
+       super(address);
+}
+public int QueryService(GUID iid1, GUID iid2, long ppvObject[]) {
+       return COM.VtblCall(3, address, iid1, iid2, ppvObject);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IShellItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IShellItem.java
new file mode 100644 (file)
index 0000000..a0f77de
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IShellItem extends IUnknown {
+
+public IShellItem(long address) {
+       super(address);
+}
+
+public int GetDisplayName(int sigdnName, long[] ppszName) {
+       return COM.VtblCall(5, address, sigdnName, ppszName);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IShellLink.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IShellLink.java
new file mode 100644 (file)
index 0000000..d487c43
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IShellLink extends IUnknown {
+
+public IShellLink(long address) {
+       super(address);
+}
+
+public int SetDescription(char[] pszName) {
+       return COM.VtblCall(7, address, pszName);
+}
+
+public int SetArguments(char[] pszArgs) {
+       return COM.VtblCall(11, address, pszArgs);
+}
+
+public int SetIconLocation(char[] pszIconPath, int iIcon) {
+       return COM.VtblCall(17, address, pszIconPath, iIcon);
+}
+
+public int SetPath(char[] pszFile) {
+       return COM.VtblCall(20, address, pszFile);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ISpecifyPropertyPages.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ISpecifyPropertyPages.java
new file mode 100644 (file)
index 0000000..31b382d
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class ISpecifyPropertyPages extends IUnknown {
+
+public ISpecifyPropertyPages(long address) {
+       super(address);
+}
+public int GetPages(CAUUID pPages){
+       return COM.VtblCall(3, address, pPages);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IStorage.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IStorage.java
new file mode 100644 (file)
index 0000000..173f5f1
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IStorage extends IUnknown
+{
+public IStorage(long address) {
+       super(address);
+}
+public int Commit(int grfCommitFlag) {
+       return COM.VtblCall(9, address, grfCommitFlag);
+}
+public int CopyTo(
+       int ciidExclude,     //Number of elements in rgiidExclude
+       GUID rgiidExclude,   //Array of interface identifiers (IIDs)
+       String[] snbExclude, //Points to a block of stream names in the storage object
+       long pstgDest         //Points to destination storage object
+       ){
+       // we only support snbExclude = null
+       if (snbExclude != null) {
+               return COM.E_INVALIDARG;
+       }
+       return COM.VtblCall(7, address, ciidExclude, rgiidExclude, 0, pstgDest);
+}
+public int CreateStream(
+       String pwcsName, //Pointer to the name of the new stream
+       int grfMode,     //Access mode for the new stream
+       int reserved1,   //Reserved; must be zero
+       int reserved2,   //Reserved; must be zero
+       long[] ppStm      //Pointer to new stream object
+){
+
+       // create a null terminated array of char
+       char[] buffer = null;
+       if (pwcsName != null) {
+               buffer = (pwcsName+"\0").toCharArray();
+       }
+
+       return COM.VtblCall(3, address, buffer, grfMode, reserved1, reserved2, ppStm);
+}
+public int OpenStream(
+       String pwcsName, //Pointer to name of stream to open
+       long reserved1,   //Reserved; must be NULL
+       int grfMode,     //Access mode for the new stream
+       int reserved2,   //Reserved; must be zero
+       long[] ppStm      //Pointer to output variable
+                        // that receives the IStream interface pointer
+) {
+
+       // create a null terminated array of char
+       char[] buffer = null;
+       if (pwcsName != null) {
+               buffer = (pwcsName+"\0").toCharArray();
+       }
+
+       return COM.VtblCall(4, address, buffer, reserved1, grfMode, reserved2, ppStm);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IStream.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IStream.java
new file mode 100644 (file)
index 0000000..3610958
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IStream extends IUnknown {
+public IStream(long address) {
+       super(address);
+}
+public int Commit( int grfCommitFlags  //Specifies how changes are committed
+){
+       return COM.VtblCall(8, address, grfCommitFlags);
+}
+public int Read(long pv, int cb, int[] pcbWritten) {
+       return COM.VtblCall(3, address, pv, cb, pcbWritten);
+}
+public int Write(long pv, int cb, int[] pcbWritten) {
+       return COM.VtblCall(4, address, pv, cb, pcbWritten);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITaskbarList3.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITaskbarList3.java
new file mode 100644 (file)
index 0000000..222857b
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class ITaskbarList3 extends IUnknown {
+
+public ITaskbarList3(long address) {
+       super(address);
+}
+
+public int SetProgressValue(long hwnd, long ullCompleted, long ullTotal) {
+       return COM.VtblCall(9, address, hwnd, ullCompleted, ullTotal);
+}
+
+public int SetProgressState(long hwnd, int tbpFlags) {
+       return COM.VtblCall(10, address, hwnd, tbpFlags);
+}
+
+public int SetOverlayIcon(long hwnd, long hIcon, long pszDescription) {
+       return COM.VtblCall(18, address, hwnd, hIcon, pszDescription);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeInfo.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeInfo.java
new file mode 100644 (file)
index 0000000..a21658b
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class ITfDisplayAttributeInfo extends IUnknown {
+
+public ITfDisplayAttributeInfo(long address) {
+       super(address);
+}
+
+public int GetAttributeInfo(TF_DISPLAYATTRIBUTE pda) {
+       return COM.VtblCall(5, address, pda);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeProvider.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfDisplayAttributeProvider.java
new file mode 100644 (file)
index 0000000..3f8f985
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class ITfDisplayAttributeProvider extends IUnknown {
+
+public ITfDisplayAttributeProvider(long address) {
+       super(address);
+}
+
+public int EnumDisplayAttributeInfo(long [] ppEnum) {
+       return COM.VtblCall(3, address, ppEnum);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfInputProcessorProfiles.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITfInputProcessorProfiles.java
new file mode 100644 (file)
index 0000000..29e06c9
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Nikita Nemkin <nikita@nemkin.ru> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class ITfInputProcessorProfiles extends IUnknown {
+
+public ITfInputProcessorProfiles(long address) {
+       super(address);
+}
+
+public int GetDefaultLanguageProfile(int langid, GUID catid, GUID pclsid, GUID pguidProfile) {
+       return COM.VtblCall(8, address, langid, catid, pclsid, pguidProfile);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITypeInfo.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/ITypeInfo.java
new file mode 100644 (file)
index 0000000..ad33f5d
--- /dev/null
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+
+import org.eclipse.swt.internal.win32.*;
+
+public class ITypeInfo extends IUnknown
+{
+
+public ITypeInfo(long address) {
+       super(address);
+}
+public int GetDocumentation(int index, String[] name, String[] docString, int[] pdwHelpContext, String[] helpFile ) {
+       long[] pBstrName = null;
+       if (name != null) pBstrName = new long[1];
+       long[] pBstrDocString = null;
+       if (docString != null) pBstrDocString = new long[1];
+       long[] pBstrHelpFile  = null;
+       if (helpFile != null) pBstrHelpFile = new long[1];
+       int rc = COM.VtblCall(12, address, index, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
+       if (name != null && pBstrName[0] != 0) {
+               int size = COM.SysStringByteLen(pBstrName[0]);
+               if (size > 0){
+                       // get the unicode character array from the global memory and create a String
+                       char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
+                       OS.MoveMemory(buffer, pBstrName[0], size);
+                       name[0] = new String(buffer);
+                       int subindex = name[0].indexOf("\0");
+                       if (subindex > 0)
+                               name[0] = name[0].substring(0, subindex);
+               }
+               COM.SysFreeString(pBstrName[0]);
+       }
+       if (docString != null && pBstrDocString[0] != 0) {
+               int size = COM.SysStringByteLen(pBstrDocString[0]);
+               if (size > 0){
+                       // get the unicode character array from the global memory and create a String
+                       char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
+                       OS.MoveMemory(buffer, pBstrDocString[0], size);
+                       docString[0] = new String(buffer);
+                       int subindex = docString[0].indexOf("\0");
+                       if (subindex > 0)
+                               docString[0] = docString[0].substring(0, subindex);
+               }
+               COM.SysFreeString(pBstrDocString[0]);
+       }
+       if (helpFile != null && pBstrHelpFile[0] != 0) {
+               int size = COM.SysStringByteLen(pBstrHelpFile[0]);
+               if (size > 0){
+                       // get the unicode character array from the global memory and create a String
+                       char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
+                       OS.MoveMemory(buffer, pBstrHelpFile[0], size);
+                       helpFile[0] = new String(buffer);
+                       int subindex = helpFile[0].indexOf("\0");
+                       if (subindex > 0)
+                               helpFile[0] = helpFile[0].substring(0, subindex);
+               }
+               COM.SysFreeString(pBstrHelpFile[0]);
+       }
+       return rc;
+}
+public int GetFuncDesc(int index, long[] ppFuncDesc) {
+       return COM.VtblCall(5, address, index, ppFuncDesc);
+}
+public int GetImplTypeFlags(int index, int[] pImplTypeFlags) {
+       return COM.VtblCall(9, address, index, pImplTypeFlags);
+}
+public int GetNames(int memid, String[] names, int cMaxNames, int[] pcNames){
+
+       int nameSize = names.length;
+       long[] rgBstrNames = new long[nameSize];
+       int rc = COM.VtblCall(7, address, memid, rgBstrNames, nameSize, pcNames);
+
+       if (rc == COM.S_OK) {
+               for (int i = 0; i < pcNames[0]; i++) {
+                       int size = COM.SysStringByteLen(rgBstrNames[i]);
+                       if (size > 0){
+                               // get the unicode character array from the global memory and create a String
+                               char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
+                               OS.MoveMemory(buffer, rgBstrNames[i], size);
+                               names[i] = new String(buffer);
+                               int subindex = names[i].indexOf("\0");
+                               if (subindex > 0)
+                                       names[i] = names[i].substring(0, subindex);
+                       }
+                       COM.SysFreeString(rgBstrNames[i]);
+               }
+       }
+
+       return rc;
+}
+public int GetRefTypeInfo(int hRefType, long[] ppTInfo) {
+       return COM.VtblCall(14, address, hRefType, ppTInfo);
+}
+public int GetRefTypeOfImplType(int index, int[] pRefType) {
+       return COM.VtblCall(8, address, index, pRefType);
+}
+public int GetTypeAttr(long[] ppTypeAttr) {
+       return COM.VtblCall(3, address, ppTypeAttr);
+}
+public int GetVarDesc(int index, long[] ppVarDesc ) {
+       return COM.VtblCall(6, address, index, ppVarDesc);
+}
+public int ReleaseFuncDesc(long pFuncDesc ) {
+       return COM.VtblCall(20, address, pFuncDesc);
+}
+public int ReleaseTypeAttr(long pTypeAttr) {
+       return COM.VtblCall(19, address, pTypeAttr);
+}
+public int ReleaseVarDesc(long pVarDesc ) {
+       return COM.VtblCall(21, address, pVarDesc);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IUnknown.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IUnknown.java
new file mode 100644 (file)
index 0000000..613713a
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class IUnknown
+{
+       long address;
+public IUnknown(long address) {
+       this.address = address;
+}
+public int AddRef() {
+       return COM.VtblCall(1, address);
+}
+public long getAddress() {
+       return address;
+}
+public int QueryInterface(GUID riid, long[] ppvObject) {
+       return COM.VtblCall(0, address, riid, ppvObject);
+}
+public int Release() {
+       return COM.VtblCall(2, address);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IViewObject2.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/IViewObject2.java
new file mode 100644 (file)
index 0000000..606fa9e
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+import org.eclipse.swt.internal.win32.*;
+
+public class IViewObject2 extends IUnknown
+{
+public IViewObject2(long address) {
+       super(address);
+}
+public int GetExtent(int dwAspect, int lindex, long ptd, SIZE lpsizel) {
+       return COM.VtblCall(9, address, dwAspect, lindex, ptd, lpsizel);
+}
+public int SetAdvise(int dwAspects, int dwAdvf, long pIAdviseSink) {
+       return COM.VtblCall(7, address, dwAspects, dwAdvf, pIAdviseSink);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/LICINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/LICINFO.java
new file mode 100644 (file)
index 0000000..2093932
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class LICINFO {
+       public int cbLicInfo;
+       public boolean fRuntimeKeyAvail;
+       public boolean fLicVerified;
+       public static final int sizeof = COM.LICINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/OLECMD.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/OLECMD.java
new file mode 100644 (file)
index 0000000..6fbeed7
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class OLECMD {
+       public int cmdID;
+       public int cmdf;
+       public static final int sizeof = COM.OLECMD_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/OLEINPLACEFRAMEINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/OLEINPLACEFRAMEINFO.java
new file mode 100644 (file)
index 0000000..1c28d09
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class OLEINPLACEFRAMEINFO {
+       public int cb;
+       public int fMDIApp;
+       /** @field cast=(HWND) */
+       public long hwndFrame;
+       /** @field cast=(HACCEL) */
+       public long haccel;
+       public int cAccelEntries;
+       public static final int sizeof = COM.OLEINPLACEFRAMEINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/STGMEDIUM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/STGMEDIUM.java
new file mode 100644 (file)
index 0000000..4f25f70
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class STGMEDIUM {
+       public int tymed;
+       /** @field accessor=hGlobal,cast=(HGLOBAL) */
+       public long unionField;
+       /** @field cast=(IUnknown *) */
+       public long pUnkForRelease;
+       public static final int sizeof = COM.STGMEDIUM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/TYPEATTR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/TYPEATTR.java
new file mode 100644 (file)
index 0000000..97e9b2f
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public final class TYPEATTR {
+//     GUID guid
+       /** @field accessor=guid.Data1 */
+       public int guid_Data1;
+       /** @field accessor=guid.Data2 */
+       public short guid_Data2;
+       /** @field accessor=guid.Data3 */
+       public short guid_Data3;
+       /** @field accessor=guid.Data4 */
+       public byte[] guid_Data4 = new byte[8];
+       public int lcid;
+       public int dwReserved;
+       public int memidConstructor;
+       public int memidDestructor;
+       /** @field cast=(OLECHAR FAR *) */
+       public long lpstrSchema;
+       public int cbSizeInstance;
+       public int typekind;
+       public short cFuncs;
+       public short cVars;
+       public short cImplTypes;
+       public short cbSizeVft;
+       public short cbAlignment;
+       public short wTypeFlags;
+       public short wMajorVerNum;
+       public short wMinorVerNum;
+//     TYPEDESC tdescAlias
+       /** @field accessor=tdescAlias.lptdesc,cast=(struct FARSTRUCT tagTYPEDESC FAR *) */
+       public long tdescAlias_unionField;
+       /** @field accessor=tdescAlias.vt */
+       public short tdescAlias_vt;
+//     IDLDESC idldesctype
+       /** @field accessor=idldescType.dwReserved */
+       public int idldescType_dwReserved;
+       /** @field accessor=idldescType.wIDLFlags */
+       public short idldescType_wIDLFlags;
+       public static final int sizeof = COM.TYPEATTR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/VARDESC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/VARDESC.java
new file mode 100644 (file)
index 0000000..0618a7b
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class VARDESC {
+       public int memid;
+       /** @field cast=(OLECHAR FAR *) */
+       public long lpstrSchema;
+       public int oInst;
+//     ELEMDESC elemdescVar
+//     TYPEDESC elemdescVar.tdesc
+       /** @field accessor=elemdescVar.tdesc.lptdesc,cast=(struct FARSTRUCT tagTYPEDESC FAR *) */
+       public long elemdescVar_tdesc_union;
+       /** @field accessor=elemdescVar.tdesc.vt */
+       public short elemdescVar_tdesc_vt;
+//     PARAMDESC elemdescFunc.paramdesc
+       /** @field accessor=elemdescVar.paramdesc.pparamdescex,cast=(LPPARAMDESCEX) */
+       public long elemdescVar_paramdesc_pparamdescex;
+       /** @field accessor=elemdescVar.paramdesc.wParamFlags */
+       public short elemdescVar_paramdesc_wParamFlags;
+       public short wVarFlags;
+       public int varkind;
+       public static final int sizeof = COM.VARDESC_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/VARIANT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/VARIANT.java
new file mode 100644 (file)
index 0000000..a9e1112
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.ole.win32;
+
+public class VARIANT {
+       public short vt;
+       public short wReserved1;
+       public short wReserved2;
+       public short wReserved3;
+       public int lVal;
+       public static final int sizeof = COM.VARIANT_sizeof();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/ole/win32/package.html
new file mode 100644 (file)
index 0000000..f3116a3
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT internal Win32 OLE implementation classes.
+<h2>
+Package Specification</h2>
+This package contains the internal classes which implement the Microsoft 
+Win32 platform interface to the Object Linking and Embedding mechanism
+that the win32 variant of SWT is capable of using.
+<p>
+Referencing any of the classes in this package directly guarantees
+that the code is platform specific. Applications should not need to
+reference the classes in this package directly.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/LAYERPLANEDESCRIPTOR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/LAYERPLANEDESCRIPTOR.java
new file mode 100644 (file)
index 0000000..0cf5914
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.opengl.win32;
+
+
+public class LAYERPLANEDESCRIPTOR {
+       public short nSize;
+       public short nVersion;
+       public int dwFlags;
+       public byte iPixelType;
+       public byte cColorBits;
+       public byte cRedBits;
+       public byte cRedShift;
+       public byte cGreenBits;
+       public byte cGreenShift;
+       public byte cBlueBits;
+       public byte cBlueShift;
+       public byte cAlphaBits;
+       public byte cAlphaShift;
+       public byte cAccumBits;
+       public byte cAccumRedBits;
+       public byte cAccumGreenBits;
+       public byte cAccumBlueBits;
+       public byte cAccumAlphaBits;
+       public byte cDepthBits;
+       public byte cStencilBits;
+       public byte cAuxBuffers;
+       public byte iLayerPlane;
+       public byte bReserved;
+       public int crTransparent;
+       public static final int sizeof = 36;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/PIXELFORMATDESCRIPTOR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/PIXELFORMATDESCRIPTOR.java
new file mode 100644 (file)
index 0000000..5cf0d11
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.opengl.win32;
+
+
+public class PIXELFORMATDESCRIPTOR {
+       public short nSize;
+       public short nVersion;
+       public int dwFlags;
+       public byte iPixelType;
+       public byte cColorBits;
+       public byte cRedBits;
+       public byte cRedShift;
+       public byte cGreenBits;
+       public byte cGreenShift;
+       public byte cBlueBits;
+       public byte cBlueShift;
+       public byte cAlphaBits;
+       public byte cAlphaShift;
+       public byte cAccumBits;
+       public byte cAccumRedBits;
+       public byte cAccumGreenBits;
+       public byte cAccumBlueBits;
+       public byte cAccumAlphaBits;
+       public byte cDepthBits;
+       public byte cStencilBits;
+       public byte cAuxBuffers;
+       public byte iLayerType;
+       public byte bReserved;
+       public int dwLayerMask;
+       public int dwVisibleMask;
+       public int dwDamageMask;
+       public static final int sizeof = 40;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/WGL.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/opengl/win32/WGL.java
new file mode 100644 (file)
index 0000000..bbcd315
--- /dev/null
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.opengl.win32;
+
+import org.eclipse.swt.internal.*;
+
+public class WGL extends Platform {
+       static {
+               Library.loadLibrary("swt-wgl");
+       }
+
+       public static final int WGL_FONT_LINES      = 0;
+       public static final int WGL_FONT_POLYGONS   = 1;
+
+       /* LAYERPLANEDESCRIPTOR flags */
+       public static final int LPD_DOUBLEBUFFER        = 0x00000001;
+       public static final int LPD_STEREO              = 0x00000002;
+       public static final int LPD_SUPPORT_GDI         = 0x00000010;
+       public static final int LPD_SUPPORT_OPENGL      = 0x00000020;
+       public static final int LPD_SHARE_DEPTH         = 0x00000040;
+       public static final int LPD_SHARE_STENCIL       = 0x00000080;
+       public static final int LPD_SHARE_ACCUM         = 0x00000100;
+       public static final int LPD_SWAP_EXCHANGE       = 0x00000200;
+       public static final int LPD_SWAP_COPY           = 0x00000400;
+       public static final int LPD_TRANSPARENT         = 0x00001000;
+
+       public static final int LPD_TYPE_RGBA        = 0;
+       public static final int LPD_TYPE_COLORINDEX  = 1;
+
+       /* wglSwapLayerBuffers flags */
+       public static final int WGL_SWAP_MAIN_PLANE     = 0x00000001;
+       public static final int WGL_SWAP_OVERLAY1       = 0x00000002;
+       public static final int WGL_SWAP_OVERLAY2       = 0x00000004;
+       public static final int WGL_SWAP_OVERLAY3       = 0x00000008;
+       public static final int WGL_SWAP_OVERLAY4       = 0x00000010;
+       public static final int WGL_SWAP_OVERLAY5       = 0x00000020;
+       public static final int WGL_SWAP_OVERLAY6       = 0x00000040;
+       public static final int WGL_SWAP_OVERLAY7       = 0x00000080;
+       public static final int WGL_SWAP_OVERLAY8       = 0x00000100;
+       public static final int WGL_SWAP_OVERLAY9       = 0x00000200;
+       public static final int WGL_SWAP_OVERLAY10      = 0x00000400;
+       public static final int WGL_SWAP_OVERLAY11      = 0x00000800;
+       public static final int WGL_SWAP_OVERLAY12      = 0x00001000;
+       public static final int WGL_SWAP_OVERLAY13      = 0x00002000;
+       public static final int WGL_SWAP_OVERLAY14      = 0x00004000;
+       public static final int WGL_SWAP_OVERLAY15      = 0x00008000;
+       public static final int WGL_SWAP_UNDERLAY1      = 0x00010000;
+       public static final int WGL_SWAP_UNDERLAY2      = 0x00020000;
+       public static final int WGL_SWAP_UNDERLAY3      = 0x00040000;
+       public static final int WGL_SWAP_UNDERLAY4      = 0x00080000;
+       public static final int WGL_SWAP_UNDERLAY5      = 0x00100000;
+       public static final int WGL_SWAP_UNDERLAY6      = 0x00200000;
+       public static final int WGL_SWAP_UNDERLAY7      = 0x00400000;
+       public static final int WGL_SWAP_UNDERLAY8      = 0x00800000;
+       public static final int WGL_SWAP_UNDERLAY9      = 0x01000000;
+       public static final int WGL_SWAP_UNDERLAY10     = 0x02000000;
+       public static final int WGL_SWAP_UNDERLAY11     = 0x04000000;
+       public static final int WGL_SWAP_UNDERLAY12     = 0x08000000;
+       public static final int WGL_SWAP_UNDERLAY13     = 0x10000000;
+       public static final int WGL_SWAP_UNDERLAY14     = 0x20000000;
+       public static final int WGL_SWAP_UNDERLAY15     = 0x40000000;
+
+       /* pixel types */
+       public static final int PFD_TYPE_RGBA        = 0;
+       public static final int PFD_TYPE_COLORINDEX  = 1;
+
+       /* layer types */
+       public static final int PFD_MAIN_PLANE       = 0;
+       public static final int PFD_OVERLAY_PLANE    = 1;
+       public static final int PFD_UNDERLAY_PLANE   = (-1);
+
+       /* PIXELFORMATDESCRIPTOR flags */
+       public static final int PFD_DOUBLEBUFFER            = 0x00000001;
+       public static final int PFD_STEREO                  = 0x00000002;
+       public static final int PFD_DRAW_TO_WINDOW          = 0x00000004;
+       public static final int PFD_DRAW_TO_BITMAP          = 0x00000008;
+       public static final int PFD_SUPPORT_GDI             = 0x00000010;
+       public static final int PFD_SUPPORT_OPENGL          = 0x00000020;
+       public static final int PFD_GENERIC_FORMAT          = 0x00000040;
+       public static final int PFD_NEED_PALETTE            = 0x00000080;
+       public static final int PFD_NEED_SYSTEM_PALETTE     = 0x00000100;
+       public static final int PFD_SWAP_EXCHANGE           = 0x00000200;
+       public static final int PFD_SWAP_COPY               = 0x00000400;
+       public static final int PFD_SWAP_LAYER_BUFFERS      = 0x00000800;
+       public static final int PFD_GENERIC_ACCELERATED     = 0x00001000;
+       public static final int PFD_SUPPORT_DIRECTDRAW      = 0x00002000;
+
+       /* PIXELFORMATDESCRIPTOR flags for use in ChoosePixelFormat only */
+       public static final int PFD_DEPTH_DONTCARE          = 0x20000000;
+       public static final int PFD_DOUBLEBUFFER_DONTCARE   = 0x40000000;
+       public static final int PFD_STEREO_DONTCARE         = 0x80000000;
+
+/** @param hdc cast=(HDC) */
+public static final native int ChoosePixelFormat(long hdc, PIXELFORMATDESCRIPTOR ppfd);
+/** @param hdc cast=(HDC) */
+public static final native int DescribePixelFormat(long hdc, int iPixelFormat, int nBytes, PIXELFORMATDESCRIPTOR ppfd);
+/** @param hdc cast=(HDC) */
+public static final native int GetPixelFormat(long hdc);
+/** @param hdc cast=(HDC) */
+public static final native boolean SetPixelFormat(long hdc, int iPixelFormat, PIXELFORMATDESCRIPTOR ppfd);
+/** @param hdc cast=(HDC) */
+public static final native boolean SwapBuffers(long hdc);
+/**
+ * @param hglrcSrc cast=(HGLRC)
+ * @param hglrcDst cast=(HGLRC)
+ */
+public static final native boolean wglCopyContext(long hglrcSrc, long hglrcDst, int mask);
+/** @param hdc cast=(HDC) */
+public static final native long wglCreateContext(long hdc);
+/** @param hdc cast=(HDC) */
+public static final native long wglCreateLayerContext(long hdc, int iLayerPlane);
+/** @param hglrc cast=(HGLRC) */
+public static final native boolean wglDeleteContext(long hglrc);
+public static final native long wglGetCurrentContext();
+public static final native long wglGetCurrentDC();
+public static final native long wglGetProcAddress(byte[] lpszProc);
+/**
+ * @param hdc cast=(HDC)
+ * @param hglrc cast=(HGLRC)
+ */
+public static final native boolean wglMakeCurrent(long hdc, long hglrc);
+/**
+ * @param hglrc1 cast=(HGLRC)
+ * @param hglrc2 cast=(HGLRC)
+ */
+public static final native boolean wglShareLists(long hglrc1, long hglrc2);
+/** @param hdc cast=(HDC) */
+public static final native boolean wglDescribeLayerPlane(long hdc, int iPixelFormat, int iLayerPlane, int nBytes, LAYERPLANEDESCRIPTOR plpd);
+/**
+ * @param hdc cast=(HDC)
+ * @param pcr cast=(COLORREF *)
+ */
+public static final native int wglSetLayerPaletteEntries(long hdc, int iLayerPlane, int iStart, int cEntries, int[] pcr);
+/**
+ * @param hdc cast=(HDC)
+ * @param pcr cast=(COLORREF *)
+ */
+public static final native int wglGetLayerPaletteEntries(long hdc, int iLayerPlane, int iStart, int cEntries, int[] pcr);
+/** @param hdc cast=(HDC) */
+public static final native boolean wglRealizeLayerPalette(long hdc, int iLayerPlane, boolean bRealize);
+/** @param hdc cast=(HDC) */
+public static final native boolean wglSwapLayerBuffers(long hdc, int fuPlanes);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/package.html
new file mode 100644 (file)
index 0000000..d1b671e
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT internal classes
+<h2>
+Package Specification</h2>
+This package provides the <code>Callback</code> class which is used to
+map the operating system's callback mechanism to Java message sends, and
+the <code>Converter</code> class which provides translation between Unicode
+and platform specific character sets.
+<p>
+Applications should not need to reference the classes in this package
+directly.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebCookieManager.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebCookieManager.java
new file mode 100644 (file)
index 0000000..ea7ed42
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebCookieManager extends IUnknown {
+
+public IWebCookieManager (long address) {
+       super (address);
+}
+
+public int cookieStorage (long[] storage) {
+       return COM.VtblCall (3, getAddress (), storage);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDataSource.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDataSource.java
new file mode 100644 (file)
index 0000000..2d54239
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebDataSource extends IUnknown {
+
+public IWebDataSource (long address) {
+       super (address);
+}
+
+public int representation (long[] rep) {
+       return COM.VtblCall (5, getAddress (), rep);
+}
+
+public int webFrame (long[] frame) {
+       return COM.VtblCall (6, getAddress (), frame);
+}
+
+public int request (long[] request) {
+       return COM.VtblCall (8, getAddress (), request);
+}
+
+public int pageTitle (long[] title) {
+       return COM.VtblCall (12, getAddress (), title);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDocumentRepresentation.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDocumentRepresentation.java
new file mode 100644 (file)
index 0000000..e18eda8
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebDocumentRepresentation extends IUnknown {
+
+public IWebDocumentRepresentation (long address) {
+       super (address);
+}
+
+public int documentSource (long[] source) {
+       return COM.VtblCall (8, getAddress (), source);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDownload.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebDownload.java
new file mode 100644 (file)
index 0000000..610252b
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebDownload extends IUnknown {
+
+public IWebDownload (long address) {
+       super (address);
+}
+
+public int cancel () {
+       return COM.VtblCall (4, getAddress ());
+}
+
+public int setDeletesFileUponFailure (int deletesFileUponFailure) {
+       return COM.VtblCall (12, getAddress (), deletesFileUponFailure);
+}
+
+public int setDestination (long path, int allowOverwrite) {
+       return COM.VtblCall (13, getAddress(), path, allowOverwrite);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebError.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebError.java
new file mode 100644 (file)
index 0000000..c8ac6b9
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebError extends IUnknown {
+
+public IWebError (long address) {
+       super (address);
+}
+
+public int code (int[] result) {
+       return COM.VtblCall (4, getAddress (), result);
+}
+
+//public int domain (long[] result) {
+//     return COM.VtblCall (5, getAddress (), result);
+//}
+
+public int localizedDescription (long[] result) {
+       return COM.VtblCall (6, getAddress (), result);
+}
+
+//public int localizedFailureReason (long[] result) {
+//     return COM.VtblCall (7, getAddress (), result);
+//}
+
+//public int userInfo (long[] result) {
+//return COM.VtblCall (11, getAddress (), result);
+//}
+
+public int failingURL (long[] result) {
+       return COM.VtblCall (12, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebErrorPrivate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebErrorPrivate.java
new file mode 100644 (file)
index 0000000..deec3f5
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebErrorPrivate extends IUnknown {
+
+public IWebErrorPrivate (long address) {
+       super (address);
+}
+
+public int sslPeerCertificate (long[] result) {
+       return COM.VtblCall (3, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebFrame.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebFrame.java
new file mode 100644 (file)
index 0000000..5ca43a6
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebFrame extends IUnknown {
+
+public IWebFrame (long address) {
+       super (address);
+}
+
+public int loadRequest (long request) {
+       return COM.VtblCall (8, getAddress (), request);
+}
+
+public int loadHTMLString (long string, long baseURL) {
+       return COM.VtblCall (10, getAddress (), string, baseURL);
+}
+
+public int dataSource (long[] source) {
+       return COM.VtblCall (13, getAddress (), source);
+}
+
+public long globalContext () {
+       return COM.VtblCall (23, getAddress ());
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebFramePrivate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebFramePrivate.java
new file mode 100644 (file)
index 0000000..9873a90
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebFramePrivate extends IUnknown {
+
+public IWebFramePrivate (long address) {
+       super (address);
+}
+
+public int setInPrintingMode (int value, long printDC) {
+       return COM.VtblCall (8, getAddress (), value, printDC);
+}
+
+public int getPrintedPageCount (long printDC, int[] pageCount) {
+       return COM.VtblCall (9, getAddress (), printDC, pageCount);
+}
+
+public int spoolPages (long printDC, int startPage, int endPage, long[] ctx) {
+       return COM.VtblCall (10, getAddress (), printDC, startPage, endPage, ctx);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebIBActions.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebIBActions.java
new file mode 100644 (file)
index 0000000..dd5e1ea
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebIBActions extends IUnknown {
+
+public IWebIBActions (long address) {
+       super (address);
+}
+
+public int stopLoading (long sender) {
+       return COM.VtblCall (4, getAddress (), sender);
+}
+
+public int reload (long sender) {
+       return COM.VtblCall (5, getAddress (), sender);
+}
+
+public int canGoBack (long sender, int[] result) {
+       return COM.VtblCall (6, getAddress (), sender, result);
+}
+
+public int canGoForward (long sender, int[] result) {
+       return COM.VtblCall (8, getAddress (), sender, result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebMutableURLRequest.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebMutableURLRequest.java
new file mode 100644 (file)
index 0000000..a072917
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebMutableURLRequest extends IWebURLRequest {
+
+public IWebMutableURLRequest (long address) {
+       super (address);
+}
+
+//public int setHTTPBody (long data) {
+//     return COM.VtblCall (21, getAddress (), data);
+//}
+
+//public int setHTTPBodyStream (long data) {
+//     return COM.VtblCall (22, getAddress (), data);
+//}
+
+public int setHTTPMethod (int post) {
+       return COM.VtblCall (23, getAddress (), post);
+}
+
+public int setURL (long theUrl) {
+       return COM.VtblCall (27, getAddress (), theUrl);
+}
+
+public int setValue (long value, long field) {
+       return COM.VtblCall (28, getAddress (), value, field);
+}
+
+public int setAllowsAnyHTTPSCertificate () {
+       return COM.VtblCall (29, getAddress ());
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebMutableURLRequestPrivate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebMutableURLRequestPrivate.java
new file mode 100644 (file)
index 0000000..fb8046a
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebMutableURLRequestPrivate extends IUnknown {
+
+public IWebMutableURLRequestPrivate (long address) {
+       super (address);
+}
+
+//public int setClientCertificate (long cert) {
+//return COM.VtblCall (3, getAddress (), cert);
+//}
+
+public int cfRequest () {
+       return COM.VtblCall (4, getAddress ());
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebOpenPanelResultListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebOpenPanelResultListener.java
new file mode 100644 (file)
index 0000000..0e2ae45
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebOpenPanelResultListener extends IUnknown {
+
+public IWebOpenPanelResultListener (long address) {
+       super (address);
+}
+
+public int chooseFilename (long fileName) {
+       return COM.VtblCall (3, getAddress (), fileName);
+}
+
+public int cancel () {
+       return COM.VtblCall (4, getAddress ());
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebPolicyDecisionListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebPolicyDecisionListener.java
new file mode 100644 (file)
index 0000000..97b505e
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebPolicyDecisionListener extends IUnknown{
+
+public IWebPolicyDecisionListener (long address) {
+       super (address);
+}
+
+public int use () {
+       return COM.VtblCall (3, getAddress ());
+}
+
+public int download () {
+       return COM.VtblCall (4, getAddress ());
+}
+
+public int ignore () {
+       return COM.VtblCall (5, getAddress ());
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebPreferences.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebPreferences.java
new file mode 100644 (file)
index 0000000..36c9b0d
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebPreferences extends IUnknown {
+
+public IWebPreferences (long address) {
+       super (address);
+}
+
+public int initWithIdentifier (long identifier, long[] preferences) {
+       return COM.VtblCall (4, getAddress (), identifier, preferences);
+}
+
+public int setJavaEnabled (int enabled) {
+       return COM.VtblCall (33, getAddress (), enabled);
+}
+
+public int setJavaScriptEnabled (int enabled) {
+       return COM.VtblCall (35, getAddress (), enabled);
+}
+
+public int setJavaScriptCanOpenWindowsAutomatically (int enabled) {
+       return COM.VtblCall (37, getAddress (), enabled);
+}
+
+public int setTabsToLinks (int enabled) {
+       return COM.VtblCall (52, getAddress (), enabled);
+}
+
+public int setFontSmoothing (int smoothingType) {
+       return COM.VtblCall (63, getAddress (), smoothingType);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallenge.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallenge.java
new file mode 100644 (file)
index 0000000..886c372
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebURLAuthenticationChallenge extends IUnknown {
+
+public IWebURLAuthenticationChallenge (long address) {
+       super (address);
+}
+
+public int previousFailureCount (int[] result) {
+       return COM.VtblCall (7, getAddress (), result);
+}
+
+public int proposedCredential (long[] result) {
+       return COM.VtblCall (8, getAddress (), result);
+}
+
+public int protectionSpace (long[] result) {
+       return COM.VtblCall (9, getAddress (), result);
+}
+
+public int sender (long[] sender) {
+       return COM.VtblCall (10, getAddress (), sender);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallengeSender.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLAuthenticationChallengeSender.java
new file mode 100644 (file)
index 0000000..bd4b66b
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebURLAuthenticationChallengeSender extends IUnknown {
+
+public IWebURLAuthenticationChallengeSender (long address) {
+       super (address);
+}
+
+public int cancelAuthenticationChallenge (long challenge) {
+       return COM.VtblCall (3, getAddress (), challenge);
+}
+
+public int useCredential (long credential, long challenge) {
+       return COM.VtblCall (5, getAddress (), credential, challenge);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLCredential.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLCredential.java
new file mode 100644 (file)
index 0000000..0fe000b
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebURLCredential extends IUnknown {
+
+public IWebURLCredential (long address) {
+       super (address);
+}
+
+public int hasPassword (int[] result) {
+       return COM.VtblCall (3, getAddress (), result);
+}
+
+public int initWithUser (long user, long password, long persistence) {
+       return COM.VtblCall (4, getAddress (), user, password, persistence);
+}
+
+public int password (long[] password) {
+       return COM.VtblCall (5, getAddress (), password);
+}
+
+public int user (long[] result) {
+       return COM.VtblCall (7, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLProtectionSpace.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLProtectionSpace.java
new file mode 100644 (file)
index 0000000..4766a27
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebURLProtectionSpace extends IUnknown {
+
+public IWebURLProtectionSpace(long address) {
+       super(address);
+}
+
+public int host (long[] result) {
+       return COM.VtblCall (4, getAddress (), result);
+}
+
+public int port (int[] result) {
+       return COM.VtblCall (8, getAddress (), result);
+}
+
+public int realm (long[] result) {
+       return COM.VtblCall (11, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLRequest.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLRequest.java
new file mode 100644 (file)
index 0000000..b426d90
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebURLRequest extends IUnknown {
+
+public IWebURLRequest (long address) {
+       super (address);
+}
+
+//public int HTTPBody (long[] result) {
+//     return COM.VtblCall (6, getAddress (), result);
+//}
+
+public int HTTPMethod (long[] result) {
+       return COM.VtblCall (8, getAddress (), result);
+}
+
+public int URL (long[] result) {
+       return COM.VtblCall (13, getAddress (), result);
+}
+
+public int mutableCopy (long[] result) {
+       return COM.VtblCall (16, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLResponse.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebURLResponse.java
new file mode 100644 (file)
index 0000000..a157911
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebURLResponse extends IUnknown {
+
+public IWebURLResponse (long address) {
+       super (address);
+}
+
+public int expectedContentLength (long[] result) {
+       return COM.VtblCall (3, getAddress (), result);
+}
+
+public int URL (long[] result) {
+       return COM.VtblCall (8, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebView.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebView.java
new file mode 100644 (file)
index 0000000..f5f8904
--- /dev/null
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+public class IWebView extends IUnknown {
+
+public IWebView (long address) {
+       super (address);
+}
+
+public int canShowMIMEType (long mimeType, int[] canShow) {
+       return COM.VtblCall (3, getAddress (), mimeType, canShow);
+}
+
+public int initWithFrame (RECT frame, long frameName, long groupName) {
+       return COM.VtblCall (9, getAddress(), frame, frameName, groupName);
+}
+
+public int setUIDelegate (long delegate) {
+       return COM.VtblCall (10, getAddress (), delegate);
+}
+
+public int setResourceLoadDelegate (long delegate) {
+       return COM.VtblCall (12, getAddress (), delegate);
+}
+
+public int setDownloadDelegate (long delegate) {
+       return COM.VtblCall (14, getAddress (), delegate);
+}
+
+public int setFrameLoadDelegate (long delegate) {
+       return COM.VtblCall (16, getAddress (), delegate);
+}
+
+public int setPolicyDelegate (long delegate) {
+       return COM.VtblCall (18, getAddress (), delegate);
+}
+
+public int mainFrame (long[] frame) {
+       return COM.VtblCall (20, getAddress (), frame);
+}
+
+public int goBack (int[] succeeded) {
+       return COM.VtblCall (24, getAddress(), succeeded);
+}
+
+public int goForward (int[] succeeded) {
+       return COM.VtblCall (25, getAddress(), succeeded);
+}
+
+public int setCustomUserAgent (long valueString) {
+       return COM.VtblCall (31, getAddress (), valueString);
+}
+
+public int setPreferences (long prefs) {
+       return COM.VtblCall (41, getAddress (), prefs);
+}
+
+public int preferences (long[] prefs) {
+       return COM.VtblCall (42, getAddress (), prefs);
+}
+
+public int setHostWindow (long window) {
+       return COM.VtblCall (45, getAddress (), window);
+}
+
+public int hostWindow (long[] window) {
+       return COM.VtblCall (46, getAddress (), window);
+}
+
+public int estimatedProgress (long estimatedProgress) {
+       return COM.VtblCall (51, getAddress (), estimatedProgress);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebViewPrivate.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/IWebViewPrivate.java
new file mode 100644 (file)
index 0000000..e067052
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.ole.win32.*;
+
+public class IWebViewPrivate extends IUnknown {
+
+public IWebViewPrivate (long address) {
+       super (address);
+}
+
+public int viewWindow (long[] window) {
+       return COM.VtblCall (5, getAddress (), window);
+}
+
+public int setInitialFocus (int forwardEnabled) {
+       return COM.VtblCall (28, getAddress (), forwardEnabled);
+}
+
+public int shouldClose (int[] result) {
+       return COM.VtblCall (33, getAddress (), result);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/JSClassDefinition.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/JSClassDefinition.java
new file mode 100644 (file)
index 0000000..595928e
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+/** @jniclass flags=cpp */
+public class JSClassDefinition {
+       public int version;
+       /** @field cast=(JSClassAttributes) */
+       public int attributes;
+       /** @field cast=(const char*) */
+       public long className;
+       /** @field cast=(JSClassRef) */
+       public long parentClass;
+       /** @field cast=(const JSStaticValue*) */
+       public long staticValues;
+       /** @field cast=(const JSStaticFunction*) */
+       public long staticFunctions;
+       /** @field cast=(JSObjectInitializeCallback) */
+       public long initialize;
+       /** @field cast=(JSObjectFinalizeCallback) */
+       public long finalize;
+       /** @field cast=(JSObjectHasPropertyCallback) */
+       public long hasProperty;
+       /** @field cast=(JSObjectGetPropertyCallback) */
+       public long getProperty;
+       /** @field cast=(JSObjectSetPropertyCallback) */
+       public long setProperty;
+       /** @field cast=(JSObjectDeletePropertyCallback) */
+       public long deleteProperty;
+       /** @field cast=(JSObjectGetPropertyNamesCallback) */
+       public long getPropertyNames;
+       /** @field cast=(JSObjectCallAsFunctionCallback) */
+       public long callAsFunction;
+       /** @field cast=(JSObjectCallAsConstructorCallback) */
+       public long callAsConstructor;
+       /** @field cast=(JSObjectHasInstanceCallback) */
+       public long hasInstance;
+       /** @field cast=(JSObjectConvertToTypeCallback) */
+       public long convertToType;
+
+       public static final int sizeof = WebKit_win32.JSClassDefinition_sizeof();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/WebKit_win32.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/webkit/WebKit_win32.java
new file mode 100644 (file)
index 0000000..3f2a020
--- /dev/null
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.webkit;
+
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/** @jniclass flags=cpp */
+public class WebKit_win32 extends C {
+       //public static final GUID CLSID_DOMEventListener = IIDFromString("{AC3D1BC3-4976-4431-8A19-4812C5EFE39C}"); //$NON-NLS-1$
+       public static final GUID CLSID_WebCookieManager = IIDFromString("{3F35F332-BB2B-49b3-AEDD-27B317687E07}"); //$NON-NLS-1$
+       public static final GUID CLSID_WebMutableURLRequest = IIDFromString("{a062ecc3-bb1b-4694-a569-f59e0ad6be0c}"); //$NON-NLS-1$
+       public static final GUID CLSID_WebPreferences = IIDFromString("{67B89F90-F778-438B-ABBF-34D1ACBF8651}"); //$NON-NLS-1$
+       public static final GUID CLSID_WebURLCredential = IIDFromString("{7433F53B-7FE9-484a-9432-72909457A646}"); //$NON-NLS-1$
+       public static final GUID CLSID_WebView = IIDFromString("{d6bca079-f61c-4e1e-b453-32a0477d02e3}"); //$NON-NLS-1$
+       //public static final GUID IID_IDOMEventListener = IIDFromString("{7f8a0a96-f864-44fb-87fb-c5f03666e8e6}"); //$NON-NLS-1$
+       public static final GUID IID_IWebCookieManager = IIDFromString("{7053FE94-3623-444f-A298-209A90879A8C}"); //$NON-NLS-1$
+       public static final GUID IID_IWebDownloadDelegate = IIDFromString("{16A32AE6-C862-40cd-9225-2CAF823F40F9}"); //$NON-NLS-1$
+       public static final GUID IID_IWebErrorPrivate = IIDFromString("{19FED49C-7016-48a6-B5C6-07ADE116531B}"); //$NON-NLS-1$
+       public static final GUID IID_IWebFrameLoadDelegate = IIDFromString("{3354665B-84BA-4fdf-B35E-BF5CF9D96026}"); //$NON-NLS-1$
+       public static final GUID IID_IWebFramePrivate = IIDFromString("{A1657D07-4881-4475-9D10-76548731D448}"); //$NON-NLS-1$
+       public static final GUID IID_IWebIBActions = IIDFromString("{8F0E3A30-B924-44f8-990A-1AE61ED6C632}"); //$NON-NLS-1$
+       public static final GUID IID_IWebMutableURLRequest = IIDFromString("{C4042773-371F-427e-AFA9-9D4B358A0D93}"); //$NON-NLS-1$
+       public static final GUID IID_IWebMutableURLRequestPrivate = IIDFromString("{AD675B60-2CE9-478c-B2AA-CAD643FF18AC}"); //$NON-NLS-1$;
+       public static final GUID IID_IWebPolicyDelegate = IIDFromString("{9B0BAE6C-A496-4000-9E22-2E89F0747401}"); //$NON-NLS-1$
+       public static final GUID IID_IWebPreferences = IIDFromString("{0930D594-A5A3-46e1-858E-AB17A13CD28E}"); //$NON-NLS-1$
+       public static final GUID IID_IWebResourceLoadDelegate = IIDFromString("{AF3289AA-90DB-4ca4-A112-A1E5F0517953}"); //$NON-NLS-1$
+       public static final GUID IID_IWebUIDelegate = IIDFromString("{042B7EE3-A5A4-4a8f-8C33-775CD9E89C7C}"); //$NON-NLS-1$
+       public static final GUID IID_IWebURLCredential = IIDFromString("{A1E9D765-FACE-4189-BBE3-AED7EBF65EBD}"); //$NON-NLS-1$
+       public static final GUID IID_IWebView = IIDFromString("{174BBEFD-058E-49C7-91DF-6F110AA4AC28}"); //$NON-NLS-1$
+       public static final GUID IID_IWebViewPrivate = IIDFromString("{44914369-DEB5-4fcf-A6A3-30C02E73154F}"); //$NON-NLS-1$
+
+       public static final int CFHTTPCookieSessionOnlyFlag   = 1 << 1;
+       public static final int FontSmoothingTypeWindows = 4;
+       public static final int kCFStringEncodingUTF8 = 0x08000100;
+
+       public static final int kJSTypeUndefined = 0;
+       public static final int kJSTypeNull = 1;
+       public static final int kJSTypeBoolean = 2;
+       public static final int kJSTypeNumber = 3;
+       public static final int kJSTypeString = 4;
+       public static final int kJSTypeObject = 5;
+
+       public static final int WebURLCredentialPersistenceForSession = 1;
+       public static final int WebURLErrorBadURL = -1000;
+       public static final int WebURLErrorServerCertificateNotYetValid = -1204;
+       public static final int WebURLErrorSecureConnectionFailed = -1200;
+
+static GUID IIDFromString (String lpsz) {
+       int length = lpsz.length ();
+       char[] buffer = new char[length + 1];
+       lpsz.getChars (0, length, buffer, 0);
+       GUID lpiid = new GUID ();
+       if (COM.IIDFromString (buffer, lpiid) == COM.S_OK) return lpiid;
+       return null;
+}
+
+/**
+ * @param theArray cast=(CFArrayRef)
+ */
+public static final native int CFArrayGetCount (long theArray);
+/**
+ * @param theArray cast=(CFArrayRef)
+ * @param idx cast=(CFIndex)
+ */
+public static final native long CFArrayGetValueAtIndex (long theArray, int idx);
+/**
+ * @param allocator cast=(CFAllocatorRef)
+ * @param bytes cast=(const UInt8 *)
+ * @param length cast=(CFIndex)
+ */
+public static final native long CFDataCreate (long allocator, byte [] bytes, int length);
+/**
+ * @param theData cast=(CFDataRef)
+ */
+public static final native long CFDataGetBytePtr (long theData);
+/**
+ * @param theData cast=(CFDataRef)
+ */
+public static final native int CFDataGetLength (long theData);
+/**
+ * @param allocator    cast=(CFAllocatorRef)
+ * @param keys cast=(const void **)
+ * @param values cast=(const void **)
+ * @param numValues cast=(CFIndex)
+ * @param keyCallBacks cast=(const CFDictionaryKeyCallBacks *)
+ * @param valueCallBacks cast=(const CFDictionaryValueCallBacks *)
+ */
+public static final native long CFDictionaryCreate (long allocator, long[] keys, long[] values, int numValues, long keyCallBacks, long valueCallBacks);
+/**
+ * @param inAllocator cast=(CFAllocatorRef)
+ * @param headerFields cast=(CFDictionaryRef)
+ * @param inURL        cast=(CFURLRef)
+ */
+public static final native long CFHTTPCookieCreateWithResponseHeaderFields (long inAllocator, long headerFields, long inURL);
+/**
+ * @param inCookie cast=(CFHTTPCookieRef)
+ */
+public static final native int CFHTTPCookieGetFlags (long inCookie);
+/**
+ * @param inCookie cast=(CFHTTPCookieRef)
+ */
+public static final native long CFHTTPCookieGetName (long inCookie);
+/**
+ * @param inCookie cast=(CFHTTPCookieRef)
+ */
+public static final native long CFHTTPCookieGetValue (long inCookie);
+/**
+ * @param inCookieStorage cast=(CFHTTPCookieStorageRef)
+ */
+public static final native long CFHTTPCookieStorageCopyCookies (long inCookieStorage);
+/**
+ * @param inCookieStorage cast=(CFHTTPCookieStorageRef)
+ * @param inURL cast=(CFURLRef)
+ * @param sendSecureCookies cast=(Boolean)
+ */
+public static final native long CFHTTPCookieStorageCopyCookiesForURL (long inCookieStorage, long inURL, boolean sendSecureCookies);
+/**
+ * @param inCookieStorage cast=(CFHTTPCookieStorageRef)
+ * @param inCookie cast=(CFHTTPCookieRef)
+ */
+public static final native void CFHTTPCookieStorageDeleteCookie (long inCookieStorage, long inCookie);
+/**
+ * @param inCookieStorage cast=(CFHTTPCookieStorageRef)
+ * @param inCookie cast=(CFHTTPCookieRef)
+ */
+public static final native void CFHTTPCookieStorageSetCookie (long inCookieStorage, long inCookie);
+/**
+ * @param cf cast=(CFTypeRef)
+ */
+public static final native void CFRelease (long cf);
+/**
+ * @param alloc cast=(CFAllocatorRef)
+ * @param chars cast=(const UniChar *)
+ * @param numChars cast=(CFIndex)
+ */
+public static final native int CFStringCreateWithCharacters (long alloc, char[] chars, int numChars);
+/**
+ * @param theString cast=(CFStringRef)
+ * @param idx cast=(CFIndex)
+ */
+public static final native char CFStringGetCharacterAtIndex (long theString, int idx);
+/**
+ * @param theString cast=(CFStringRef)
+ */
+public static final native long CFStringGetCharactersPtr (long theString);
+/**
+ * @param theString cast=(CFStringRef)
+ */
+public static final native int CFStringGetLength (long theString);
+/**
+ * @param allocator cast=(CFAllocatorRef)
+ * @param URLString cast=(CFStringRef)
+ * @param baseURL cast=(CFURLRef)
+ */
+public static final native long CFURLCreateWithString (long allocator, long URLString, long baseURL);
+/**
+ * @param alloc cast=(CFAllocatorRef)
+ * @param origRequest cast=(CFURLRequestRef)
+ */
+public static final native long CFURLRequestCreateMutableCopy (long    alloc, long origRequest);
+/**
+ * @param request cast=(CFURLRequestRef)
+ */
+public static final native long CFURLRequestCopyHTTPRequestBody (long request);
+/**
+ * @param mutableHTTPRequest cast=(CFMutableURLRequestRef)
+ * @param httpBody cast=(CFDataRef)
+ */
+public static final native void CFURLRequestSetHTTPRequestBody (long mutableHTTPRequest, long httpBody);
+/**
+ * @param mutableRequest cast=(CFMutableURLRequestRef)
+ * @param url cast=(CFURLRef)
+ */
+public static final native void CFURLRequestSetURL (long mutableRequest, long url);
+
+/**
+ * @param definition cast=(const JSClassDefinition*)
+ */
+public static final native long JSClassCreate (long definition);
+/**
+ * @param jsClass cast=(JSClassRef)
+ */
+public static final native long JSClassRetain (long jsClass);
+/**
+ * @param ctx cast=(JSContextRef)
+ */
+public static final native long JSContextGetGlobalObject (long ctx);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param script cast=(JSStringRef)
+ * @param thisObject cast=(JSObjectRef)
+ * @param sourceURL cast=(JSStringRef)
+ * @param exception cast=(JSValueRef *)
+ */
+public static final native long JSEvaluateScript (long ctx, long script, long thisObject, long sourceURL, int startingLineNumber, long[] exception);
+/**
+ * @param ctx cast=(JSGlobalContextRef)
+ */
+public static final native int JSGlobalContextRetain (long ctx);
+/**
+ * @param object cast=(JSObjectRef)
+ */
+public static final native long JSObjectGetPrivate (long object);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param object cast=(JSObjectRef)
+ * @param propertyName cast=(JSStringRef)
+ * @param exception cast=(JSValueRef*)
+ */
+public static final native long JSObjectGetProperty (long ctx, long object, long propertyName, long[] exception);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param object cast=(JSObjectRef)
+ * @param propertyIndex cast=(unsigned)
+ * @param exception cast=(JSValueRef*)
+ */
+public static final native long JSObjectGetPropertyAtIndex (long ctx, long object, int propertyIndex, long[] exception);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param jsClass cast=(JSClassRef)
+ * @param data cast=(void *)
+ */
+public static final native int JSObjectMake (long ctx, long jsClass, long data);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param argumentCount cast=(size_t)
+ * @param arguments cast=(const struct OpaqueJSValue * const*)
+ * @param exception cast=(JSValueRef*)
+ */
+public static final native long JSObjectMakeArray (long ctx, long argumentCount, long[] arguments, long[] exception);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param name cast=(JSStringRef)
+ * @param callAsFunction cast=(JSObjectCallAsFunctionCallback)
+ */
+public static final native int JSObjectMakeFunctionWithCallback (long ctx, long name, long callAsFunction);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param object cast=(JSObjectRef)
+ * @param propertyName cast=(JSStringRef)
+ * @param value cast=(JSValueRef)
+ * @param attributes cast=(JSPropertyAttributes)
+ * @param exception cast=(JSValueRef *)
+ */
+public static final native void JSObjectSetProperty (long ctx, long object, long propertyName, long value, long attributes, long[] exception);
+/**
+ * @param string cast=(const char*)
+ */
+public static final native long JSStringCreateWithUTF8CString (byte[] string);
+/**
+ * @param string cast=(JSStringRef)
+ */
+public static final native int JSStringGetLength (long string);
+/**
+ * @param string cast=(JSStringRef)
+ */
+public static final native long JSStringGetMaximumUTF8CStringSize (long string);
+/**
+ * @param string cast=(JSStringRef)
+ * @param buffer cast=(char *)
+ * @param bufferSize cast=(size_t)
+ */
+public static final native int JSStringGetUTF8CString (long string, byte[] buffer, long bufferSize);
+/**
+ * @param a cast=(JSStringRef)
+ * @param b    cast=(const char *)
+ */
+public static final native int JSStringIsEqualToUTF8CString (long a, byte[] b);
+/**
+ * @param string cast=(JSStringRef)
+ */
+public static final native void JSStringRelease (long string);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param value cast=(JSValueRef)
+ */
+public static final native int JSValueGetType (long ctx, long value);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param value        cast=(JSValueRef)
+ * @param jsClass      cast=(JSClassRef)
+ */
+public static final native int JSValueIsObjectOfClass (long ctx, long value, long jsClass);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param b cast=(bool)
+ */
+public static final native long JSValueMakeBoolean (long ctx, long b);
+/**
+ * @param ctx cast=(JSContextRef)
+ */
+public static final native long JSValueMakeNull (long ctx);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param number cast=(double)
+ */
+public static final native long JSValueMakeNumber (long ctx, double number);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param string cast=(JSStringRef)
+ */
+public static final native long JSValueMakeString (long ctx, long string);
+/**
+ * @param ctx cast=(JSContextRef)
+ */
+public static final native long JSValueMakeUndefined (long ctx);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param value cast=(JSValueRef)
+ * @param exception cast=(JSValueRef*)
+ */
+public static final native double JSValueToNumber (long ctx, long value, long[] exception);
+/**
+ * @param ctx cast=(JSContextRef)
+ * @param value cast=(JSValueRef)
+ * @param exception cast=(JSValueRef*)
+ */
+public static final native long JSValueToStringCopy (long ctx, long value, long[] exception);
+/** @method flags=const address*/
+public static final native long kCFCopyStringDictionaryKeyCallBacks ();
+/** @method flags=const address*/
+public static final native long kCFTypeDictionaryValueCallBacks ();
+
+public static final native int JSClassDefinition_sizeof ();
+/**
+ * @param dest cast=(void *)
+ * @param src cast=(const void *),flags=no_out
+ * @param size cast=(size_t)
+ */
+public static final native void memmove (long dest, JSClassDefinition src, long size);
+/** @method flags=no_gen */
+public static final native int WebKitCreateInstance (byte[] rclsid, long pUnkOuter, byte[] refiid, long[] ppvObject);
+public static final int WebKitCreateInstance (GUID clsid, long pUnkOuter, GUID iid, long[] ppvObject) {
+       byte[] rclsid = new byte[GUID.sizeof];
+       OS.IIDFromString ((clsid.toString () + '\0').toCharArray (), rclsid);
+       byte[] refiid = new byte[GUID.sizeof];
+       OS.IIDFromString ((iid.toString () + '\0').toCharArray (), refiid);
+       return WebKitCreateInstance (rclsid, pUnkOuter, refiid, ppvObject);
+}
+
+/** @method flags=no_gen */
+public static final native long JSObjectCallAsFunctionProc_CALLBACK (long func);
+/** @method flags=no_gen */
+public static final native long JSObjectGetPropertyProc_CALLBACK (long func);
+/** @method flags=no_gen */
+public static final native long JSObjectHasPropertyProc_CALLBACK (long func);
+/** @method flags=no_gen */
+public static final native long willPerformClientRedirectToURL_CALLBACK (long func);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ACCEL.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ACCEL.java
new file mode 100644 (file)
index 0000000..7cd4293
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class ACCEL {
+       public byte fVirt;
+       public short key;
+       public short cmd;
+       public static final int sizeof = OS.ACCEL_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ACTCTX.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ACTCTX.java
new file mode 100644 (file)
index 0000000..4b187b3
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class ACTCTX {
+       public int cbSize;
+       public int dwFlags;
+       /** @field cast=(LPCTSTR) */
+       public long lpSource;
+       public short wProcessorArchitecture;
+       public short wLangId;
+       /** @field cast=(LPCTSTR) */
+       public long lpAssemblyDirectory;
+       /** @field cast=(LPCTSTR) */
+       public long lpResourceName;
+       /** @field cast=(LPCTSTR) */
+       public long lpApplicationName;
+       /** @field cast=(HMODULE) */
+       public long hModule;
+       public static final int sizeof = OS.ACTCTX_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BITMAP.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BITMAP.java
new file mode 100644 (file)
index 0000000..01084c6
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class BITMAP {
+       public int bmType;
+       public int bmWidth;
+       public int bmHeight;
+       public int bmWidthBytes;
+       public short bmPlanes;
+       public short bmBitsPixel;
+       /** @field cast=(LPVOID) */
+       public long bmBits;
+       public static final int sizeof = OS.BITMAP_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BITMAPINFOHEADER.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BITMAPINFOHEADER.java
new file mode 100644 (file)
index 0000000..db9c0d3
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class BITMAPINFOHEADER {
+       public int biSize;
+       public int biWidth;
+       public int biHeight;
+       public short biPlanes;
+       public short biBitCount;
+       public int biCompression;
+       public int biSizeImage;
+       public int biXPelsPerMeter;
+       public int biYPelsPerMeter;
+       public int biClrUsed;
+       public int biClrImportant;
+       public static final int sizeof = OS.BITMAPINFOHEADER_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BLENDFUNCTION.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BLENDFUNCTION.java
new file mode 100644 (file)
index 0000000..2113bc3
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class BLENDFUNCTION {
+       public byte BlendOp;
+       public byte BlendFlags;
+       public byte SourceConstantAlpha;
+       public byte AlphaFormat;
+       public static final int sizeof = OS.BLENDFUNCTION_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BP_PAINTPARAMS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BP_PAINTPARAMS.java
new file mode 100644 (file)
index 0000000..388560f
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class BP_PAINTPARAMS {
+       public int cbSize;
+       public int dwFlags;
+       /** @field cast=(RECT*) */
+       public long prcExclude;
+       /** @field cast=(BLENDFUNCTION*) */
+       public long pBlendFunction;
+       public static final int sizeof = OS.BP_PAINTPARAMS_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BROWSEINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BROWSEINFO.java
new file mode 100644 (file)
index 0000000..3a9ee07
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class BROWSEINFO {
+       /** @field cast=(HWND) */
+       public long hwndOwner;
+       /** @field cast=(LPCITEMIDLIST) */
+       public long pidlRoot;
+       /** @field cast=(LPTSTR) */
+       public long pszDisplayName;
+       /** @field cast=(LPCTSTR) */
+       public long lpszTitle;
+       public int ulFlags;
+       /** @field cast=(BFFCALLBACK) */
+       public long lpfn;
+       public long lParam;
+       public int iImage;
+       public static final int sizeof = OS.BROWSEINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BUTTON_IMAGELIST.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/BUTTON_IMAGELIST.java
new file mode 100644 (file)
index 0000000..13b39ed
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class BUTTON_IMAGELIST {
+       /** @field cast=(HIMAGELIST) */
+       public long himl;
+       /** @field accessor=margin.left,cast=(LONG) */
+       public int margin_left;
+       /** @field accessor=margin.top,cast=(LONG) */
+       public int margin_top;
+       /** @field accessor=margin.right,cast=(LONG) */
+       public int margin_right;
+       /** @field accessor=margin.bottom,cast=(LONG) */
+       public int margin_bottom;
+       /** @field cast=(UINT) */
+       public int uAlign;
+       public static final int sizeof = OS.BUTTON_IMAGELIST_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CANDIDATEFORM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CANDIDATEFORM.java
new file mode 100644 (file)
index 0000000..517b834
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class CANDIDATEFORM {
+       public int dwIndex;
+       public int dwStyle;
+       public POINT ptCurrentPos = new POINT();
+       public RECT rcArea = new RECT();
+       public static final int sizeof = OS.CANDIDATEFORM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_CONTEXT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_CONTEXT.java
new file mode 100644 (file)
index 0000000..d4bb416
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CERT_CONTEXT {
+       public int dwCertEncodingType;
+       /** @field cast=(BYTE *) */
+       public long pbCertEncoded;
+       public int cbCertEncoded;
+       /** @field cast=(PCERT_INFO) */
+       public long pCertInfo;
+       /** @field cast=(HCERTSTORE) */
+       public long hCertStore;
+
+       public static final int sizeof = OS.CERT_CONTEXT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_INFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_INFO.java
new file mode 100644 (file)
index 0000000..f38f3aa
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CERT_INFO {
+       public int dwVersion;
+       public CRYPT_INTEGER_BLOB SerialNumber = new CRYPT_INTEGER_BLOB ();
+       public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CRYPT_ALGORITHM_IDENTIFIER ();
+       public CERT_NAME_BLOB Issuer = new CERT_NAME_BLOB ();
+       public FILETIME NotBefore = new FILETIME ();
+       public FILETIME NotAfter = new FILETIME ();
+       public CERT_NAME_BLOB Subject = new CERT_NAME_BLOB ();
+       public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo = new CERT_PUBLIC_KEY_INFO ();
+       public CRYPT_BIT_BLOB IssuerUniqueId = new CRYPT_BIT_BLOB ();
+       public CRYPT_BIT_BLOB SubjectUniqueId = new CRYPT_BIT_BLOB ();
+       public int cExtension;
+       /** @field cast=(PCERT_EXTENSION) */
+       public long rgExtension;
+
+       public static final int sizeof = OS.CERT_INFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_NAME_BLOB.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_NAME_BLOB.java
new file mode 100644 (file)
index 0000000..c563cbc
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CERT_NAME_BLOB {
+       public int cbData;
+       /** @field cast=(BYTE *) */
+       public long pbData;
+
+       static final public int sizeof = OS.CERT_NAME_BLOB_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_PUBLIC_KEY_INFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CERT_PUBLIC_KEY_INFO.java
new file mode 100644 (file)
index 0000000..64557cd
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CERT_PUBLIC_KEY_INFO {
+       public CRYPT_ALGORITHM_IDENTIFIER Algorithm = new CRYPT_ALGORITHM_IDENTIFIER ();
+       public CRYPT_BIT_BLOB PublicKey = new CRYPT_BIT_BLOB ();
+
+       static final public int sizeof = OS.CERT_PUBLIC_KEY_INFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CHOOSECOLOR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CHOOSECOLOR.java
new file mode 100644 (file)
index 0000000..22015a0
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class CHOOSECOLOR {
+       public int lStructSize;
+       /** @field cast=(HWND) */
+       public long hwndOwner;
+       /** @field cast=(HANDLE) */
+       public long hInstance;
+       public int rgbResult;
+       /** @field cast=(COLORREF *) */
+       public long lpCustColors;
+       public int Flags;
+       public long lCustData;
+       /** @field cast=(LPCCHOOKPROC) */
+       public long lpfnHook;
+       /** @field cast=(LPCTSTR) */
+       public long lpTemplateName;
+       public static final int sizeof = OS.CHOOSECOLOR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CHOOSEFONT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CHOOSEFONT.java
new file mode 100644 (file)
index 0000000..5b0773c
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class CHOOSEFONT {
+       public int lStructSize;
+       /** @field cast=(HWND) */
+       public long hwndOwner;
+       /** @field cast=(HDC) */
+       public long hDC;
+       /** @field cast=(LPLOGFONT) */
+       public long lpLogFont;
+       public int iPointSize;
+       public int Flags;
+       public int rgbColors;
+       public long lCustData;
+       /** @field cast=(LPCFHOOKPROC) */
+       public long lpfnHook;
+       /** @field cast=(LPCTSTR) */
+       public long lpTemplateName;
+       /** @field cast=(HINSTANCE) */
+       public long hInstance;
+       /** @field cast=(LPTSTR) */
+       public long lpszStyle;
+       public short nFontType;
+       public int nSizeMin;
+       public int nSizeMax;
+       public static final int sizeof = OS.CHOOSEFONT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CIDA.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CIDA.java
new file mode 100644 (file)
index 0000000..ad00853
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Paul Pazderski and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+/**
+ * @see <a href="https://docs.microsoft.com/en-us/windows/desktop/api/shlobj_core/ns-shlobj_core-_ida">WinAPI documentation: CIDA</a>
+ */
+public class CIDA {
+       public int cidl;
+       /** @field accessor=aoffset[0] */
+       public int aoffset;
+       // minimum size since the actual size depends on the number of offsets
+       public static final int sizeof = OS.CIDA_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/COMBOBOXINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/COMBOBOXINFO.java
new file mode 100644 (file)
index 0000000..aa46d5f
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class COMBOBOXINFO {
+       public int cbSize;
+       /** @field accessor=rcItem.left */
+       public int itemLeft;
+       /** @field accessor=rcItem.top */
+       public int itemTop;
+       /** @field accessor=rcItem.right */
+       public int itemRight;
+       /** @field accessor=rcItem.bottom */
+       public int itemBottom;
+       /** @field accessor=rcButton.left */
+       public int buttonLeft;
+       /** @field accessor=rcButton.top */
+       public int buttonTop;
+       /** @field accessor=rcButton.right */
+       public int buttonRight;
+       /** @field accessor=rcButton.bottom */
+       public int buttonBottom;
+       public int stateButton;
+       /** @field cast=(HWND) */
+       public long hwndCombo;
+       /** @field cast=(HWND) */
+       public long hwndItem;
+       /** @field cast=(HWND) */
+       public long hwndList;
+       public static final int sizeof = OS.COMBOBOXINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/COMPOSITIONFORM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/COMPOSITIONFORM.java
new file mode 100644 (file)
index 0000000..7014495
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class COMPOSITIONFORM {
+       public int dwStyle;
+//     POINT ptCurrentPos;
+       /** @field accessor=ptCurrentPos.x */
+       public int x;
+       /** @field accessor=ptCurrentPos.y */
+       public int y;
+//     RECT rcArea;
+       /** @field accessor=rcArea.left */
+       public int left;
+       /** @field accessor=rcArea.top */
+       public int top;
+       /** @field accessor=rcArea.right */
+       public int right;
+       /** @field accessor=rcArea.bottom */
+       public int bottom;
+       public static final int sizeof = OS.COMPOSITIONFORM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CREATESTRUCT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CREATESTRUCT.java
new file mode 100644 (file)
index 0000000..0f25f7a
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class CREATESTRUCT {
+       /** @field cast=(LPVOID) */
+       public long lpCreateParams;
+       /** @field cast=(HINSTANCE) */
+       public long hInstance;
+       /** @field cast=(HMENU) */
+       public long hMenu;
+       /** @field cast=(HWND) */
+       public long hwndParent;
+       public int cy;
+       public int cx;
+       public int y;
+       public int x;
+       public int style;
+       /** @field cast=(LPCTSTR) */
+       public long lpszName;
+       /** @field cast=(LPCTSTR) */
+       public long lpszClass;
+       public int dwExStyle;
+       public static final int sizeof = OS.CREATESTRUCT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_ALGORITHM_IDENTIFIER.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_ALGORITHM_IDENTIFIER.java
new file mode 100644 (file)
index 0000000..47d3c42
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CRYPT_ALGORITHM_IDENTIFIER {
+       /** @field cast=(LPSTR) */
+       public long pszObjId;
+       public CRYPT_OBJID_BLOB Parameters = new CRYPT_OBJID_BLOB ();
+
+       static final public int sizeof = OS.CRYPT_ALGORITHM_IDENTIFIER_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_BIT_BLOB.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_BIT_BLOB.java
new file mode 100644 (file)
index 0000000..a6cb3b1
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CRYPT_BIT_BLOB {
+       public int cbData;
+       /** @field cast=(BYTE *) */
+       public long pbData;
+       public int cUnusedBits;
+
+       static final public int sizeof = OS.CRYPT_BIT_BLOB_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_INTEGER_BLOB.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_INTEGER_BLOB.java
new file mode 100644 (file)
index 0000000..1d83007
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CRYPT_INTEGER_BLOB {
+       public int cbData;
+       /** @field cast=(BYTE *) */
+       public long pbData;
+
+       static final public int sizeof = OS.CRYPT_INTEGER_BLOB_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_OBJID_BLOB.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/CRYPT_OBJID_BLOB.java
new file mode 100644 (file)
index 0000000..56cccdf
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class CRYPT_OBJID_BLOB {
+       public int cbData;
+       /** @field cast=(BYTE *) */
+       public long pbData;
+
+       static final public int sizeof = OS.CRYPT_OBJID_BLOB_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DEVMODE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DEVMODE.java
new file mode 100644 (file)
index 0000000..33b4de4
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class DEVMODE {
+       public char[] dmDeviceName = new char[OS.CCHDEVICENAME];
+       public short dmSpecVersion;
+       public short dmDriverVersion;
+       public short dmSize;
+       public short dmDriverExtra;
+       public int dmFields;
+       public short dmOrientation;
+       public short dmPaperSize;
+       public short dmPaperLength;
+       public short dmPaperWidth;
+       public short dmScale;
+       public short dmCopies;
+       public short dmDefaultSource;
+       public short dmPrintQuality;
+       public short dmColor;
+       public short dmDuplex;
+       public short dmYResolution;
+       public short dmTTOption;
+       public short dmCollate;
+       public char[] dmFormName = new char[OS.CCHFORMNAME];
+       public short dmLogPixels;
+       public int dmBitsPerPel;
+       public int dmPelsWidth;
+       public int dmPelsHeight;
+       public int dmNup;
+       public int dmDisplayFrequency;
+       public int dmICMMethod;
+       public int dmICMIntent;
+       public int dmMediaType;
+       public int dmDitherType;
+       public int dmReserved1;
+       public int dmReserved2;
+       public int dmPanningWidth;
+       public int dmPanningHeight;
+       public static final int sizeof = OS.DEVMODE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DIBSECTION.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DIBSECTION.java
new file mode 100644 (file)
index 0000000..80bebaf
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class DIBSECTION extends BITMAP {
+       /** @field accessor=dsBmih.biSize */
+       public int biSize;
+       /** @field accessor=dsBmih.biWidth */
+       public int biWidth;
+       /** @field accessor=dsBmih.biHeight */
+       public int biHeight;
+       /** @field accessor=dsBmih.biPlanes */
+       public short biPlanes;
+       /** @field accessor=dsBmih.biBitCount */
+       public short biBitCount;
+       /** @field accessor=dsBmih.biCompression */
+       public int biCompression;
+       /** @field accessor=dsBmih.biSizeImage */
+       public int biSizeImage;
+       /** @field accessor=dsBmih.biXPelsPerMeter */
+       public int biXPelsPerMeter;
+       /** @field accessor=dsBmih.biYPelsPerMeter */
+       public int biYPelsPerMeter;
+       /** @field accessor=dsBmih.biClrUsed */
+       public int biClrUsed;
+       /** @field accessor=dsBmih.biClrImportant */
+       public int biClrImportant;
+       /** @field accessor=dsBitfields[0] */
+       public int dsBitfields0;
+       /** @field accessor=dsBitfields[1] */
+       public int dsBitfields1;
+       /** @field accessor=dsBitfields[2] */
+       public int dsBitfields2;
+       /** @field cast=(HANDLE) */
+       public long dshSection;
+       public int dsOffset;
+       public static final int sizeof = OS.DIBSECTION_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DOCHOSTUIINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DOCHOSTUIINFO.java
new file mode 100644 (file)
index 0000000..5cca035
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class DOCHOSTUIINFO {
+       public int cbSize;
+       public int dwFlags;
+       public int dwDoubleClick;
+       /** @field cast=(OLECHAR *) */
+       public long pchHostCss;
+       /** @field cast=(OLECHAR *) */
+       public long pchHostNS;
+       public static final int sizeof = OS.DOCHOSTUIINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DOCINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DOCINFO.java
new file mode 100644 (file)
index 0000000..e0ad9ab
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class DOCINFO {
+       public int cbSize;
+       /** @field cast=(LPCTSTR) */
+       public long lpszDocName; // LPCTSTR
+       /** @field cast=(LPCTSTR) */
+       public long lpszOutput; // LPCTSTR
+       /** @field cast=(LPCTSTR) */
+       public long lpszDatatype;// LPCTSTR
+       public int fwType; // DWORD
+       public static final int sizeof = OS.DOCINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DRAWITEMSTRUCT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DRAWITEMSTRUCT.java
new file mode 100644 (file)
index 0000000..0a7cb94
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class DRAWITEMSTRUCT {
+       public int CtlType;
+       public int CtlID;
+       public int itemID;
+       public int itemAction;
+       public int itemState;
+       /** @field cast=(HWND) */
+       public long hwndItem;
+       /** @field cast=(HDC) */
+       public long hDC;
+//     RECT rcItem;
+       /** @field accessor=rcItem.left */
+       public int left;
+       /** @field accessor=rcItem.top */
+       public int top;
+       /** @field accessor=rcItem.bottom */
+       public int bottom;
+       /** @field accessor=rcItem.right */
+       public int right;
+       public long itemData;
+       public static final int sizeof = OS.DRAWITEMSTRUCT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DROPFILES.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DROPFILES.java
new file mode 100644 (file)
index 0000000..a618b72
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class DROPFILES {
+       public int pFiles; // Offset of the file list from the beginning of this structure, in bytes.
+//     POINT pt; // Drop point. The coordinates depend on fNC.
+       /** @field accessor=pt.x */
+       public int pt_x;
+       /** @field accessor=pt.y */
+       public int pt_y;
+       public int 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.
+       public int 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.
+       public static final int sizeof = OS.DROPFILES_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DTTOPTS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/DTTOPTS.java
new file mode 100644 (file)
index 0000000..a642165
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+public class DTTOPTS {
+       public int dwSize;
+       public int dwFlags;
+       public int crText;
+       public int crBorder;
+       public int crShadow;
+       public int iTextShadowType;
+       public POINT ptShadowOffset;
+       public int iBorderSize;
+       public int iFontPropId;
+       public int iColorPropId;
+       public int iStateId;
+       public boolean fApplyOverlay;
+       public int iGlowSize;
+       /** @field cast=(DTT_CALLBACK_PROC) */
+       public long pfnDrawTextCallback;
+       public long lParam;
+       public static final int sizeof = OS.DTTOPTS_sizeof ();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EMR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EMR.java
new file mode 100644 (file)
index 0000000..d84d89f
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class EMR {
+       public int iType;
+       public int nSize;
+       public static final int sizeof = OS.EMR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EMREXTCREATEFONTINDIRECTW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EMREXTCREATEFONTINDIRECTW.java
new file mode 100644 (file)
index 0000000..387ad58
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class EMREXTCREATEFONTINDIRECTW {
+       public EMR emr = new EMR();
+       public int ihFont;
+       public EXTLOGFONTW elfw = new EXTLOGFONTW();
+       public static final int sizeof = OS.EMREXTCREATEFONTINDIRECTW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EXTLOGFONTW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/EXTLOGFONTW.java
new file mode 100644 (file)
index 0000000..5ca4ddb
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class EXTLOGFONTW {
+       public LOGFONT elfLogFont = new LOGFONT();
+       public char[] elfFullName = new char[OS.LF_FULLFACESIZE];
+       public char[] elfStyle = new char[OS.LF_FACESIZE];
+       public int elfVersion;
+       public int elfStyleSize;
+       public int elfMatch;
+       public int elfReserved;
+       public byte[] elfVendorId = new byte[OS.ELF_VENDOR_SIZE];
+       public int elfCulture;
+       public PANOSE elfPanose = new PANOSE();
+       public static final int sizeof = OS.EXTLOGFONTW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FILETIME.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FILETIME.java
new file mode 100644 (file)
index 0000000..4343052
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class FILETIME {
+       public int dwLowDateTime;
+       public int dwHighDateTime;
+       static final public int sizeof = OS.FILETIME_sizeof ();
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FLICK_DATA.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FLICK_DATA.java
new file mode 100644 (file)
index 0000000..f431d46
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.swt.internal.win32;
+
+public class FLICK_DATA {
+       public int iFlickActionCommandCode;
+       public byte iFlickDirection;
+       public boolean fControlModifier;
+       public boolean fMenuModifier;
+       public boolean fAltGRModifier;
+       public boolean fWinModifier;
+       public boolean fShiftModifier;
+       public int iReserved;
+       public boolean fOnInkingSurface;
+       public int iActionArgument;
+       public static final int sizeof = OS.FLICK_DATA_sizeof();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FLICK_POINT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/FLICK_POINT.java
new file mode 100644 (file)
index 0000000..29acddf
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class FLICK_POINT {
+       public int x;
+       public int y;
+       public static final int sizeof = OS.FLICK_POINT_sizeof();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GCP_RESULTS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GCP_RESULTS.java
new file mode 100644 (file)
index 0000000..00312c6
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class GCP_RESULTS {
+       public int lStructSize;
+       /** @field cast=(LPTSTR) */
+       public long lpOutString;
+       /** @field cast=(UINT  *) */
+       public long lpOrder;
+       /** @field cast=(int  *) */
+       public long lpDx;
+       /** @field cast=(int  *) */
+       public long lpCaretPos;
+       /** @field cast=(LPSTR) */
+       public long lpClass;
+       /** @field cast=(LPWSTR) */
+       public long lpGlyphs;
+       public int nGlyphs;
+       public int nMaxFit;
+       public static final int sizeof = OS.GCP_RESULTS_sizeof ();
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GESTURECONFIG.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GESTURECONFIG.java
new file mode 100644 (file)
index 0000000..c6ecf6e
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class GESTURECONFIG {
+       public int dwID;                     // gesture ID
+       public int dwWant;                   // settings related to gesture ID that are to be turned on
+       public int dwBlock;                  // settings related to gesture ID that are to be turned off
+       public static final int sizeof = OS.GESTURECONFIG_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GESTUREINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GESTUREINFO.java
new file mode 100644 (file)
index 0000000..991c6a9
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class GESTUREINFO {
+       public int cbSize;
+       public int dwFlags;
+       public int dwID;
+       /** @field cast=(HWND) */
+       public long hwndTarget;
+       //      POINTS ptsLocation
+       /** @field accessor=ptsLocation.x */
+       public short x;
+       /** @field accessor=ptsLocation.y */
+       public short y;
+       public int dwInstanceID;
+       public int dwSequenceID;
+       public long ullArguments;
+       public int cbExtraArgs;
+       public static final int sizeof = OS.GESTUREINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GRADIENT_RECT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GRADIENT_RECT.java
new file mode 100644 (file)
index 0000000..669a2c4
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class GRADIENT_RECT {
+       public int UpperLeft;
+       public int LowerRight;
+       public static final int sizeof = OS.GRADIENT_RECT_sizeof ();
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GUITHREADINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/GUITHREADINFO.java
new file mode 100644 (file)
index 0000000..4b25342
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class GUITHREADINFO {
+       /** @field cast=(DWORD) */
+       public int cbSize;
+       /** @field cast=(DWORD) */
+       public int flags;
+       /** @field cast=(HWND) */
+       public long hwndActive;
+       /** @field cast=(HWND) */
+       public long hwndFocus;
+       /** @field cast=(HWND) */
+       public long hwndCapture;
+       /** @field cast=(HWND) */
+       public long hwndMenuOwner;
+       /** @field cast=(HWND) */
+       public long hwndMoveSize;
+       /** @field cast=(HWND) */
+       public long hwndCaret;
+//     RECT rcCaret;
+       /** @field accessor=rcCaret.left */
+       public int left;
+       /** @field accessor=rcCaret.top */
+       public int top;
+       /** @field accessor=rcCaret.right */
+       public int right;
+       /** @field accessor=rcCaret.bottom */
+       public int bottom;
+       public static int sizeof = OS.GUITHREADINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDHITTESTINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDHITTESTINFO.java
new file mode 100644 (file)
index 0000000..6ad7644
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class HDHITTESTINFO {
+//     POINT pt;
+       /** @field accessor=pt.x */
+       public int x;
+       /** @field accessor=pt.y */
+       public int y;
+       public int flags;
+       public int iItem;
+       public static int sizeof = OS.HDHITTESTINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDITEM.java
new file mode 100644 (file)
index 0000000..57503ae
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class HDITEM {
+       public int mask;
+       public int cxy;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+       /** @field cast=(HBITMAP) */
+       public long hbm;
+       public int cchTextMax;
+       public int fmt;
+       public long lParam;
+       public int iImage;
+       public int iOrder;
+       public int type;
+       /** @field cast=(void *) */
+       public long pvFilter;
+       public static int sizeof = OS.HDITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDLAYOUT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HDLAYOUT.java
new file mode 100644 (file)
index 0000000..59c67a2
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class HDLAYOUT {
+       /** @field cast=(RECT *) */
+       public long prc;
+       /** @field cast=(WINDOWPOS *) */
+       public long pwpos;
+       public static final int sizeof = OS.HDLAYOUT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HELPINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HELPINFO.java
new file mode 100644 (file)
index 0000000..9116340
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class HELPINFO {
+       public int cbSize;
+       public int iContextType;
+       public int iCtrlId;
+       /** @field cast=(HANDLE) */
+       public long hItemHandle;
+       public int dwContextId;
+//     POINT MousePos
+       /** @field accessor=MousePos.x */
+       public int x;
+       /** @field accessor=MousePos.y */
+       public int y;
+       public static final int sizeof = OS.HELPINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HIGHCONTRAST.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/HIGHCONTRAST.java
new file mode 100644 (file)
index 0000000..aff9bc1
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class HIGHCONTRAST {
+       public int cbSize;
+       public int dwFlags;
+       /** @field cast=(LPTSTR) */
+       public long lpszDefaultScheme;
+       public static final int sizeof = OS.HIGHCONTRAST_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ICONINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/ICONINFO.java
new file mode 100644 (file)
index 0000000..edc107f
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class ICONINFO {
+       public boolean fIcon;
+       public int xHotspot;
+       public int yHotspot;
+       /** @field cast=(HBITMAP) */
+       public long hbmMask;
+       /** @field cast=(HBITMAP) */
+       public long hbmColor;
+       public static final int sizeof = OS.ICONINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/INITCOMMONCONTROLSEX.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/INITCOMMONCONTROLSEX.java
new file mode 100644 (file)
index 0000000..caed98f
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class INITCOMMONCONTROLSEX {
+       public int dwSize;
+       public int dwICC;
+       public static final int sizeof = OS.INITCOMMONCONTROLSEX_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/INPUT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/INPUT.java
new file mode 100644 (file)
index 0000000..0a29340
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class INPUT {
+       public int type;
+       public static final int sizeof = OS.INPUT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/KEYBDINPUT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/KEYBDINPUT.java
new file mode 100644 (file)
index 0000000..d502bc0
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class KEYBDINPUT {
+       public short wVk;
+       public short wScan;
+       public int dwFlags;
+       public int time;
+       public long dwExtraInfo;
+       public static final int sizeof = OS.KEYBDINPUT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LITEM.java
new file mode 100644 (file)
index 0000000..af5e613
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LITEM {
+       public int mask;
+       public int iLink;
+       public int state;
+       public int stateMask;
+       public char[] szID = new char[OS.MAX_LINKID_TEXT];
+       public char[] szUrl = new char[OS.L_MAX_URL_LENGTH];
+       public static final int sizeof = OS.LITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGBRUSH.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGBRUSH.java
new file mode 100644 (file)
index 0000000..0b09d15
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LOGBRUSH {
+       public int lbStyle;
+       public int lbColor;
+       public long lbHatch;
+       public static final int sizeof = OS.LOGBRUSH_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGFONT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGFONT.java
new file mode 100644 (file)
index 0000000..30e9628
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LOGFONT {
+       public int lfHeight;
+       public int lfWidth;
+       public int lfEscapement;
+       public int lfOrientation;
+       public int lfWeight;
+       public byte lfItalic;
+       public byte lfUnderline;
+       public byte lfStrikeOut;
+       public byte lfCharSet;
+       public byte lfOutPrecision;
+       public byte lfClipPrecision;
+       public byte lfQuality;
+       public byte lfPitchAndFamily;
+       public char[] lfFaceName = new char[OS.LF_FACESIZE];
+       public static final int sizeof = OS.LOGFONT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGPEN.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LOGPEN.java
new file mode 100644 (file)
index 0000000..dec9b46
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LOGPEN {
+       public int lopnStyle;
+//     POINT lopnWidth;
+       /** @field accessor=lopnWidth.x */
+       public int x;
+       /** @field accessor=lopnWidth.y */
+       public int y;
+       public int lopnColor;
+       public static final int sizeof = OS.LOGPEN_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LRESULT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LRESULT.java
new file mode 100644 (file)
index 0000000..c76f7e2
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+/** @jniclass flags=no_gen */
+public class LRESULT {
+       public long value;
+       public static final LRESULT ONE = new LRESULT (1);
+       public static final LRESULT ZERO = new LRESULT (0);
+
+public LRESULT (long value) {
+       this.value = value;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVCOLUMN.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVCOLUMN.java
new file mode 100644 (file)
index 0000000..b30d10f
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LVCOLUMN {
+       public int mask;
+       public int fmt;
+       public int cx;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+       public int cchTextMax;
+       public int iSubItem;
+       public int iImage;
+       public int iOrder;
+       public static final int sizeof = OS.LVCOLUMN_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVHITTESTINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVHITTESTINFO.java
new file mode 100644 (file)
index 0000000..239be56
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LVHITTESTINFO {
+//     POINT pt;
+       /** @field accessor=pt.x */
+       public int x;
+       /** @field accessor=pt.y */
+       public int y;
+       public int flags;
+       public int iItem;
+       public int iSubItem;
+       public static int sizeof = OS.LVHITTESTINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVINSERTMARK.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVINSERTMARK.java
new file mode 100644 (file)
index 0000000..6f853e3
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LVINSERTMARK {
+       public int cbSize;
+       public int dwFlags;
+       public int iItem;
+       public int dwReserved;
+       public static final int sizeof = OS.LVINSERTMARK_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/LVITEM.java
new file mode 100644 (file)
index 0000000..ccfc1c1
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class LVITEM {
+       public int mask;
+       public int iItem;
+       public int iSubItem;
+       public int state;
+       public int stateMask;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+       public int cchTextMax;
+       public int iImage;
+       public long lParam;
+       public int iIndent;
+       public int iGroupId;
+       public int cColumns;
+       /** @field cast=(PUINT) */
+       public long puColumns;
+       public static final int sizeof = OS.LVITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MARGINS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MARGINS.java
new file mode 100644 (file)
index 0000000..097fb18
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MARGINS {
+       public int cxLeftWidth;
+       public int cxRightWidth;
+       public int cyTopHeight;
+       public int cyBottomHeight;
+       public static final int sizeof = OS.MARGINS_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MCHITTESTINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MCHITTESTINFO.java
new file mode 100644 (file)
index 0000000..733cd4a
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MCHITTESTINFO {
+       public int cbSize;
+       public POINT pt = new POINT ();
+       public int uHit;
+       public SYSTEMTIME st = new SYSTEMTIME ();
+//     public RECT rc = new RECT ();
+//     public int iOffset;
+//     public int iRow;
+//     public int iCol;
+       public static final int sizeof = OS.MCHITTESTINFO_sizeof ();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MEASUREITEMSTRUCT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MEASUREITEMSTRUCT.java
new file mode 100644 (file)
index 0000000..8d719d3
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MEASUREITEMSTRUCT {
+       public int CtlType;
+       public int CtlID;
+       public int itemID;
+       public int itemWidth;
+       public int itemHeight;
+       public long itemData;
+       public static final int sizeof = OS.MEASUREITEMSTRUCT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUBARINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUBARINFO.java
new file mode 100644 (file)
index 0000000..873e646
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MENUBARINFO {
+       public int cbSize;
+//     RECT  rcBar;
+       /** @field accessor=rcBar.left */
+       public int left;
+       /** @field accessor=rcBar.top */
+       public int top;
+       /** @field accessor=rcBar.right */
+       public int right;
+       /** @field accessor=rcBar.bottom */
+       public int bottom;
+       /** @field cast=(HMENU) */
+       public long hMenu;
+       /** @field cast=(HWND) */
+       public long hwndMenu;
+       public boolean fBarFocused;
+       public boolean fFocused;
+       public static final int sizeof = OS.MENUBARINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUINFO.java
new file mode 100644 (file)
index 0000000..cfb2a7f
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MENUINFO {
+       public int cbSize;
+       public int fMask;
+       public int dwStyle;
+       public int cyMax;
+       /** @field cast=(HBRUSH) */
+       public long hbrBack;
+       public int dwContextHelpID;
+       public long dwMenuData;
+       public static final int sizeof = OS.MENUINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUITEMINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MENUITEMINFO.java
new file mode 100644 (file)
index 0000000..63df535
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MENUITEMINFO {
+       public int cbSize;
+       public int fMask;
+       public int fType;
+       public int fState;
+       public int wID;
+       /** @field cast=(HMENU) */
+       public long hSubMenu;
+       /** @field cast=(HBITMAP) */
+       public long hbmpChecked;
+       /** @field cast=(HBITMAP) */
+       public long hbmpUnchecked;
+       public long dwItemData;
+       /** @field cast=(LPTSTR) */
+       public long dwTypeData;
+       public int cch;
+       /** @field cast=(HBITMAP) */
+       public long hbmpItem;
+       public static final int sizeof = OS.MENUITEMINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MINMAXINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MINMAXINFO.java
new file mode 100644 (file)
index 0000000..1bd8c79
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MINMAXINFO {
+//     POINT ptReserved;
+       /** @field accessor=ptReserved.x */
+       public int ptReserved_x;
+       /** @field accessor=ptReserved.y */
+       public int ptReserved_y;
+//     POINT ptMaxSize;
+       /** @field accessor=ptMaxSize.x */
+       public int ptMaxSize_x;
+       /** @field accessor=ptMaxSize.y */
+       public int ptMaxSize_y;
+//     POINT ptMaxPosition;
+       /** @field accessor=ptMaxPosition.x */
+       public int ptMaxPosition_x;
+       /** @field accessor=ptMaxPosition.y */
+       public int ptMaxPosition_y;
+//     POINT ptMinTrackSize;
+       /** @field accessor=ptMinTrackSize.x */
+       public int ptMinTrackSize_x;
+       /** @field accessor=ptMinTrackSize.y */
+       public int ptMinTrackSize_y;
+//     POINT ptMaxTrackSize;
+       /** @field accessor=ptMaxTrackSize.x */
+       public int ptMaxTrackSize_x;
+       /** @field accessor=ptMaxTrackSize.y */
+       public int ptMaxTrackSize_y;
+       public static final int sizeof = OS.MINMAXINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MONITORINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MONITORINFO.java
new file mode 100644 (file)
index 0000000..acf2483
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MONITORINFO {
+       public int cbSize;
+//     RECT rcMonitor;
+       /** @field accessor=rcMonitor.left */
+       public int rcMonitor_left;
+       /** @field accessor=rcMonitor.top */
+       public int rcMonitor_top;
+       /** @field accessor=rcMonitor.right */
+       public int rcMonitor_right;
+       /** @field accessor=rcMonitor.bottom */
+       public int rcMonitor_bottom;
+//     RECT rcWork;
+       /** @field accessor=rcWork.left */
+       public int rcWork_left;
+       /** @field accessor=rcWork.top */
+       public int rcWork_top;
+       /** @field accessor=rcWork.right */
+       public int rcWork_right;
+       /** @field accessor=rcWork.bottom */
+       public int rcWork_bottom;
+       public int dwFlags;
+       public static final int sizeof = OS.MONITORINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MOUSEINPUT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MOUSEINPUT.java
new file mode 100644 (file)
index 0000000..87f0f9f
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MOUSEINPUT {
+       public int dx;
+       public int dy;
+       public int mouseData;
+       public int dwFlags;
+       public int time;
+       public long dwExtraInfo;
+       public static final int sizeof = OS.MOUSEINPUT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MSG.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/MSG.java
new file mode 100644 (file)
index 0000000..c4652ec
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class MSG {
+       /** @field cast=(HWND) */
+       public long hwnd;
+       public int message;
+       public long wParam;
+       public long lParam;
+       public int time;
+//     POINT pt;
+       /** @field accessor=pt.x */
+       public int x;
+       /** @field accessor=pt.y */
+       public int y;
+       public static final int sizeof = OS.MSG_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMCUSTOMDRAW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMCUSTOMDRAW.java
new file mode 100644 (file)
index 0000000..5fcc482
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMCUSTOMDRAW extends NMHDR {
+       public int dwDrawStage;
+       /** @field cast=(HDC) */
+       public long hdc;
+//     RECT rc;
+       /** @field accessor=rc.left */
+       public int left;
+       /** @field accessor=rc.top */
+       public int top;
+       /** @field accessor=rc.right */
+       public int right;
+       /** @field accessor=rc.bottom */
+       public int bottom;
+       public long dwItemSpec;
+       public int uItemState;
+       public long lItemlParam;
+       public static final int sizeof = OS.NMCUSTOMDRAW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMHDR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMHDR.java
new file mode 100644 (file)
index 0000000..2ce1e11
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMHDR {
+       /** @field cast=(HWND) */
+       public long hwndFrom;
+       public long idFrom;
+       public int code;
+       public static final int sizeof = OS.NMHDR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMHEADER.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMHEADER.java
new file mode 100644 (file)
index 0000000..15b302f
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMHEADER extends NMHDR {
+       public int iItem;
+       public int iButton;
+       /** @field cast=(HDITEM FAR *) */
+       public long pitem;
+       public static int sizeof = OS.NMHEADER_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLINK.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLINK.java
new file mode 100644 (file)
index 0000000..342a8bb
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMLINK extends NMHDR {
+//     LITEM item;
+       /** @field accessor=item.mask */
+       public int mask;
+       /** @field accessor=item.iLink */
+       public int iLink;
+       /** @field accessor=item.state */
+       public int state;
+       /** @field accessor=item.stateMask */
+       public int stateMask;
+       /** @field accessor=item.szID */
+       public char[] szID = new char[OS.MAX_LINKID_TEXT];
+       /** @field accessor=item.szUrl */
+       public char[] szUrl = new char[OS.L_MAX_URL_LENGTH];
+       public static final int sizeof = OS.NMLINK_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLISTVIEW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLISTVIEW.java
new file mode 100644 (file)
index 0000000..dcbfaee
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMLISTVIEW extends NMHDR {
+       public int iItem;
+       public int iSubItem;
+       public int uNewState;
+       public int uOldState;
+       public int uChanged;
+//     POINT ptAction;
+       /** @field accessor=ptAction.x */
+       public int x;
+       /** @field accessor=ptAction.y */
+       public int y;
+       public long lParam;
+       public static int sizeof = OS.NMLISTVIEW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVCUSTOMDRAW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVCUSTOMDRAW.java
new file mode 100644 (file)
index 0000000..878d50b
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMLVCUSTOMDRAW extends NMCUSTOMDRAW {
+       public int clrText;
+       public int clrTextBk;
+       public int iSubItem;
+       public int dwItemType;
+       public int clrFace;
+       public int iIconEffect;
+       public int iIconPhase;
+       public int iPartId;
+       public int iStateId;
+//     RECT rcText;
+       /** @field accessor=rcText.left */
+       public int rcText_left;
+       /** @field accessor=rcText.top */
+       public int rcText_top;
+       /** @field accessor=rcText.right */
+       public int rcText_right;
+       /** @field accessor=rcText.bottom */
+       public int rcText_bottom;
+       public int uAlign;
+       public static final int sizeof = OS.NMLVCUSTOMDRAW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVDISPINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVDISPINFO.java
new file mode 100644 (file)
index 0000000..3d550e8
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMLVDISPINFO extends NMHDR {
+//     LVITEM item;
+       /** @field accessor=item.mask */
+       public int mask;
+       /** @field accessor=item.iItem */
+       public int iItem;
+       /** @field accessor=item.iSubItem */
+       public int iSubItem;
+       /** @field accessor=item.state */
+       public int state;
+       /** @field accessor=item.stateMask */
+       public int stateMask;
+       /** @field accessor=item.pszText,cast=(LPTSTR) */
+       public long pszText;
+       /** @field accessor=item.cchTextMax */
+       public int cchTextMax;
+       /** @field accessor=item.iImage */
+       public int iImage;
+       /** @field accessor=item.lParam */
+       public long lParam;
+       /** @field accessor=item.iIndent */
+       public int iIndent;
+       /** @field accessor=item.iGroupId */
+       public int iGroupId;
+       /** @field accessor=item.cColumns */
+       public int cColumns;
+       /** @field accessor=item.puColumns,cast=(PUINT) */
+       public long puColumns;
+       public static final int sizeof = OS.NMLVDISPINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVFINDITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVFINDITEM.java
new file mode 100644 (file)
index 0000000..29daa5d
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMLVFINDITEM extends NMHDR {
+       public int iStart;
+//     LVFINDINFO lvfi;
+       /** @field accessor=lvfi.flags */
+       public int flags;
+       /** @field accessor=lvfi.psz,cast=(LPCTSTR) */
+       public long psz;
+       /** @field accessor=lvfi.lParam */
+       public long lParam;
+//     POINT pt;
+       /** @field accessor=lvfi.pt.x */
+       public int x;
+       /** @field accessor=lvfi.pt.y */
+       public int y;
+       /** @field accessor=lvfi.vkDirection */
+       public int vkDirection;
+       public static final int sizeof = OS.NMLVFINDITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVODSTATECHANGE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMLVODSTATECHANGE.java
new file mode 100644 (file)
index 0000000..b2f171e
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMLVODSTATECHANGE extends NMHDR {
+//     NMHDR hdr;
+       public int iFrom;
+       public int iTo;
+       public int uNewState;
+       public int uOldState;
+       public static final int sizeof = OS.NMLVODSTATECHANGE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMREBARCHEVRON.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMREBARCHEVRON.java
new file mode 100644 (file)
index 0000000..85c311b
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMREBARCHEVRON extends NMHDR {
+       public int uBand;
+       public int wID;
+       public long lParam;
+//     RECT rc;
+       /** @field accessor=rc.left */
+       public int left;
+       /** @field accessor=rc.top */
+       public int top;
+       /** @field accessor=rc.right */
+       public int right;
+       /** @field accessor=rc.bottom */
+       public int bottom;
+       public long lParamNM;
+       public static int sizeof = OS.NMREBARCHEVRON_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMREBARCHILDSIZE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMREBARCHILDSIZE.java
new file mode 100644 (file)
index 0000000..f1a61b2
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMREBARCHILDSIZE extends NMHDR {
+       public int uBand;
+       public int wID;
+//  RECT rcChild;
+       /** @field accessor=rcChild.left */
+       public int rcChild_left;
+       /** @field accessor=rcChild.top */
+       public int rcChild_top;
+       /** @field accessor=rcChild.right */
+       public int rcChild_right;
+       /** @field accessor=rcChild.bottom */
+       public int rcChild_bottom;
+//  RECT rcBand;
+       /** @field accessor=rcBand.left */
+       public int rcBand_left;
+       /** @field accessor=rcBand.top */
+       public int rcBand_top;
+       /** @field accessor=rcBand.right */
+       public int rcBand_right;
+       /** @field accessor=rcBand.bottom */
+       public int rcBand_bottom;
+       public static final int sizeof = OS.NMREBARCHILDSIZE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTBCUSTOMDRAW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTBCUSTOMDRAW.java
new file mode 100644 (file)
index 0000000..00ef24e
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2017 Conrad Groth and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Conrad Groth - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTBCUSTOMDRAW extends NMCUSTOMDRAW {
+       public NMCUSTOMDRAW nmcd;
+       /** @field cast=(HBRUSH) */
+       public long hbrMonoDither;
+       /** @field cast=(HBRUSH) */
+       public long hbrLines;
+       /** @field cast=(HPEN) */
+       public long hpenLines;
+       public int clrText;
+       public int clrMark;
+       public int clrTextHighlight;
+       public int clrBtnFace;
+       public int clrBtnHighlight;
+       public int clrHighlightHotTrack;
+       // RECT rcText;
+       /** @field accessor=rcText.left */
+       public int rcText_left;
+       /** @field accessor=rcText.top */
+       public int rcText_top;
+       /** @field accessor=rcText.right */
+       public int rcText_right;
+       /** @field accessor=rcText.bottom */
+       public int rcText_bottom;
+       public int nStringBkMode;
+       public int nHLStringBkMode;
+       public int iListGap;
+       public static final int sizeof = OS.NMTBCUSTOMDRAW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTBHOTITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTBHOTITEM.java
new file mode 100644 (file)
index 0000000..5853518
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTBHOTITEM extends NMHDR {
+       public int idOld;
+       public int idNew;
+       public int dwFlags;
+       public static final int sizeof = OS.NMTBHOTITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTOOLBAR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTOOLBAR.java
new file mode 100644 (file)
index 0000000..9383762
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTOOLBAR extends NMHDR {
+       public int iItem;
+//     TBBUTTON tbButton;
+       /** @field accessor=tbButton.iBitmap */
+       public int iBitmap;
+       /** @field accessor=tbButton.idCommand */
+       public int idCommand;
+       /** @field accessor=tbButton.fsState */
+       public byte fsState;
+       /** @field accessor=tbButton.fsStyle */
+       public byte fsStyle;
+       /** @field accessor=tbButton.dwData */
+       public long dwData;
+       /** @field accessor=tbButton.iString */
+       public long iString;
+       public int cchText;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+//     RECT rcButton;
+       /** @field accessor=rcButton.left */
+       public int left;
+       /** @field accessor=rcButton.top */
+       public int top;
+       /** @field accessor=rcButton.right */
+       public int right;
+       /** @field accessor=rcButton.bottom */
+       public int bottom;
+       public static final int sizeof = OS.NMTOOLBAR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTREEVIEW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTREEVIEW.java
new file mode 100644 (file)
index 0000000..dde9089
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTREEVIEW {
+       public NMHDR hdr = new NMHDR ();
+       public int action;
+       public TVITEM itemOld = new TVITEM ();
+       public TVITEM itemNew = new TVITEM ();
+       public POINT ptDrag = new POINT ();
+       public static final int sizeof = OS.NMTREEVIEW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTTCUSTOMDRAW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTTCUSTOMDRAW.java
new file mode 100644 (file)
index 0000000..97bddf9
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTTCUSTOMDRAW extends NMCUSTOMDRAW {
+       public int uDrawFlags;
+       public static final int sizeof = OS.NMTTCUSTOMDRAW_sizeof ();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTTDISPINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTTDISPINFO.java
new file mode 100644 (file)
index 0000000..5c040e9
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTTDISPINFO extends NMHDR {
+       /** @field cast=(void *) */
+       public long lpszText;
+       public char[] szText = new char[80];
+       /** @field cast=(HINSTANCE) */
+       public long hinst;
+       public int uFlags;
+       public long lParam;
+       public static final int sizeof = OS.NMTTDISPINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVCUSTOMDRAW.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVCUSTOMDRAW.java
new file mode 100644 (file)
index 0000000..d5a81d4
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTVCUSTOMDRAW extends NMCUSTOMDRAW {
+       public int clrText;
+       public int clrTextBk;
+       public int iLevel;
+       public static final int sizeof = OS.NMTVCUSTOMDRAW_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVDISPINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVDISPINFO.java
new file mode 100644 (file)
index 0000000..cae9d2a
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTVDISPINFO extends NMHDR {
+//     TVITEM item;
+       /** @field accessor=item.mask */
+       public int mask;
+       /** @field accessor=item.hItem,cast=(HTREEITEM) */
+       public long hItem;
+       /** @field accessor=item.state */
+       public int state;
+       /** @field accessor=item.stateMask */
+       public int stateMask;
+       /** @field accessor=item.pszText,cast=(LPTSTR) */
+       public long pszText;
+       /** @field accessor=item.cchTextMax */
+       public int cchTextMax;
+       /** @field accessor=item.iImage */
+       public int iImage;
+       /** @field accessor=item.iSelectedImage */
+       public int iSelectedImage;
+       /** @field accessor=item.cChildren */
+       public int cChildren;
+       /** @field accessor=item.lParam */
+       public long lParam;
+       public static final int sizeof = OS.NMTVDISPINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVITEMCHANGE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMTVITEMCHANGE.java
new file mode 100644 (file)
index 0000000..53f1991
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMTVITEMCHANGE extends NMHDR {
+       public int uChanged;
+       /** @field cast=(HTREEITEM) */
+       public long hItem;
+       public int uStateNew;
+       public int uStateOld;
+       public long lParam;
+       public static int sizeof = OS.NMTVITEMCHANGE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMUPDOWN.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NMUPDOWN.java
new file mode 100644 (file)
index 0000000..ee24797
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NMUPDOWN extends NMHDR {
+       public int iPos;
+       public int iDelta;
+       public static final int sizeof = OS.NMUPDOWN_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NONCLIENTMETRICS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NONCLIENTMETRICS.java
new file mode 100644 (file)
index 0000000..c2b3d86
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NONCLIENTMETRICS {
+       public int cbSize;
+       public int iBorderWidth;
+       public int iScrollWidth;
+       public int iScrollHeight;
+       public int iCaptionWidth;
+       public int iCaptionHeight;
+       public LOGFONT lfCaptionFont = new LOGFONT ();
+       public int iSmCaptionWidth;
+       public int iSmCaptionHeight;
+       public LOGFONT lfSmCaptionFont = new LOGFONT ();
+       public int iMenuWidth;
+       public int iMenuHeight;
+       public LOGFONT lfMenuFont = new LOGFONT ();
+       public LOGFONT lfStatusFont = new LOGFONT ();
+       public LOGFONT lfMessageFont = new LOGFONT ();
+       public static final int sizeof = OS.NONCLIENTMETRICS_sizeof ();
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NOTIFYICONDATA.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/NOTIFYICONDATA.java
new file mode 100644 (file)
index 0000000..d226b47
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class NOTIFYICONDATA {
+       public int cbSize;
+       /** @field cast=(HWND) */
+       public long hWnd;
+       public int uID;
+       public int uFlags;
+       public int uCallbackMessage;
+       /** @field cast=(HICON) */
+       public long hIcon;
+       public char szTip[] = new char [128];
+       public int dwState;
+       public int dwStateMask;
+       public char szInfo[] = new char [256];
+       public char szInfoTitle[] = new char [64];
+       public int uVersion;
+       public int dwInfoFlags;
+       public static final int sizeof = OS.NOTIFYICONDATA_V2_SIZE;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OFNOTIFY.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OFNOTIFY.java
new file mode 100644 (file)
index 0000000..e213180
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class OFNOTIFY extends NMHDR {
+       /** @field cast=(LPOPENFILENAME) */
+       public long lpOFN;
+       /** @field cast=(LPTSTR) */
+       public long pszFile;
+       public static int sizeof = OS.OFNOTIFY_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OPENFILENAME.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OPENFILENAME.java
new file mode 100644 (file)
index 0000000..af18ce2
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class OPENFILENAME {
+       public int lStructSize;
+       /** @field cast=(HWND) */
+       public long hwndOwner;
+       /** @field cast=(HINSTANCE) */
+       public long hInstance;
+       /** @field cast=(LPCTSTR) */
+       public long lpstrFilter;
+       /** @field cast=(LPTSTR) */
+       public long lpstrCustomFilter;
+       public int nMaxCustFilter;
+       public int nFilterIndex;
+       /** @field cast=(LPTSTR) */
+       public long lpstrFile;
+       public int nMaxFile;
+       /** @field cast=(LPTSTR) */
+       public long lpstrFileTitle;
+       public int nMaxFileTitle;
+       /** @field cast=(LPCTSTR) */
+       public long lpstrInitialDir;
+       /** @field cast=(LPCTSTR) */
+       public long lpstrTitle;
+       public int Flags;
+       public short nFileOffset;
+       public short nFileExtension;
+       /** @field cast=(LPCTSTR) */
+       public long lpstrDefExt;
+       public long lCustData;
+       /** @field cast=(LPOFNHOOKPROC) */
+       public long lpfnHook;
+       /** @field cast=(LPCTSTR) */
+       public long lpTemplateName;
+       /** @field cast=(void *) */
+       public long pvReserved;
+       public int dwReserved;
+       public int FlagsEx;
+       public static final int sizeof = OS.OPENFILENAME_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OS.java
new file mode 100644 (file)
index 0000000..281c6af
--- /dev/null
@@ -0,0 +1,4641 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Martin Karpisek <martin.karpisek@gmail.com> - Bug 443250
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+
+import org.eclipse.swt.internal.*;
+
+public class OS extends C {
+       static {
+               Library.loadLibrary ("swt"); //$NON-NLS-1$
+       }
+
+       /*
+       * SWT Windows flags
+       */
+       public static final boolean IsDBLocale;
+       public static final int WIN32_VERSION;
+
+       public static final String NO_MANIFEST = "org.eclipse.swt.internal.win32.OS.NO_MANIFEST";
+
+       /* Forward references */
+       public static final int ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x00000008;
+       public static final int ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x00000010;
+       public static final int ACTCTX_FLAG_HMODULE_VALID = 0x00000080;
+       public static final int MANIFEST_RESOURCE_ID = 2;
+       public static final int SM_IMMENABLED = 0x52;
+
+       static {
+               /* Get the Windows version */
+               int dwVersion = OS.GetVersion ();
+               WIN32_VERSION = VERSION (dwVersion & 0xff, (dwVersion >> 8) & 0xff);
+
+               /* Load the manifest to force the XP Theme */
+               if (System.getProperty (NO_MANIFEST) == null) {
+                       ACTCTX pActCtx = new ACTCTX ();
+                       pActCtx.cbSize = ACTCTX.sizeof;
+                       pActCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT;
+                       pActCtx.hModule = OS.GetLibraryHandle ();
+                       pActCtx.lpResourceName = MANIFEST_RESOURCE_ID;
+                       long hActCtx = OS.CreateActCtx (pActCtx);
+                       long [] lpCookie = new long [1];
+                       OS.ActivateActCtx (hActCtx, lpCookie);
+                       /*
+                       * 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.
+                       */
+               }
+
+               /* Make the process DPI aware for Windows Vista */
+               OS.SetProcessDPIAware ();
+
+               /* Get the DBCS flag */
+               IsDBLocale = OS.GetSystemMetrics (SM_IMMENABLED) != 0;
+       }
+
+       /* Constants */
+       public static final int ABS_DOWNDISABLED = 8;
+       public static final int ABS_DOWNHOT = 6;
+       public static final int ABS_DOWNNORMAL = 5;
+       public static final int ABS_DOWNPRESSED = 7;
+       public static final int ABS_LEFTDISABLED = 12;
+       public static final int ABS_LEFTHOT = 10;
+       public static final int ABS_LEFTNORMAL = 9;
+       public static final int ABS_LEFTPRESSED = 11;
+       public static final int ABS_RIGHTDISABLED = 16;
+       public static final int ABS_RIGHTHOT = 14;
+       public static final int ABS_RIGHTNORMAL = 13;
+       public static final int ABS_RIGHTPRESSED = 15;
+       public static final int ABS_UPDISABLED = 4;
+       public static final int ABS_UPHOT = 2;
+       public static final int ABS_UPNORMAL = 1;
+       public static final int ABS_UPPRESSED = 3;
+       public static final int AC_SRC_OVER = 0;
+       public static final int AC_SRC_ALPHA = 1;
+       public static final int ALTERNATE = 1;
+       public static final int ASSOCF_NOTRUNCATE = 0x00000020;
+       public static final int ASSOCF_INIT_IGNOREUNKNOWN = 0x400;
+       public static final int ASSOCSTR_COMMAND = 1;
+       public static final int ASSOCSTR_DEFAULTICON = 15;
+       public static final int ASSOCSTR_FRIENDLYAPPNAME = 4;
+       public static final int ASSOCSTR_FRIENDLYDOCNAME = 3;
+       public static final int ATTR_INPUT = 0x00;
+       public static final int ATTR_TARGET_CONVERTED = 0x01;
+       public static final int ATTR_CONVERTED = 0x02;
+       public static final int ATTR_TARGET_NOTCONVERTED = 0x03;
+       public static final int ATTR_INPUT_ERROR = 0x04;
+       public static final int ATTR_FIXEDCONVERTED = 0x05;
+       public static final int BCM_FIRST = 0x1600;
+       public static final int BCM_GETIDEALSIZE = BCM_FIRST + 0x1;
+       public static final int BCM_GETIMAGELIST = BCM_FIRST + 0x3;
+       public static final int BCM_GETNOTE = BCM_FIRST + 0xa;
+       public static final int BCM_GETNOTELENGTH = BCM_FIRST + 0xb;
+       public static final int BCM_SETIMAGELIST = BCM_FIRST + 0x2;
+       public static final int BCM_SETNOTE = BCM_FIRST + 0x9;
+       public static final int BDR_RAISEDOUTER = 0x0001;
+       public static final int BDR_SUNKENOUTER = 0x0002;
+       public static final int BDR_RAISEDINNER = 0x0004;
+       public static final int BDR_SUNKENINNER = 0x0008;
+       public static final int BDR_OUTER = 0x0003;
+       public static final int BDR_INNER = 0x000c;
+       public static final int BDR_RAISED = 0x0005;
+       public static final int BDR_SUNKEN = 0x000a;
+       public static final int BFFM_INITIALIZED = 0x1;
+       public static final int BFFM_SETSELECTION = 0x467;
+       public static final int BFFM_VALIDATEFAILED = 0x4;
+       public static final int BF_ADJUST = 0x2000;
+       public static final int BF_LEFT = 0x0001;
+       public static final int BF_TOP = 0x0002;
+       public static final int BF_RIGHT = 0x0004;
+       public static final int BF_BOTTOM = 0x0008;
+       public static final int BF_RECT = (BF_LEFT | BF_TOP | BF_RIGHT | BF_BOTTOM);
+       public static final int BIF_EDITBOX = 0x10;
+       public static final int BIF_NEWDIALOGSTYLE = 0x40;
+       public static final int BIF_RETURNONLYFSDIRS = 0x1;
+       public static final int BIF_VALIDATE = 0x20;
+       public static final int BITSPIXEL = 0xc;
+       public static final int BI_BITFIELDS = 3;
+       public static final int BI_RGB = 0;
+       public static final int BLACKNESS = 0x42;
+       public static final int BLACK_BRUSH = 4;
+       public static final int BUTTON_IMAGELIST_ALIGN_LEFT = 0;
+       public static final int BUTTON_IMAGELIST_ALIGN_RIGHT = 1;
+       public static final int BUTTON_IMAGELIST_ALIGN_CENTER = 4;
+       public static final int BM_CLICK = 0xf5;
+       public static final int BM_GETCHECK = 0xf0;
+       public static final int BM_SETCHECK = 0xf1;
+       public static final int BM_SETIMAGE = 0xf7;
+       public static final int BM_SETSTYLE = 0xf4;
+       public static final int BN_CLICKED = 0x0;
+       public static final int BN_DOUBLECLICKED = 0x5;
+       public static final int BPBF_COMPATIBLEBITMAP = 0;
+       public static final int BPBF_DIB = 1;
+       public static final int BPBF_TOPDOWNDIB = 2;
+       public static final int BPBF_TOPDOWNMONODIB = 3;
+       public static final int BPPF_ERASE = 0x0001;
+       public static final int BPPF_NOCLIP = 0x0002;
+       public static final int BPPF_NONCLIENT = 0x0004;
+       public static final int BP_PUSHBUTTON = 1;
+       public static final int BP_RADIOBUTTON = 2;
+       public static final int BP_CHECKBOX = 3;
+       public static final int BP_GROUPBOX = 4;
+       public static final int BST_CHECKED = 0x1;
+       public static final int BST_INDETERMINATE = 0x2;
+       public static final int BST_UNCHECKED = 0x0;
+       public static final int BS_3STATE = 0x5;
+       public static final int BS_BITMAP = 0x80;
+       public static final int BS_CENTER = 0x300;
+       public static final int BS_CHECKBOX = 0x2;
+       public static final int BS_COMMANDLINK =  0xe;
+       public static final int BS_DEFPUSHBUTTON = 0x1;
+       public static final int BS_FLAT = 0x8000;
+       public static final int BS_GROUPBOX = 0x7;
+       public static final int BS_ICON = 0x40;
+       public static final int BS_LEFT = 0x100;
+       public static final int BS_MULTILINE = 0x2000;
+       public static final int BS_NOTIFY = 0x4000;
+       public static final int BS_OWNERDRAW = 0xb;
+       public static final int BS_PATTERN = 0x3;
+       public static final int BS_PUSHBUTTON = 0x0;
+       public static final int BS_PUSHLIKE = 0x1000;
+       public static final int BS_RADIOBUTTON = 0x4;
+       public static final int BS_RIGHT = 0x200;
+       public static final int BS_SOLID = 0x0;
+       public static final int BTNS_AUTOSIZE = 0x10;
+       public static final int BTNS_BUTTON = 0x0;
+       public static final int BTNS_CHECK = 0x2;
+       public static final int BTNS_CHECKGROUP = 0x6;
+       public static final int BTNS_DROPDOWN = 0x8;
+       public static final int BTNS_GROUP = 0x4;
+       public static final int BTNS_SEP = 0x1;
+       public static final int BTNS_SHOWTEXT = 0x40;
+       public static final int CBN_DROPDOWN = 0x7;
+       public static final int CBN_EDITCHANGE = 0x5;
+       public static final int CBN_KILLFOCUS = 0x4;
+       public static final int CBN_SELCHANGE = 0x1;
+       public static final int CBN_SETFOCUS = 0x3;
+       public static final int CBS_AUTOHSCROLL = 0x40;
+       public static final int CBS_DROPDOWN = 0x2;
+       public static final int CBS_DROPDOWNLIST = 0x3;
+       public static final int CBS_CHECKEDNORMAL = 5;
+       public static final int CBS_MIXEDNORMAL = 9;
+       public static final int CBS_NOINTEGRALHEIGHT = 0x400;
+       public static final int CBS_SIMPLE = 0x1;
+       public static final int CBS_UNCHECKEDNORMAL = 1;
+       public static final int CBS_CHECKEDDISABLED = 8;
+       public static final int CBS_CHECKEDHOT = 6;
+       public static final int CBS_CHECKEDPRESSED = 7;
+       public static final int CBS_MIXEDDISABLED = 12;
+       public static final int CBS_MIXEDHOT = 10;
+       public static final int CBS_MIXEDPRESSED = 11;
+       public static final int CBS_UNCHECKEDDISABLED = 4;
+       public static final int CBS_UNCHECKEDHOT = 2;
+       public static final int CBS_UNCHECKEDPRESSED = 3;
+       public static final int CB_ADDSTRING = 0x143;
+       public static final int CB_DELETESTRING = 0x144;
+       public static final int CB_ERR = 0xffffffff;
+       public static final int CB_ERRSPACE = 0xfffffffe;
+       public static final int CB_FINDSTRINGEXACT = 0x158;
+       public static final int CB_GETCOUNT = 0x146;
+       public static final int CB_GETCURSEL = 0x147;
+       public static final int CB_GETDROPPEDCONTROLRECT = 0x152;
+       public static final int CB_GETDROPPEDSTATE = 0x157;
+       public static final int CB_GETDROPPEDWIDTH = 0x015f;
+       public static final int CB_GETEDITSEL = 0x140;
+       public static final int CB_GETHORIZONTALEXTENT = 0x015d;
+       public static final int CB_GETITEMHEIGHT = 0x154;
+       public static final int CB_GETLBTEXT = 0x148;
+       public static final int CB_GETLBTEXTLEN = 0x149;
+       public static final int CB_INSERTSTRING = 0x14a;
+       public static final int CB_LIMITTEXT = 0x141;
+       public static final int CB_RESETCONTENT = 0x14b;
+       public static final int CB_SELECTSTRING = 0x14d;
+       public static final int CB_SETCURSEL = 0x14e;
+       public static final int CB_SETDROPPEDWIDTH= 0x0160;
+       public static final int CB_SETEDITSEL = 0x142;
+       public static final int CB_SETHORIZONTALEXTENT = 0x015e;
+       public static final int CB_SETITEMHEIGHT = 0x0153;
+       public static final int CB_SHOWDROPDOWN = 0x14f;
+       public static final int CCHDEVICENAME = 32;
+       public static final int CCHFORMNAME = 32;
+       public static final int CCHILDREN_SCROLLBAR = 5;
+       public static final int CCM_FIRST = 0x2000;
+       public static final int CCM_SETBKCOLOR = 0x2001;
+       public static final int CCM_SETVERSION = 0x2007;
+       public static final int CCS_NODIVIDER = 0x40;
+       public static final int CCS_NORESIZE = 0x4;
+       public static final int CCS_VERT = 0x80;
+       public static final int CC_ANYCOLOR = 0x100;
+       public static final int CC_ENABLEHOOK = 0x10;
+       public static final int CC_FULLOPEN = 0x2;
+       public static final int CC_RGBINIT = 0x1;
+       public static final int CDDS_POSTERASE = 0x00000004;
+       public static final int CDDS_POSTPAINT = 0x00000002;
+       public static final int CDDS_PREERASE = 0x00000003;
+       public static final int CDDS_PREPAINT = 0x00000001;
+       public static final int CDDS_ITEM = 0x00010000;
+       public static final int CDDS_ITEMPOSTPAINT = CDDS_ITEM | CDDS_POSTPAINT;
+       public static final int CDDS_ITEMPREPAINT = CDDS_ITEM | CDDS_PREPAINT;
+       public static final int CDDS_SUBITEM = 0x00020000;
+       public static final int CDDS_SUBITEMPOSTPAINT = CDDS_ITEMPOSTPAINT | CDDS_SUBITEM;
+       public static final int CDDS_SUBITEMPREPAINT = CDDS_ITEMPREPAINT | CDDS_SUBITEM;
+       public static final int CDIS_SELECTED = 0x0001;
+       public static final int CDIS_GRAYED = 0x0002;
+       public static final int CDIS_DISABLED = 0x0004;
+       public static final int CDIS_CHECKED = 0x0008;
+       public static final int CDIS_FOCUS = 0x0010;
+       public static final int CDIS_DEFAULT = 0x0020;
+       public static final int CDIS_HOT = 0x0040;
+       public static final int CDIS_MARKED = 0x0080;
+       public static final int CDIS_INDETERMINATE = 0x0100;
+       public static final int CDIS_SHOWKEYBOARDCUES = 0x0200;
+       public static final int CDIS_DROPHILITED = 0x1000;
+       public static final int CDM_FIRST = 0x0400 + 100;
+       public static final int CDM_GETSPEC = CDM_FIRST;
+       public static final int CDN_FIRST = -601;
+       public static final int CDN_SELCHANGE = CDN_FIRST - 1;
+       public static final int CDRF_DODEFAULT = 0x00000000;
+       public static final int CDRF_DOERASE = 0x00000008;
+       public static final int CDRF_NEWFONT = 0x00000002;
+       public static final int CDRF_NOTIFYITEMDRAW = 0x00000020;
+       public static final int CDRF_NOTIFYPOSTERASE = 0x00000040;
+       public static final int CDRF_NOTIFYPOSTPAINT = 0x00000010;
+       public static final int CDRF_NOTIFYSUBITEMDRAW = 0x00000020;
+       public static final int CDRF_SKIPDEFAULT = 0x04;
+       public static final int CDRF_SKIPPOSTPAINT = 0x00000100;
+       public static final int CERT_SIMPLE_NAME_STR = 1;
+       public static final int CFE_AUTOCOLOR = 0x40000000;
+       public static final int CFE_ITALIC = 0x2;
+       public static final int CFE_STRIKEOUT = 0x8;
+       public static final int CFE_UNDERLINE = 0x4;
+       public static final int CFM_BOLD = 0x1;
+       public static final int CFM_CHARSET = 0x8000000;
+       public static final int CFM_COLOR = 0x40000000;
+       public static final int CFM_FACE = 0x20000000;
+       public static final int CFM_ITALIC = 0x2;
+       public static final int CFM_SIZE = 0x80000000;
+       public static final int CFM_STRIKEOUT = 0x8;
+       public static final int CFM_UNDERLINE = 0x4;
+       public static final int CFM_WEIGHT = 0x400000;
+       public static final int CFS_POINT = 0x2;
+       public static final int CFS_RECT = 0x1;
+       public static final int CFS_CANDIDATEPOS = 0x0040;
+       public static final int CFS_EXCLUDE = 0x0080;
+       public static final int CF_EFFECTS = 0x100;
+       public static final int CF_INITTOLOGFONTSTRUCT = 0x40;
+       public static final int CF_SCREENFONTS = 0x1;
+       public static final int CF_TEXT = 0x1;
+       public static final int CF_UNICODETEXT = 13;
+       public static final int CF_USESTYLE = 0x80;
+       public static final int CLR_DEFAULT = 0xff000000;
+       public static final int CLR_INVALID = 0xffffffff;
+       public static final int CLR_NONE = 0xffffffff;
+       public static final int COLORONCOLOR = 0x3;
+       public static final int COLOR_3DDKSHADOW = 0x15;
+       public static final int COLOR_3DFACE = 0xf;
+       public static final int COLOR_3DHIGHLIGHT = 0x14;
+       public static final int COLOR_3DHILIGHT = 0x14;
+       public static final int COLOR_3DLIGHT = 0x16;
+       public static final int COLOR_3DSHADOW = 0x10;
+       public static final int COLOR_ACTIVECAPTION = 0x2;
+       public static final int COLOR_BTNFACE = 0xf;
+       public static final int COLOR_BTNHIGHLIGHT = 0x14;
+       public static final int COLOR_BTNSHADOW = 0x10;
+       public static final int COLOR_BTNTEXT = 0x12;
+       public static final int COLOR_CAPTIONTEXT = 0x9;
+       public static final int COLOR_GRADIENTACTIVECAPTION = 0x1b;
+       public static final int COLOR_GRADIENTINACTIVECAPTION = 0x1c;
+       public static final int COLOR_GRAYTEXT = 0x11;
+       public static final int COLOR_HIGHLIGHT = 0xd;
+       public static final int COLOR_HIGHLIGHTTEXT = 0xe;
+       public static final int COLOR_HOTLIGHT = 26;
+       public static final int COLOR_INACTIVECAPTION = 0x3;
+       public static final int COLOR_INACTIVECAPTIONTEXT = 0x13;
+       public static final int COLOR_INFOBK = 0x18;
+       public static final int COLOR_INFOTEXT = 0x17;
+       public static final int COLOR_MENU = 0x4;
+       public static final int COLOR_MENUTEXT = 0x7;
+       public static final int COLOR_SCROLLBAR = 0x0;
+       public static final int COLOR_WINDOW = 0x5;
+       public static final int COLOR_WINDOWFRAME = 0x6;
+       public static final int COLOR_WINDOWTEXT = 0x8;
+       public static final int COMPLEXREGION = 0x3;
+       public static final int CP_ACP = 0x0;
+       public static final int CP_UTF8 = 65001;
+       public static final int CP_DROPDOWNBUTTON = 1;
+       public static final int CPS_COMPLETE = 0x1;
+       public static final int CS_DBLCLKS = 0x8;
+       public static final int CS_DROPSHADOW = 0x20000;
+       public static final int CS_GLOBALCLASS = 0x4000;
+       public static final int CS_HREDRAW = 0x2;
+       public static final int CS_VREDRAW = 0x1;
+       public static final int CS_OWNDC = 0x20;
+       public static final int CW_USEDEFAULT = 0x80000000;
+       public static final int CWP_SKIPINVISIBLE = 0x0001;
+       public static final String DATETIMEPICK_CLASS = "SysDateTimePick32"; //$NON-NLS-1$
+       public static final int DCX_CACHE = 0x2;
+       public static final int DCX_CLIPCHILDREN = 0x8;
+       public static final int DCX_CLIPSIBLINGS = 0x10;
+       public static final int DCX_INTERSECTRGN = 0x80;
+       public static final int DCX_WINDOW = 0x1;
+       public static final int DEFAULT_CHARSET = 0x1;
+       public static final int DEFAULT_GUI_FONT = 0x11;
+       public static final int DFCS_BUTTONCHECK = 0x0;
+       public static final int DFCS_CHECKED = 0x400;
+       public static final int DFCS_FLAT = 0x4000;
+       public static final int DFCS_INACTIVE = 0x100;
+       public static final int DFCS_PUSHED = 0x200;
+       public static final int DFCS_SCROLLDOWN = 0x1;
+       public static final int DFCS_SCROLLLEFT = 0x2;
+       public static final int DFCS_SCROLLRIGHT = 0x3;
+       public static final int DFCS_SCROLLUP = 0x0;
+       public static final int DFC_BUTTON = 0x4;
+       public static final int DFC_SCROLL = 0x3;
+       public static final int DIB_RGB_COLORS = 0x0;
+       public static final int DI_NORMAL = 0x3;
+       public static final int DI_NOMIRROR = 0x10;
+       public static final int DLGC_BUTTON = 0x2000;
+       public static final int DLGC_HASSETSEL = 0x8;
+       public static final int DLGC_STATIC = 0x100;
+       public static final int DLGC_WANTALLKEYS = 0x4;
+       public static final int DLGC_WANTARROWS = 0x1;
+       public static final int DLGC_WANTCHARS = 0x80;
+       public static final int DLGC_WANTTAB = 0x2;
+       public static final short DMCOLLATE_FALSE = 0;
+       public static final short DMCOLLATE_TRUE = 1;
+       public static final int DM_SETDEFID = 0x401;
+       public static final int DM_COLLATE = 0x00008000;
+       public static final int DM_COPIES = 0x00000100;
+       public static final int DM_DUPLEX = 0x00001000;
+       public static final int DM_ORIENTATION = 0x00000001;
+       public static final int DM_OUT_BUFFER = 2;
+       public static final short DMORIENT_PORTRAIT = 1;
+       public static final short DMORIENT_LANDSCAPE = 2;
+       public static final short DMDUP_SIMPLEX = 1;
+       public static final short DMDUP_VERTICAL = 2;
+       public static final short DMDUP_HORIZONTAL = 3;
+       public static final int DSTINVERT = 0x550009;
+       public static final int DT_BOTTOM = 0x8;
+       public static final int DT_CALCRECT = 0x400;
+       public static final int DT_CENTER = 0x1;
+       public static final int DT_EDITCONTROL = 0x2000;
+       public static final int DT_EXPANDTABS = 0x40;
+       public static final int DT_ENDELLIPSIS = 32768;
+       public static final int DT_HIDEPREFIX = 0x100000;
+       public static final int DT_LEFT = 0x0;
+       public static final int DT_NOPREFIX = 0x800;
+       public static final int DT_RASPRINTER = 0x2;
+       public static final int DT_RIGHT = 0x2;
+       public static final int DT_RTLREADING = 0x00020000;
+       public static final int DT_SINGLELINE = 0x20;
+       public static final int DT_TOP = 0;
+       public static final int DT_VCENTER = 4;
+       public static final int DT_WORDBREAK = 0x10;
+       public static final int DTM_FIRST = 0x1000;
+       public static final int DTM_GETSYSTEMTIME = DTM_FIRST + 1;
+       public static final int DTM_SETMCSTYLE = DTM_FIRST + 11;
+       public static final int DTM_GETIDEALSIZE = DTM_FIRST + 15;
+       public static final int DTM_SETFORMAT = DTM_FIRST + 50;
+       public static final int DTM_SETSYSTEMTIME = DTM_FIRST + 2;
+       public static final int DTN_FIRST = 0xFFFFFD08;
+       public static final int DTN_DATETIMECHANGE = DTN_FIRST + 1;
+       public static final int DTN_CLOSEUP = DTN_FIRST + 7;
+       public static final int DTN_DROPDOWN = DTN_FIRST + 6;
+       public static final int DTS_LONGDATEFORMAT = 0x0004;
+       public static final int DTS_SHORTDATECENTURYFORMAT = 0x000C;
+       public static final int DTS_SHORTDATEFORMAT = 0x0000;
+       public static final int DTS_TIMEFORMAT = 0x0009;
+       public static final int DTS_UPDOWN = 0x0001;
+       public static final int E_POINTER = 0x80004003;
+       public static final int EBP_NORMALGROUPBACKGROUND = 5;
+       public static final int EBP_NORMALGROUPCOLLAPSE = 6;
+       public static final int EBP_NORMALGROUPEXPAND = 7;
+       public static final int EBP_NORMALGROUPHEAD = 8;
+       public static final int EBNGC_NORMAL = 1;
+       public static final int EBNGC_HOT = 2;
+       public static final int EBNGC_PRESSED = 3;
+       public static final int EBP_HEADERBACKGROUND = 1;
+       public static final int EC_LEFTMARGIN = 0x1;
+       public static final int EC_RIGHTMARGIN = 0x2;
+       public static final int EDGE_RAISED = (BDR_RAISEDOUTER | BDR_RAISEDINNER);
+       public static final int EDGE_SUNKEN = (BDR_SUNKENOUTER | BDR_SUNKENINNER);
+       public static final int EDGE_ETCHED = (BDR_SUNKENOUTER | BDR_RAISEDINNER);
+       public static final int EDGE_BUMP = (BDR_RAISEDOUTER | BDR_SUNKENINNER);
+       public static final int ELF_VENDOR_SIZE = 4;
+       public static final int EM_CANUNDO = 0xc6;
+       public static final int EM_CHARFROMPOS = 0xd7;
+       public static final int EM_DISPLAYBAND = 0x433;
+       public static final int EM_GETFIRSTVISIBLELINE = 0xce;
+       public static final int EM_GETLIMITTEXT = 0xd5;
+       public static final int EM_GETLINE = 0xc4;
+       public static final int EM_GETLINECOUNT = 0xba;
+       public static final int EM_GETMARGINS = 0xd4;
+       public static final int EM_GETPASSWORDCHAR = 0xd2;
+       public static final int EM_GETSCROLLPOS = 0x4dd;
+       public static final int EM_GETSEL = 0xb0;
+       public static final int EM_LIMITTEXT = 0xc5;
+       public static final int EM_LINEFROMCHAR = 0xc9;
+       public static final int EM_LINEINDEX = 0xbb;
+       public static final int EM_LINELENGTH = 0xc1;
+       public static final int EM_LINESCROLL = 0xb6;
+       public static final int EM_POSFROMCHAR = 0xd6;
+       public static final int EM_REPLACESEL = 0xc2;
+       public static final int EM_SCROLLCARET = 0xb7;
+       public static final int EM_SETBKGNDCOLOR = 0x443;
+       public static final int EM_SETLIMITTEXT = 0xc5;
+       public static final int EM_SETMARGINS = 211;
+       public static final int EM_SETOPTIONS = 0x44d;
+       public static final int EM_SETPARAFORMAT = 0x447;
+       public static final int EM_SETPASSWORDCHAR = 0xcc;
+       public static final int EM_SETCUEBANNER = 0x1500 + 1;
+       public static final int EM_SETREADONLY = 0xcf;
+       public static final int EM_SETRECT = 0xb3;
+       public static final int EM_SETSEL = 0xb1;
+       public static final int EM_SETTABSTOPS = 0xcb;
+       public static final int EM_UNDO = 199;
+       public static final int EMR_EXTCREATEFONTINDIRECTW = 82;
+       public static final int EMR_EXTTEXTOUTW = 84;
+       public static final int EN_ALIGN_LTR_EC = 0x0700;
+       public static final int EN_ALIGN_RTL_EC = 0x0701;
+       public static final int EN_CHANGE = 0x300;
+       public static final int EP_EDITTEXT = 1;
+       public static final int ERROR_FILE_NOT_FOUND = 0x2;
+       public static final int ERROR_NO_MORE_ITEMS = 0x103;
+       public static final int ESB_DISABLE_BOTH = 0x3;
+       public static final int ESB_ENABLE_BOTH = 0x0;
+       public static final int ES_AUTOHSCROLL = 0x80;
+       public static final int ES_AUTOVSCROLL = 0x40;
+       public static final int ES_CENTER = 0x1;
+       public static final int ES_MULTILINE = 0x4;
+       public static final int ES_NOHIDESEL = 0x100;
+       public static final int ES_PASSWORD = 0x20;
+       public static final int ES_READONLY = 0x800;
+       public static final int ES_RIGHT = 0x2;
+       public static final int ETO_CLIPPED = 0x4;
+       public static final int ETS_NORMAL = 1;
+       public static final int ETS_HOT = 2;
+       public static final int ETS_SELECTED = 3;
+       public static final int ETS_DISABLED = 4;
+       public static final int ETS_FOCUSED = 5;
+       public static final int ETS_READONLY = 6;
+       public static final int EVENT_OBJECT_FOCUS = 0x8005;
+       public static final int EVENT_OBJECT_LOCATIONCHANGE = 0x800B;
+       public static final int EVENT_OBJECT_SELECTIONWITHIN = 0x8009;
+       public static final int EVENT_OBJECT_VALUECHANGE = 0x800E;
+       public static final short FADF_FIXEDSIZE = 0x10;
+       public static final short FADF_HAVEVARTYPE = 0x80;
+       public static final int FALT = 0x10;
+       public static final int FCONTROL = 0x8;
+       public static final int FE_FONTSMOOTHINGCLEARTYPE = 0x0002;
+       public static final int FEATURE_DISABLE_NAVIGATION_SOUNDS = 21;
+       public static final int FILE_ATTRIBUTE_NORMAL = 0x00000080;
+       public static final int FILE_MAP_READ = 4;
+       public static final int FLICKDIRECTION_RIGHT = 0;
+       public static final int FLICKDIRECTION_UPRIGHT = 1;
+       public static final int FLICKDIRECTION_UP = 2;
+       public static final int FLICKDIRECTION_UPLEFT = 3;
+       public static final int FLICKDIRECTION_LEFT = 4;
+       public static final int FLICKDIRECTION_DOWNLEFT = 5;
+       public static final int FLICKDIRECTION_DOWN = 6;
+       public static final int FLICKDIRECTION_DOWNRIGHT = 7;
+       public static final int FLICKDIRECTION_INVALID = 8;
+       public static final int FNERR_INVALIDFILENAME = 0x3002;
+       public static final int FNERR_BUFFERTOOSMALL = 0x3003;
+       public static final int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
+       public static final int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+       public static final int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+       public static final int FOS_NOCHANGEDIR = 0x8;
+       public static final int FOS_PICKFOLDERS = 0x20;
+       public static final int FOS_FORCEFILESYSTEM = 0x40;
+       public static final int FR_PRIVATE = 0x10;
+       public static final int FSHIFT = 0x4;
+       public static final int FVIRTKEY = 0x1;
+       public static final int GBS_NORMAL = 1;
+       public static final int GBS_DISABLED = 2;
+       public static final int GBF_DIRECT = 0x00000001;
+       public static final int GBF_COPY = 0x00000002;
+       public static final int GBF_VALIDBITS = 0x00000003;
+       public static final int GCP_REORDER = 0x0002;
+       public static final int GCP_GLYPHSHAPE = 0x0010;
+       public static final int GCP_CLASSIN = 0x00080000;
+       public static final int GCP_LIGATE = 0x0020;
+       public static final int GCS_COMPSTR = 0x8;
+       public static final int GCS_RESULTSTR = 0x800;
+       public static final int GCS_COMPATTR = 0x0010;
+       public static final int GCS_COMPCLAUSE = 0x0020;
+       public static final int GCS_CURSORPOS = 0x0080;
+       public static final int GET_FEATURE_FROM_PROCESS = 0x2;
+       public static final int GF_BEGIN = 1;
+       public static final int GF_INERTIA = 2;
+       public static final int GF_END = 4;
+       public static final int GGI_MARK_NONEXISTING_GLYPHS = 1;
+       public static final int GID_BEGIN = 1;
+       public static final int GID_END = 2;
+       public static final int GID_ZOOM = 3;
+       public static final int GID_PAN = 4;
+       public static final int GID_ROTATE = 5;
+       public static final int GID_TWOFINGERTAP = 6;
+       public static final int GID_PRESSANDTAP = 7;
+       public static final int GLPS_CLOSED = 1;
+       public static final int GLPS_OPENED = 2;
+       public static final int GM_ADVANCED = 2;
+       public static final int GMDI_USEDISABLED = 0x1;
+       public static final int GMEM_FIXED = 0x0;
+       public static final int GMEM_MOVEABLE = 0x2;
+       public static final int GMEM_ZEROINIT = 0x40;
+       public static final int GRADIENT_FILL_RECT_H = 0x0;
+       public static final int GRADIENT_FILL_RECT_V = 0x1;
+       public static final int GUI_16BITTASK = 0x20;
+       public static final int GUI_CARETBLINKING = 0x1;
+       public static final int GUI_INMENUMODE = 0x4;
+       public static final int GUI_INMOVESIZE = 0x2;
+       public static final int GUI_POPUPMENUMODE = 0x10;
+       public static final int GUI_SYSTEMMENUMODE = 0x8;
+       public static final int GWL_EXSTYLE = 0xffffffec;
+       public static final int GWL_ID = -12;
+       public static final int GWL_HWNDPARENT = -8;
+       public static final int GWL_STYLE = 0xfffffff0;
+       public static final int GWL_USERDATA = 0xffffffeb;
+       public static final int GWL_WNDPROC = 0xfffffffc;
+       public static final int GWLP_ID = -12;
+       public static final int GWLP_HWNDPARENT = -8;
+       public static final int GWLP_USERDATA = 0xffffffeb;
+       public static final int GWLP_WNDPROC = 0xfffffffc;
+       public static final int GW_CHILD = 0x5;
+       public static final int GW_HWNDFIRST = 0x0;
+       public static final int GW_HWNDLAST = 0x1;
+       public static final int GW_HWNDNEXT = 0x2;
+       public static final int GW_HWNDPREV = 0x3;
+       public static final int GW_OWNER = 0x4;
+       public static final int HBMMENU_CALLBACK = 0xffffffff;
+       public static final int HCBT_CREATEWND = 3;
+       public static final int HCF_HIGHCONTRASTON = 0x1;
+       public static final int HDF_BITMAP = 0x2000;
+       public static final int HDF_BITMAP_ON_RIGHT = 0x1000;
+       public static final int HDF_CENTER = 2;
+       public static final int HDF_JUSTIFYMASK = 0x3;
+       public static final int HDF_IMAGE = 0x0800;
+       public static final int HDF_LEFT = 0;
+       public static final int HDF_OWNERDRAW = 0x8000;
+       public static final int HDF_RIGHT = 1;
+       public static final int HDF_SORTUP = 0x0400;
+       public static final int HDF_SORTDOWN = 0x0200;
+       public static final int HDI_BITMAP = 0x0010;
+       public static final int HDI_IMAGE = 32;
+       public static final int HDI_ORDER = 0x80;
+       public static final int HDI_TEXT = 0x2;
+       public static final int HDI_WIDTH = 0x1;
+       public static final int HDI_FORMAT = 0x4;
+       public static final int HDM_FIRST = 0x1200;
+       public static final int HDM_DELETEITEM = HDM_FIRST + 2;
+       public static final int HDM_GETBITMAPMARGIN = HDM_FIRST + 21;
+       public static final int HDM_GETITEMCOUNT = 0x1200;
+       public static final int HDM_GETITEM = HDM_FIRST + 11;
+       public static final int HDM_GETITEMRECT = HDM_FIRST + 7;
+       public static final int HDM_GETORDERARRAY = HDM_FIRST + 17;
+       public static final int HDM_HITTEST = HDM_FIRST + 6;
+       public static final int HDM_INSERTITEM = HDM_FIRST + 10;
+       public static final int HDM_LAYOUT = HDM_FIRST + 5;
+       public static final int HDM_ORDERTOINDEX = HDM_FIRST + 15;
+       public static final int HDM_SETIMAGELIST = HDM_FIRST + 8;
+       public static final int HDM_SETITEM = HDM_FIRST + 12;
+       public static final int HDM_SETORDERARRAY = HDM_FIRST + 18;
+       public static final int HDN_FIRST = 0xfffffed4;
+       public static final int HDN_BEGINDRAG = HDN_FIRST - 10;
+       public static final int HDN_BEGINTRACK = 0xfffffeba;
+       public static final int HDN_DIVIDERDBLCLICK = HDN_FIRST - 25;
+       public static final int HDN_ENDDRAG = HDN_FIRST - 11;
+       public static final int HDN_ITEMCHANGED = 0xfffffebf;
+       public static final int HDN_ITEMCHANGING = HDN_FIRST - 20;
+       public static final int HDN_ITEMCLICK = HDN_FIRST - 22;
+       public static final int HDN_ITEMDBLCLICK = HDN_FIRST - 23;
+       public static final int HDS_BUTTONS = 0x2;
+       public static final int HDS_CHECKBOXES = 0x400;
+       public static final int HDS_DRAGDROP = 0x0040;
+       public static final int HDS_FILTERBAR = 0x100;
+       public static final int HDS_FLAT = 0x200;
+       public static final int HDS_FULLDRAG = 0x80;
+       public static final int HDS_HIDDEN = 0x8;
+       public static final int HDS_HOTTRACK = 0x4;
+       public static final int HDS_NOSIZING = 0x800;
+       public static final int HDS_OVERFLOW = 0x1000;
+       public static final int HEAP_ZERO_MEMORY = 0x8;
+       public static final int HELPINFO_MENUITEM = 0x2;
+       public static final int HHT_ONDIVIDER = 0x4;
+       public static final int HHT_ONDIVOPEN = 0x8;
+       public static final int HICF_ARROWKEYS = 0x2;
+       public static final int HICF_LEAVING = 0x20;
+       public static final int HICF_MOUSE = 0x1;
+       public static final int HINST_COMMCTRL = 0xffffffff;
+       public static final int HKEY_CLASSES_ROOT = 0x80000000;
+       public static final int HKEY_CURRENT_USER = 0x80000001;
+       public static final int HKEY_LOCAL_MACHINE = 0x80000002;
+       public static final int HORZRES = 0x8;
+       public static final int HTBORDER = 0x12;
+       public static final int HTCAPTION = 0x2;
+       public static final int HTCLIENT = 0x1;
+       public static final int HTERROR = -2;
+       public static final int HTHSCROLL = 0x6;
+       public static final int HTMENU = 0x5;
+       public static final int HTNOWHERE = 0x0;
+       public static final int HTSYSMENU = 0x3;
+       public static final int HTTRANSPARENT = 0xffffffff;
+       public static final int HTVSCROLL = 0x7;
+       public static final int HWND_BOTTOM = 0x1;
+       public static final int HWND_TOP = 0x0;
+       public static final int HWND_TOPMOST = 0xffffffff;
+       public static final int HWND_NOTOPMOST = -2;
+       public static final int ICC_COOL_CLASSES = 0x400;
+       public static final int ICC_DATE_CLASSES = 0x100;
+       public static final int ICM_NOTOPEN = 0x0;
+       public static final int ICON_BIG = 0x1;
+       public static final int ICON_SMALL = 0x0;
+       public static final int I_IMAGECALLBACK = -1;
+       public static final int I_IMAGENONE = -2;
+       public static final int IDABORT = 0x3;
+       public static final int IDANI_CAPTION = 3;
+       public static final int IDB_STD_SMALL_COLOR = 0x0;
+       public static final int IDC_APPSTARTING = 0x7f8a;
+       public static final int IDC_ARROW = 0x7f00;
+       public static final int IDC_CROSS = 0x7f03;
+       public static final int IDC_HAND = 0x7f89;
+       public static final int IDC_HELP = 0x7f8b;
+       public static final int IDC_IBEAM = 0x7f01;
+       public static final int IDC_NO = 0x7f88;
+       public static final int IDC_SIZE = 0x7f80;
+       public static final int IDC_SIZEALL = 0x7f86;
+       public static final int IDC_SIZENESW = 0x7f83;
+       public static final int IDC_SIZENS = 0x7f85;
+       public static final int IDC_SIZENWSE = 0x7f82;
+       public static final int IDC_SIZEWE = 0x7f84;
+       public static final int IDC_UPARROW = 0x7f04;
+       public static final int IDC_WAIT = 0x7f02;
+       public static final int IDI_APPLICATION = 32512;
+       public static final int IDNO = 0x7;
+       public static final int IDOK = 0x1;
+       public static final int IDRETRY = 0x4;
+       public static final int IDYES = 0x6;
+       public static final int ILC_COLOR = 0x0;
+       public static final int ILC_COLOR16 = 0x10;
+       public static final int ILC_COLOR24 = 0x18;
+       public static final int ILC_COLOR32 = 0x20;
+       public static final int ILC_COLOR4 = 0x4;
+       public static final int ILC_COLOR8 = 0x8;
+       public static final int ILC_MASK = 0x1;
+       public static final int ILC_MIRROR = 0x2000;
+       public static final int IMAGE_ICON = 0x1;
+       public static final int IME_CMODE_FULLSHAPE = 0x8;
+       public static final int IME_CMODE_KATAKANA = 0x2;
+       public static final int IME_CMODE_NATIVE = 0x1;
+       public static final int IME_CMODE_ROMAN = 0x10;
+       public static final int IME_ESC_HANJA_MODE = 0x1008;
+       public static final int IMEMOUSE_LDOWN = 1;
+       public static final int INPUT_KEYBOARD = 1;
+       public static final int INPUT_MOUSE = 0;
+       public static final int INTERNET_MAX_URL_LENGTH = 2084;
+       public static final int INTERNET_OPTION_END_BROWSER_SESSION = 42;
+       public static final int KEY_ENUMERATE_SUB_KEYS = 0x8;
+       public static final int KEY_NOTIFY = 0x10;
+       public static final int KEY_QUERY_VALUE = 0x1;
+       public static final int KEY_READ = 0x20019;
+       public static final int KEY_WRITE = 0x20006;
+       public static final int KEYEVENTF_EXTENDEDKEY = 0x0001;
+       public static final int KEYEVENTF_KEYUP = 0x0002;
+       public static final int L_MAX_URL_LENGTH = 2084;
+       public static final int LANG_JAPANESE = 0x11;
+       public static final int LANG_KOREAN = 0x12;
+       public static final int LANG_NEUTRAL = 0x0;
+       public static final int LANG_USER_DEFAULT = 1 << 10;
+       public static final int LAYOUT_RTL = 0x1;
+       public static final int LBN_DBLCLK = 0x2;
+       public static final int LBN_SELCHANGE = 0x1;
+       public static final int LBS_EXTENDEDSEL = 0x800;
+       public static final int LBS_MULTIPLESEL = 0x8;
+       public static final int LBS_NOINTEGRALHEIGHT = 0x100;
+       public static final int LBS_NOTIFY = 0x1;
+       public static final int LB_ADDSTRING = 0x180;
+       public static final int LB_DELETESTRING = 0x182;
+       public static final int LB_ERR = 0xffffffff;
+       public static final int LB_ERRSPACE = 0xfffffffe;
+       public static final int LB_FINDSTRINGEXACT = 0x1a2;
+       public static final int LB_GETCARETINDEX = 0x19f;
+       public static final int LB_GETCOUNT = 0x18b;
+       public static final int LB_GETCURSEL = 0x188;
+       public static final int LB_GETHORIZONTALEXTENT = 0x193;
+       public static final int LB_GETITEMHEIGHT = 0x1a1;
+       public static final int LB_GETITEMRECT = 0x198;
+       public static final int LB_GETSEL = 0x187;
+       public static final int LB_GETSELCOUNT = 0x190;
+       public static final int LB_GETSELITEMS = 0x191;
+       public static final int LB_GETTEXT = 0x189;
+       public static final int LB_GETTEXTLEN = 0x18a;
+       public static final int LB_GETTOPINDEX = 0x18e;
+       public static final int LB_INITSTORAGE = 0x1a8;
+       public static final int LB_INSERTSTRING = 0x181;
+       public static final int LB_RESETCONTENT = 0x184;
+       public static final int LB_SELITEMRANGE = 0x19b;
+       public static final int LB_SELITEMRANGEEX = 0x183;
+       public static final int LB_SETANCHORINDEX = 0xf19c;
+       public static final int LB_SETCARETINDEX = 0x19e;
+       public static final int LB_SETCURSEL = 0x186;
+       public static final int LB_SETHORIZONTALEXTENT = 0x194;
+       public static final int LB_SETSEL = 0x185;
+       public static final int LB_SETTOPINDEX = 0x197;
+       public static final int LF_FULLFACESIZE = 64;
+       public static final int LF_FACESIZE = 32;
+       public static final int LGRPID_ARABIC = 0xd;
+       public static final int LGRPID_HEBREW = 0xc;
+       public static final int LGRPID_INSTALLED = 1;
+       public static final int LIF_ITEMINDEX = 0x1;
+       public static final int LIF_STATE = 0x2;
+       public static final int LIM_SMALL = 0;
+       public static final int LIS_FOCUSED = 0x1;
+       public static final int LIS_ENABLED = 0x2;
+       public static final int LISS_HOT = 0x2;
+       public static final int LISS_SELECTED = 0x3;
+       public static final int LISS_SELECTEDNOTFOCUS = 0x5;
+       public static final int LM_GETIDEALSIZE = 0x701;
+       public static final int LM_SETITEM = 0x702;
+       public static final int LM_GETITEM = 0x703;
+       public static final int LCID_SUPPORTED = 0x2;
+       public static final int LOCALE_IDEFAULTANSICODEPAGE = 0x1004;
+       public static final int LOCALE_SDECIMAL = 14;
+       public static final int LOCALE_SISO3166CTRYNAME = 0x5a;
+       public static final int LOCALE_SISO639LANGNAME = 0x59;
+       public static final int LOCALE_STIMEFORMAT = 0x00001003;
+       public static final int LOCALE_SYEARMONTH = 0x00001006;
+       public static final int LOCALE_USER_DEFAULT = 1024;
+       public static final int LOGPIXELSX = 0x58;
+       public static final int LOGPIXELSY = 0x5a;
+       public static final int LPSTR_TEXTCALLBACK = 0xffffffff;
+       public static final int LR_DEFAULTCOLOR = 0x0;
+       public static final int LR_SHARED = 0x8000;
+       public static final int LVCFMT_BITMAP_ON_RIGHT = 0x1000;
+       public static final int LVCFMT_CENTER = 0x2;
+       public static final int LVCFMT_IMAGE = 0x800;
+       public static final int LVCFMT_LEFT = 0x0;
+       public static final int LVCFMT_RIGHT = 0x1;
+       public static final int LVCF_FMT = 0x1;
+       public static final int LVCF_IMAGE = 0x10;
+       public static final int LVCFMT_JUSTIFYMASK = 0x3;
+       public static final int LVCF_TEXT = 0x4;
+       public static final int LVCF_WIDTH = 0x2;
+       public static final int LVHT_ONITEM = 0xe;
+       public static final int LVHT_ONITEMICON = 0x2;
+       public static final int LVHT_ONITEMLABEL = 0x4;
+       public static final int LVHT_ONITEMSTATEICON = 0x8;
+       public static final int LVIF_IMAGE = 0x2;
+       public static final int LVIF_INDENT = 0x10;
+       public static final int LVIF_STATE = 0x8;
+       public static final int LVIF_TEXT = 0x1;
+       public static final int LVIM_AFTER = 0x00000001;
+       public static final int LVIR_BOUNDS = 0x0;
+       public static final int LVIR_ICON = 0x1;
+       public static final int LVIR_LABEL = 0x2;
+       public static final int LVIR_SELECTBOUNDS = 0x3;
+       public static final int LVIS_DROPHILITED = 0x8;
+       public static final int LVIS_FOCUSED = 0x1;
+       public static final int LVIS_SELECTED = 0x2;
+       public static final int LVIS_STATEIMAGEMASK = 0xf000;
+       public static final int LVM_FIRST = 0x1000;
+       public static final int LVM_APPROXIMATEVIEWRECT = 0x1040;
+       public static final int LVM_CREATEDRAGIMAGE = LVM_FIRST + 33;
+       public static final int LVM_DELETEALLITEMS = 0x1009;
+       public static final int LVM_DELETECOLUMN = 0x101c;
+       public static final int LVM_DELETEITEM = 0x1008;
+       public static final int LVM_ENSUREVISIBLE = 0x1013;
+       public static final int LVM_GETBKCOLOR = 0x1000;
+       public static final int LVM_GETCOLUMN = 0x105f;
+       public static final int LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59;
+       public static final int LVM_GETCOLUMNWIDTH = 0x101d;
+       public static final int LVM_GETCOUNTPERPAGE = 0x1028;
+       public static final int LVM_GETEXTENDEDLISTVIEWSTYLE = 0x1037;
+       public static final int LVM_GETHEADER = 0x101f;
+       public static final int LVM_GETIMAGELIST = 0x1002;
+       public static final int LVM_GETITEM = 0x104b;
+       public static final int LVM_GETITEMCOUNT = 0x1004;
+       public static final int LVM_GETITEMRECT = 0x100e;
+       public static final int LVM_GETITEMSTATE = 0x102c;
+       public static final int LVM_GETNEXTITEM = 0x100c;
+       public static final int LVM_GETSELECTEDCOLUMN = LVM_FIRST + 174;
+       public static final int LVM_GETSELECTEDCOUNT = 0x1032;
+       public static final int LVM_GETSTRINGWIDTH = 0x1057;
+       public static final int LVM_GETSUBITEMRECT = 0x1038;
+       public static final int LVM_GETTEXTCOLOR = 0x1023;
+       public static final int LVM_GETTOOLTIPS = 0x104e;
+       public static final int LVM_GETTOPINDEX = 0x1027;
+       public static final int LVM_HITTEST = 0x1012;
+       public static final int LVM_INSERTCOLUMN = 0x1061;
+       public static final int LVM_INSERTITEM = 0x104d;
+       public static final int LVM_REDRAWITEMS = LVM_FIRST + 21;
+       public static final int LVM_SCROLL = 0x1014;
+       public static final int LVM_SETBKCOLOR = 0x1001;
+       public static final int LVM_SETCALLBACKMASK = LVM_FIRST + 11;
+       public static final int LVM_SETCOLUMN = 0x1060;
+       public static final int LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58;
+       public static final int LVM_SETCOLUMNWIDTH = 0x101e;
+       public static final int LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036;
+       public static final int LVM_SETIMAGELIST = 0x1003;
+       public static final int LVM_SETINSERTMARK = LVM_FIRST + 166;
+       public static final int LVM_SETITEM = 0x104c;
+       public static final int LVM_SETITEMCOUNT = LVM_FIRST + 47;
+       public static final int LVM_SETITEMSTATE = 0x102b;
+       public static final int LVM_SETSELECTIONMARK = LVM_FIRST + 67;
+       public static final int LVM_SETSELECTEDCOLUMN = LVM_FIRST + 140;
+       public static final int LVM_SETTEXTBKCOLOR = 0x1026;
+       public static final int LVM_SETTEXTCOLOR = 0x1024;
+       public static final int LVM_SETTOOLTIPS = LVM_FIRST + 74;
+       public static final int LVM_SUBITEMHITTEST = LVM_FIRST + 57;
+       public static final int LVNI_FOCUSED = 0x1;
+       public static final int LVNI_SELECTED = 0x2;
+       public static final int LVN_BEGINDRAG = 0xffffff93;
+       public static final int LVN_BEGINRDRAG = 0xffffff91;
+       public static final int LVN_COLUMNCLICK = 0xffffff94;
+       public static final int LVN_FIRST = 0xffffff9c;
+       public static final int LVN_GETDISPINFO = LVN_FIRST - 77;
+       public static final int LVN_ITEMACTIVATE = 0xffffff8e;
+       public static final int LVN_ITEMCHANGED = 0xffffff9b;
+       public static final int LVN_MARQUEEBEGIN = 0xffffff64;
+       public static final int LVN_ODFINDITEM = LVN_FIRST - 79;
+       public static final int LVN_ODSTATECHANGED = LVN_FIRST - 15;
+       public static final int LVP_LISTITEM = 1;
+       public static final int LVSCW_AUTOSIZE = 0xffffffff;
+       public static final int LVSCW_AUTOSIZE_USEHEADER = 0xfffffffe;
+       public static final int LVSICF_NOINVALIDATEALL = 0x1;
+       public static final int LVSICF_NOSCROLL = 0x2;
+       public static final int LVSIL_SMALL = 0x1;
+       public static final int LVSIL_STATE = 0x2;
+       public static final int LVS_EX_DOUBLEBUFFER = 0x10000;
+       public static final int LVS_EX_FULLROWSELECT = 0x20;
+       public static final int LVS_EX_GRIDLINES = 0x1;
+       public static final int LVS_EX_HEADERDRAGDROP = 0x10;
+       public static final int LVS_EX_LABELTIP = 0x4000;
+       public static final int LVS_EX_ONECLICKACTIVATE = 0x40;
+       public static final int LVS_EX_SUBITEMIMAGES = 0x2;
+       public static final int LVS_EX_TRACKSELECT = 0x8;
+       public static final int LVS_EX_TRANSPARENTBKGND = 0x800000;
+       public static final int LVS_EX_TWOCLICKACTIVATE = 0x80;
+       public static final int LVS_LIST = 0x3;
+       public static final int LVS_NOCOLUMNHEADER = 0x4000;
+       public static final int LVS_NOSCROLL = 0x2000;
+       public static final int LVS_OWNERDATA = 0x1000;
+       public static final int LVS_OWNERDRAWFIXED = 0x400;
+       public static final int LVS_REPORT = 0x1;
+       public static final int LVS_SHAREIMAGELISTS = 0x40;
+       public static final int LVS_SHOWSELALWAYS = 0x8;
+       public static final int LVS_SINGLESEL = 0x4;
+       public static final int LWA_COLORKEY = 0x00000001;
+       public static final int LWA_ALPHA = 0x00000002;
+       public static final int MAX_LINKID_TEXT = 48;
+       public static final int MAX_PATH = 260;
+       public static final int MA_NOACTIVATE = 0x3;
+       public static final int MB_ABORTRETRYIGNORE = 0x2;
+       public static final int MB_APPLMODAL = 0x0;
+       public static final int MB_ICONERROR = 0x10;
+       public static final int MB_ICONINFORMATION = 0x40;
+       public static final int MB_ICONQUESTION = 0x20;
+       public static final int MB_ICONWARNING = 0x30;
+       public static final int MB_OK = 0x0;
+       public static final int MB_OKCANCEL = 0x1;
+       public static final int MB_PRECOMPOSED = 0x1;
+       public static final int MB_RETRYCANCEL = 0x5;
+       public static final int MB_RIGHT = 0x00080000;
+       public static final int MB_RTLREADING = 0x100000;
+       public static final int MB_SYSTEMMODAL = 0x1000;
+       public static final int MB_TASKMODAL = 0x2000;
+       public static final int MB_TOPMOST = 0x00040000;
+       public static final int MB_YESNO = 0x4;
+       public static final int MB_YESNOCANCEL = 0x3;
+       public static final int MCHT_CALENDAR = 0x20000;
+       public static final int MCHT_CALENDARDATE = MCHT_CALENDAR | 0x0001;
+       public static final int MCM_FIRST = 0x1000;
+       public static final int MCM_GETCURSEL = MCM_FIRST + 1;
+       public static final int MCM_GETMINREQRECT = MCM_FIRST + 9;
+       public static final int MCM_HITTEST = MCM_FIRST + 14;
+       public static final int MCM_SETCURSEL = MCM_FIRST + 2;
+       public static final int MCN_FIRST = 0xFFFFFD12;
+       public static final int MCN_SELCHANGE = MCN_FIRST + 1;
+       public static final int MCN_SELECT = MCN_FIRST + 4;
+       public static final int MCS_NOTODAY = 0x0010;
+       public static final int MCS_WEEKNUMBERS = 0x0004;
+       public static final int MDIS_ALLCHILDSTYLES = 0x0001;
+       public static final int MDT_EFFECTIVE_DPI = 0;
+       public static final int MFS_CHECKED = 0x8;
+       public static final int MFS_DISABLED = 0x3;
+       public static final int MFS_GRAYED = 0x3;
+       public static final int MFT_RADIOCHECK = 0x200;
+       public static final int MFT_RIGHTJUSTIFY = 0x4000;
+       public static final int MFT_RIGHTORDER = 0x2000;
+       public static final int MFT_SEPARATOR = 0x800;
+       public static final int MFT_STRING = 0x0;
+       public static final int MF_BYCOMMAND = 0x0;
+       public static final int MF_BYPOSITION = 0x400;
+       public static final int MF_CHECKED = 0x8;
+       public static final int MF_DISABLED = 0x2;
+       public static final int MF_ENABLED = 0x0;
+       public static final int MF_GRAYED = 0x1;
+       public static final int MF_HILITE = 0x80;
+       public static final int MF_POPUP = 0x10;
+       public static final int MF_SEPARATOR = 0x800;
+       public static final int MF_SYSMENU = 0x2000;
+       public static final int MF_UNCHECKED = 0x0;
+       public static final int MIIM_BITMAP = 0x80;
+       public static final int MIIM_DATA = 0x20;
+       public static final int MIIM_FTYPE = 0x100;
+       public static final int MIIM_ID = 0x2;
+       public static final int MIIM_STATE = 0x1;
+       public static final int MIIM_STRING = 0x40;
+       public static final int MIIM_SUBMENU = 0x4;
+       public static final int MIIM_TYPE = 0x10;
+       public static final int MIM_BACKGROUND = 0x2;
+       public static final int MIM_STYLE = 0x10;
+       public static final int MK_ALT = 0x20;
+       public static final int MK_CONTROL = 0x8;
+       public static final int MK_LBUTTON = 0x1;
+       public static final int MK_MBUTTON = 0x10;
+       public static final int MK_RBUTTON = 0x2;
+       public static final int MK_SHIFT = 0x4;
+       public static final int MK_XBUTTON1 = 0x20;
+       public static final int MK_XBUTTON2 = 0x40;
+       public static final int MM_TEXT = 0x1;
+       public static final int MNC_CLOSE = 0x1;
+       public static final int MNS_CHECKORBMP = 0x4000000;
+       public static final int MONITOR_DEFAULTTOPRIMARY = 0x1;
+       public static final int MONITOR_DEFAULTTONEAREST = 0x2;
+       public static final String MONTHCAL_CLASS = "SysMonthCal32"; //$NON-NLS-1$
+       public static final int MOUSEEVENTF_ABSOLUTE = 0x8000;
+       public static final int MOUSEEVENTF_LEFTDOWN = 0x0002;
+       public static final int MOUSEEVENTF_LEFTUP = 0x0004;
+       public static final int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
+       public static final int MOUSEEVENTF_MIDDLEUP = 0x0040;
+       public static final int MOUSEEVENTF_MOVE = 0x0001;
+       public static final int MOUSEEVENTF_RIGHTDOWN = 0x0008;
+       public static final int MOUSEEVENTF_RIGHTUP = 0x0010;
+       public static final int MOUSEEVENTF_VIRTUALDESK = 0x4000;
+       public static final int MOUSEEVENTF_WHEEL = 0x0800;
+       public static final int MOUSEEVENTF_XDOWN = 0x0080;
+       public static final int MOUSEEVENTF_XUP = 0x0100;
+       public static final int MSGF_DIALOGBOX = 0;
+       public static final int MSGF_COMMCTRL_BEGINDRAG = 0x4200;
+       public static final int MSGF_COMMCTRL_SIZEHEADER = 0x4201;
+       public static final int MSGF_COMMCTRL_DRAGSELECT = 0x4202;
+       public static final int MSGF_COMMCTRL_TOOLBARCUST = 0x4203;
+       public static final int MSGF_MAINLOOP = 8;
+       public static final int MSGF_MENU = 2;
+       public static final int MSGF_MOVE = 3;
+       public static final int MSGF_MESSAGEBOX = 1;
+       public static final int MSGF_NEXTWINDOW = 6;
+       public static final int MSGF_SCROLLBAR = 5;
+       public static final int MSGF_SIZE = 4;
+       public static final int MSGF_USER = 4096;
+       public static final int MWT_LEFTMULTIPLY = 2;
+       public static final int NI_COMPOSITIONSTR = 0x15;
+       public static final int NID_READY = 0x80;
+       public static final int NID_MULTI_INPUT = 0x40;
+       public static final int NIF_ICON = 0x00000002;
+       public static final int NIF_INFO = 0x00000010;
+       public static final int NIF_MESSAGE = 0x00000001;
+       public static final int NIF_STATE = 0x00000008;
+       public static final int NIF_TIP = 0x00000004;
+       public static final int NIIF_ERROR = 0x00000003;
+       public static final int NIIF_INFO = 0x00000001;
+       public static final int NIIF_NONE = 0x00000000;
+       public static final int NIIF_WARNING = 0x00000002;
+       public static final int NIM_ADD = 0x00000000;
+       public static final int NIM_DELETE = 0x00000002;
+       public static final int NIM_MODIFY = 0x00000001;
+       public static final int NIN_SELECT = 0x400 + 0;
+       public static final int NINF_KEY = 0x1;
+       public static final int NIN_KEYSELECT = NIN_SELECT | NINF_KEY;
+       public static final int NIN_BALLOONSHOW = 0x400 + 2;
+       public static final int NIN_BALLOONHIDE = 0x400 + 3;
+       public static final int NIN_BALLOONTIMEOUT = 0x400 + 4;
+       public static final int NIN_BALLOONUSERCLICK = 0x400 + 5;
+       public static final int NIS_HIDDEN = 0x00000001;
+       public static final int NM_FIRST = 0x0;
+       public static final int NM_CLICK = 0xfffffffe;
+       public static final int NM_CUSTOMDRAW = NM_FIRST - 12;
+       public static final int NM_DBLCLK = 0xfffffffd;
+       public static final int NM_RECOGNIZEGESTURE = NM_FIRST - 16;
+       public static final int NM_RELEASEDCAPTURE = NM_FIRST - 16;
+       public static final int NM_RETURN = 0xfffffffc;
+       public static final int NOTIFYICONDATA_V2_SIZE = NOTIFYICONDATA_V2_SIZE ();
+       public static final int NULLREGION = 0x1;
+       public static final int NULL_BRUSH = 0x5;
+       public static final int NULL_PEN = 0x8;
+       public static final int OBJID_WINDOW = 0x00000000;
+       public static final int OBJID_SYSMENU = 0xFFFFFFFF;
+       public static final int OBJID_TITLEBAR = 0xFFFFFFFE;
+       public static final int OBJID_MENU = 0xFFFFFFFD;
+       public static final int OBJID_CLIENT = 0xFFFFFFFC;
+       public static final int OBJID_VSCROLL = 0xFFFFFFFB;
+       public static final int OBJID_HSCROLL = 0xFFFFFFFA;
+       public static final int OBJID_SIZEGRIP = 0xFFFFFFF9;
+       public static final int OBJID_CARET = 0xFFFFFFF8;
+       public static final int OBJID_CURSOR = 0xFFFFFFF7;
+       public static final int OBJID_ALERT = 0xFFFFFFF6;
+       public static final int OBJID_SOUND = 0xFFFFFFF5;
+       public static final int OBJID_QUERYCLASSNAMEIDX = 0xFFFFFFF4;
+       public static final int OBJID_NATIVEOM = 0xFFFFFFF0;
+       public static final int OBJ_BITMAP = 0x7;
+       public static final int OBJ_FONT = 0x6;
+       public static final int OBJ_PEN = 0x1;
+       public static final int OBM_CHECKBOXES = 0x7ff7;
+       public static final int ODS_SELECTED = 0x1;
+       public static final int ODT_MENU = 0x1;
+       public static final int OFN_ALLOWMULTISELECT = 0x200;
+       public static final int OFN_EXPLORER = 0x80000;
+       public static final int OFN_ENABLEHOOK = 0x20;
+       public static final int OFN_ENABLESIZING = 0x800000;
+       public static final int OFN_HIDEREADONLY = 0x4;
+       public static final int OFN_NOCHANGEDIR = 0x8;
+       public static final int OFN_OVERWRITEPROMPT = 0x2;
+       public static final int OIC_BANG = 0x7F03;
+       public static final int OIC_HAND = 0x7F01;
+       public static final int OIC_INFORMATION = 0x7F04;
+       public static final int OIC_QUES = 0x7F02;
+       public static final int OIC_WINLOGO = 0x7F05;
+       public static final int OPAQUE = 0x2;
+       public static final int PATCOPY = 0xf00021;
+       public static final int PATINVERT = 0x5a0049;
+       public static final int PBM_GETPOS = 0x408;
+       public static final int PBM_GETRANGE = 0x407;
+       public static final int PBM_GETSTATE = 0x400 + 17;
+       public static final int PBM_SETBARCOLOR = 0x409;
+       public static final int PBM_SETBKCOLOR = 0x2001;
+       public static final int PBM_SETMARQUEE = 0x400 + 10;
+       public static final int PBM_SETPOS = 0x402;
+       public static final int PBM_SETRANGE32 = 0x406;
+       public static final int PBM_SETSTATE = 0x400 + 16;
+       public static final int PBM_STEPIT = 0x405;
+       public static final int PBS_MARQUEE = 0x08;
+       public static final int PBS_SMOOTH = 0x1;
+       public static final int PBS_VERTICAL = 0x4;
+       public static final int PBS_NORMAL = 1;
+       public static final int PBS_HOT = 2;
+       public static final int PBS_PRESSED = 3;
+       public static final int PBS_DISABLED = 4;
+       public static final int PBS_DEFAULTED = 5;
+       public static final int PBST_NORMAL = 0x0001;
+       public static final int PBST_ERROR = 0x0002;
+       public static final int PBST_PAUSED = 0x0003;
+       public static final int PD_ALLPAGES = 0x0;
+       public static final int PD_COLLATE = 0x10;
+       public static final int PD_PAGENUMS = 0x2;
+       public static final int PD_PRINTTOFILE = 0x20;
+       public static final int PD_RETURNDC = 0x100;
+       public static final int PD_RETURNDEFAULT = 0x00000400;
+       public static final int PD_SELECTION = 0x1;
+       public static final int PD_USEDEVMODECOPIESANDCOLLATE = 0x40000;
+       public static final int PFM_TABSTOPS = 0x10;
+       public static final int PHYSICALHEIGHT = 0x6f;
+       public static final int PHYSICALOFFSETX = 0x70;
+       public static final int PHYSICALOFFSETY = 0x71;
+       public static final int PHYSICALWIDTH = 0x6e;
+       public static final int PLANES = 0xe;
+       public static final int PM_NOREMOVE = 0x0;
+       public static final int PM_NOYIELD = 0x2;
+       public static final int QS_HOTKEY = 0x0080;
+       public static final int QS_KEY = 0x0001;
+       public static final int QS_MOUSEMOVE = 0x0002;
+       public static final int QS_MOUSEBUTTON = 0x0004;
+       public static final int QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON;
+       public static final int QS_INPUT = QS_KEY | QS_MOUSE;
+       public static final int QS_POSTMESSAGE = 0x0008;
+       public static final int QS_TIMER = 0x0010;
+       public static final int QS_PAINT = 0x0020;
+       public static final int QS_SENDMESSAGE = 0x0040;
+       public static final int QS_ALLINPUT = QS_MOUSEMOVE | QS_MOUSEBUTTON | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_SENDMESSAGE;
+       public static final int PM_QS_INPUT = QS_INPUT << 16;
+       public static final int PM_QS_POSTMESSAGE = (QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) << 16;
+       public static final int PM_QS_PAINT = QS_PAINT << 16;
+       public static final int PM_QS_SENDMESSAGE = QS_SENDMESSAGE << 16;
+       public static final int PM_REMOVE = 0x1;
+       public static final String PROGRESS_CLASS = "msctls_progress32"; //$NON-NLS-1$
+       public static final int PP_BAR = 1;
+       public static final int PP_BARVERT = 2;
+       public static final int PP_CHUNK = 3;
+       public static final int PP_CHUNKVERT = 4;
+       public static final int PRF_CHILDREN = 16;
+       public static final int PRF_CLIENT = 0x4;
+       public static final int PRF_ERASEBKGND = 0x8;
+       public static final int PRF_NONCLIENT = 0x2;
+       public static final int PROGRESSCHUNKSIZE = 2411;
+       public static final int PROGRESSSPACESIZE = 2412;
+       public static final int PS_DASH = 0x1;
+       public static final int PS_DASHDOT = 0x3;
+       public static final int PS_DASHDOTDOT = 0x4;
+       public static final int PS_DOT = 0x2;
+       public static final int PS_ENDCAP_FLAT = 0x200;
+       public static final int PS_ENDCAP_SQUARE = 0x100;
+       public static final int PS_ENDCAP_ROUND = 0x000;
+       public static final int PS_ENDCAP_MASK = 0xF00;
+       public static final int PS_GEOMETRIC = 0x10000;
+       public static final int PS_JOIN_BEVEL = 0x1000;
+       public static final int PS_JOIN_MASK = 0xF000;
+       public static final int PS_JOIN_MITER = 0x2000;
+       public static final int PS_JOIN_ROUND = 0x0000;
+       public static final int PS_SOLID = 0x0;
+       public static final int PS_STYLE_MASK = 0xf;
+       public static final int PS_TYPE_MASK = 0x000f0000;
+       public static final int PS_USERSTYLE = 0x7;
+       public static final int R2_COPYPEN = 0xd;
+       public static final int R2_XORPEN = 0x7;
+       public static final int RASTERCAPS = 0x26;
+       public static final int RASTER_FONTTYPE = 0x1;
+       public static final int RBBIM_CHILD = 0x10;
+       public static final int RBBIM_CHILDSIZE = 0x20;
+       public static final int RBBIM_COLORS = 0x2;
+       public static final int RBBIM_HEADERSIZE = 0x800;
+       public static final int RBBIM_ID = 0x100;
+       public static final int RBBIM_IDEALSIZE = 0x200;
+       public static final int RBBIM_SIZE = 0x40;
+       public static final int RBBIM_STYLE = 0x1;
+       public static final int RBBIM_TEXT = 0x4;
+       public static final int RBBS_BREAK = 0x1;
+       public static final int RBBS_GRIPPERALWAYS = 0x80;
+       public static final int RBBS_NOGRIPPER = 0x00000100;
+       public static final int RBBS_USECHEVRON = 0x00000200;
+       public static final int RBBS_VARIABLEHEIGHT = 0x40;
+       public static final int RBN_FIRST = 0xfffffcc1;
+       public static final int RBN_BEGINDRAG = RBN_FIRST - 4;
+       public static final int RBN_CHILDSIZE = RBN_FIRST - 8;
+       public static final int RBN_CHEVRONPUSHED = RBN_FIRST - 10;
+       public static final int RBN_HEIGHTCHANGE = 0xfffffcc1;
+       public static final int RBS_UNCHECKEDNORMAL = 1;
+       public static final int RBS_UNCHECKEDHOT = 2;
+       public static final int RBS_UNCHECKEDPRESSED = 3;
+       public static final int RBS_UNCHECKEDDISABLED = 4;
+       public static final int RBS_CHECKEDNORMAL = 5;
+       public static final int RBS_CHECKEDHOT = 6;
+       public static final int RBS_CHECKEDPRESSED = 7;
+       public static final int RBS_CHECKEDDISABLED = 8;
+       public static final int RBS_DBLCLKTOGGLE = 0x8000;
+       public static final int RBS_BANDBORDERS = 0x400;
+       public static final int RBS_VARHEIGHT = 0x200;
+       public static final int RB_DELETEBAND = 0x402;
+       public static final int RB_GETBANDBORDERS = 0x422;
+       public static final int RB_GETBANDCOUNT = 0x40c;
+       public static final int RB_GETBANDINFO = 0x41c;
+       public static final int RB_GETBANDMARGINS = 0x428;
+       public static final int RB_GETBARHEIGHT = 0x41b;
+       public static final int RB_GETBKCOLOR = 0x414;
+       public static final int RB_GETRECT = 0x409;
+       public static final int RB_GETTEXTCOLOR = 0x416;
+       public static final int RB_IDTOINDEX = 0x410;
+       public static final int RB_INSERTBAND = 0x40a;
+       public static final int RB_MOVEBAND = 0x427;
+       public static final int RB_SETBANDINFO = 0x40b;
+       public static final int RB_SETBKCOLOR = 0x413;
+       public static final int RB_SETTEXTCOLOR = 0x415;
+       public static final int RDW_ALLCHILDREN = 0x80;
+       public static final int RDW_ERASE = 0x4;
+       public static final int RDW_FRAME = 0x400;
+       public static final int RDW_INVALIDATE = 0x1;
+       public static final int RDW_UPDATENOW = 0x100;
+       public static final String REBARCLASSNAME = "ReBarWindow32"; //$NON-NLS-1$
+       public static final int REG_DWORD = 4;
+       public static final int REG_OPTION_VOLATILE = 0x1;
+       public static final int RGN_AND = 0x1;
+       public static final int RGN_COPY = 5;
+       public static final int RGN_DIFF = 0x4;
+       public static final int RGN_ERROR = 0;
+       public static final int RGN_OR = 0x2;
+       public static final int RP_BAND = 3;
+       public static final int SBP_ARROWBTN = 0x1;
+       public static final int SBP_THUMBBTNHORZ = 2;
+       public static final int SBP_THUMBBTNVERT = 3;
+       public static final int SBP_LOWERTRACKHORZ = 4;
+       public static final int SBP_UPPERTRACKHORZ = 5;
+       public static final int SBP_LOWERTRACKVERT = 6;
+       public static final int SBP_UPPERTRACKVERT = 7;
+       public static final int SBP_GRIPPERHORZ = 8;
+       public static final int SBP_GRIPPERVERT = 9;
+       public static final int SBP_SIZEBOX = 10;
+       public static final int SBS_HORZ = 0x0;
+       public static final int SBS_VERT = 0x1;
+       public static final int SB_BOTH = 0x3;
+       public static final int SB_BOTTOM = 0x7;
+       public static final int SB_NONE = 0;
+       public static final int SB_CONST_ALPHA = 0x00000001;
+       public static final int SB_PIXEL_ALPHA = 0x00000002;
+       public static final int SB_PREMULT_ALPHA = 0x00000004;
+       public static final int SB_CTL = 0x2;
+       public static final int SB_ENDSCROLL = 0x8;
+       public static final int SB_HORZ = 0x0;
+       public static final int SB_LINEDOWN = 0x1;
+       public static final int SB_LINEUP = 0x0;
+       public static final int SB_PAGEDOWN = 0x3;
+       public static final int SB_PAGEUP = 0x2;
+       public static final int SB_THUMBPOSITION = 0x4;
+       public static final int SB_THUMBTRACK = 0x5;
+       public static final int SB_TOP = 0x6;
+       public static final int SB_VERT = 0x1;
+       public static final int SC_CLOSE = 0xf060;
+       public static final int SC_MOVE = 0xf010;
+       public static final int SC_HSCROLL = 0xf080;
+       public static final int SC_KEYMENU = 0xf100;
+       public static final int SC_MAXIMIZE = 0xf030;
+       public static final int SC_MINIMIZE = 0xf020;
+       public static final int SC_NEXTWINDOW = 0xF040;
+       public static final int SC_RESTORE = 0xf120;
+       public static final int SC_SIZE = 0xf000;
+       public static final int SC_TASKLIST = 0xf130;
+       public static final int SC_VSCROLL = 0xf070;
+       public static final int SCRBS_NORMAL = 1;
+       public static final int SCRBS_HOT = 2;
+       public static final int SCRBS_PRESSED = 3;
+       public static final int SCRBS_DISABLED = 4;
+       public static final int SEM_FAILCRITICALERRORS = 0x1;
+       public static final int SET_FEATURE_ON_PROCESS = 0x2;
+       public static final int SHADEBLENDCAPS = 120;
+       public static final int SHGFI_ICON = 0x000000100;
+       public static final int SHGFI_SMALLICON= 0x1;
+       public static final int SHGFI_USEFILEATTRIBUTES = 0x000000010;
+       public static final int SIGDN_FILESYSPATH = 0x80058000;
+       public static final int SIF_ALL = 0x17;
+       public static final int SIF_DISABLENOSCROLL = 0x8;
+       public static final int SIF_PAGE = 0x2;
+       public static final int SIF_POS = 0x4;
+       public static final int SIF_RANGE = 0x1;
+       public static final int SIF_TRACKPOS = 0x10;
+       public static final int SIP_DOWN = 1;
+       public static final int SIP_UP = 0;
+       public static final int SIPF_ON = 0x1;
+       public static final int SIZE_RESTORED = 0;
+       public static final int SIZE_MINIMIZED = 1;
+       public static final int SIZE_MAXIMIZED = 2;
+       public static final int SM_CMONITORS = 80;
+       public static final int SM_CXBORDER = 0x5;
+       public static final int SM_CXCURSOR = 0xd;
+       public static final int SM_CXDOUBLECLK = 36;
+       public static final int SM_CYDOUBLECLK = 37;
+       public static final int SM_CXEDGE = 0x2d;
+       public static final int SM_CXFOCUSBORDER = 83;
+       public static final int SM_CXHSCROLL = 0x15;
+       public static final int SM_CXICON = 0x0b;
+       public static final int SM_CYICON = 0x0c;
+       public static final int SM_CXVIRTUALSCREEN = 78;
+       public static final int SM_CYVIRTUALSCREEN = 79;
+       public static final int SM_CXSMICON = 49;
+       public static final int SM_CYSMICON = 50;
+       public static final int SM_CXSCREEN = 0x0;
+       public static final int SM_XVIRTUALSCREEN = 76;
+       public static final int SM_YVIRTUALSCREEN = 77;
+       public static final int SM_CXVSCROLL = 0x2;
+       public static final int SM_CYBORDER = 0x6;
+       public static final int SM_CYCURSOR = 0xe;
+       public static final int SM_CYFOCUSBORDER = 84;
+       public static final int SM_CYHSCROLL = 0x3;
+       public static final int SM_CYMENU = 0xf;
+       public static final int SM_CXMINTRACK = 34;
+       public static final int SM_CYMINTRACK = 35;
+       public static final int SM_CMOUSEBUTTONS = 43;
+       public static final int SM_CYSCREEN = 0x1;
+       public static final int SM_CYVSCROLL = 0x14;
+       public static final int SM_DIGITIZER = 94;
+       public static final int SM_MAXIMUMTOUCHES= 95;
+       public static final int SPI_GETFONTSMOOTHINGTYPE = 0x200A;
+       public static final int SPI_GETHIGHCONTRAST = 66;
+       public static final int SPI_GETWORKAREA = 0x30;
+       public static final int SPI_GETMOUSEVANISH = 0x1020;
+       public static final int SPI_GETNONCLIENTMETRICS = 41;
+       public static final int SPI_GETWHEELSCROLLLINES = 104;
+       public static final int SPI_GETCARETWIDTH = 0x2006;
+       public static final int SPI_SETSIPINFO = 224;
+       public static final int SPI_SETHIGHCONTRAST = 67;
+       public static final int SRCAND = 0x8800c6;
+       public static final int SRCCOPY = 0xcc0020;
+       public static final int SRCINVERT = 0x660046;
+       public static final int SRCPAINT = 0xee0086;
+       public static final int SS_BITMAP = 0xe;
+       public static final int SS_CENTER = 0x1;
+       public static final int SS_CENTERIMAGE = 0x200;
+       public static final int SS_EDITCONTROL = 0x2000;
+       public static final int SS_ICON = 0x3;
+       public static final int SS_LEFT = 0x0;
+       public static final int SS_LEFTNOWORDWRAP = 0xc;
+       public static final int SS_NOTIFY = 0x100;
+       public static final int SS_OWNERDRAW = 0xd;
+       public static final int SS_REALSIZEIMAGE = 0x800;
+       public static final int SS_RIGHT = 0x2;
+       public static final int SSA_FALLBACK = 0x00000020;
+       public static final int SSA_GLYPHS = 0x00000080;
+       public static final int SSA_METAFILE = 0x00000800;
+       public static final int SSA_LINK = 0x00001000;
+       public static final int STARTF_USESHOWWINDOW = 0x1;
+       public static final int STATE_SYSTEM_INVISIBLE = 0x00008000;
+       public static final int STATE_SYSTEM_OFFSCREEN = 0x00010000;
+       public static final int STATE_SYSTEM_UNAVAILABLE = 0x00000001;
+       public static final int STD_COPY = 0x1;
+       public static final int STD_CUT = 0x0;
+       public static final int STD_FILENEW = 0x6;
+       public static final int STD_FILEOPEN = 0x7;
+       public static final int STD_FILESAVE = 0x8;
+       public static final int STD_PASTE = 0x2;
+       public static final int STM_GETIMAGE = 0x173;
+       public static final int STM_SETIMAGE = 0x172;
+       public static final int SWP_ASYNCWINDOWPOS = 0x4000;
+       public static final int SWP_DRAWFRAME = 0x20;
+       public static final int SWP_NOACTIVATE = 0x10;
+       public static final int SWP_NOCOPYBITS = 0x100;
+       public static final int SWP_NOMOVE = 0x2;
+       public static final int SWP_NOREDRAW = 0x8;
+       public static final int SWP_NOSIZE = 0x1;
+       public static final int SWP_NOZORDER = 0x4;
+       public static final int SW_ERASE = 0x4;
+       public static final int SW_HIDE = 0x0;
+       public static final int SW_INVALIDATE = 0x2;
+       public static final int SW_MINIMIZE = 0x6;
+       public static final int SW_PARENTOPENING = 0x3;
+       public static final int SW_RESTORE = 0x9;
+       public static final int SW_SCROLLCHILDREN = 0x1;
+       public static final int SW_SHOW = 0x5;
+       public static final int SW_SHOWMAXIMIZED = 0x3;
+       public static final int SW_SHOWMINIMIZED = 0x2;
+       public static final int SW_SHOWMINNOACTIVE = 0x7;
+       public static final int SW_SHOWNA = 0x8;
+       public static final int SW_SHOWNOACTIVATE = 0x4;
+       public static final int SYSRGN = 0x4;
+       public static final int SYSTEM_FONT = 0xd;
+       public static final int S_OK = 0x0;
+       public static final int TABP_TABITEM = 1;
+       public static final int TABP_TABITEMLEFTEDGE = 2;
+       public static final int TABP_TABITEMRIGHTEDGE = 3;
+       public static final int TABP_TABITEMBOTHEDGE = 4;
+       public static final int TABP_TOPTABITEM = 5;
+       public static final int TABP_TOPTABITEMLEFTEDGE = 6;
+       public static final int TABP_TOPTABITEMRIGHTEDGE = 7;
+       public static final int TABP_TOPTABITEMBOTHEDGE = 8;
+       public static final int TABP_PANE = 9;
+       public static final int TABP_BODY = 10;
+       public static final int TBCDRF_BLENDICON = 0x200000;
+       public static final int TBCDRF_HILITEHOTTRACK = 0x20000;
+       public static final int TBCDRF_NOBACKGROUND = 0x400000;
+       public static final int TBCDRF_NOEDGES = 0x10000;
+       public static final int TBCDRF_NOETCHEDEFFECT = 0x100000;
+       public static final int TBCDRF_NOMARK = 0x80000;
+       public static final int TBCDRF_NOOFFSET = 0x40000;
+       public static final int TBCDRF_USECDCOLORS = 0x800000;
+       public static final int TBIF_COMMAND = 0x20;
+       public static final int TBIF_STATE = 0x4;
+       public static final int TBIF_IMAGE = 0x1;
+       public static final int TBIF_LPARAM = 0x10;
+       public static final int TBIF_SIZE = 0x40;
+       public static final int TBIF_STYLE = 0x8;
+       public static final int TBIF_TEXT = 0x2;
+       public static final int TB_GETEXTENDEDSTYLE = 0x400 + 85;
+       public static final int TBM_GETLINESIZE = 0x418;
+       public static final int TBM_GETPAGESIZE = 0x416;
+       public static final int TBM_GETPOS = 0x400;
+       public static final int TBM_GETRANGEMAX = 0x402;
+       public static final int TBM_GETRANGEMIN = 0x401;
+       public static final int TBM_GETTHUMBRECT = 0x419;
+       public static final int TBM_SETLINESIZE = 0x417;
+       public static final int TBM_SETPAGESIZE = 0x415;
+       public static final int TBM_SETPOS = 0x405;
+       public static final int TBM_SETRANGEMAX = 0x408;
+       public static final int TBM_SETRANGEMIN = 0x407;
+       public static final int TBM_SETTICFREQ = 0x414;
+       public static final int TBN_DROPDOWN = 0xfffffd3a;
+       public static final int TBN_FIRST = 0xfffffd44;
+       public static final int TBN_HOTITEMCHANGE = 0xFFFFFD37;
+       public static final int TBSTATE_CHECKED = 0x1;
+       public static final int TBSTATE_PRESSED = 0x02;
+       public static final int TBSTYLE_CUSTOMERASE = 0x2000;
+       public static final int TBSTYLE_DROPDOWN = 0x8;
+       public static final int TBSTATE_ENABLED = 0x4;
+       public static final int TBSTYLE_AUTOSIZE = 0x10;
+       public static final int TBSTYLE_EX_DOUBLEBUFFER = 0x80;
+       public static final int TBSTYLE_EX_DRAWDDARROWS = 0x1;
+       public static final int TBSTYLE_EX_HIDECLIPPEDBUTTONS = 0x10;
+       public static final int TBSTYLE_EX_MIXEDBUTTONS = 0x8;
+       public static final int TBSTYLE_FLAT = 0x800;
+       public static final int TBSTYLE_LIST = 0x1000;
+       public static final int TBSTYLE_TOOLTIPS = 0x100;
+       public static final int TBSTYLE_TRANSPARENT = 0x8000;
+       public static final int TBSTYLE_WRAPABLE = 0x200;
+       public static final int TBS_AUTOTICKS = 0x1;
+       public static final int TBS_BOTH = 0x8;
+       public static final int TBS_DOWNISLEFT = 0x0400;
+       public static final int TBS_HORZ = 0x0;
+       public static final int TBS_VERT = 0x2;
+       public static final int TB_ADDSTRING = 0x44d;
+       public static final int TB_AUTOSIZE = 0x421;
+       public static final int TB_BUTTONCOUNT = 0x418;
+       public static final int TB_BUTTONSTRUCTSIZE = 0x41e;
+       public static final int TB_COMMANDTOINDEX = 0x419;
+       public static final int TB_DELETEBUTTON = 0x416;
+       public static final int TB_ENDTRACK = 0x8;
+       public static final int TB_GETBUTTON = 0x417;
+       public static final int TB_GETBUTTONINFO = 0x43f;
+       public static final int TB_GETBUTTONSIZE = 0x43a;
+       public static final int TB_GETBUTTONTEXT = 0x44b;
+       public static final int TB_GETDISABLEDIMAGELIST = 0x437;
+       public static final int TB_GETHOTIMAGELIST = 0x435;
+       public static final int TB_GETHOTITEM = 0x0400 + 71;
+       public static final int TB_GETIMAGELIST = 0x431;
+       public static final int TB_GETITEMRECT = 0x41d;
+       public static final int TB_GETPADDING = 0x0400 + 86;
+       public static final int TB_GETROWS = 0x428;
+       public static final int TB_GETSTATE = 0x412;
+       public static final int TB_GETTOOLTIPS = 0x423;
+       public static final int TB_INSERTBUTTON = 0x443;
+       public static final int TB_LOADIMAGES = 0x432;
+       public static final int TB_MAPACCELERATOR = 0x0400 + 90;
+       public static final int TB_SETBITMAPSIZE = 0x420;
+       public static final int TB_SETBUTTONINFO = 0x440;
+       public static final int TB_SETBUTTONSIZE = 0x41f;
+       public static final int TB_SETDISABLEDIMAGELIST = 0x436;
+       public static final int TB_SETEXTENDEDSTYLE = 0x454;
+       public static final int TB_SETHOTIMAGELIST = 0x434;
+       public static final int TB_SETHOTITEM =  0x0400 + 72;
+       public static final int TB_SETIMAGELIST = 0x430;
+       public static final int TB_SETPARENT = 0x400 + 37;
+       public static final int TB_SETROWS = 0x427;
+       public static final int TB_SETSTATE = 0x411;
+       public static final int TB_THUMBPOSITION = 0x4;
+       public static final int TBPF_NOPROGRESS = 0x0;
+       public static final int TBPF_INDETERMINATE = 0x1;
+       public static final int TBPF_NORMAL = 0x2;
+       public static final int TBPF_ERROR = 0x4;
+       public static final int TBPF_PAUSED = 0x8;
+       public static final int TCIF_IMAGE = 0x2;
+       public static final int TCIF_TEXT = 0x1;
+       public static final int TCI_SRCCHARSET = 0x1;
+       public static final int TCI_SRCCODEPAGE = 0x2;
+       public static final int TCM_ADJUSTRECT = 0x1328;
+       public static final int TCM_DELETEITEM = 0x1308;
+       public static final int TCM_GETCURSEL = 0x130b;
+       public static final int TCM_GETITEMCOUNT = 0x1304;
+       public static final int TCM_GETITEMRECT = 0x130a;
+       public static final int TCM_GETTOOLTIPS = 0x132d;
+       public static final int TCM_HITTEST = 0x130d;
+       public static final int TCM_INSERTITEM = 0x133e;
+       public static final int TCM_SETCURSEL = 0x130c;
+       public static final int TCM_SETIMAGELIST = 0x1303;
+       public static final int TCM_SETITEM = 0x133d;
+       public static final int TCN_SELCHANGE = 0xfffffdd9;
+       public static final int TCN_SELCHANGING = 0xfffffdd8;
+       public static final int TCS_BOTTOM = 0x0002;
+       public static final int TCS_FOCUSNEVER = 0x8000;
+       public static final int TCS_MULTILINE = 0x200;
+       public static final int TCS_TABS = 0x0;
+       public static final int TCS_TOOLTIPS = 0x4000;
+       public static final int TECHNOLOGY = 0x2;
+       public static final int TF_ATTR_INPUT = 0;
+       public static final int TF_ATTR_TARGET_CONVERTED = 1;
+       public static final int TF_ATTR_CONVERTED = 2;
+       public static final int TF_ATTR_TARGET_NOTCONVERTED = 3;
+       public static final int TF_ATTR_INPUT_ERROR = 4;
+       public static final int TF_ATTR_FIXEDCONVERTED = 5;
+       public static final int TF_ATTR_OTHER = -1;
+       public static final int TF_CT_NONE = 0;
+       public static final int TF_CT_SYSCOLOR = 1;
+       public static final int TF_CT_COLORREF = 2;
+       public static final int TF_LS_NONE = 0;
+       public static final int TF_LS_SOLID = 1;
+       public static final int TF_LS_DOT = 2;
+       public static final int TF_LS_DASH = 3;
+       public static final int TF_LS_SQUIGGLE = 4;
+       public static final int TIS_NORMAL = 1;
+       public static final int TIS_HOT = 2;
+       public static final int TIS_SELECTED = 3;
+       public static final int TIS_DISABLED = 4;
+       public static final int TIS_FOCUSED = 5;
+       public static final int TKP_TRACK = 1;
+       public static final int TKP_TRACKVERT = 2;
+       public static final int TKP_THUMB = 3;
+       public static final int TKP_THUMBBOTTOM = 4;
+       public static final int TKP_THUMBTOP = 5;
+       public static final int TKP_THUMBVERT = 6;
+       public static final int TKP_THUMBLEFT = 7;
+       public static final int TKP_THUMBRIGHT = 8;
+       public static final int TKP_TICS = 9;
+       public static final int TKP_TICSVERT = 10;
+       public static final int TME_HOVER = 0x1;
+       public static final int TME_LEAVE = 0x2;
+       public static final int TME_QUERY = 0x40000000;
+       public static final int TMPF_VECTOR = 0x2;
+       public static final int TMT_CONTENTMARGINS = 3602;
+       public static final int TOUCHEVENTF_MOVE = 0x0001;
+       public static final int TOUCHEVENTF_DOWN = 0x0002;
+       public static final int TOUCHEVENTF_UP = 0x0004;
+       public static final int TOUCHEVENTF_INRANGE = 0x0008;
+       public static final int TOUCHEVENTF_PRIMARY = 0x0010;
+       public static final int TOUCHEVENTF_NOCOALESCE = 0x0020;
+       public static final int TOUCHEVENTF_PALM = 0x0080;
+       public static final String TOOLBARCLASSNAME = "ToolbarWindow32"; //$NON-NLS-1$
+       public static final String TOOLTIPS_CLASS = "tooltips_class32"; //$NON-NLS-1$
+       public static final int TP_BUTTON = 1;
+       public static final int TP_DROPDOWNBUTTON = 2;
+       public static final int TP_SPLITBUTTON = 3;
+       public static final int TP_SPLITBUTTONDROPDOWN = 4;
+       public static final int TP_SEPARATOR = 5;
+       public static final int TP_SEPARATORVERT = 6;
+       public static final int TPM_LEFTALIGN = 0x0;
+       public static final int TPM_LEFTBUTTON = 0x0;
+       public static final int TPM_RIGHTBUTTON = 0x2;
+       public static final int TPM_RIGHTALIGN = 0x8;
+       public static final String TRACKBAR_CLASS = "msctls_trackbar32"; //$NON-NLS-1$
+       public static final int TRANSPARENT = 0x1;
+       public static final int TREIS_DISABLED = 4;
+       public static final int TREIS_HOT = 2;
+       public static final int TREIS_NORMAL = 1;
+       public static final int TREIS_SELECTED = 3;
+       public static final int TREIS_SELECTEDNOTFOCUS = 5;
+       public static final int TS_TRUE = 1;
+       public static final int TTDT_AUTOMATIC = 0;
+       public static final int TTDT_RESHOW = 1;
+       public static final int TTDT_AUTOPOP = 2;
+       public static final int TTDT_INITIAL = 3;
+       public static final int TTF_ABSOLUTE = 0x80;
+       public static final int TTF_IDISHWND = 0x1;
+       public static final int TTF_SUBCLASS = 0x10;
+       public static final int TTF_RTLREADING = 0x4;
+       public static final int TTF_TRACK = 0x20;
+       public static final int TTF_TRANSPARENT = 0x100;
+       public static final int TTI_NONE = 0;
+       public static final int TTI_INFO = 1;
+       public static final int TTI_WARNING = 2;
+       public static final int TTI_ERROR= 3;
+       public static final int TTM_ACTIVATE = 0x400 + 1;
+       public static final int TTM_ADDTOOL = 0x432;
+       public static final int TTM_ADJUSTRECT = 0x400 + 31;
+       public static final int TTM_GETCURRENTTOOL = 0x400 + 59;
+       public static final int TTM_GETDELAYTIME = 0x400 + 21;
+       public static final int TTM_DELTOOL = 0x433;
+       public static final int TTM_GETTOOLINFO = 0x400 + 53;
+       public static final int TTM_GETTOOLCOUNT = 0x40D;
+       public static final int TTM_NEWTOOLRECT = 0x400 + 52;
+       public static final int TTM_POP = 0x400 + 28;
+       public static final int TTM_SETDELAYTIME = 0x400 + 3;
+       public static final int TTM_SETMAXTIPWIDTH = 0x418;
+       public static final int TTM_SETTITLE = 0x400 + 33;
+       public static final int TTM_TRACKPOSITION = 1042;
+       public static final int TTM_TRACKACTIVATE = 1041;
+       public static final int TTM_UPDATE = 0x41D;
+       public static final int TTM_UPDATETIPTEXT = 0x400 + 57;
+       public static final int TTN_FIRST = 0xfffffdf8;
+       public static final int TTN_GETDISPINFO = 0xfffffdee;
+       public static final int TTN_POP = TTN_FIRST - 2;
+       public static final int TTN_SHOW = TTN_FIRST - 1;
+       public static final int TTS_ALWAYSTIP = 0x1;
+       public static final int TTS_BALLOON = 0x40;
+       public static final int TTS_NOANIMATE = 0x10;
+       public static final int TTS_NOFADE = 0x20;
+       public static final int TTS_NOPREFIX = 0x02;
+       public static final int TV_FIRST = 0x1100;
+       public static final int TVE_COLLAPSE = 0x1;
+       public static final int TVE_COLLAPSERESET = 0x8000;
+       public static final int TVE_EXPAND = 0x2;
+       public static final int TVGN_CARET = 0x9;
+       public static final int TVGN_CHILD = 0x4;
+       public static final int TVGN_DROPHILITED = 0x8;
+       public static final int TVGN_FIRSTVISIBLE = 0x5;
+       public static final int TVGN_LASTVISIBLE = 0xa;
+       public static final int TVGN_NEXT = 0x1;
+       public static final int TVGN_NEXTVISIBLE = 0x6;
+       public static final int TVGN_PARENT = 0x3;
+       public static final int TVGN_PREVIOUS = 0x2;
+       public static final int TVGN_PREVIOUSVISIBLE = 0x7;
+       public static final int TVGN_ROOT = 0x0;
+       public static final int TVHT_ONITEM = 0x46;
+       public static final int TVHT_ONITEMBUTTON = 16;
+       public static final int TVHT_ONITEMICON = 0x2;
+       public static final int TVHT_ONITEMINDENT = 0x8;
+       public static final int TVHT_ONITEMRIGHT = 0x20;
+       public static final int TVHT_ONITEMLABEL = 0x4;
+       public static final int TVHT_ONITEMSTATEICON = 0x40;
+       public static final int TVIF_HANDLE = 0x10;
+       public static final int TVIF_IMAGE = 0x2;
+       public static final int TVIF_INTEGRAL = 0x0080;
+       public static final int TVIF_PARAM = 0x4;
+       public static final int TVIF_SELECTEDIMAGE = 0x20;
+       public static final int TVIF_STATE = 0x8;
+       public static final int TVIF_TEXT = 0x1;
+       public static final int TVIS_DROPHILITED = 0x8;
+       public static final int TVIS_EXPANDED = 0x20;
+       public static final int TVIS_SELECTED = 0x2;
+       public static final int TVIS_STATEIMAGEMASK = 0xf000;
+       public static final long TVI_FIRST = -0x0FFFF;
+       public static final long TVI_LAST = -0x0FFFE;
+       public static final long TVI_ROOT = -0x10000;
+       public static final long TVI_SORT = -0x0FFFD;
+       public static final int TVM_CREATEDRAGIMAGE = TV_FIRST + 18;
+       public static final int TVM_DELETEITEM = 0x1101;
+       public static final int TVM_ENSUREVISIBLE = 0x1114;
+       public static final int TVM_EXPAND = 0x1102;
+       public static final int TVM_GETBKCOLOR = 0x111f;
+       public static final int TVM_GETCOUNT = 0x1105;
+       public static final int TVM_GETEXTENDEDSTYLE = TV_FIRST + 45;
+       public static final int TVM_GETIMAGELIST = 0x1108;
+       public static final int TVM_GETITEM = 0x113e;
+       public static final int TVM_GETITEMHEIGHT = 0x111c;
+       public static final int TVM_GETITEMRECT = 0x1104;
+       public static final int TVM_GETITEMSTATE = TV_FIRST + 39;
+       public static final int TVM_GETNEXTITEM = 0x110a;
+       public static final int TVM_GETTEXTCOLOR = 0x1120;
+       public static final int TVM_GETTOOLTIPS = TV_FIRST + 25;
+       public static final int TVM_GETVISIBLECOUNT = TV_FIRST + 16;
+       public static final int TVM_HITTEST = 0x1111;
+       public static final int TVM_INSERTITEM = 0x1132;
+       public static final int TVM_MAPACCIDTOHTREEITEM = TV_FIRST + 42;
+       public static final int TVM_MAPHTREEITEMTOACCID = TV_FIRST + 43;
+       public static final int TVM_SELECTITEM = 0x110b;
+       public static final int TVM_SETBKCOLOR = 0x111d;
+       public static final int TVM_SETEXTENDEDSTYLE = TV_FIRST + 44;
+       public static final int TVM_SETIMAGELIST = 0x1109;
+       public static final int TVM_SETINDENT = TV_FIRST + 7;
+       public static final int TVM_SETINSERTMARK = 0x111a;
+       public static final int TVM_SETITEM = 0x113f;
+       public static final int TVM_SETITEMHEIGHT = TV_FIRST + 27;
+       public static final int TVM_SETSCROLLTIME = TV_FIRST + 33;
+       public static final int TVM_SETTEXTCOLOR = 0x111e;
+       public static final int TVM_SORTCHILDREN = TV_FIRST + 19;
+       public static final int TVM_SORTCHILDRENCB = TV_FIRST + 21;
+       public static final int TVN_BEGINDRAG = 0xfffffe38;
+       public static final int TVN_BEGINRDRAG = 0xfffffe37;
+       public static final int TVN_FIRST = 0xfffffe70;
+       public static final int TVN_GETDISPINFO = TVN_FIRST - 52;
+       public static final int TVN_ITEMCHANGING = TVN_FIRST - 17;
+       public static final int TVN_ITEMEXPANDED = TVN_FIRST - 55;
+       public static final int TVN_ITEMEXPANDING = 0xfffffe3a;
+       public static final int TVN_SELCHANGED = 0xfffffe3d;
+       public static final int TVN_SELCHANGING = 0xfffffe3e;
+       public static final int TVP_GLYPH = 2;
+       public static final int TVP_TREEITEM = 1;
+       public static final int TVSIL_NORMAL = 0x0;
+       public static final int TVSIL_STATE = 0x2;
+       public static final int TVS_DISABLEDRAGDROP = 0x10;
+       public static final int TVS_EX_AUTOHSCROLL = 0x0020;
+       public static final int TVS_EX_DOUBLEBUFFER = 0x0004;
+       public static final int TVS_EX_DIMMEDCHECKBOXES = 0x0200;
+       public static final int TVS_EX_DRAWIMAGEASYNC = 0x0400;
+       public static final int TVS_EX_EXCLUSIONCHECKBOXES = 0x0100;
+       public static final int TVS_EX_FADEINOUTEXPANDOS = 0x0040;
+       public static final int TVS_EX_MULTISELECT = 0x0002;
+       public static final int TVS_EX_NOINDENTSTATE = 0x0008;
+       public static final int TVS_EX_PARTIALCHECKBOXES = 0x0080;
+       public static final int TVS_EX_RICHTOOLTIP = 0x0010;
+       public static final int TVS_FULLROWSELECT = 0x1000;
+       public static final int TVS_HASBUTTONS = 0x1;
+       public static final int TVS_HASLINES = 0x2;
+       public static final int TVS_LINESATROOT = 0x4;
+       public static final int TVS_NOHSCROLL = 0x8000;
+       public static final int TVS_NONEVENHEIGHT = 0x4000;
+       public static final int TVS_NOSCROLL = 0x2000;
+       public static final int TVS_NOTOOLTIPS = 0x80;
+       public static final int TVS_SHOWSELALWAYS = 0x20;
+       public static final int TVS_TRACKSELECT = 0x200;
+       public static final int UDM_GETACCEL = 0x046C;
+       public static final int UDM_GETRANGE32 = 0x0470;
+       public static final int UDM_GETPOS32 = 0x0472;
+       public static final int UDM_SETACCEL = 0x046B;
+       public static final int UDM_SETRANGE32 = 0x046f;
+       public static final int UDM_SETPOS32 = 0x0471;
+       public static final int UDN_DELTAPOS = -722;
+       public static final int UDS_ALIGNLEFT = 0x008;
+       public static final int UDS_ALIGNRIGHT = 0x004;
+       public static final int UDS_AUTOBUDDY = 0x0010;
+       public static final int UDS_WRAP = 0x0001;
+       public static final int UIS_CLEAR = 2;
+       public static final int UIS_INITIALIZE = 3;
+       public static final int UIS_SET = 1;
+       public static final int UISF_HIDEACCEL = 0x2;
+       public static final int UISF_HIDEFOCUS = 0x1;
+       public static final String UPDOWN_CLASS = "msctls_updown32"; //$NON-NLS-1$
+       public static final int USP_E_SCRIPT_NOT_IN_FONT = 0x80040200;
+       public static final int VERTRES = 0xa;
+       public static final int VK_BACK = 0x8;
+       public static final int VK_CANCEL = 0x3;
+       public static final int VK_CAPITAL = 0x14;
+       public static final int VK_CONTROL = 0x11;
+       public static final int VK_DECIMAL = 0x6E;
+       public static final int VK_DELETE = 0x2e;
+       public static final int VK_DIVIDE = 0x6f;
+       public static final int VK_DOWN = 0x28;
+       public static final int VK_END = 0x23;
+       public static final int VK_ESCAPE = 0x1b;
+       public static final int VK_F1 = 0x70;
+       public static final int VK_F10 = 0x79;
+       public static final int VK_F11 = 0x7a;
+       public static final int VK_F12 = 0x7b;
+       public static final int VK_F13 = 0x7c;
+       public static final int VK_F14 = 0x7d;
+       public static final int VK_F15 = 0x7e;
+       public static final int VK_F16 = 0x7F;
+       public static final int VK_F17 = 0x80;
+       public static final int VK_F18 = 0x81;
+       public static final int VK_F19 = 0x82;
+       public static final int VK_F20 = 0x83;
+       public static final int VK_F2 = 0x71;
+       public static final int VK_F3 = 0x72;
+       public static final int VK_F4 = 0x73;
+       public static final int VK_F5 = 0x74;
+       public static final int VK_F6 = 0x75;
+       public static final int VK_F7 = 0x76;
+       public static final int VK_F8 = 0x77;
+       public static final int VK_F9 = 0x78;
+       public static final int VK_HANJA = 0x19;
+       public static final int VK_HOME = 0x24;
+       public static final int VK_INSERT = 0x2d;
+       public static final int VK_L = 0x4c;
+       public static final int VK_LBUTTON = 0x1;
+       public static final int VK_LEFT = 0x25;
+       public static final int VK_LCONTROL = 0xA2;
+       public static final int VK_LMENU = 0xA4;
+       public static final int VK_LSHIFT = 0xA0;
+       public static final int VK_MBUTTON = 0x4;
+       public static final int VK_MENU = 0x12;
+       public static final int VK_MULTIPLY = 0x6A;
+       public static final int VK_N = 0x4e;
+       public static final int VK_O = 0x4f;
+       public static final int VK_NEXT = 0x22;
+       public static final int VK_NUMLOCK = 0x90;
+       public static final int VK_NUMPAD0 = 0x60;
+       public static final int VK_NUMPAD1 = 0x61;
+       public static final int VK_NUMPAD2 = 0x62;
+       public static final int VK_NUMPAD3 = 0x63;
+       public static final int VK_NUMPAD4 = 0x64;
+       public static final int VK_NUMPAD5 = 0x65;
+       public static final int VK_NUMPAD6 = 0x66;
+       public static final int VK_NUMPAD7 = 0x67;
+       public static final int VK_NUMPAD8 = 0x68;
+       public static final int VK_NUMPAD9 = 0x69;
+       public static final int VK_PAUSE = 0x13;
+       public static final int VK_PRIOR = 0x21;
+       public static final int VK_RBUTTON = 0x2;
+       public static final int VK_RETURN = 0xd;
+       public static final int VK_RIGHT = 0x27;
+       public static final int VK_RCONTROL = 0xA3;
+       public static final int VK_RMENU = 0xA5;
+       public static final int VK_RSHIFT = 0xA1;
+       public static final int VK_SCROLL = 0x91;
+       public static final int VK_SEPARATOR = 0x6C;
+       public static final int VK_SHIFT = 0x10;
+       public static final int VK_SNAPSHOT = 0x2C;
+       public static final int VK_SPACE = 0x20;
+       public static final int VK_SUBTRACT = 0x6D;
+       public static final int VK_TAB = 0x9;
+       public static final int VK_UP = 0x26;
+       public static final int VK_XBUTTON1 = 0x05;
+       public static final int VK_XBUTTON2 = 0x06;
+       public static final int VK_ADD = 0x6B;
+       public static final int VT_BOOL = 11;
+       public static final int VT_LPWSTR = 31;
+       public static final short VARIANT_TRUE = -1;
+       public static final short VARIANT_FALSE = 0;
+       public static final short WA_CLICKACTIVE = 2;
+       public static final String WC_HEADER = "SysHeader32"; //$NON-NLS-1$
+       public static final String WC_LINK = "SysLink"; //$NON-NLS-1$
+       public static final String WC_LISTVIEW = "SysListView32"; //$NON-NLS-1$
+       public static final String WC_TABCONTROL = "SysTabControl32"; //$NON-NLS-1$
+       public static final String WC_TREEVIEW = "SysTreeView32"; //$NON-NLS-1$
+       public static final int WINDING = 2;
+       public static final int WH_CBT = 5;
+       public static final int WH_GETMESSAGE = 0x3;
+       public static final int WH_MSGFILTER = 0xFFFFFFFF;
+       public static final int WH_FOREGROUNDIDLE = 11;
+       public static final int WHEEL_DELTA = 120;
+       public static final int WHEEL_PAGESCROLL = 0xFFFFFFFF;
+       public static final int WHITE_BRUSH = 0;
+       public static final int WHITENESS = 0x00FF0062;
+       public static final int WM_ACTIVATE = 0x6;
+       public static final int WM_ACTIVATEAPP = 0x1c;
+       public static final int WM_APP = 0x8000;
+       public static final int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320;
+       public static final int WM_CANCELMODE = 0x1f;
+       public static final int WM_CAPTURECHANGED = 0x0215;
+       public static final int WM_CHANGEUISTATE = 0x0127;
+       public static final int WM_CHAR = 0x102;
+       public static final int WM_CLEAR = 0x303;
+       public static final int WM_CLOSE = 0x10;
+       public static final int WM_COMMAND = 0x111;
+       public static final int WM_CONTEXTMENU = 0x7b;
+       public static final int WM_COPY = 0x301;
+       public static final int WM_CREATE = 0x0001;
+       public static final int WM_CTLCOLORBTN = 0x135;
+       public static final int WM_CTLCOLORDLG = 0x136;
+       public static final int WM_CTLCOLOREDIT = 0x133;
+       public static final int WM_CTLCOLORLISTBOX = 0x134;
+       public static final int WM_CTLCOLORMSGBOX = 0x132;
+       public static final int WM_CTLCOLORSCROLLBAR = 0x137;
+       public static final int WM_CTLCOLORSTATIC = 0x138;
+       public static final int WM_CUT = 0x300;
+       public static final int WM_DEADCHAR = 0x103;
+       public static final int WM_DESTROY = 0x2;
+       public static final int WM_DPICHANGED = 0x02E0;
+       public static final int WM_DRAWITEM = 0x2b;
+       public static final int WM_ENDSESSION = 0x16;
+       public static final int WM_ENTERIDLE = 0x121;
+       public static final int WM_ERASEBKGND = 0x14;
+       public static final int WM_GESTURE = 0x0119;
+       public static final int WM_GETDLGCODE = 0x87;
+       public static final int WM_GETFONT = 0x31;
+       public static final int WM_GETOBJECT = 0x003D;
+       public static final int WM_GETMINMAXINFO = 0x0024;
+       public static final int WM_HELP = 0x53;
+       public static final int WM_HOTKEY = 0x0312;
+       public static final int WM_HSCROLL = 0x114;
+       public static final int WM_IME_CHAR = 0x286;
+       public static final int WM_IME_COMPOSITION = 0x10f;
+       public static final int WM_IME_COMPOSITION_START = 0x010D;
+       public static final int WM_IME_ENDCOMPOSITION = 0x010E;
+       public static final int WM_INITDIALOG = 0x110;
+       public static final int WM_INITMENUPOPUP = 0x117;
+       public static final int WM_INPUTLANGCHANGE = 0x51;
+       public static final int WM_KEYDOWN = 0x100;
+       public static final int WM_KEYFIRST = 0x100;
+       public static final int WM_KEYLAST = 0x108;
+       public static final int WM_KEYUP = 0x101;
+       public static final int WM_KILLFOCUS = 0x8;
+       public static final int WM_LBUTTONDBLCLK = 0x203;
+       public static final int WM_LBUTTONDOWN = 0x201;
+       public static final int WM_LBUTTONUP = 0x202;
+       public static final int WM_MBUTTONDBLCLK = 0x209;
+       public static final int WM_MBUTTONDOWN = 0x207;
+       public static final int WM_MBUTTONUP = 0x208;
+       public static final int WM_MEASUREITEM = 0x2c;
+       public static final int WM_MENUCHAR = 0x120;
+       public static final int WM_MENUSELECT = 0x11f;
+       public static final int WM_MOUSEACTIVATE = 0x21;
+       public static final int WM_MOUSEFIRST = 0x200;
+       public static final int WM_MOUSEHOVER = 0x2a1;
+       public static final int WM_MOUSELEAVE = 0x2a3;
+       public static final int WM_MOUSEMOVE = 0x200;
+       public static final int WM_MOUSEWHEEL = 0x20a;
+       public static final int WM_MOUSEHWHEEL = 0x20e;
+       public static final int WM_MOUSELAST = 0x20d;
+       public static final int WM_MOVE = 0x3;
+       public static final int WM_NCACTIVATE = 0x86;
+       public static final int WM_NCCALCSIZE = 0x83;
+       public static final int WM_NCHITTEST = 0x84;
+       public static final int WM_NCLBUTTONDOWN = 0x00A1;
+       public static final int WM_NCPAINT = 0x85;
+       public static final int WM_NOTIFY = 0x4e;
+       public static final int WM_NULL = 0x0;
+       public static final int WM_PAINT = 0xf;
+       public static final int WM_PARENTNOTIFY = 0x0210;
+       public static final int WM_ENTERMENULOOP = 0x0211;
+       public static final int WM_EXITMENULOOP = 0x0212;
+       public static final int WM_ENTERSIZEMOVE = 0x0231;
+       public static final int WM_EXITSIZEMOVE = 0x0232;
+       public static final int WM_PASTE = 0x302;
+       public static final int WM_PRINT = 0x0317;
+       public static final int WM_PRINTCLIENT = 0x0318;
+       public static final int WM_QUERYENDSESSION = 0x11;
+       public static final int WM_QUERYOPEN = 0x13;
+       public static final int WM_QUERYUISTATE = 0x129;
+       public static final int WM_RBUTTONDBLCLK = 0x206;
+       public static final int WM_RBUTTONDOWN = 0x204;
+       public static final int WM_RBUTTONUP = 0x205;
+       public static final int WM_SETCURSOR = 0x20;
+       public static final int WM_SETFOCUS = 0x7;
+       public static final int WM_SETFONT = 0x30;
+       public static final int WM_SETICON = 0x80;
+       public static final int WM_SETREDRAW = 0xb;
+       public static final int WM_SETTEXT = 12;
+       public static final int WM_SETTINGCHANGE = 0x1A;
+       public static final int WM_SHOWWINDOW = 0x18;
+       public static final int WM_SIZE = 0x5;
+       public static final int WM_SYSCHAR = 0x106;
+       public static final int WM_SYSCOLORCHANGE = 0x15;
+       public static final int WM_SYSCOMMAND = 0x112;
+       public static final int WM_SYSKEYDOWN = 0x104;
+       public static final int WM_SYSKEYUP = 0x105;
+       public static final int WM_TABLET_FLICK = 0x02C0 + 11;
+       public static final int WM_TIMER = 0x113;
+       public static final int WM_THEMECHANGED = 0x031a;
+       public static final int WM_TOUCH = 0x240;
+       public static final int WM_UNDO = 0x304;
+       public static final int WM_UNINITMENUPOPUP = 0x0125;
+       public static final int WM_UPDATEUISTATE = 0x0128;
+       public static final int WM_USER = 0x400;
+       public static final int WM_VSCROLL = 0x115;
+       public static final int WM_WINDOWPOSCHANGED = 0x47;
+       public static final int WM_WINDOWPOSCHANGING = 0x46;
+       public static final int WPF_RESTORETOMAXIMIZED = 0x0002;
+       public static final int WS_BORDER = 0x800000;
+       public static final int WS_CAPTION = 0xc00000;
+       public static final int WS_CHILD = 0x40000000;
+       public static final int WS_CLIPCHILDREN = 0x2000000;
+       public static final int WS_CLIPSIBLINGS = 0x4000000;
+       public static final int WS_DISABLED = 0x4000000;
+       public static final int WS_EX_APPWINDOW = 0x40000;
+       public static final int WS_EX_CAPTIONOKBTN = 0x80000000;
+       public static final int WS_EX_CLIENTEDGE = 0x200;
+       public static final int WS_EX_COMPOSITED = 0x2000000;
+       public static final int WS_EX_DLGMODALFRAME = 0x1;
+       public static final int WS_EX_LAYERED = 0x00080000;
+       public static final int WS_EX_LAYOUTRTL = 0x00400000;
+       public static final int WS_EX_LEFTSCROLLBAR = 0x00004000;
+       public static final int WS_EX_MDICHILD = 0x00000040;
+       public static final int WS_EX_NOINHERITLAYOUT = 0x00100000;
+       public static final int WS_EX_NOACTIVATE = 0x08000000;
+       public static final int WS_EX_RIGHT = 0x00001000;
+       public static final int WS_EX_RTLREADING = 0x00002000;
+       public static final int WS_EX_STATICEDGE = 0x20000;
+       public static final int WS_EX_TOOLWINDOW = 0x80;
+       public static final int WS_EX_TOPMOST = 0x8;
+       public static final int WS_EX_TRANSPARENT = 0x20;
+       public static final int WS_HSCROLL = 0x100000;
+       public static final int WS_MAXIMIZEBOX = 0x10000;
+       public static final int WS_MINIMIZEBOX = 0x20000;
+       public static final int WS_OVERLAPPED = 0x0;
+       public static final int WS_OVERLAPPEDWINDOW = 0xcf0000;
+       public static final int WS_POPUP = 0x80000000;
+       public static final int WS_SYSMENU = 0x80000;
+       public static final int WS_TABSTOP = 0x10000;
+       public static final int WS_THICKFRAME = 0x40000;
+       public static final int WS_VISIBLE = 0x10000000;
+       public static final int WS_VSCROLL = 0x200000;
+       public static final int WM_XBUTTONDOWN = 0x020B;
+       public static final int WM_XBUTTONUP = 0x020C;
+       public static final int WM_XBUTTONDBLCLK = 0x020D;
+       public static final int XBUTTON1 = 0x1;
+       public static final int XBUTTON2 = 0x2;
+       public static final int X509_ASN_ENCODING = 1;
+
+public static int VERSION (int major, int minor) {
+       return major << 16 | minor;
+}
+
+/** 64 bit */
+public static final native int ACCEL_sizeof ();
+public static final native int ACTCTX_sizeof ();
+public static final native int BITMAP_sizeof ();
+public static final native int BITMAPINFOHEADER_sizeof ();
+public static final native int BLENDFUNCTION_sizeof ();
+public static final native int BP_PAINTPARAMS_sizeof ();
+public static final native int BROWSEINFO_sizeof ();
+public static final native int BUTTON_IMAGELIST_sizeof ();
+public static final native int CANDIDATEFORM_sizeof ();
+public static final native int CERT_CONTEXT_sizeof ();
+public static final native int CERT_INFO_sizeof ();
+public static final native int CERT_NAME_BLOB_sizeof ();
+public static final native int CERT_PUBLIC_KEY_INFO_sizeof ();
+public static final native int CHOOSECOLOR_sizeof ();
+public static final native int CHOOSEFONT_sizeof ();
+public static final native int COMBOBOXINFO_sizeof ();
+public static final native int COMPOSITIONFORM_sizeof ();
+public static final native int CREATESTRUCT_sizeof ();
+public static final native int CRYPT_ALGORITHM_IDENTIFIER_sizeof ();
+public static final native int CRYPT_BIT_BLOB_sizeof ();
+public static final native int CRYPT_INTEGER_BLOB_sizeof ();
+public static final native int CRYPT_OBJID_BLOB_sizeof ();
+public static final native int DEVMODE_sizeof ();
+public static final native int DIBSECTION_sizeof ();
+public static final native int DOCHOSTUIINFO_sizeof ();
+public static final native int DOCINFO_sizeof ();
+public static final native int DRAWITEMSTRUCT_sizeof ();
+public static final native int DROPFILES_sizeof ();
+public static final native int DTTOPTS_sizeof ();
+public static final native int EMR_sizeof ();
+public static final native int EMREXTCREATEFONTINDIRECTW_sizeof ();
+public static final native int EXTLOGFONTW_sizeof ();
+public static final native int FILETIME_sizeof ();
+public static final native int FLICK_DATA_sizeof ();
+public static final native int FLICK_POINT_sizeof ();
+public static final native int GCP_RESULTS_sizeof ();
+public static final native int GESTURECONFIG_sizeof ();
+public static final native int GESTUREINFO_sizeof ();
+public static final native int GRADIENT_RECT_sizeof ();
+public static final native int GUITHREADINFO_sizeof ();
+public static final native int HDITEM_sizeof ();
+public static final native int HDLAYOUT_sizeof ();
+public static final native int HDHITTESTINFO_sizeof ();
+public static final native int HELPINFO_sizeof ();
+public static final native int HIGHCONTRAST_sizeof ();
+public static final native int ICONINFO_sizeof ();
+public static final native int CIDA_sizeof ();
+public static final native int INITCOMMONCONTROLSEX_sizeof ();
+public static final native int INPUT_sizeof ();
+public static final native int KEYBDINPUT_sizeof ();
+public static final native int LITEM_sizeof ();
+public static final native int LOGBRUSH_sizeof ();
+public static final native int LOGFONT_sizeof ();
+public static final native int LOGPEN_sizeof ();
+public static final native int LVCOLUMN_sizeof ();
+public static final native int LVHITTESTINFO_sizeof ();
+public static final native int LVITEM_sizeof ();
+public static final native int LVINSERTMARK_sizeof ();
+public static final native int MARGINS_sizeof ();
+public static final native int MCHITTESTINFO_sizeof ();
+public static final native int MEASUREITEMSTRUCT_sizeof ();
+public static final native int MENUBARINFO_sizeof ();
+public static final native int MENUINFO_sizeof ();
+public static final native int MENUITEMINFO_sizeof ();
+public static final native int MINMAXINFO_sizeof ();
+public static final native int MOUSEINPUT_sizeof ();
+public static final native int MONITORINFO_sizeof ();
+public static final native int MSG_sizeof ();
+public static final native int NMCUSTOMDRAW_sizeof ();
+public static final native int NMHDR_sizeof ();
+public static final native int NMHEADER_sizeof ();
+public static final native int NMLINK_sizeof ();
+public static final native int NMLISTVIEW_sizeof ();
+public static final native int NMLVCUSTOMDRAW_sizeof ();
+public static final native int NMLVDISPINFO_sizeof ();
+public static final native int NMLVFINDITEM_sizeof ();
+public static final native int NMLVODSTATECHANGE_sizeof ();
+public static final native int NMREBARCHEVRON_sizeof ();
+public static final native int NMREBARCHILDSIZE_sizeof ();
+public static final native int NMTBHOTITEM_sizeof ();
+public static final native int NMTREEVIEW_sizeof ();
+public static final native int NMTOOLBAR_sizeof ();
+public static final native int NMTTDISPINFO_sizeof ();
+public static final native int NMTTCUSTOMDRAW_sizeof ();
+public static final native int NMTBCUSTOMDRAW_sizeof ();
+public static final native int NMTVCUSTOMDRAW_sizeof ();
+public static final native int NMTVDISPINFO_sizeof ();
+public static final native int NMTVITEMCHANGE_sizeof ();
+public static final native int NMUPDOWN_sizeof ();
+public static final native int NONCLIENTMETRICS_sizeof ();
+/** @method flags=const */
+public static final native int NOTIFYICONDATA_V2_SIZE ();
+public static final native int OFNOTIFY_sizeof ();
+public static final native int OPENFILENAME_sizeof ();
+public static final native int OUTLINETEXTMETRIC_sizeof ();
+public static final native int PAINTSTRUCT_sizeof ();
+public static final native int PANOSE_sizeof ();
+public static final native int POINT_sizeof ();
+public static final native int PRINTDLG_sizeof ();
+public static final native int PROCESS_INFORMATION_sizeof ();
+public static final native int PROPVARIANT_sizeof ();
+public static final native int PROPERTYKEY_sizeof ();
+public static final native int REBARBANDINFO_sizeof ();
+public static final native int RECT_sizeof ();
+public static final native int SAFEARRAY_sizeof ();
+public static final native int SAFEARRAYBOUND_sizeof ();
+public static final native int SCRIPT_ANALYSIS_sizeof ();
+public static final native int SCRIPT_CONTROL_sizeof ();
+public static final native int SCRIPT_DIGITSUBSTITUTE_sizeof ();
+public static final native int SCRIPT_FONTPROPERTIES_sizeof ();
+public static final native int SCRIPT_ITEM_sizeof ();
+public static final native int SCRIPT_LOGATTR_sizeof ();
+public static final native int SCRIPT_PROPERTIES_sizeof ();
+public static final native int SCRIPT_STATE_sizeof ();
+public static final native int SCRIPT_STRING_ANALYSIS_sizeof ();
+public static final native int SCROLLBARINFO_sizeof ();
+public static final native int SCROLLINFO_sizeof ();
+public static final native int SHDRAGIMAGE_sizeof();
+public static final native int SHELLEXECUTEINFO_sizeof ();
+public static final native int SHFILEINFO_sizeof ();
+public static final native int SIZE_sizeof ();
+public static final native int STARTUPINFO_sizeof ();
+public static final native int SYSTEMTIME_sizeof ();
+public static final native int TBBUTTON_sizeof ();
+public static final native int TBBUTTONINFO_sizeof ();
+public static final native int TCITEM_sizeof ();
+public static final native int TCHITTESTINFO_sizeof ();
+public static final native int TEXTMETRIC_sizeof ();
+public static final native int TF_DA_COLOR_sizeof ();
+public static final native int TF_DISPLAYATTRIBUTE_sizeof ();
+public static final native int TOOLINFO_sizeof ();
+public static final native int TOUCHINPUT_sizeof();
+public static final native int TRACKMOUSEEVENT_sizeof ();
+public static final native int TRIVERTEX_sizeof ();
+public static final native int TVHITTESTINFO_sizeof ();
+public static final native int TVINSERTSTRUCT_sizeof ();
+public static final native int TVITEM_sizeof ();
+public static final native int TVITEMEX_sizeof ();
+public static final native int TVSORTCB_sizeof ();
+public static final native int UDACCEL_sizeof ();
+public static final native int WINDOWPLACEMENT_sizeof ();
+public static final native int WINDOWPOS_sizeof ();
+public static final native int WNDCLASS_sizeof ();
+
+/** Ansi/Unicode wrappers */
+
+public static final long AddFontResourceEx (TCHAR lpszFilename, int fl, long pdv) {
+       char [] lpszFilename1 = lpszFilename == null ? null : lpszFilename.chars;
+       return AddFontResourceEx (lpszFilename1, fl, pdv);
+}
+
+public static final int AssocQueryString(int flags, int str, TCHAR pszAssoc, TCHAR pszExtra, TCHAR pszOut, int[] pcchOut) {
+       char [] pszAssoc1 = pszAssoc == null ? null : pszAssoc.chars;
+       char [] pszExtra1 = pszExtra == null ? null : pszExtra.chars;
+       char [] pszOut1 = pszOut == null ? null : pszOut.chars;
+       return AssocQueryString (flags, str, pszAssoc1, pszExtra1, pszOut1, pcchOut);
+}
+
+public static final long CreateDC (TCHAR lpszDriver, TCHAR lpszDevice, long lpszOutput, long lpInitData) {
+       char [] lpszDriver1 = lpszDriver == null ? null : lpszDriver.chars;
+       char [] lpszDevice1 = lpszDevice == null ? null : lpszDevice.chars;
+       return CreateDC (lpszDriver1, lpszDevice1, lpszOutput, lpInitData);
+}
+
+public static final long CreateWindowEx (int dwExStyle, TCHAR lpClassName, TCHAR lpWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, long hWndParent, long hMenu, long hInstance, CREATESTRUCT lpParam) {
+       char [] lpClassName1 = lpClassName == null ? null : lpClassName.chars;
+       char [] lpWindowName1 = lpWindowName == null ? null : lpWindowName.chars;
+       return CreateWindowEx (dwExStyle, lpClassName1, lpWindowName1, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+}
+
+public static final int DocumentProperties (long hWnd, long hPrinter, TCHAR pDeviceName, long pDevModeOutput, long pDevModeInput, int fMode) {
+       char [] pDeviceName1 = pDeviceName == null ? null : pDeviceName.chars;
+       return DocumentProperties (hWnd, hPrinter, pDeviceName1, pDevModeOutput, pDevModeInput, fMode);
+}
+
+public static final int DrawText (long hDC, TCHAR lpString, int nCount, RECT lpRect, int uFormat) {
+       char [] lpString1 = lpString == null ? null : lpString.chars;
+       return DrawText (hDC, lpString1, nCount, lpRect, uFormat);
+}
+
+public static final int ExpandEnvironmentStrings (TCHAR lpSrc, TCHAR lpDst, int nSize) {
+       char [] lpSrc1 = lpSrc == null ? null : lpSrc.chars;
+       char [] lpDst1 = lpDst == null ? null : lpDst.chars;
+       return ExpandEnvironmentStrings (lpSrc1, lpDst1, nSize);
+}
+
+public static final int ExtractIconEx (TCHAR lpszFile, int nIconIndex, long [] phiconLarge, long [] phiconSmall, int nIcons) {
+       char [] lpszFile1 = lpszFile == null ? null : lpszFile.chars;
+       return ExtractIconEx (lpszFile1, nIconIndex, phiconLarge, phiconSmall, nIcons);
+}
+
+public static final boolean GetClassInfo (long hInstance, TCHAR lpClassName, WNDCLASS lpWndClass) {
+       boolean result;
+
+       char [] lpClassName1 = lpClassName == null ? null : lpClassName.chars;
+       result = GetClassInfo (hInstance, lpClassName1, lpWndClass);
+
+       /*
+       * WINAPI GetClassInfo copies lpClassName1 pointer to WNDCLASS.lpszClassName.
+       * But because JNI code copies java's TCHAR to temporary native string, temporary pointer gets copied.
+       * Upon return from JNI GetClassInfo, WNDCLASS contains pointer to already freed memory.
+       * Usually the memory stays untouched for a short while, and code seems to work just fine.
+       * To prevent this subtle error, field is zeroed to draw attention.
+       */
+       lpWndClass.lpszClassName = 0;
+
+       return result;
+}
+
+public static final int GetLocaleInfo (int Locale, int LCType, TCHAR lpLCData, int cchData) {
+       char [] lpLCData1 = lpLCData == null ? null : lpLCData.chars;
+       return GetLocaleInfo (Locale, LCType, lpLCData1, cchData);
+}
+
+public static final int GetModuleFileName (long hModule, TCHAR lpFilename, int inSize) {
+       char [] lpFilename1 = lpFilename == null ? null : lpFilename.chars;
+       return GetModuleFileName (hModule, lpFilename1, inSize);
+}
+
+public static final int GetProfileString (TCHAR lpAppName, TCHAR lpKeyName, TCHAR lpDefault, TCHAR lpReturnedString, int nSize) {
+       char [] lpAppName1 = lpAppName == null ? null : lpAppName.chars;
+       char [] lpKeyName1 = lpKeyName == null ? null : lpKeyName.chars;
+       char [] lpDefault1 = lpDefault == null ? null : lpDefault.chars;
+       char [] lpReturnedString1 = lpReturnedString == null ? null : lpReturnedString.chars;
+       return GetProfileString (lpAppName1, lpKeyName1, lpDefault1, lpReturnedString1, nSize);
+}
+
+public static final int GetWindowText (long hWnd, TCHAR lpString, int nMaxCount) {
+       char [] lpString1 = lpString == null ? null : lpString.chars;
+       return GetWindowText (hWnd, lpString1, nMaxCount);
+}
+
+public static final int GlobalAddAtom (TCHAR lpString) {
+       char [] lpString1 = lpString == null ? null : lpString.chars;
+       return GlobalAddAtom (lpString1);
+}
+
+public static final long ImmEscape (long hKL,long hIMC, int uEscape, TCHAR lpData) {
+       char [] lpData1 = lpData == null ? null : lpData.chars;
+       return ImmEscape (hKL, hIMC, uEscape, lpData1);
+}
+
+public static final boolean InternetGetCookie (TCHAR lpszUrl, TCHAR lpszCookieName, TCHAR lpszCookieData, int[] lpdwSize) {
+       char [] url = lpszUrl == null ? null : lpszUrl.chars;
+       char [] cookieName = lpszCookieName == null ? null : lpszCookieName.chars;
+       char [] cookieData = lpszCookieData == null ? null : lpszCookieData.chars;
+       return InternetGetCookie (url, cookieName, cookieData, lpdwSize);
+}
+
+public static final boolean InternetSetCookie (TCHAR lpszUrl, TCHAR lpszCookieName, TCHAR lpszCookieData) {
+       char [] url = lpszUrl == null ? null : lpszUrl.chars;
+       char [] cookieName = lpszCookieName == null ? null : lpszCookieName.chars;
+       char [] cookieData = lpszCookieData == null ? null : lpszCookieData.chars;
+       return InternetSetCookie (url, cookieName, cookieData);
+}
+
+public static final int MessageBox (long hWnd, TCHAR lpText, TCHAR lpCaption, int uType) {
+       char [] lpText1 = lpText == null ? null : lpText.chars;
+       char [] lpCaption1 = lpCaption == null ? null : lpCaption.chars;
+       return MessageBox (hWnd, lpText1, lpCaption1, uType);
+}
+
+public static final void MoveMemory (long Destination, TCHAR Source, int Length) {
+       char [] Source1 = Source == null ? null : Source.chars;
+       MoveMemory (Destination, Source1, Length);
+}
+
+public static final void MoveMemory (TCHAR Destination, long Source, int Length) {
+       char [] Destination1 = Destination == null ? null : Destination.chars;
+       MoveMemory (Destination1, Source, Length);
+}
+
+public static final boolean OpenPrinter (TCHAR pPrinterName, long [] phPrinter, long pDefault) {
+       char [] pPrinterName1 = pPrinterName == null ? null : pPrinterName.chars;
+       return OpenPrinter (pPrinterName1, phPrinter, pDefault);
+}
+
+public static final int readRegistryDword(int hkeyLocation, String key, String valueName) throws Exception {
+       if (key == null || valueName == null) throw new Exception("Registry key/valueName is null.");
+       long [] phkResult = new long [1];
+       TCHAR regKey = new TCHAR (0, key, true);
+       TCHAR lpValueName = new TCHAR (0, valueName, true);
+       if (OS.RegOpenKeyEx(hkeyLocation, regKey, 0, OS.KEY_READ, phkResult) == 0) {
+               int[] lpcbData = new int[] { 4 };
+               int[] lpData = new int[1];
+               int result = OS.RegQueryValueEx(phkResult[0], lpValueName, 0, null, lpData, lpcbData);
+               OS.RegCloseKey(phkResult[0]);
+               if (result == 0) {
+                       return lpData[0];
+               }
+       }
+       throw new Exception("Registry entry not found.");
+}
+
+public static final int RegCreateKeyEx (long hKey, TCHAR lpSubKey, int Reserved, TCHAR lpClass, int dwOptions, int samDesired, long lpSecurityAttributes, long[] phkResult, long[] lpdwDisposition) {
+       char [] lpClass1 = lpClass == null ? null : lpClass.chars;
+       char [] lpSubKey1 = lpSubKey == null ? null : lpSubKey.chars;
+       return RegCreateKeyEx (hKey, lpSubKey1, Reserved, lpClass1, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
+}
+
+public static final int RegDeleteValue (long hKey, TCHAR lpValueName) {
+       char [] lpValueName1 = lpValueName == null ? null : lpValueName.chars;
+       return RegDeleteValue (hKey, lpValueName1);
+}
+
+public static final int RegEnumKeyEx (long hKey, int dwIndex, TCHAR lpName, int [] lpcName, int [] lpReserved, TCHAR lpClass, int [] lpcClass, FILETIME lpftLastWriteTime) {
+       char [] lpName1 = lpName == null ? null : lpName.chars;
+       char [] lpClass1 = lpClass == null ? null : lpClass.chars;
+       return RegEnumKeyEx (hKey, dwIndex, lpName1, lpcName, lpReserved, lpClass1, lpcClass, lpftLastWriteTime);
+}
+
+public static final int RegisterClass (TCHAR lpszClassName, WNDCLASS lpWndClass) {
+       /* Allocate a native string */
+       long hHeap = OS.GetProcessHeap ();
+       int byteCount = lpszClassName.length () * TCHAR.sizeof;
+       lpWndClass.lpszClassName = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (lpWndClass.lpszClassName, lpszClassName, byteCount);
+
+       int result = RegisterClass (lpWndClass);
+
+       /* Release and forget native string */
+       OS.HeapFree (hHeap, 0, lpWndClass.lpszClassName);
+       lpWndClass.lpszClassName = 0;
+
+       return result;
+}
+
+public static final int RegisterClipboardFormat (TCHAR lpszFormat) {
+       char [] lpszFormat1 = lpszFormat == null ? null : lpszFormat.chars;
+       return RegisterClipboardFormat (lpszFormat1);
+}
+
+public static final int RegisterWindowMessage (TCHAR lpString) {
+       char [] lpString1 = lpString == null ? null : lpString.chars;
+       return RegisterWindowMessage (lpString1);
+}
+
+public static final int RegOpenKeyEx (long hKey, TCHAR lpSubKey, int ulOptions, int samDesired, long[] phkResult) {
+       char [] lpSubKey1 = lpSubKey == null ? null : lpSubKey.chars;
+       return RegOpenKeyEx (hKey, lpSubKey1, ulOptions, samDesired, phkResult);
+}
+
+public static final int RegQueryValueEx (long hKey, TCHAR lpValueName, long lpReserved, int[] lpType, TCHAR lpData, int[] lpcbData) {
+       char [] lpValueName1 = lpValueName == null ? null : lpValueName.chars;
+       char [] lpData1 = lpData == null ? null : lpData.chars;
+       return RegQueryValueEx (hKey, lpValueName1, lpReserved, lpType, lpData1, lpcbData);
+}
+
+public static final int RegQueryValueEx (long hKey, TCHAR lpValueName, long lpReserved, int[] lpType, int [] lpData, int[] lpcbData) {
+       char [] lpValueName1 = lpValueName == null ? null : lpValueName.chars;
+       return RegQueryValueEx (hKey, lpValueName1, lpReserved, lpType, lpData, lpcbData);
+}
+
+public static final int RegSetValueEx (long hKey, TCHAR lpValueName, int Reserved, int dwType, int[] lpData, int cbData) {
+       char [] lpValueName1 = lpValueName == null ? null : lpValueName.chars;
+       return RegSetValueEx (hKey, lpValueName1, Reserved, dwType, lpData, cbData);
+}
+
+public static final long SendMessage (long hWnd, int Msg, long wParam, TCHAR lParam) {
+       char [] lParam1 = lParam == null ? null : lParam.chars;
+       return SendMessage (hWnd, Msg, wParam, lParam1);
+}
+
+public static final boolean SetDllDirectory (TCHAR lpPathName) {
+       char [] lpPathName1 = lpPathName == null ? null : lpPathName.chars;
+       return SetDllDirectory (lpPathName1);
+}
+
+public static final boolean SetWindowText (long hWnd, TCHAR lpString) {
+       char [] lpString1 = lpString == null ? null : lpString.chars;
+       return SetWindowText (hWnd, lpString1);
+}
+
+public static final boolean SHGetPathFromIDList (long pidl, TCHAR pszPath) {
+       char [] pszPath1 = pszPath == null ? null : pszPath.chars;
+       return SHGetPathFromIDList (pidl, pszPath1);
+}
+
+public static final boolean UnregisterClass (TCHAR lpClassName, long hInstance) {
+       char [] lpClassName1 = lpClassName == null ? null : lpClassName.chars;
+       return UnregisterClass (lpClassName1, hInstance);
+}
+
+public static final int UrlCreateFromPath (TCHAR pszPath, TCHAR pszURL, int[] pcchUrl, int flags) {
+       char [] path = pszPath == null ? null : pszPath.chars;
+       char [] url = pszURL == null ? null : pszURL.chars;
+       return UrlCreateFromPath (path, url, pcchUrl, flags);
+}
+
+/** Natives */
+
+/** @param hdc cast=(HDC) */
+public static final native int AbortDoc (long hdc);
+/**
+ * @param hActCtx cast=(HANDLE)
+ * @param lpCookie cast=(ULONG_PTR*)
+ */
+public static final native boolean ActivateActCtx (long hActCtx, long [] lpCookie);
+/** @param hkl cast=(HKL) */
+public static final native long ActivateKeyboardLayout(long hkl, int Flags);
+/** @param pdv cast=(PVOID) */
+public static final native int AddFontResourceEx(char[] lpszFilename, int fl, long pdv);
+public static final native boolean AdjustWindowRectEx (RECT lpRect, int dwStyle, boolean bMenu, int dwExStyle);
+public static final native boolean AllowSetForegroundWindow (int dwProcessId);
+/**
+ * @param hdcDest cast=(HDC)
+ * @param hdcSrc cast=(HDC)
+ * @param blendFunction flags=struct
+ */
+public static final native boolean AlphaBlend(long hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, long hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction);
+/** @param hdc cast=(HDC) */
+public static final native boolean Arc (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nXStartArc, int nYStartArc, int nXEndArc, int nYEndArc);
+public static final native int AssocQueryString (int flags, int str, char[] pszAssoc, char[] pszExtra, char[] pszOut, int[] pcchOut);
+/**
+ * @param hdcTarget cast=(HDC)
+ * @param phdc cast=(HDC*)
+ */
+public static final native long BeginBufferedPaint (long hdcTarget, RECT prcTarget, int dwFormat, BP_PAINTPARAMS pPaintParams, long [] phdc);
+public static final native long BeginDeferWindowPos (int nNumWindows);
+/** @param hWnd cast=(HWND) */
+public static final native long BeginPaint (long hWnd, PAINTSTRUCT lpPaint);
+/** @param hdc cast=(HDC) */
+public static final native boolean BeginPath(long hdc);
+/**
+ * @param hdcDest cast=(HDC)
+ * @param hdcSrc cast=(HDC)
+ */
+public static final native boolean BitBlt (long hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, long hdcSrc, int nXSrc, int nYSrc, int dwRop);
+/** @param hWnd cast=(HWND) */
+public static final native boolean BringWindowToTop (long hWnd);
+public static final native int BufferedPaintInit ();
+public static final native int BufferedPaintUnInit ();
+/**
+ * @param hhk cast=(HHOOK)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long CallNextHookEx(long hhk, int nCode, long wParam, long lParam);
+/**
+ * @param lpPrevWndFunc cast=(WNDPROC)
+ * @param hWnd cast=(HWND)
+ */
+public static final native long CallWindowProc (long lpPrevWndFunc, long hWnd, int Msg, long wParam, long lParam);
+/**
+ * @param pName cast=(PCERT_NAME_BLOB)
+ * @param psz cast=(LPWSTR)
+ */
+public static final native int CertNameToStr (int dwCertEncodingType, CERT_NAME_BLOB pName, int dwStrType, char[] psz, int csz);
+/** @param ch cast=(LPWSTR) */
+public static final native long CharLower (long ch);
+/** @param ch cast=(LPWSTR) */
+public static final native long CharUpper (long ch);
+/**
+ * @param hWndParent cast=(HWND)
+ * @param pt flags=struct
+ * @param flags cast=(UINT)
+ */
+public static final native long ChildWindowFromPointEx (long hWndParent, POINT pt, int flags);
+/** @param lpcc cast=(LPCHOOSECOLORW) */
+public static final native boolean ChooseColor (CHOOSECOLOR lpcc);
+/** @param chooseFont cast=(LPCHOOSEFONTW) */
+public static final native boolean ChooseFont (CHOOSEFONT chooseFont);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ClientToScreen (long hWnd, POINT lpPoint);
+public static final native boolean CloseClipboard ();
+/** @param hdc cast=(HDC) */
+public static final native long CloseEnhMetaFile (long hdc);
+/**
+ * @method flags=dynamic
+ * @param hGesture cast=(HGESTUREINFO)
+ */
+public static final native long CloseGestureInfoHandle (long hGesture);
+/** @param hObject cast=(HANDLE) */
+public static final native boolean CloseHandle (long hObject);
+/** @param hPrinter cast=(HANDLE) */
+public static final native boolean ClosePrinter (long hPrinter);
+/** @param hTheme cast=(HTHEME) */
+public static final native int CloseThemeData (long hTheme);
+/**
+ * @method flags=dynamic
+ * @param hTouchInput cast=(HTOUCHINPUT)
+ */
+public static final native boolean CloseTouchInputHandle(long hTouchInput);
+/**
+ * @param rclsid cast=(REFCLSID)
+ * @param pUnkOuter cast=(LPUNKNOWN)
+ * @param riid cast=(REFIID)
+ * @param ppv cast=(LPVOID *)
+ */
+public static final native int CoCreateInstance (byte[] rclsid, long pUnkOuter, int dwClsContext, byte[] riid, long[] ppv);
+public static final native int CoInternetIsFeatureEnabled (int FeatureEntry, int dwFlags);
+/** @param fEnable cast=(BOOL) */
+public static final native int CoInternetSetFeatureEnabled (int FeatureEntry, int dwFlags, boolean fEnable);
+/**
+ * @param hrgnDest cast=(HRGN)
+ * @param hrgnSrc1 cast=(HRGN)
+ * @param hrgnSrc2 cast=(HRGN)
+ */
+public static final native int CombineRgn (long hrgnDest, long hrgnSrc1, long hrgnSrc2, int fnCombineMode);
+public static final native int CommDlgExtendedError ();
+/** @param hImage cast=(HANDLE) */
+public static final native long CopyImage (long hImage, int uType, int cxDesired, int cyDesired, int fuFlags);
+/** @param cb cast=(ULONG) */
+public static final native long CoTaskMemAlloc(int cb);
+/** @param pv cast=(LPVOID) */
+public static final native void CoTaskMemFree(long pv);
+/** @param lpaccl cast=(LPACCEL) */
+public static final native long CreateAcceleratorTable (byte [] lpaccl, int cEntries);
+/** @param pActCtx flags=no_out */
+public static final native long CreateActCtx (ACTCTX pActCtx);
+/** @param lpvBits cast=(CONST VOID *),flags=no_out critical */
+public static final native long CreateBitmap (int nWidth, int nHeight, int cPlanes, int cBitsPerPel, byte [] lpvBits);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hBitmap cast=(HBITMAP)
+ */
+public static final native boolean CreateCaret (long hWnd, long hBitmap, int nWidth, int nHeight);
+/** @param hdc cast=(HDC) */
+public static final native long CreateCompatibleBitmap (long hdc, int nWidth, int nHeight);
+/** @param hdc cast=(HDC) */
+public static final native long CreateCompatibleDC (long hdc);
+/**
+ * @param hInst cast=(HINSTANCE)
+ * @param pvANDPlane cast=(CONST VOID *),flags=no_out critical
+ * @param pvXORPlane cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native long CreateCursor (long hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte [] pvANDPlane, byte [] pvXORPlane);
+/**
+ * @param lpszDriver cast=(LPWSTR)
+ * @param lpszDevice cast=(LPWSTR)
+ * @param lpszOutput cast=(LPWSTR)
+ * @param lpInitData cast=(CONST DEVMODEW *)
+ */
+public static final native long CreateDC (char [] lpszDriver, char [] lpszDevice, long lpszOutput, long lpInitData);
+/**
+ * @param hdc cast=(HDC)
+ * @param pbmi cast=(BITMAPINFO *),flags=no_out critical
+ * @param ppvBits cast=(VOID **),flags=no_in critical
+ * @param hSection cast=(HANDLE)
+ */
+public static final native long CreateDIBSection(long hdc, byte[] pbmi, int iUsage, long[] ppvBits, long hSection, int dwOffset);
+/**
+ * @param hdc cast=(HDC)
+ * @param pbmi cast=(BITMAPINFO *),flags=no_out critical
+ * @param ppvBits cast=(VOID **),flags=no_in critical
+ * @param hSection cast=(HANDLE)
+ */
+public static final native long CreateDIBSection(long hdc, long pbmi, int iUsage, long[] ppvBits, long hSection, int dwOffset);
+/**
+ * @param hdcRef cast=(HDC)
+ * @param lpFilename cast=(LPCWSTR)
+ * @param lpDescription cast=(LPCWSTR)
+ */
+public static final native long CreateEnhMetaFile (long hdcRef, char[] lpFilename, RECT lpRect, char[] lpDescription);
+/** @param lplf cast=(LPLOGFONTW) */
+public static final native long CreateFontIndirect (long lplf);
+/** @param lplf flags=no_out */
+public static final native long CreateFontIndirect (LOGFONT lplf);
+/** @param lplf flags=no_out */
+public static final native long CreateIconIndirect (ICONINFO lplf);
+public static final native long CreateMenu ();
+/** @param hbmp cast=(HBITMAP) */
+public static final native long CreatePatternBrush (long hbmp);
+/** @param crColor cast=(COLORREF) */
+public static final native long CreatePen (int fnPenStyle, int nWidth, int crColor);
+/** @param lppt cast=(CONST POINT *) */
+public static final native long CreatePolygonRgn(int[] lppt, int cPoints, int fnPolyFillMode);
+public static final native long CreatePopupMenu ();
+/**
+ * @param lpApplicationName cast=(LPCWSTR)
+ * @param lpCommandLine cast=(LPWSTR)
+ * @param lpProcessAttributes cast=(LPSECURITY_ATTRIBUTES)
+ * @param lpThreadAttributes cast=(LPSECURITY_ATTRIBUTES)
+ * @param lpEnvironment cast=(LPVOID)
+ * @param lpCurrentDirectory cast=(LPWSTR)
+ * @param lpStartupInfo cast=(LPSTARTUPINFOW)
+ * @param lpProcessInformation cast=(LPPROCESS_INFORMATION)
+ */
+public static final native boolean CreateProcess (long lpApplicationName, long lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, boolean bInheritHandles, int dwCreationFlags, long lpEnvironment, long lpCurrentDirectory, STARTUPINFO lpStartupInfo, PROCESS_INFORMATION lpProcessInformation);
+public static final native long CreateRectRgn (int left, int top, int right, int bottom);
+/** @param colorRef cast=(COLORREF) */
+public static final native long CreateSolidBrush (int colorRef);
+/**
+ * @param hGlobal cast=(HGLOBAL)
+ * @param fDeleteOnRelease cast=(BOOL)
+ * @param ppstm cast=(LPSTREAM *)
+ */
+public static final native int CreateStreamOnHGlobal(long hGlobal, boolean fDeleteOnRelease, long[] ppstm);
+/**
+ * @param lpClassName cast=(LPWSTR)
+ * @param lpWindowName cast=(LPWSTR)
+ * @param hWndParent cast=(HWND)
+ * @param hMenu cast=(HMENU)
+ * @param hInstance cast=(HINSTANCE)
+ */
+public static final native long CreateWindowEx (int dwExStyle, char [] lpClassName, char [] lpWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, long hWndParent, long hMenu, long hInstance, CREATESTRUCT lpParam);
+/**
+ * @param hWinPosInfo cast=(HDWP)
+ * @param hWnd cast=(HWND)
+ * @param hWndInsertAfter cast=(HWND)
+ */
+public static final native long DeferWindowPos (long hWinPosInfo, long hWnd, long hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long DefMDIChildProc (long hWnd, int Msg, long wParam, long lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hWndMDIClient cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long DefFrameProc (long hWnd, long hWndMDIClient, int Msg, long wParam, long lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long DefWindowProc (long hWnd, int Msg, long wParam, long lParam);
+/** @param hdc cast=(HDC) */
+public static final native boolean DeleteDC (long hdc);
+/** @param hemf cast=(HENHMETAFILE) */
+public static final native boolean DeleteEnhMetaFile (long hemf);
+/** @param hMenu cast=(HMENU) */
+public static final native boolean DeleteMenu (long hMenu, int uPosition, int uFlags);
+/** @param hGdiObj cast=(HGDIOBJ) */
+public static final native boolean DeleteObject (long hGdiObj);
+/** @param hAccel cast=(HACCEL) */
+public static final native boolean DestroyAcceleratorTable (long hAccel);
+public static final native boolean DestroyCaret ();
+/** @param hCursor cast=(HCURSOR) */
+public static final native boolean DestroyCursor (long hCursor);
+/** @param hIcon cast=(HICON) */
+public static final native boolean DestroyIcon (long hIcon);
+/** @param hMenu cast=(HMENU) */
+public static final native boolean DestroyMenu (long hMenu);
+/** @param hWnd cast=(HWND) */
+public static final native boolean DestroyWindow (long hWnd);
+public static final native long DispatchMessage (MSG lpmsg);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hPrinter cast=(HANDLE)
+ * @param pDeviceName cast=(LPWSTR)
+ * @param pDevModeOutput cast=(PDEVMODEW)
+ * @param pDevModeInput cast=(PDEVMODEW)
+ */
+public static final native int DocumentProperties (long hWnd, long hPrinter, char[] pDeviceName, long pDevModeOutput, long pDevModeInput, int fMode);
+/**
+ * @param hwnd cast=(HWND)
+ * @param pt flags=struct
+ */
+public static final native boolean DragDetect (long hwnd, POINT pt);
+/** @param hDrop cast=(HDROP) */
+public static final native void DragFinish (long hDrop);
+/**
+ * @param hDrop cast=(HDROP)
+ * @param lpszFile cast=(LPWSTR)
+ */
+public static final native int DragQueryFile (long hDrop, int iFile, char[] lpszFile, int cch);
+/** @param hdc cast=(HDC) */
+public static final native boolean DrawEdge (long hdc, RECT qrc, int edge, int grfFlags);
+/** @param hDC cast=(HDC) */
+public static final native boolean DrawFocusRect (long hDC, RECT lpRect);
+/** @param hdc cast=(HDC) */
+public static final native boolean DrawFrameControl (long hdc, RECT lprc, int uType, int uState);
+/**
+ * @param hdc cast=(HDC)
+ * @param hIcon cast=(HICON)
+ * @param hbrFlickerFreeDraw cast=(HBRUSH)
+ */
+public static final native boolean DrawIconEx (long hdc, int xLeft, int yTop, long hIcon, int cxWidth, int cyWidth, int istepIfAniCur, long hbrFlickerFreeDraw, int diFlags);
+/** @param hWnd cast=(HWND) */
+public static final native boolean DrawMenuBar (long hWnd);
+/**
+ * @param hDC cast=(HDC)
+ * @param lpString cast=(LPWSTR),flags=no_out critical
+ */
+public static final native int DrawText (long hDC, char [] lpString, int nCount, RECT lpRect, int uFormat);
+/**
+ * @param hTheme cast=(HTHEME)
+ * @param hdc cast=(HDC)
+ * @param pRect cast=(const RECT *)
+ * @param pClipRect cast=(const RECT *)
+ */
+public static final native int DrawThemeBackground (long hTheme, long hdc, int iPartId, int iStateId, RECT pRect, RECT pClipRect);
+/**
+ * @param hTheme cast=(HTHEME)
+ * @param hdc cast=(HDC)
+ */
+public static final native int DrawThemeText (long hTheme, long hdc, int iPartId, int iStateId, char[] pszText, int iCharCount, int dwTextFlags, int dwTextFlags2, RECT pRect);
+/** @param hdc cast=(HDC) */
+public static final native boolean Ellipse (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
+/** @param hMenu cast=(HMENU) */
+public static final native boolean EnableMenuItem (long hMenu, int uIDEnableItem, int uEnable);
+/** @param hWnd cast=(HWND) */
+public static final native boolean EnableScrollBar (long hWnd, int wSBflags, int wArrows);
+/** @param hWnd cast=(HWND) */
+public static final native boolean EnableWindow (long hWnd, boolean bEnable);
+/**
+ * @param pLangGroupEnumProc cast=(LANGUAGEGROUP_ENUMPROCW)
+ * @param lParam cast=(LONG_PTR)
+ */
+public static final native boolean EnumSystemLanguageGroups (long pLangGroupEnumProc, int dwFlags, long lParam);
+/** @param lpLocaleEnumProc cast=(LOCALE_ENUMPROCW) */
+public static final native boolean EnumSystemLocales (long lpLocaleEnumProc, int dwFlags);
+/** @param hWinPosInfo cast=(HDWP) */
+public static final native boolean EndDeferWindowPos (long hWinPosInfo);
+/** @param hBufferedPaint cast=(HPAINTBUFFER) */
+public static final native int EndBufferedPaint (long hBufferedPaint, boolean fUpdateTarget);
+/** @param hdc cast=(HDC) */
+public static final native int EndDoc (long hdc);
+/** @param hdc cast=(HDC) */
+public static final native int EndPage (long hdc);
+/** @param hWnd cast=(HWND) */
+public static final native int EndPaint (long hWnd, PAINTSTRUCT lpPaint);
+/**
+ * @param hdc cast=(HDC)
+ * @param lprcClip cast=(LPCRECT)
+ * @param lpfnEnum cast=(MONITORENUMPROC)
+ * @param dwData cast=(LPARAM)
+ */
+public static final native boolean EnumDisplayMonitors (long hdc, RECT lprcClip, long lpfnEnum, int dwData);
+/**
+ * @param hdc cast=(HDC)
+ * @param hemf cast=(HENHMETAFILE)
+ * @param lpEnhMetaFunc cast=(ENHMFENUMPROC)
+ * @param lpData cast=(LPVOID)
+ */
+public static final native boolean EnumEnhMetaFile(long hdc, long hemf, long lpEnhMetaFunc, long lpData, RECT lpRect);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpszFamily cast=(LPCWSTR)
+ * @param lpEnumFontFamProc cast=(FONTENUMPROCW)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native int EnumFontFamilies (long hdc, char [] lpszFamily, long lpEnumFontFamProc, long lParam);
+/**
+ * @param lprc1 cast=(CONST RECT *),flags=no_out
+ * @param lprc2 cast=(CONST RECT *),flags=no_out
+ */
+public static final native boolean EqualRect (RECT lprc1, RECT lprc2);
+/** @param hdc cast=(HDC) */
+public static final native int ExcludeClipRect (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
+public static final native int ExpandEnvironmentStrings (char [] lpSrc, char [] lsDst, int nSize);
+/**
+ * @param lplb cast=(CONST LOGBRUSH *)
+ * @param lpStyle cast=(CONST DWORD *)
+ */
+public static final native long ExtCreatePen (int dwPenStyle, int dwWidth, LOGBRUSH lplb, int dwStyleCount, int[] lpStyle);
+/**
+ * @param lpXform cast=(XFORM *)
+ * @param lpRgnData cast=(CONST RGNDATA *)
+ */
+public static final native long ExtCreateRegion (float[] lpXform, int nCount, int[] lpRgnData);
+/**
+ * @param hdc cast=(HDC)
+ * @param lprc flags=no_out
+ * @param lpString cast=(LPWSTR),flags=no_out critical
+ * @param lpDx cast=(CONST INT *),flags=no_out critical
+ */
+public static final native boolean ExtTextOut (long hdc, int X, int Y, int fuOptions, RECT lprc, char[] lpString, int cbCount, int[] lpDx);
+/**
+ * @param lpszFile cast=(LPWSTR)
+ * @param phiconLarge cast=(HICON FAR *)
+ * @param phiconSmall cast=(HICON FAR *)
+ */
+public static final native int ExtractIconEx (char [] lpszFile, int nIconIndex, long [] phiconLarge, long [] phiconSmall, int nIcons);
+public static final native boolean FileTimeToSystemTime (FILETIME lpFileTime, SYSTEMTIME lpSystemTime);
+/**
+ * @param hDC cast=(HDC)
+ * @param lprc flags=no_out
+ * @param hbr cast=(HBRUSH)
+ */
+public static final native int FillRect (long hDC, RECT lprc, long hbr);
+/**
+ * @param lpSource cast=(LPCVOID)
+ * @param lpBuffer cast=(LPWSTR)
+ * @param Arguments cast=(va_list*)
+ */
+public static final native int FormatMessage (int dwFlags, long lpSource, int dwMessageId, int dwLanguageId, long [] lpBuffer, int nSize, long Arguments);
+/** @param dwLimit cast=(DWORD) */
+public static final native int GdiSetBatchLimit (int dwLimit);
+public static final native int GET_WHEEL_DELTA_WPARAM(long wParam);
+public static final native int GET_X_LPARAM(long lp);
+public static final native int GET_Y_LPARAM(long lp);
+public static final native int GetACP ();
+public static final native long GetActiveWindow ();
+/** @param hDC cast=(HDC) */
+public static final native int GetBkColor (long hDC);
+public static final native long GetCapture ();
+public static final native boolean GetCaretPos (POINT lpPoint);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpabc cast=(LPABC),flags=no_in critical
+ */
+public static final native boolean GetCharABCWidths (long hdc, int iFirstChar, int iLastChar, int [] lpabc);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpString cast=(LPWSTR),flags=no_out critical
+ * @param lpResults cast=(LPGCP_RESULTSW)
+ */
+public static final native int GetCharacterPlacement (long hdc, char[] lpString, int nCount, int nMaxExtent, GCP_RESULTS lpResults, int dwFlags);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpBuffer cast=(LPINT),flags=no_in critical
+ */
+public static final native boolean GetCharWidth (long hdc, int iFirstChar, int iLastChar, int [] lpBuffer);
+/**
+ * @param hInstance cast=(HINSTANCE)
+ * @param lpClassName cast=(LPWSTR)
+ * @param lpWndClass cast=(LPWNDCLASSW)
+ */
+public static final native boolean GetClassInfo (long hInstance, char [] lpClassName, WNDCLASS lpWndClass);
+/** @param hWnd cast=(HWND) */
+public static final native int GetClassName (long hWnd, char [] lpClassName, int nMaxCount);
+/** @param hWnd cast=(HWND) */
+public static final native boolean GetClientRect (long hWnd, RECT lpRect);
+public static final native long GetClipboardData (int uFormat);
+/** @param lpszFormatName cast=(LPWSTR) */
+public static final native int GetClipboardFormatName (int format, char[] lpszFormatName, int cchMaxCount);
+/** @param hdc cast=(HDC) */
+public static final native int GetClipBox (long hdc, RECT lprc);
+/**
+ * @param hdc cast=(HDC)
+ * @param hrgn cast=(HRGN)
+ */
+public static final native int GetClipRgn (long hdc, long hrgn);
+/** @param hwndCombo cast=(HWND) */
+public static final native boolean GetComboBoxInfo (long hwndCombo, COMBOBOXINFO pcbi);
+/** @param hdc cast=(HDC) */
+public static final native long GetCurrentObject (long hdc, int uObjectType);
+public static final native int GetCurrentProcessId ();
+public static final native int GetCurrentThreadId ();
+/** @method flags=dynamic */
+public static final native int GetCurrentProcessExplicitAppUserModelID(long[] AppID);
+public static final native long GetCursor ();
+public static final native boolean GetCursorPos (POINT lpPoint);
+/** @param hwnd cast=(HWND) */
+public static final native long GetDC (long hwnd);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hrgnClip cast=(HRGN)
+ */
+public static final native long GetDCEx (long hWnd, long hrgnClip, int flags);
+public static final native long GetDesktopWindow ();
+/** @param hdc cast=(HDC) */
+public static final native int GetDeviceCaps (long hdc, int nIndex);
+public static final native int GetDialogBaseUnits ();
+/**
+ * @param hdc cast=(HDC)
+ * @param pColors cast=(RGBQUAD *),flags=no_in critical
+ */
+public static final native int GetDIBColorTable (long hdc, int uStartIndex, int cEntries, byte[] pColors);
+/**
+ * @param hdc cast=(HDC)
+ * @param hbmp cast=(HBITMAP)
+ * @param lpvBits cast=(LPVOID),flags=critical
+ * @param lpbi cast=(LPBITMAPINFO),flags=critical
+ */
+public static final native int GetDIBits (long hdc, long hbmp, int uStartScan, int cScanLines, byte[] lpvBits, byte[] lpbi, int uUsage);
+/** @param hDlg cast=(HWND) */
+public static final native long GetDlgItem (long hDlg, int nIDDlgItem);
+public static final native int GetDoubleClickTime ();
+/** @method flags=dynamic */
+public static final native int GetDpiForMonitor (long hmonitor, int dpiType, int [] dpiX, int [] dpiY);
+public static final native long GetFocus ();
+/** @param hdc cast=(HDC) */
+public static final native int GetFontLanguageInfo (long hdc);
+public static final native long GetForegroundWindow ();
+/**
+ * @method flags=dynamic
+ * @param hGestureInfo cast=(HGESTUREINFO)
+ * @param pGestureInfo cast=(PGESTUREINFO)
+ */
+public static final native boolean GetGestureInfo(long hGestureInfo, GESTUREINFO pGestureInfo);
+/** @param hdc cast=(HDC) */
+public static final native int GetGraphicsMode (long hdc);
+/**
+ * @param hdc cast=(HDC)
+ * @param pgi cast=(LPWORD)
+ */
+public static final native int GetGlyphIndices (long hdc, char[] lpstr, int c, short[] pgi, int fl);
+/**
+ * @param idThread cast=(DWORD)
+ * @param lpgui cast=(LPGUITHREADINFO)
+ */
+public static final native boolean GetGUIThreadInfo (int idThread, GUITHREADINFO lpgui);
+/**
+ * @param hIcon cast=(HICON)
+ * @param piconinfo flags=no_in
+ */
+public static final native boolean GetIconInfo (long hIcon, ICONINFO piconinfo);
+/** @param lpList cast=(HKL FAR *) */
+public static final native int GetKeyboardLayoutList (int nBuff, long [] lpList);
+public static final native long GetKeyboardLayout (int idThread);
+public static final native short GetKeyState (int nVirtKey);
+/** @param lpKeyState cast=(PBYTE) */
+public static final native boolean GetKeyboardState (byte [] lpKeyState);
+/** @param hWnd cast=(HWND) */
+public static final native long GetLastActivePopup (long hWnd);
+public static final native int GetLastError ();
+/** @param hwnd cast=(HWND) */
+public static final native boolean GetLayeredWindowAttributes (long hwnd, int [] pcrKey, byte [] pbAlpha, int [] pdwFlags);
+/** @param hdc cast=(HDC) */
+public static final native int GetLayout (long hdc);
+/* returns the instance handle to the swt library */
+/** @method flags=no_gen */
+public static final native long GetLibraryHandle ();
+/** @param lpLCData cast=(LPWSTR) */
+public static final native int GetLocaleInfo (int Locale, int LCType, char [] lpLCData, int cchData);
+/** @param hWnd cast=(HWND) */
+public static final native long GetMenu (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean GetMenuBarInfo (long hWnd, int idObject, int idItem, MENUBARINFO pmbi);
+/** @param hMenu cast=(HMENU) */
+public static final native int GetMenuDefaultItem (long hMenu, int fByPos, int gmdiFlags);
+/** @param hmenu cast=(HMENU) */
+public static final native boolean GetMenuInfo (long hmenu, MENUINFO lpcmi);
+/** @param hMenu cast=(HMENU) */
+public static final native int GetMenuItemCount (long hMenu);
+/**
+ * @param hMenu cast=(HMENU)
+ * @param lpmii cast=(LPMENUITEMINFOW)
+ */
+public static final native boolean GetMenuItemInfo (long hMenu, int uItem, boolean fByPosition, MENUITEMINFO lpmii);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hMenu cast=(HMENU)
+ */
+public static final native boolean GetMenuItemRect (long hWnd, long hMenu, int uItem, RECT lprcItem);
+/** @param hWnd cast=(HWND) */
+public static final native boolean GetMessage (MSG lpMsg, long hWnd, int wMsgFilterMin, int wMsgFilterMax);
+public static final native int GetMessagePos ();
+public static final native int GetMessageTime ();
+/**
+ * @param hdc cast=(HDC)
+ * @param hrgn cast=(HRGN)
+ */
+public static final native int GetMetaRgn (long hdc, long hrgn);
+/**
+ * @param hTheme cast=(HTHEME)
+ * @param hdc cast=(HDC)
+ * @param prc flags=no_out
+ * @param psz flags=no_in
+ */
+public static final native int GetThemePartSize(long hTheme, long hdc, int iPartId, int iStateId, RECT prc, int eSize, SIZE psz);
+/**
+ * @param hTheme cast=(HTHEME)
+ * @param hdc cast=(HDC)
+ */
+public static final native int GetThemeTextExtent (long hTheme, long hdc, int iPartId, int iStateId, char[] pszText, int iCharCount, int dwTextFlags, RECT pBoundingRect, RECT pExtentRect);
+/**
+ * @param hModule cast=(HMODULE)
+ * @param lpFilename cast=(LPWSTR)
+ */
+public static final native int GetModuleFileName (long hModule, char [] lpFilename, int inSize);
+/** @param lpModuleName cast=(LPWSTR) */
+public static final native long GetModuleHandle (char [] lpModuleName);
+/**
+ * @param hmonitor cast=(HMONITOR)
+ * @param lpmi cast=(LPMONITORINFO)
+ */
+public static final native boolean GetMonitorInfo (long hmonitor, MONITORINFO lpmi);
+/**
+ * @param hgdiobj cast=(HGDIOBJ)
+ * @param lpvObject flags=no_in
+ */
+public static final native int GetObject (long hgdiobj, int cbBuffer, BITMAP lpvObject);
+/**
+ * @param hgdiobj cast=(HGDIOBJ)
+ * @param lpvObject flags=no_in
+ */
+public static final native int GetObject (long hgdiobj, int cbBuffer, DIBSECTION lpvObject);
+/**
+ * @param hgdiobj cast=(HGDIOBJ)
+ * @param lpvObject flags=no_in
+ */
+public static final native int GetObject (long hgdiobj, int cbBuffer, LOGBRUSH lpvObject);
+/**
+ * @param hgdiobj cast=(HGDIOBJ)
+ * @param lpvObject flags=no_in
+ */
+public static final native int GetObject (long hgdiobj, int cbBuffer, LOGFONT lpvObject);
+/**
+ * @param hgdiobj cast=(HGDIOBJ)
+ * @param lpvObject cast=(LPVOID),flags=no_in
+ */
+public static final native int GetObject (long hgdiobj, int cbBuffer, long lpvObject);
+/** @param lpofn cast=(LPOPENFILENAMEW) */
+public static final native boolean GetOpenFileName (OPENFILENAME lpofn);
+/** @param hdc cast=(HDC) */
+public static final native int GetOutlineTextMetrics (long hdc, int cbData, OUTLINETEXTMETRIC lpOTM);
+/** @param hWnd cast=(HWND) */
+public static final native long GetParent (long hWnd);
+/** @param hdc cast=(HDC) */
+public static final native int GetPixel (long hdc, int x, int y);
+/** @param hdc cast=(HDC) */
+public static final native int GetPolyFillMode (long hdc);
+/**
+ * @param pPrinterName cast=(LPWSTR)
+ * @param phPrinter cast=(LPHANDLE)
+ * @param pDefault cast=(LPPRINTER_DEFAULTSW)
+ */
+public static final native boolean OpenPrinter (char[] pPrinterName, long [] phPrinter, long pDefault);
+public static final native long GetProcessHeap ();
+/**
+ * @param lpAppName cast=(LPWSTR)
+ * @param lpKeyName cast=(LPWSTR)
+ * @param lpDefault cast=(LPWSTR)
+ * @param lpReturnedString cast=(LPWSTR)
+ */
+public static final native int GetProfileString (char [] lpAppName, char [] lpKeyName, char [] lpDefault, char [] lpReturnedString, int nSize);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpString cast=(LPCWSTR)
+ */
+public static final native long GetProp (long hWnd, long lpString);
+/**
+ * @param hdc cast=(HDC)
+ * @param hrgn cast=(HRGN)
+ */
+public static final native int GetRandomRgn (long hdc, long hrgn, int iNum);
+/**
+ * @param hRgn cast=(HRGN)
+ * @param lpRgnData cast=(RGNDATA *),flags=no_in critical
+ */
+public static final native int GetRegionData (long hRgn, int dwCount, int [] lpRgnData);
+/**
+ * @param hrgn cast=(HRGN)
+ * @param lprc flags=no_in
+ */
+public static final native int GetRgnBox (long hrgn, RECT lprc);
+/** @param hdc cast=(HDC) */
+public static final native int GetROP2 (long hdc);
+/** @param lpofn cast=(LPOPENFILENAMEW) */
+public static final native boolean GetSaveFileName (OPENFILENAME lpofn);
+/** @param hwnd cast=(HWND) */
+public static final native boolean GetScrollBarInfo (long hwnd, int idObject, SCROLLBARINFO psbi);
+/** @param hwnd cast=(HWND) */
+public static final native boolean GetScrollInfo (long hwnd, int flags, SCROLLINFO info);
+/** @param lpStartupInfo cast=(LPSTARTUPINFOW) */
+public static final native void GetStartupInfo (STARTUPINFO lpStartupInfo);
+public static final native long GetStockObject (int fnObject);
+public static final native int GetSysColor (int nIndex);
+public static final native long GetSysColorBrush (int nIndex);
+public static final native short GetSystemDefaultUILanguage ();
+/** @param hWnd cast=(HWND) */
+public static final native long GetSystemMenu (long hWnd, boolean bRevert);
+public static final native int GetSystemMetrics (int nIndex);
+/** @param hDC cast=(HDC) */
+public static final native int GetTextColor (long hDC);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpString cast=(LPWSTR),flags=no_out critical
+ * @param lpSize flags=no_in
+ */
+public static final native boolean GetTextExtentPoint32 (long hdc, char [] lpString, int cbString, SIZE lpSize);
+/**
+ * @param hdc cast=(HDC)
+ * @param lptm flags=no_in
+ */
+public static final native boolean GetTextMetrics (long hdc, TEXTMETRIC lptm);
+/**
+ * @method flags=dynamic
+ * @param hTouchInput cast=(HTOUCHINPUT)
+ * @param cInputs cast=(UINT)
+ * @param pTouchInputs cast=(PTOUCHINPUT)
+ */
+public static final native boolean GetTouchInputInfo(long hTouchInput, int cInputs, long pTouchInputs, int cbSize);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpRect cast=(LPRECT)
+ * @param bErase cast=(BOOL)
+ */
+public static final native boolean GetUpdateRect (long hWnd, RECT lpRect, boolean bErase);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hRgn cast=(HRGN)
+ */
+public static final native int GetUpdateRgn (long hWnd, long hRgn, boolean bErase);
+public static final native int GetVersion ();
+/** @param hWnd cast=(HWND) */
+public static final native long GetWindow (long hWnd, int uCmd);
+/** @param hWnd cast=(HWND) */
+public static final native int GetWindowLong (long hWnd, int nIndex);
+/** @param hWnd cast=(HWND) */
+public static final native long GetWindowLongPtr (long hWnd, int nIndex);
+/** @param hWnd cast=(HWND) */
+public static final native long GetWindowDC (long hWnd);
+/** @param hdc cast=(HDC) */
+public static final native boolean GetWindowOrgEx (long hdc, POINT lpPoint);
+/** @param hWnd cast=(HWND) */
+public static final native boolean GetWindowPlacement (long hWnd, WINDOWPLACEMENT lpwndpl);
+/** @param hWnd cast=(HWND) */
+public static final native boolean GetWindowRect (long hWnd, RECT lpRect);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hRgn cast=(HRGN)
+ */
+public static final native int GetWindowRgn (long hWnd, long hRgn);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpString cast=(LPWSTR)
+ */
+public static final native int GetWindowText (long hWnd, char [] lpString, int nMaxCount);
+/** @param hWnd cast=(HWND) */
+public static final native int GetWindowTextLength (long hWnd);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpdwProcessId cast=(LPDWORD)
+ */
+public static final native int GetWindowThreadProcessId (long hWnd, int [] lpdwProcessId);
+public static final native double GID_ROTATE_ANGLE_FROM_ARGUMENT(long dwArgument);
+/** @param lpString cast=(LPCWSTR) */
+public static final native int GlobalAddAtom (char [] lpString);
+public static final native long GlobalAlloc (int uFlags, int dwBytes);
+/** @param hMem cast=(HANDLE) */
+public static final native long GlobalFree (long hMem);
+/** @param hMem cast=(HANDLE) */
+public static final native long GlobalLock (long hMem);
+/** @param hMem cast=(HANDLE) */
+public static final native int GlobalSize (long hMem);
+/** @param hMem cast=(HANDLE) */
+public static final native boolean GlobalUnlock (long hMem);
+/**
+ * @param hdc cast=(HDC)
+ * @param pVertex cast=(PTRIVERTEX)
+ * @param dwNumVertex cast=(ULONG)
+ * @param pMesh cast=(PVOID)
+ * @param dwNumMesh cast=(ULONG)
+ * @param dwMode cast=(ULONG)
+ */
+public static final native boolean GradientFill (long hdc, long pVertex, int dwNumVertex, long pMesh, int dwNumMesh, int dwMode);
+public static final native int HIWORD(long l);
+/** @param hHeap cast=(HANDLE) */
+public static final native long HeapAlloc (long hHeap, int dwFlags, int dwBytes);
+/**
+ * @param hHeap cast=(HANDLE)
+ * @param lpMem cast=(LPVOID)
+ */
+public static final native boolean HeapFree (long hHeap, int dwFlags, long lpMem);
+/** @param hWnd cast=(HWND) */
+public static final native boolean HideCaret (long hWnd);
+/**
+ * @param lpsz cast=(LPOLESTR)
+ * @param lpiid cast=(LPIID)
+ */
+public static final native int IIDFromString (char[] lpsz, byte[] lpiid);
+/**
+ * @param pidl cast=(PCIDLIST_ABSOLUTE)
+ */
+public static final native int ILGetSize(long pidl);
+/**
+ * @param himl cast=(HIMAGELIST)
+ * @param hbmImage cast=(HBITMAP)
+ * @param hbmMask cast=(HBITMAP)
+ */
+public static final native int ImageList_Add (long himl, long hbmImage, long hbmMask);
+/**
+ * @param himl cast=(HIMAGELIST)
+ * @param hbmImage cast=(HBITMAP)
+ * @param crMask cast=(COLORREF)
+ */
+public static final native int ImageList_AddMasked (long himl, long hbmImage, int crMask);
+/** @param himl cast=(HIMAGELIST) */
+public static final native boolean ImageList_BeginDrag (long himl, int iTrack, int dxHotspot, int dyHotspot);
+public static final native long ImageList_Create (int cx, int cy, int flags, int cInitial, int cGrow);
+/** @param himl cast=(HIMAGELIST) */
+public static final native boolean ImageList_Destroy (long himl);
+/** @param hwndLock cast=(HWND) */
+public static final native boolean ImageList_DragEnter (long hwndLock, int x, int y);
+/** @param hwndLock cast=(HWND) */
+public static final native boolean ImageList_DragLeave (long hwndLock);
+public static final native boolean ImageList_DragMove (int x, int y);
+/** @param fShow cast=(BOOL) */
+public static final native boolean ImageList_DragShowNolock (boolean fShow);
+public static final native void ImageList_EndDrag ();
+/**
+ * @param himl cast=(HIMAGELIST)
+ * @param cx cast=(int *)
+ * @param cy cast=(int *)
+ */
+public static final native boolean ImageList_GetIconSize (long himl, int [] cx, int [] cy);
+/** @param himl cast=(HIMAGELIST) */
+public static final native int ImageList_GetImageCount (long himl);
+/** @param himl cast=(HIMAGELIST) */
+public static final native boolean ImageList_Remove (long himl, int i);
+/**
+ * @param himl cast=(HIMAGELIST)
+ * @param hbmImage cast=(HBITMAP)
+ * @param hbmMask cast=(HBITMAP)
+ */
+public static final native boolean ImageList_Replace (long himl, int i, long hbmImage, long hbmMask);
+/**
+ * @param himl cast=(HIMAGELIST)
+ * @param hicon cast=(HICON)
+ */
+public static final native int ImageList_ReplaceIcon (long himl, int i, long hicon);
+/** @param himl cast=(HIMAGELIST) */
+public static final native boolean ImageList_SetIconSize (long himl, int cx, int cy);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hIMC cast=(HIMC)
+ */
+public static final native long ImmAssociateContext (long hWnd, long hIMC);
+public static final native long ImmCreateContext ();
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmDestroyContext (long hIMC);
+/**
+ * @param hKL cast=(HKL)
+ * @param hIMC cast=(HIMC)
+ * @param lpData cast=(LPVOID)
+ */
+public static final native long ImmEscape (long hKL, long hIMC, int uEscape, char[] lpData);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmGetCompositionFont (long hIMC, LOGFONT lplf);
+/**
+ * @param hIMC cast=(HIMC)
+ * @param lpBuf cast=(LPWSTR)
+ */
+public static final native int ImmGetCompositionString (long hIMC, int dwIndex, char [] lpBuf, int dwBufLen);
+/**
+ * @param hIMC cast=(HIMC)
+ * @param lpBuf cast=(LPWSTR)
+ */
+public static final native int ImmGetCompositionString (long hIMC, int dwIndex, int [] lpBuf, int dwBufLen);
+/**
+ * @param hIMC cast=(HIMC)
+ * @param lpBuf cast=(LPWSTR)
+ */
+public static final native int ImmGetCompositionString (long hIMC, int dwIndex, byte [] lpBuf, int dwBufLen);
+/** @param hWnd cast=(HWND) */
+public static final native long ImmGetContext (long hWnd);
+/**
+ * @param hIMC cast=(HIMC)
+ * @param lpfdwConversion cast=(LPDWORD)
+ * @param lpfdwSentence cast=(LPDWORD)
+ */
+public static final native boolean ImmGetConversionStatus (long hIMC, int [] lpfdwConversion, int [] lpfdwSentence);
+/** @param hWnd cast=(HWND) */
+public static final native long ImmGetDefaultIMEWnd (long hWnd);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmGetOpenStatus (long hIMC);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmNotifyIME (long hIMC, int dwAction, int dwIndex, int dwValue);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hIMC cast=(HIMC)
+ */
+public static final native boolean ImmReleaseContext (long hWnd, long hIMC);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmSetCompositionFont (long hIMC, LOGFONT lplf);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmSetCompositionWindow (long hIMC, COMPOSITIONFORM lpCompForm);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmSetCandidateWindow (long hIMC, CANDIDATEFORM lpCandidate);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmSetConversionStatus (long hIMC, int fdwConversion, int dwSentence);
+/** @param hIMC cast=(HIMC) */
+public static final native boolean ImmSetOpenStatus (long hIMC, boolean fOpen);
+public static final native void InitCommonControls ();
+public static final native boolean InitCommonControlsEx (INITCOMMONCONTROLSEX lpInitCtrls);
+/**
+ * @param hMenu cast=(HMENU)
+ * @param lpmii cast=(LPMENUITEMINFOW)
+ */
+public static final native boolean InsertMenuItem (long hMenu, int uItem, boolean fByPosition, MENUITEMINFO lpmii);
+/**
+ * @param lpszUrl cast=(LPCWSTR)
+ * @param lpszCookieName cast=(LPCWSTR)
+ * @param lpszCookieData cast=(LPWSTR)
+ * @param lpdwSize cast=(LPDWORD)
+ */
+public static final native boolean InternetGetCookie (char[] lpszUrl, char[] lpszCookieName, char[] lpszCookieData, int[] lpdwSize);
+/**
+ * @param lpszUrl cast=(LPCWSTR)
+ * @param lpszCookieName cast=(LPCWSTR)
+ * @param lpszCookieData cast=(LPCWSTR)
+ */
+public static final native boolean InternetSetCookie (char[] lpszUrl, char[] lpszCookieName, char[] lpszCookieData);
+/**
+ * @param hInternet cast=(HINTERNET)
+ * @param lpBuffer cast=(LPVOID)
+ */
+public static final native boolean InternetSetOption (long hInternet, int dwOption, long lpBuffer, int dwBufferLength);
+/** @param hdc cast=(HDC) */
+public static final native int IntersectClipRect (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
+/**
+ * @param lprcDst flags=no_in
+ * @param lprcSrc1 flags=no_out
+ * @param lprcSrc2 flags=no_out
+ */
+public static final native boolean IntersectRect (RECT lprcDst, RECT lprcSrc1, RECT lprcSrc2);
+/** @param hWnd cast=(HWND) */
+public static final native boolean InvalidateRect (long hWnd, RECT lpRect, boolean bErase);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hRgn cast=(HRGN)
+ */
+public static final native boolean InvalidateRgn (long hWnd, long hRgn, boolean bErase);
+public static final native boolean IsAppThemed ();
+/** @param hWnd cast=(HWND) */
+public static final native boolean IsHungAppWindow (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean IsIconic (long hWnd);
+/**
+ * @method flags=dynamic
+ * @param hWnd cast=(HWND)
+ * @param outFlags cast=(PULONG)
+ */
+public static final native boolean IsTouchWindow (long hWnd, long[] outFlags);
+/** @param hWnd cast=(HWND) */
+public static final native boolean IsWindowEnabled (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean IsWindowVisible (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean IsZoomed (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean KillTimer (long hWnd, long uIDEvent);
+/** @param hdc cast=(HDC) */
+public static final native boolean LineTo (long hdc, int x1, int x2);
+/**
+ * @param hInstance cast=(HINSTANCE)
+ * @param lpBitmapName cast=(LPWSTR)
+ */
+public static final native long LoadBitmap (long hInstance, long lpBitmapName);
+/**
+ * @param hInstance cast=(HINSTANCE)
+ * @param lpCursorName cast=(LPWSTR)
+ */
+public static final native long LoadCursor (long hInstance, long lpCursorName);
+/**
+ * @param hInstance cast=(HINSTANCE)
+ * @param lpIconName cast=(LPWSTR)
+ */
+public static final native long LoadIcon (long hInstance, long lpIconName);
+/**
+ * @param hinst cast=(HINSTANCE)
+ * @param pszName cast=(PCWSTR)
+ * @param phico cast=(HICON *)
+ */
+public static final native int LoadIconMetric (long hinst, long pszName, int lims, long [] phico);
+/**
+ * @param hinst cast=(HINSTANCE)
+ * @param lpszName cast=(LPWSTR)
+ */
+public static final native long LoadImage (long hinst, long lpszName, int uType, int cxDesired, int cyDesired, int fuLoad);
+/** @param hMem cast=(HLOCAL) */
+public static final native long LocalFree (long hMem);
+public static final native int LODWORD (long l);
+public static final native int LOWORD (long l);
+/** @param hdc cast=(HDC) */
+public static final native boolean LPtoDP (long hdc, POINT lpPoints, int nCount);
+public static final native int MAKEWORD(int l, int h);
+public static final native long MAKEWPARAM(int l, int h);
+public static final native long MAKELPARAM(int l, int h);
+public static final native long MAKELRESULT(int l, int h);
+public static final native int MapVirtualKey (int uCode, int uMapType);
+/**
+ * @param hWndFrom cast=(HWND)
+ * @param hWndTo cast=(HWND)
+ * @param lpPoints cast=(LPPOINT)
+ */
+public static final native int MapWindowPoints (long hWndFrom, long hWndTo, POINT lpPoints, int cPoints);
+/**
+ * @param hWndFrom cast=(HWND)
+ * @param hWndTo cast=(HWND)
+ * @param lpPoints cast=(LPPOINT)
+ */
+public static final native int MapWindowPoints (long hWndFrom, long hWndTo, RECT lpPoints, int cPoints);
+public static final native boolean MessageBeep (int uType);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpText cast=(LPWSTR)
+ * @param lpCaption cast=(LPWSTR)
+ */
+public static final native int MessageBox (long hWnd, char [] lpText, char [] lpCaption, int uType);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpXform cast=(XFORM *)
+ */
+public static final native boolean ModifyWorldTransform(long hdc, float [] lpXform, int iMode);
+/** @param hwnd cast=(HWND) */
+public static final native long MonitorFromWindow (long hwnd, int dwFlags);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (char[] Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (byte [] Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (byte [] Destination, ACCEL Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (byte [] Destination, BITMAPINFOHEADER Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (int [] Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (long [] Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (double[] Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (float[] Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in critical
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (short[] Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long Destination, byte [] Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long Destination, char [] Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long Destination, int [] Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (long Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, DEVMODE Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, DOCHOSTUIINFO Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, GRADIENT_RECT Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, LOGFONT Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, MEASUREITEMSTRUCT Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, MINMAXINFO Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, MSG Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, UDACCEL Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, NMTTDISPINFO Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (long Destination, OPENFILENAME Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, RECT Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, SAFEARRAY Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (SAFEARRAY Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, TRIVERTEX Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, WINDOWPOS Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (BITMAPINFOHEADER Destination, byte [] Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (BITMAPINFOHEADER Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (CERT_CONTEXT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (CERT_INFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (DEVMODE Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (DOCHOSTUIINFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (DRAWITEMSTRUCT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (FLICK_DATA Destination, long [] Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (FLICK_POINT Destination, long [] Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (HDITEM Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (HELPINFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (LOGFONT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (MEASUREITEMSTRUCT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (MINMAXINFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (OFNOTIFY Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (OPENFILENAME Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (POINT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (POINT Destination, long[] Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMHDR Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMCUSTOMDRAW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMLVCUSTOMDRAW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTBCUSTOMDRAW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTBHOTITEM Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTREEVIEW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTVCUSTOMDRAW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTVITEMCHANGE Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMUPDOWN Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, NMLVCUSTOMDRAW Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, NMTBCUSTOMDRAW Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, NMTVCUSTOMDRAW Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, NMLVDISPINFO Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, NMTVDISPINFO Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMLVDISPINFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTVDISPINFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMLVODSTATECHANGE Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMHEADER Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMLINK Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMLISTVIEW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMREBARCHILDSIZE Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMREBARCHEVRON Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTOOLBAR Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTTCUSTOMDRAW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (NMTTDISPINFO Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (EMR Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (EMREXTCREATEFONTINDIRECTW Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, SHDRAGIMAGE Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (TEXTMETRIC Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (TOUCHINPUT Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (WINDOWPOS Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (MSG Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (UDACCEL Destination, long Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, DROPFILES Source, int Length);
+/**
+ * @param DestinationPtr cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long DestinationPtr, double[] Source, int Length);
+/**
+ * @param DestinationPtr cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long DestinationPtr, float[] Source, int Length);
+/**
+ * @param DestinationPtr cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long DestinationPtr, long[] Source, int Length);
+/**
+ * @param DestinationPtr cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out critical
+ */
+public static final native void MoveMemory (long DestinationPtr, short[] Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (SCRIPT_ITEM Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (SCRIPT_LOGATTR Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param SourcePtr cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (SCRIPT_PROPERTIES Destination, long SourcePtr, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, KEYBDINPUT Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, MOUSEINPUT Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, GESTURECONFIG Source, int Length);
+/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, CIDA Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (CIDA Destination, long Source, int Length);
+/**
+ * @param hdc cast=(HDC)
+ * @param lPoint cast=(LPPOINT)
+ */
+public static final native boolean MoveToEx (long hdc, int x1, int x2, long lPoint);
+/**
+ * @param lpMultiByteStr cast=(LPCSTR),flags=no_out critical
+ * @param lpWideCharStr cast=(LPWSTR),flags=no_in critical
+ */
+public static final native int MultiByteToWideChar (int CodePage, int dwFlags, byte [] lpMultiByteStr, int cchMultiByte, char [] lpWideCharStr, int cchWideChar);
+/**
+ * @param lpMultiByteStr cast=(LPCSTR)
+ * @param lpWideCharStr cast=(LPWSTR),flags=no_in critical
+ */
+public static final native int MultiByteToWideChar (int CodePage, int dwFlags, long lpMultiByteStr, int cchMultiByte, char [] lpWideCharStr, int cchWideChar);
+/**
+ * @param event cast=(DWORD)
+ * @param hwnd cast=(HWND)
+ * @param idObject cast=(LONG)
+ * @param idChild cast=(LONG)
+ */
+public static final native void NotifyWinEvent (int event, long hwnd, int idObject, int idChild);
+public static final native boolean OffsetRect (RECT lprc, int dx, int dy);
+/** @param hrgn cast=(HRGN) */
+public static final native int OffsetRgn (long hrgn, int nXOffset, int nYOffset);
+/** @param pvReserved cast=(LPVOID) */
+public static final native int OleInitialize (long pvReserved);
+public static final native void OleUninitialize ();
+/** @param hWndNewOwner cast=(HWND) */
+public static final native boolean OpenClipboard (long hWndNewOwner);
+/**
+ * @param hwnd cast=(HWND)
+ * @param pszClassList cast=(LPCWSTR)
+ */
+public static final native long OpenThemeData (long hwnd, char[] pszClassList);
+/** @param hdc cast=(HDC) */
+public static final native boolean PatBlt (long hdc, int x1, int x2, int w, int h, int rop);
+/** @param szfile cast=(LPCWSTR) */
+public static final native boolean PathIsExe (long szfile);
+/** @param hWnd cast=(HWND) */
+public static final native boolean PeekMessage (MSG lpMsg, long hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);
+/** @param hdc cast=(HDC) */
+public static final native boolean Pie (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nXStartArc, int nYStartArc, int nXEndArc, int nYEndArc);
+/** @param pt flags=struct */
+public static final native void POINTSTOPOINT(POINT pt, long pts);
+/**
+ * @param hdc cast=(HDC)
+ * @param points cast=(CONST POINT *),flags=no_out critical
+ */
+public static final native boolean Polygon (long hdc, int [] points, int nPoints);
+/**
+ * @param hdc cast=(HDC)
+ * @param points cast=(CONST POINT *),flags=no_out critical
+ */
+public static final native boolean Polyline (long hdc, int[] points, int nPoints);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native boolean PostMessage (long hWnd, int Msg, long wParam, long lParam);
+/**
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native boolean PostThreadMessage (int idThread, int Msg, long wParam, long lParam);
+public static final native short PRIMARYLANGID (int lgid);
+/** @param lppd cast=(LPPRINTDLGW) */
+public static final native boolean PrintDlg (PRINTDLG lppd);
+/**
+ * @param hwnd cast=(HWND)
+ * @param hdcBlt cast=(HDC)
+ */
+public static final native boolean PrintWindow (long hwnd, long hdcBlt, int nFlags);
+public static final native int PSPropertyKeyFromString (char[] pszString, PROPERTYKEY pkey);
+/**
+ * @param rect flags=no_out
+ * @param pt flags=no_out struct
+ */
+public static final native boolean PtInRect (RECT rect, POINT pt);
+/** @param hrgn cast=(HRGN) */
+public static final native boolean PtInRegion (long hrgn, int X, int Y);
+/** @param hdc cast=(HDC) */
+public static final native boolean Rectangle (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
+/**
+ * @param hrgn cast=(HRGN)
+ * @param lprc flags=no_out
+ */
+public static final native boolean RectInRegion (long hrgn, RECT lprc);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hrgnUpdate cast=(HRGN)
+ */
+public static final native boolean RedrawWindow (long hWnd, RECT lprcUpdate, long hrgnUpdate, int flags);
+/** @param hKey cast=(HKEY) */
+public static final native int RegCloseKey (long hKey);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpSubKey cast=(LPWSTR)
+ * @param lpClass cast=(LPWSTR)
+ * @param lpSecurityAttributes cast=(LPSECURITY_ATTRIBUTES)
+ * @param phkResult cast=(PHKEY)
+ * @param lpdwDisposition cast=(LPDWORD)
+ */
+public static final native int RegCreateKeyEx (long hKey, char[] lpSubKey, int Reserved, char[] lpClass, int dwOptions, int samDesired, long lpSecurityAttributes, long[] phkResult, long[] lpdwDisposition);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpValueName cast=(LPWSTR)
+ */
+public static final native int RegDeleteValue (long hKey, char[] lpValueName);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpName cast=(LPWSTR)
+ * @param lpcName cast=(LPDWORD)
+ * @param lpReserved cast=(LPDWORD)
+ * @param lpClass cast=(LPWSTR)
+ * @param lpcClass cast=(LPDWORD)
+ */
+public static final native int RegEnumKeyEx (long hKey, int dwIndex, char [] lpName, int [] lpcName, int [] lpReserved, char [] lpClass, int [] lpcClass, FILETIME lpftLastWriteTime);
+/** @param lpWndClass cast=(LPWNDCLASSW) */
+public static final native int RegisterClass (WNDCLASS lpWndClass);
+/**
+ * @method flags=dynamic
+ * @param hWnd cast=(HWND)
+ * @param ulFlags cast=(ULONG)
+ */
+public static final native boolean RegisterTouchWindow(long hWnd, int ulFlags);
+/** @param lpString cast=(LPWSTR) */
+public static final native int RegisterWindowMessage (char [] lpString);
+/** @param lpszFormat cast=(LPWSTR) */
+public static final native int RegisterClipboardFormat (char[] lpszFormat);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpSubKey cast=(LPWSTR)
+ * @param phkResult cast=(PHKEY)
+ */
+public static final native int RegOpenKeyEx (long hKey, char[] lpSubKey, int ulOptions, int samDesired, long[] phkResult);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpValueName cast=(LPWSTR)
+ * @param lpReserved cast=(LPDWORD)
+ * @param lpType cast=(LPDWORD)
+ * @param lpData cast=(LPBYTE)
+ * @param lpcbData cast=(LPDWORD)
+ */
+public static final native int RegQueryValueEx (long hKey, char[] lpValueName, long lpReserved, int[] lpType, char [] lpData, int[] lpcbData);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpValueName cast=(LPWSTR)
+ * @param lpReserved cast=(LPDWORD)
+ * @param lpType cast=(LPDWORD)
+ * @param lpData cast=(LPBYTE)
+ * @param lpcbData cast=(LPDWORD)
+ */
+public static final native int RegQueryValueEx (long hKey, char[] lpValueName, long lpReserved, int[] lpType, int [] lpData, int[] lpcbData);
+/**
+ * @param hKey cast=(HKEY)
+ * @param lpValueName cast=(LPWSTR)
+ * @param lpData cast=(const BYTE*)
+ */
+public static final native int RegSetValueEx (long hKey, char[] lpValueName, int Reserved, int dwType, int[] lpData, int cbData);
+public static final native boolean ReleaseCapture ();
+/**
+ * @param hWnd cast=(HWND)
+ * @param hDC cast=(HDC)
+ */
+public static final native int ReleaseDC (long hWnd, long hDC);
+/** @param hMenu cast=(HMENU) */
+public static final native boolean RemoveMenu (long hMenu, int uPosition, int uFlags);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpString cast=(LPCWSTR)
+ */
+public static final native long RemoveProp (long hWnd, long lpString);
+public static final native boolean ReplyMessage (long lResult);
+/**
+ * @param hdc cast=(HDC)
+ * @param nSavedDC cast=(int)
+ */
+public static final native boolean RestoreDC (long hdc, int nSavedDC);
+/** @param hdc cast=(HDC) */
+public static final native boolean RoundRect (long hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidth, int nHeight);
+/** @param hdc cast=(HDC) */
+public static final native int SaveDC (long hdc);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ScreenToClient (long hWnd, POINT lpPoint);
+/**
+ * @param psds cast=(const SCRIPT_DIGITSUBSTITUTE*)
+ * @param psc cast=(SCRIPT_CONTROL*)
+ * @param pss cast=(SCRIPT_STATE*)
+ */
+public static final native int ScriptApplyDigitSubstitution (SCRIPT_DIGITSUBSTITUTE psds, SCRIPT_CONTROL psc, SCRIPT_STATE pss);
+/**
+ * @param pwcChars cast=(const WCHAR *)
+ * @param psa cast=(const SCRIPT_ANALYSIS *)
+ * @param psla cast=(SCRIPT_LOGATTR *)
+ */
+public static final native int ScriptBreak (char[] pwcChars, int cChars, SCRIPT_ANALYSIS psa, long psla);
+/**
+ * @param ppSp cast=(const SCRIPT_PROPERTIES ***)
+ * @param piNumScripts cast=(int *)
+ */
+public static final native int ScriptGetProperties (long[] ppSp, int[] piNumScripts);
+/**
+ * @param hdc cast=(HDC)
+ * @param psc cast=(SCRIPT_CACHE *)
+ * @param tmHeight cast=(long *)
+ */
+public static final native int ScriptCacheGetHeight (long hdc, long psc, int[] tmHeight);
+/**
+ * @param pwLogClust cast=(const WORD *)
+ * @param psva cast=(const SCRIPT_VISATTR *)
+ * @param piAdvance cast=(const int *)
+ * @param psa cast=(const SCRIPT_ANALYSIS *)
+ * @param piX cast=(int *)
+ */
+public static final native int ScriptCPtoX (int iCP, boolean fTrailing, int cChars, int cGlyphs, long pwLogClust, long psva, long piAdvance, SCRIPT_ANALYSIS psa, int[] piX);
+/** @param psc cast=(SCRIPT_CACHE *) */
+public static final native int ScriptFreeCache (long psc);
+/**
+ * @param hdc cast=(HDC)
+ * @param psc cast=(SCRIPT_CACHE *)
+ * @param sfp cast=(SCRIPT_FONTPROPERTIES *)
+ */
+public static final native int ScriptGetFontProperties (long hdc, long psc, SCRIPT_FONTPROPERTIES sfp);
+/**
+ * @param psa cast=(const SCRIPT_ANALYSIS *)
+ * @param piGlyphWidth cast=(const int *)
+ * @param pwLogClust cast=(const WORD *)
+ * @param psva cast=(const SCRIPT_VISATTR *)
+ * @param piDx cast=(int *)
+ */
+public static final native int ScriptGetLogicalWidths (SCRIPT_ANALYSIS psa, int cChars, int cGlyphs, long piGlyphWidth, long pwLogClust, long psva, int[] piDx);
+/**
+ * @param pwcInChars cast=(const WCHAR *)
+ * @param psControl cast=(const SCRIPT_CONTROL *)
+ * @param psState cast=(const SCRIPT_STATE *)
+ * @param pItems cast=(SCRIPT_ITEM *)
+ * @param pcItems cast=(int *)
+ */
+public static final native int ScriptItemize (char[] pwcInChars, int cInChars, int cMaxItems, SCRIPT_CONTROL psControl, SCRIPT_STATE psState, long pItems, int[] pcItems);
+/**
+ * @param psva cast=(SCRIPT_VISATTR *)
+ * @param piAdvance cast=(const int *)
+ * @param piJustify cast=(int *)
+ */
+public static final native int ScriptJustify (long psva, long piAdvance, int cGlyphs, int iDx, int iMinKashida, long piJustify);
+/**
+ * @param pbLevel cast=(const BYTE *)
+ * @param piVisualToLogical cast=(int *)
+ * @param piLogicalToVisual cast=(int *)
+ */
+public static final native int ScriptLayout (int cRuns, byte[] pbLevel, int[] piVisualToLogical, int[] piLogicalToVisual);
+/**
+ * @param hdc cast=(HDC)
+ * @param psc cast=(SCRIPT_CACHE *)
+ * @param pwGlyphs cast=(const WORD *)
+ * @param psva cast=(const SCRIPT_VISATTR *)
+ * @param psa cast=(SCRIPT_ANALYSIS *)
+ * @param piAdvance cast=(int *)
+ * @param pGoffset cast=(GOFFSET *)
+ * @param pABC cast=(ABC *)
+ */
+public static final native int ScriptPlace (long hdc, long psc, long pwGlyphs, int cGlyphs, long psva, SCRIPT_ANALYSIS psa, long piAdvance, long pGoffset, int[] pABC);
+/**
+ * @param Locale cast=(LCID)
+ * @param psds cast=(SCRIPT_DIGITSUBSTITUTE*)
+ */
+public static final native int ScriptRecordDigitSubstitution (int Locale, SCRIPT_DIGITSUBSTITUTE psds);
+/**
+ * @param hdc cast=(HDC)
+ * @param psc cast=(SCRIPT_CACHE *)
+ * @param pwcChars cast=(const WCHAR *)
+ * @param pwOutGlyphs cast=(WORD*)
+ */
+public static final native int ScriptGetCMap (long hdc, long psc, char[] pwcChars, int cChars, int dwFlags, short[] pwOutGlyphs);
+/**
+ * @param hdc cast=(HDC)
+ * @param psc cast=(SCRIPT_CACHE *)
+ * @param pwcChars cast=(const WCHAR *)
+ * @param psa cast=(SCRIPT_ANALYSIS *)
+ * @param pwOutGlyphs cast=(WORD *)
+ * @param pwLogClust cast=(WORD *)
+ * @param psva cast=(SCRIPT_VISATTR *)
+ * @param pcGlyphs cast=(int *)
+ */
+public static final native int ScriptShape (long hdc, long psc, char[] pwcChars, int cChars, int cMaxGlyphs, SCRIPT_ANALYSIS psa, long pwOutGlyphs, long pwLogClust, long psva, int[] pcGlyphs);
+/**
+ * @param hdc cast=(HDC)
+ * @param pString cast=(const void*)
+ * @param piDx cast=(const int*)
+ * @param pTabdef cast=(SCRIPT_TABDEF*)
+ * @param pbInClass cast=(const BYTE*)
+ * @param pssa cast=(SCRIPT_STRING_ANALYSIS*)
+ */
+public static final native int ScriptStringAnalyse (long hdc, long pString, int cString, int cGlyphs, int iCharset, int dwFlags, int iReqWidth, SCRIPT_CONTROL psControl, SCRIPT_STATE psState, long piDx, long pTabdef, long pbInClass, long pssa);
+/** @param ssa cast=(SCRIPT_STRING_ANALYSIS*),flags=struct */
+public static final native int ScriptStringOut(long ssa, int iX, int iY, int uOptions, RECT prc, int iMinSel, int iMaxSel, boolean fDisabled);
+/** @param pssa cast=(SCRIPT_STRING_ANALYSIS*) */
+public static final native int ScriptStringFree(long pssa);
+/**
+ * @param hdc cast=(const HDC)
+ * @param psc cast=(SCRIPT_CACHE *)
+ * @param lprc cast=(const RECT *)
+ * @param psa cast=(const SCRIPT_ANALYSIS *)
+ * @param pwcReserved cast=(const WCHAR *)
+ * @param pwGlyphs cast=(const WORD *)
+ * @param piAdvance cast=(const int *)
+ * @param piJustify cast=(const int *)
+ * @param pGoffset cast=(const GOFFSET *)
+ */
+public static final native int ScriptTextOut (long hdc, long psc, int x, int y, int fuOptions, RECT lprc, SCRIPT_ANALYSIS psa, long pwcReserved, int iReserved, long pwGlyphs, int cGlyphs, long piAdvance, long piJustify, long pGoffset);
+/**
+ * @param pwLogClust cast=(const WORD *)
+ * @param psva cast=(const SCRIPT_VISATTR *)
+ * @param piAdvance cast=(const int *)
+ * @param psa cast=(const SCRIPT_ANALYSIS *)
+ * @param piCP cast=(int *)
+ * @param piTrailing cast=(int *)
+ */
+public static final native int ScriptXtoCP (int iX, int cChars, int cGlyphs, long pwLogClust, long psva, long piAdvance, SCRIPT_ANALYSIS psa, int[] piCP, int[] piTrailing);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hrgnUpdate cast=(HRGN)
+ */
+public static final native int ScrollWindowEx (long hWnd, int dx, int dy, RECT prcScroll, RECT prcClip, long hrgnUpdate, RECT prcUpdate, int flags);
+/**
+ * @param hdc cast=(HDC)
+ * @param hrgn cast=(HRGN)
+ */
+public static final native int SelectClipRgn (long hdc, long hrgn);
+/**
+ * @param hDC cast=(HDC)
+ * @param HGDIObj cast=(HGDIOBJ)
+ */
+public static final native long SelectObject (long hDC, long HGDIObj);
+/** @param pInputs cast=(LPINPUT) */
+public static final native int SendInput (int nInputs, long pInputs, int cbSize);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, int [] wParam, int [] lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, char [] lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, int [] lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, long lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, LVCOLUMN lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, LVHITTESTINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, LITEM lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, LVITEM lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, LVINSERTMARK lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, MARGINS lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, MCHITTESTINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, REBARBANDINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, RECT lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, SYSTEMTIME lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, SHDRAGIMAGE lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TBBUTTON lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TBBUTTONINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TCITEM lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TCHITTESTINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TOOLINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TVHITTESTINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TVINSERTSTRUCT lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TVITEM lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, TVSORTCB lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, UDACCEL lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, HDHITTESTINFO lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, HDITEM lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, HDLAYOUT lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, BUTTON_IMAGELIST lParam);
+/**
+ * @param hWnd cast=(HWND)
+ * @param wParam cast=(WPARAM)
+ * @param lParam cast=(LPARAM)
+ */
+public static final native long SendMessage (long hWnd, int Msg, long wParam, SIZE lParam);
+/** @param hWnd cast=(HWND) */
+public static final native long SetActiveWindow (long hWnd);
+/**
+ * @param hdc cast=(HDC)
+ * @param colorRef cast=(COLORREF)
+ */
+public static final native int SetBkColor (long hdc, int colorRef);
+/** @param hdc cast=(HDC) */
+public static final native int SetBkMode (long hdc, int mode);
+/**
+ * @param hdc cast=(HDC)
+ * @param lppt cast=(LPPOINT)
+ */
+public static final native boolean SetBrushOrgEx (long hdc, int nXOrg, int nYOrg, POINT lppt);
+/** @param hWnd cast=(HWND) */
+public static final native long SetCapture (long hWnd);
+public static final native boolean SetCaretPos (int X, int Y);
+/** @method flags=dynamic */
+public static final native int SetCurrentProcessExplicitAppUserModelID (char[] AppID);
+/** @param hCursor cast=(HCURSOR) */
+public static final native long SetCursor (long hCursor);
+public static final native boolean SetCursorPos (int X, int Y);
+/**
+ * @param hdc cast=(HDC)
+ * @param pColors cast=(RGBQUAD *),flags=no_out critical
+ */
+public static final native int SetDIBColorTable (long hdc, int uStartIndex, int cEntries, byte[] pColors);
+public static final native boolean SetDllDirectory (char [] lpString);
+public static final native int SetErrorMode (int uMode);
+/** @param hWnd cast=(HWND) */
+public static final native long SetFocus (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean SetForegroundWindow (long hWnd);
+/**
+ * @method flags=dynamic
+ * @param hwnd cast=(HWND)
+ * @param pGestureConfig cast=(PGESTURECONFIG)
+ */
+public static final native boolean SetGestureConfig(long hwnd, int dwReserved, int cIDs, long pGestureConfig, int cbSize);
+/** @param hdc cast=(HDC) */
+public static final native int SetGraphicsMode (long hdc, int iMode);
+/** @param hwnd cast=(HWND) */
+public static final native boolean SetLayeredWindowAttributes(long hwnd, int crKey, byte bAlpha, int dwFlags);
+/**
+ * @param hdc cast=(HDC)
+ * @param dwLayout cast=(DWORD)
+ */
+public static final native int SetLayout (long hdc, int dwLayout);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hMenu cast=(HMENU)
+ */
+public static final native boolean SetMenu (long hWnd, long hMenu);
+/** @param hMenu cast=(HMENU) */
+public static final native boolean SetMenuDefaultItem (long hMenu, int uItem, int fByPos);
+/** @param hmenu cast=(HMENU) */
+public static final native boolean SetMenuInfo (long hmenu, MENUINFO lpcmi);
+/**
+ * @param hMenu cast=(HMENU)
+ * @param lpmii cast=(LPMENUITEMINFOW)
+ */
+public static final native boolean SetMenuItemInfo (long hMenu, int uItem, boolean fByPosition, MENUITEMINFO lpmii);
+/** @param hdc cast=(HDC) */
+public static final native int SetMetaRgn (long hdc);
+/**
+ * @param hWndChild cast=(HWND)
+ * @param hWndNewParent cast=(HWND)
+ */
+public static final native long SetParent (long hWndChild, long hWndNewParent);
+/** @param hdc cast=(HDC) */
+public static final native int SetPixel (long hdc, int X, int Y, int crColor);
+/** @param hdc cast=(HDC) */
+public static final native int SetPolyFillMode (long hdc, int iPolyFillMode);
+public static final native boolean SetProcessDPIAware ();
+/** @param lprc flags=no_in */
+public static final native boolean SetRect (RECT lprc, int xLeft, int yTop, int xRight, int yBottom);
+/** @param hrgn cast=(HRGN) */
+public static final native boolean SetRectRgn (long hrgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
+/** @param hdc cast=(HDC) */
+public static final native int SetROP2 (long hdc, int fnDrawMode);
+/** @param hwnd cast=(HWND) */
+public static final native boolean SetScrollInfo (long hwnd, int flags, SCROLLINFO info, boolean fRedraw);
+/** @param hdc cast=(HDC) */
+public static final native int SetStretchBltMode (long hdc, int iStretchMode);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpString cast=(LPCWSTR)
+ * @param hData cast=(HANDLE)
+ */
+public static final native boolean SetProp (long hWnd, long lpString, long hData);
+/**
+ * @param hdc cast=(HDC)
+ * @param colorRef cast=(COLORREF)
+ */
+public static final native int SetTextColor (long hdc, int colorRef);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpTimerFunc cast=(TIMERPROC)
+ */
+public static final native long SetTimer (long hWnd, long nIDEvent, int Elapse, long lpTimerFunc);
+/** @param hWnd cast=(HWND) */
+public static final native int SetWindowLong (long hWnd, int nIndex, int dwNewLong);
+/**
+ * @param hWnd cast=(HWND)
+ * @param dwNewLong cast=(LONG_PTR)
+ */
+public static final native long SetWindowLongPtr (long hWnd, int nIndex, long dwNewLong);
+/** @param hdc cast=(HDC) */
+public static final native boolean SetWindowOrgEx (long hdc, int X, int Y, POINT lpPoint);
+/** @param hWnd cast=(HWND) */
+public static final native boolean SetWindowPlacement (long hWnd, WINDOWPLACEMENT lpwndpl);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hWndInsertAfter cast=(HWND)
+ */
+public static final native boolean SetWindowPos(long hWnd, long hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hRgn cast=(HRGN)
+ */
+public static final native int SetWindowRgn (long hWnd, long hRgn, boolean bRedraw);
+/**
+ * @param hWnd cast=(HWND)
+ * @param lpString cast=(LPWSTR)
+ */
+public static final native boolean SetWindowText (long hWnd, char [] lpString);
+/**
+ * @param hwnd cast=(HWND)
+ * @param pszSubAppName cast=(LPCWSTR)
+ * @param pszSubIdList cast=(LPCWSTR)
+ */
+public static final native int SetWindowTheme (long hwnd, char [] pszSubAppName, char [] pszSubIdList);
+/**
+ * @param lpfn cast=(HOOKPROC)
+ * @param hMod cast=(HINSTANCE)
+ */
+public static final native long SetWindowsHookEx (int idHook, long lpfn,  long hMod,  int dwThreadId);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpXform cast=(XFORM *)
+ */
+public static final native boolean SetWorldTransform(long hdc, float[] lpXform);
+/** @param lpbi cast=(LPBROWSEINFOW) */
+public static final native long SHBrowseForFolder (BROWSEINFO lpbi);
+/**
+ * @param pszPath cast=(LPCWSTR)
+ * @param psfi cast=(SHFILEINFOW *)
+ */
+public static final native long SHGetFileInfo (char [] pszPath, int dwFileAttributes, SHFILEINFO psfi, int cbFileInfo, int uFlags);
+/** @param lpExecInfo cast=(LPSHELLEXECUTEINFOW) */
+public static final native boolean ShellExecuteEx (SHELLEXECUTEINFO lpExecInfo);
+public static final native boolean Shell_NotifyIcon (int dwMessage, NOTIFYICONDATA lpData);
+/** @param ppMalloc cast=(LPMALLOC *) */
+public static final native int SHGetMalloc (long [] ppMalloc);
+/**
+ * @param pidl cast=(LPCITEMIDLIST)
+ * @param pszPath cast=(LPWSTR)
+ */
+public static final native boolean SHGetPathFromIDList (long pidl, char [] pszPath);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ShowCaret (long hWnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ShowOwnedPopups (long hWnd, boolean fShow);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ShowScrollBar (long hWnd, int wBar, boolean bShow);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ShowWindow (long hWnd, int nCmdShow);
+/**
+ * @param hdc cast=(HDC)
+ * @param lpdi cast=(LPDOCINFOW)
+ */
+public static final native int StartDoc (long hdc, DOCINFO lpdi);
+/** @param hdc cast=(HDC) */
+public static final native int StartPage (long hdc);
+/**
+ * @param hdcDest cast=(HDC)
+ * @param hdcSrc cast=(HDC)
+ */
+public static final native boolean StretchBlt (long hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, long hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, int dwRop);
+public static final native boolean SystemParametersInfo (int uiAction, int uiParam, HIGHCONTRAST pvParam, int fWinIni);
+public static final native boolean SystemParametersInfo (int uiAction, int uiParam, RECT pvParam, int fWinIni);
+public static final native boolean SystemParametersInfo (int uiAction, int uiParam, NONCLIENTMETRICS pvParam, int fWinIni);
+public static final native boolean SystemParametersInfo (int uiAction, int uiParam, int [] pvParam, int fWinIni);
+/**
+ * @param lpKeyState cast=(PBYTE)
+ * @param pwszBuff cast=(LPWSTR)
+ */
+public static final native int ToUnicode (int wVirtKey, int wScanCode, byte [] lpKeyState, char [] pwszBuff, int cchBuff, int wFlags);
+public static final native long TOUCH_COORD_TO_PIXEL(long touchCoord);
+/**
+ * @param hwndTV cast=(HWND)
+ * @param hitem cast=(HTREEITEM)
+ */
+public static final native boolean TreeView_GetItemRect (long hwndTV, long hitem, RECT prc, boolean fItemRect);
+public static final native boolean TrackMouseEvent (TRACKMOUSEEVENT lpEventTrack);
+/**
+ * @param hMenu cast=(HMENU)
+ * @param hWnd cast=(HWND)
+ */
+public static final native boolean TrackPopupMenu (long hMenu, int uFlags, int x, int y, int nReserved, long hWnd, RECT prcRect);
+/**
+ * @param hWnd cast=(HWND)
+ * @param hAccTable cast=(HACCEL)
+ */
+public static final native int TranslateAccelerator (long hWnd, long hAccTable, MSG lpMsg);
+/**
+ * @param lpSrc cast=(DWORD *)
+ * @param lpCs cast=(LPCHARSETINFO)
+ */
+public static final native boolean TranslateCharsetInfo (long lpSrc, int [] lpCs, int dwFlags);
+/**
+ * @param hWndClient cast=(HWND)
+ * @param lpMsg cast=(LPMSG)
+ */
+public static final native boolean TranslateMDISysAccel (long hWndClient, MSG lpMsg);
+public static final native boolean TranslateMessage (MSG lpmsg);
+/**
+ * @param hdcDest cast=(HDC)
+ * @param hdcSrc cast=(HDC)
+ */
+public static final native boolean TransparentBlt (long hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int hHeightDest, long hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, int crTransparent);
+/** @param hhk cast=(HHOOK) */
+public static final native boolean UnhookWindowsHookEx (long hhk);
+/**
+ * @param lpClassName cast=(LPWSTR)
+ * @param hInstance cast=(HINSTANCE)
+ */
+public static final native boolean UnregisterClass (char [] lpClassName, long hInstance);
+/**
+ * @method flags=dynamic
+ * @param hwnd cast=(HWND)
+ */
+public static final native boolean UnregisterTouchWindow (long hwnd);
+/** @param hWnd cast=(HWND) */
+public static final native boolean UpdateWindow (long hWnd);
+/**
+ * @param pszPath cast=(LPCWSTR)
+ * @param pszURL cast=(LPWSTR)
+ */
+public static final native int UrlCreateFromPath (char[] pszPath, char[] pszURL, int[] pcchUrl, int flags);
+/** @param hWnd cast=(HWND) */
+public static final native boolean ValidateRect (long hWnd, RECT lpRect);
+/** @param ch cast=(WCHAR) */
+public static final native short VkKeyScan (short ch);
+
+public static final native boolean WaitMessage ();
+/**
+ * @param lpWideCharStr cast=(LPCWSTR),flags=no_out critical
+ * @param lpMultiByteStr cast=(LPSTR),flags=no_in critical
+ * @param lpDefaultChar cast=(LPCSTR)
+ * @param lpUsedDefaultChar cast=(LPBOOL)
+ */
+public static final native int WideCharToMultiByte (int CodePage, int dwFlags, char [] lpWideCharStr, int cchWideChar, byte [] lpMultiByteStr, int cchMultiByte, byte [] lpDefaultChar, boolean [] lpUsedDefaultChar);
+/**
+ * @param lpWideCharStr cast=(LPCWSTR),flags=no_out critical
+ * @param lpMultiByteStr cast=(LPSTR)
+ * @param lpDefaultChar cast=(LPCSTR)
+ * @param lpUsedDefaultChar cast=(LPBOOL)
+ */
+public static final native int WideCharToMultiByte (int CodePage, int dwFlags, char [] lpWideCharStr, int cchWideChar, long lpMultiByteStr, int cchMultiByte, byte [] lpDefaultChar, boolean [] lpUsedDefaultChar);
+/** @param hDC cast=(HDC) */
+public static final native long WindowFromDC (long hDC);
+/** @param lpPoint flags=struct */
+public static final native long WindowFromPoint (POINT lpPoint);
+/** @param string cast=(const wchar_t *) */
+public static final native int wcslen (long string);
+
+/** @param hFileMappingObject cast=(HANDLE)
+ *  @param dwDesiredAccess cast=(DWORD)
+ *  @param dwFileOffsetHigh cast=(DWORD)
+ *  @param dwFileOffsetLow cast=(DWORD)
+ */
+public static final native long MapViewOfFile(long hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
+/** @param lpBaseAddress cast=(LPCVOID) */
+public static final native boolean UnmapViewOfFile(long lpBaseAddress);
+
+public static final int PROCESS_DUP_HANDLE = 0x0040;
+public static final int PROCESS_VM_READ = 0x0010;
+public static final int DUPLICATE_SAME_ACCESS = 2;
+
+/**
+ * @param dwDesiredAccess cast=(DWORD)
+ * @param dwProcessId cast=(DWORD)
+ */
+public static final native long OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);
+
+public static final native long GetCurrentProcess();
+
+/**
+ * @param hSourceProcessHandle cast=(HANDLE)
+ * @param hSourceHandle cast=(HANDLE)
+ * @param hTargetProcessHandle cast=(HANDLE)
+ * @param lpTargetHandle cast=(LPHANDLE)
+ * @param dwDesiredAccess cast=(DWORD)
+ * @param dwOptions cast=(DWORD)
+ */
+public static final native boolean DuplicateHandle(long hSourceProcessHandle, long hSourceHandle, long hTargetProcessHandle,
+               long [] lpTargetHandle, int dwDesiredAccess, boolean b, int dwOptions);
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OUTLINETEXTMETRIC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/OUTLINETEXTMETRIC.java
new file mode 100644 (file)
index 0000000..daacae7
--- /dev/null
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class OUTLINETEXTMETRIC {
+       public int otmSize;
+       public TEXTMETRIC otmTextMetrics = new TEXTMETRIC ();
+       public byte otmFiller;
+       /** @field accessor=otmPanoseNumber.bFamilyType */
+       public byte otmPanoseNumber_bFamilyType;
+       /** @field accessor=otmPanoseNumber.bSerifStyle */
+       public byte otmPanoseNumber_bSerifStyle;
+       /** @field accessor=otmPanoseNumber.bWeight */
+       public byte otmPanoseNumber_bWeight;
+       /** @field accessor=otmPanoseNumber.bProportion */
+       public byte otmPanoseNumber_bProportion;
+       /** @field accessor=otmPanoseNumber.bContrast */
+       public byte otmPanoseNumber_bContrast;
+       /** @field accessor=otmPanoseNumber.bStrokeVariation */
+       public byte otmPanoseNumber_bStrokeVariation;
+       /** @field accessor=otmPanoseNumber.bArmStyle */
+       public byte otmPanoseNumber_bArmStyle;
+       /** @field accessor=otmPanoseNumber.bLetterform */
+       public byte otmPanoseNumber_bLetterform;
+       /** @field accessor=otmPanoseNumber.bMidline */
+       public byte otmPanoseNumber_bMidline;
+       /** @field accessor=otmPanoseNumber.bXHeight */
+       public byte otmPanoseNumber_bXHeight;
+       public int otmfsSelection;
+       public int otmfsType;
+       public int otmsCharSlopeRise;
+       public int otmsCharSlopeRun;
+       public int otmItalicAngle;
+       public int otmEMSquare;
+       public int otmAscent;
+       public int otmDescent;
+       public int otmLineGap;
+       public int otmsCapEmHeight;
+       public int otmsXHeight;
+       public RECT otmrcFontBox = new RECT();
+       public int otmMacAscent;
+       public int otmMacDescent;
+       public int otmMacLineGap;
+       public int otmusMinimumPPEM;
+       public POINT otmptSubscriptSize = new POINT();
+       public POINT otmptSubscriptOffset = new POINT();
+       public POINT otmptSuperscriptSize = new POINT();
+       public POINT otmptSuperscriptOffset = new POINT();
+       public int otmsStrikeoutSize;
+       public int otmsStrikeoutPosition;
+       public int otmsUnderscoreSize;
+       public int otmsUnderscorePosition;
+       /** @field cast=(PSTR) */
+       public long otmpFamilyName;
+       /** @field cast=(PSTR) */
+       public long otmpFaceName;
+       /** @field cast=(PSTR) */
+       public long otmpStyleName;
+       /** @field cast=(PSTR) */
+       public long otmpFullName;
+       public static final int sizeof = OS.OUTLINETEXTMETRIC_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PAINTSTRUCT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PAINTSTRUCT.java
new file mode 100644 (file)
index 0000000..7da7b4f
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class PAINTSTRUCT {
+       /** @field cast=(HDC) */
+       public long  hdc;
+       public boolean fErase;
+//     public RECT rcPaint;
+       /** @field accessor=rcPaint.left */
+       public int left;
+       /** @field accessor=rcPaint.top */
+       public int top;
+       /** @field accessor=rcPaint.right */
+       public int right;
+       /** @field accessor=rcPaint.bottom */
+       public int bottom;
+       public boolean fRestore;
+       public boolean fIncUpdate;
+       public byte[] rgbReserved = new byte[32];
+       public static final int sizeof = OS.PAINTSTRUCT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PANOSE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PANOSE.java
new file mode 100644 (file)
index 0000000..86ac7aa
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class PANOSE {
+       public byte bFamilyType;
+       public byte bSerifStyle;
+       public byte bWeight;
+       public byte bProportion;
+       public byte bContrast;
+       public byte bStrokeVariation;
+       public byte bArmStyle;
+       public byte bLetterform;
+       public byte bMidline;
+       public byte bXHeight;
+       public static final int sizeof = OS.PANOSE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/POINT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/POINT.java
new file mode 100644 (file)
index 0000000..690958e
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class POINT {
+       public int x;
+       public int y;
+       public static final int sizeof = OS.POINT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PRINTDLG.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PRINTDLG.java
new file mode 100644 (file)
index 0000000..93b2ad2
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class PRINTDLG {
+       public int lStructSize; // DWORD
+       /** @field cast=(HWND) */
+       public long hwndOwner; // HWND
+       /** @field cast=(HGLOBAL) */
+       public long hDevMode; // HGLOBAL
+       /** @field cast=(HGLOBAL) */
+       public long hDevNames; // HGLOBAL
+       /** @field cast=(HDC) */
+       public long hDC; // HDC
+       public int Flags; // DWORD
+       public short nFromPage; // WORD
+       public short nToPage; // WORD
+       public short nMinPage; // WORD
+       public short nMaxPage; // WORD
+       public short nCopies; // WORD
+       /** @field cast=(HINSTANCE) */
+       public long hInstance; // HINSTANCE
+       public long lCustData; // LPARAM
+       /** @field cast=(LPPRINTHOOKPROC) */
+       public long lpfnPrintHook; // LPPRINTHOOKPROC
+       /** @field cast=(LPPRINTHOOKPROC) */
+       public long lpfnSetupHook; // LPSETUPHOOKPROC
+       /** @field cast=(LPCTSTR) */
+       public long lpPrintTemplateName; // LPCTSTR
+       /** @field cast=(LPCTSTR) */
+       public long lpSetupTemplateName; // LPCTSTR
+       /** @field cast=(HGLOBAL) */
+       public long hPrintTemplate; // HGLOBAL
+       /** @field cast=(HGLOBAL) */
+       public long hSetupTemplate; // HGLOBAL
+       public static final int sizeof = OS.PRINTDLG_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PROCESS_INFORMATION.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PROCESS_INFORMATION.java
new file mode 100644 (file)
index 0000000..39a71f7
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class PROCESS_INFORMATION {
+       /** @field cast=(HANDLE) */
+       public long hProcess;
+       /** @field cast=(HANDLE) */
+       public long hThread;
+       public int dwProcessId;
+       public int dwThreadId;
+       public static int sizeof = OS.PROCESS_INFORMATION_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PROPERTYKEY.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/PROPERTYKEY.java
new file mode 100644 (file)
index 0000000..f7663b7
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class PROPERTYKEY {
+       /** @field flags=struct */
+       public byte [] fmtid = new byte [16];
+       public int pid;
+       public static final int sizeof = OS.PROPERTYKEY_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/REBARBANDINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/REBARBANDINFO.java
new file mode 100644 (file)
index 0000000..8a5e321
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class REBARBANDINFO {
+       public int cbSize;
+       public int fMask;
+       public int fStyle;
+       public int clrFore;
+       public int clrBack;
+       /** @field cast=(LPTSTR) */
+       public long lpText;
+       public int cch;
+       public int iImage;
+       /** @field cast=(HWND) */
+       public long hwndChild;
+       public int cxMinChild;
+       public int cyMinChild;
+       public int cx;
+       /** @field cast=(HBITMAP) */
+       public long hbmBack;
+       public int wID;
+       public int cyChild;
+       public int cyMaxChild;
+       public int cyIntegral;
+       public int cxIdeal;
+       public long lParam;
+       public int cxHeader;
+       public static final int sizeof = OS.REBARBANDINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/RECT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/RECT.java
new file mode 100644 (file)
index 0000000..4d13015
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class RECT {
+       public int left;
+       public int top;
+       public int right;
+       public int bottom;
+       public static final int sizeof = OS.RECT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SAFEARRAY.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SAFEARRAY.java
new file mode 100644 (file)
index 0000000..ea4085f
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SAFEARRAY {
+       public short cDims;
+       public short fFeatures;
+       public int cbElements;
+       public int cLocks;
+       /** @field cast=(PVOID) */
+       public long pvData;
+       /** @field accessor=rgsabound[0] */
+       public SAFEARRAYBOUND rgsabound;
+
+       public static final int sizeof = OS.SAFEARRAY_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SAFEARRAYBOUND.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SAFEARRAYBOUND.java
new file mode 100644 (file)
index 0000000..fbffe1e
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SAFEARRAYBOUND {
+       public int cElements;
+       public int lLbound;
+       public static final int sizeof = OS.SAFEARRAYBOUND_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_ANALYSIS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_ANALYSIS.java
new file mode 100644 (file)
index 0000000..61f61a3
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_ANALYSIS {
+       public short eScript;
+       public boolean fRTL;
+       public boolean fLayoutRTL;
+       public boolean fLinkBefore;
+       public boolean fLinkAfter;
+       public boolean fLogicalOrder;
+       public boolean fNoGlyphIndex;
+       public SCRIPT_STATE s = new SCRIPT_STATE();
+       public static final int sizeof = OS.SCRIPT_ANALYSIS_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_CONTROL.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_CONTROL.java
new file mode 100644 (file)
index 0000000..2b7b090
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_CONTROL {
+       public int uDefaultLanguage;
+       public boolean fContextDigits;
+       public boolean fInvertPreBoundDir;
+       public boolean fInvertPostBoundDir;
+       public boolean fLinkStringBefore;
+       public boolean fLinkStringAfter;
+       public boolean fNeutralOverride;
+       public boolean fNumericOverride;
+       public boolean fLegacyBidiClass;
+       public boolean fMergeNeutralItems;
+       public boolean fUseStandardBidi;
+       public int fReserved;
+       public static final int sizeof = OS.SCRIPT_CONTROL_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_DIGITSUBSTITUTE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_DIGITSUBSTITUTE.java
new file mode 100644 (file)
index 0000000..0971295
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_DIGITSUBSTITUTE {
+       public short NationalDigitLanguage;
+       public short TraditionalDigitLanguage;
+       public byte DigitSubstitute;
+       public int dwReserved;
+       public static final int sizeof = OS.SCRIPT_DIGITSUBSTITUTE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_FONTPROPERTIES.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_FONTPROPERTIES.java
new file mode 100644 (file)
index 0000000..1275b55
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_FONTPROPERTIES {
+       public int cBytes;
+       public short wgBlank;
+       public short wgDefault;
+       public short wgInvalid;
+       public short wgKashida;
+       public int iKashidaWidth;
+       public static final int sizeof = OS.SCRIPT_FONTPROPERTIES_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_ITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_ITEM.java
new file mode 100644 (file)
index 0000000..01ff76a
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_ITEM {
+       public int iCharPos;
+       public SCRIPT_ANALYSIS a = new SCRIPT_ANALYSIS();
+       public static final int sizeof = OS.SCRIPT_ITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_LOGATTR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_LOGATTR.java
new file mode 100644 (file)
index 0000000..628ee6f
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_LOGATTR {
+       public boolean fSoftBreak;
+       public boolean fWhiteSpace;
+       public boolean fCharStop;
+       public boolean fWordStop;
+       public boolean fInvalid;
+       public byte fReserved;
+       public static final int sizeof = OS.SCRIPT_LOGATTR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_PROPERTIES.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_PROPERTIES.java
new file mode 100644 (file)
index 0000000..4943140
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_PROPERTIES {
+       public short langid;
+       public boolean fNumeric;
+       public boolean fComplex;
+       public boolean fNeedsWordBreaking;
+       public boolean fNeedsCaretInfo;
+       public byte bCharSet;
+       public boolean fControl;
+       public boolean fPrivateUseArea;
+       public boolean fNeedsCharacterJustify;
+       public boolean fInvalidGlyph;
+       public boolean fInvalidLogAttr;
+       public boolean fCDM;
+       public boolean fAmbiguousCharSet;
+       public boolean fClusterSizeVaries;
+       public boolean fRejectInvalid;
+       public static final int sizeof = OS.SCRIPT_PROPERTIES_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_STATE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCRIPT_STATE.java
new file mode 100644 (file)
index 0000000..36e2300
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCRIPT_STATE {
+       public short uBidiLevel;
+       public boolean fOverrideDirection;
+       public boolean fInhibitSymSwap;
+       public boolean fCharShape;
+       public boolean fDigitSubstitute;
+       public boolean fInhibitLigate;
+       public boolean fDisplayZWG;
+       public boolean fArabicNumContext;
+       public boolean fGcpClusters;
+       public boolean fReserved;
+       public short fEngineReserved;
+       public static final int sizeof = OS.SCRIPT_STATE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCROLLBARINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCROLLBARINFO.java
new file mode 100644 (file)
index 0000000..d57b2e7
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCROLLBARINFO {
+       public int cbSize;
+       public RECT rcScrollBar = new RECT ();
+       public int dxyLineButton;
+       public int xyThumbTop;
+       public int xyThumbBottom;
+       public int reserved;
+       public int [] rgstate = new int [OS.CCHILDREN_SCROLLBAR + 1];
+       public static final int sizeof = OS.SCROLLBARINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCROLLINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SCROLLINFO.java
new file mode 100644 (file)
index 0000000..d8aeeab
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SCROLLINFO {
+       public int cbSize;
+       public int fMask;
+       public int nMin;
+       public int nMax;
+       public int nPage;
+       public int nPos;
+       public int nTrackPos;
+       public static final int sizeof = OS.SCROLLINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHDRAGIMAGE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHDRAGIMAGE.java
new file mode 100644 (file)
index 0000000..66f2552
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public final class SHDRAGIMAGE {
+       public SIZE sizeDragImage = new SIZE ();
+       public POINT ptOffset = new POINT ();
+       /** @field cast=(HBITMAP) */
+       public long hbmpDragImage;
+       public int crColorKey;
+       public static final int sizeof = OS.SHDRAGIMAGE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHELLEXECUTEINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHELLEXECUTEINFO.java
new file mode 100644 (file)
index 0000000..c3ebf66
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SHELLEXECUTEINFO {
+       public int cbSize;
+       public int fMask;
+       /** @field cast=(HWND) */
+       public long hwnd;
+       /** @field cast=(LPCTSTR) */
+       public long lpVerb;
+       /** @field cast=(LPCTSTR) */
+       public long lpFile;
+       /** @field cast=(LPCTSTR) */
+       public long lpParameters;
+       /** @field cast=(LPCTSTR) */
+       public long lpDirectory;
+       public int nShow;
+       /** @field cast=(HINSTANCE) */
+       public long hInstApp;
+       // Optional members
+       /** @field cast=(LPVOID) */
+       public long lpIDList;
+       /** @field cast=(LPCTSTR) */
+       public long lpClass;
+       /** @field cast=(HKEY) */
+       public long hkeyClass;
+       public int dwHotKey;
+//     union {
+//             HANDLE hIcon;
+//             HANDLE hMonitor;
+//     };
+       /** @field cast=(HANDLE) */
+       public long hIcon;
+       /** @field cast=(HANDLE) */
+       public long hProcess;
+       public static final int sizeof = OS.SHELLEXECUTEINFO_sizeof ();
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHFILEINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SHFILEINFO.java
new file mode 100644 (file)
index 0000000..a185867
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SHFILEINFO {
+       /** @field cast=(HICON) */
+       public long hIcon;
+       public int iIcon;
+       public int dwAttributes;
+       public char [] szDisplayName = new char [OS.MAX_PATH];
+       public char [] szTypeName = new char [80];
+       public static int sizeof = OS.SHFILEINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SIZE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SIZE.java
new file mode 100644 (file)
index 0000000..140eebf
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SIZE {
+       public int cx;
+       public int cy;
+       public static final int sizeof = OS.SIZE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/STARTUPINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/STARTUPINFO.java
new file mode 100644 (file)
index 0000000..00780f6
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class STARTUPINFO {
+       public int cb;
+       /** @field cast=(LPTSTR) */
+       public long lpReserved;
+       /** @field cast=(LPTSTR) */
+       public long lpDesktop;
+       /** @field cast=(LPTSTR) */
+       public long lpTitle;
+       public int dwX;
+       public int dwY;
+       public int dwXSize;
+       public int dwYSize;
+       public int dwXCountChars;
+       public int dwYCountChars;
+       public int dwFillAttribute;
+       public int dwFlags;
+       public short wShowWindow;
+       public short cbReserved2;
+       /** @field cast=(LPBYTE) */
+       public long lpReserved2;
+       /** @field cast=(HANDLE) */
+       public long hStdInput;
+       /** @field cast=(HANDLE) */
+       public long hStdOutput;
+       /** @field cast=(HANDLE) */
+       public long hStdError;
+       public static int sizeof = OS.STARTUPINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SYSTEMTIME.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/SYSTEMTIME.java
new file mode 100644 (file)
index 0000000..754460f
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class SYSTEMTIME {
+       public short wYear;
+       public short wMonth;
+       public short wDayOfWeek;
+       public short wDay;
+       public short wHour;
+       public short wMinute;
+       public short wSecond;
+       public short wMilliseconds;
+       public static final int sizeof = OS.SYSTEMTIME_sizeof ();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TBBUTTON.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TBBUTTON.java
new file mode 100644 (file)
index 0000000..b2f17c6
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TBBUTTON {
+       public int iBitmap;
+       public int idCommand;
+       public byte fsState;
+       public byte fsStyle;
+       public long dwData;
+       public long iString;
+       public static final int sizeof = OS.TBBUTTON_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TBBUTTONINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TBBUTTONINFO.java
new file mode 100644 (file)
index 0000000..db1c8bb
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TBBUTTONINFO {
+       public int cbSize;
+       public int dwMask;
+       public int idCommand;
+       public int iImage;
+       public byte fsState;
+       public byte fsStyle;
+       public short cx;
+       public long lParam;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+       public int cchText;
+       public static final int sizeof = OS.TBBUTTONINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCHAR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCHAR.java
new file mode 100644 (file)
index 0000000..4713177
--- /dev/null
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+import java.util.Arrays;
+
+/**
+ * This class implements the conversions between unicode characters
+ * and the <em>platform supported</em> representation for characters.
+ * <p>
+ * Note that unicode characters which can not be found in the platform
+ * encoding will be converted to an arbitrary platform specific character.
+ * </p>
+ *
+ * @jniclass flags=no_gen
+ */
+public class TCHAR {
+       public char [] chars;
+
+public final static int sizeof = 2;
+
+public TCHAR (int codePage, int length) {
+       chars = new char [length];
+}
+
+public TCHAR (int codePage, char ch, boolean terminate) {
+       this (codePage, terminate ? new char [] {ch, '\0'} : new char [] {ch}, false);
+}
+
+public TCHAR (int codePage, char [] chars, boolean terminate) {
+       int charCount = chars.length;
+       if (terminate) {
+               if (charCount == 0 || (charCount > 0 && chars [charCount - 1] != 0)) {
+                       char [] newChars = new char [charCount + 1];
+                       System.arraycopy (chars, 0, newChars, 0, charCount);
+                       chars = newChars;
+               }
+       }
+       this.chars = chars;
+}
+
+public TCHAR (int codePage, String string, boolean terminate) {
+       this (codePage, getChars (string, terminate), false);
+}
+
+static char [] getChars (String string, boolean terminate) {
+       int length = string.length ();
+       char [] chars = new char [length + (terminate ? 1 : 0)];
+       string.getChars (0, length, chars, 0);
+       return chars;
+}
+
+public void clear() {
+       Arrays.fill (chars, (char) 0);
+}
+
+public int length () {
+       return chars.length;
+}
+
+public int strlen () {
+       for (int i=0; i<chars.length; i++) {
+               if (chars [i] == '\0') return i;
+       }
+       return chars.length;
+}
+
+public int tcharAt (int index) {
+       return chars [index];
+}
+
+@Override
+public String toString () {
+       return toString (0, length ());
+}
+
+public String toString (int start, int length) {
+       return new String (chars, start, length);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCHITTESTINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCHITTESTINFO.java
new file mode 100644 (file)
index 0000000..bc4638f
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TCHITTESTINFO {
+//     POINT pt;
+       /** @field accessor=pt.x */
+       public int x;
+       /** @field accessor=pt.y */
+       public int y;
+       public int flags;
+       public static int sizeof = OS.TCHITTESTINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TCITEM.java
new file mode 100644 (file)
index 0000000..b9b1b70
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TCITEM {
+       public int mask;
+       public int dwState;
+       public int dwStateMask;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+       public int cchTextMax;
+       public int iImage;
+       public long lParam;
+       public static final int sizeof = OS.TCITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TEXTMETRIC.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TEXTMETRIC.java
new file mode 100644 (file)
index 0000000..e190d23
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TEXTMETRIC {
+       public int tmHeight;
+       public int tmAscent;
+       public int tmDescent;
+       public int tmInternalLeading;
+       public int tmExternalLeading;
+       public int tmAveCharWidth;
+       public int tmMaxCharWidth;
+       public int tmWeight;
+       public int tmOverhang;
+       public int tmDigitizedAspectX;
+       public int tmDigitizedAspectY;
+       public char tmFirstChar;
+       public char tmLastChar;
+       public char tmDefaultChar;
+       public char tmBreakChar;
+       public byte tmItalic;
+       public byte tmUnderlined;
+       public byte tmStruckOut;
+       public byte tmPitchAndFamily;
+       public byte tmCharSet;
+       public static final int sizeof = OS.TEXTMETRIC_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TF_DA_COLOR.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TF_DA_COLOR.java
new file mode 100644 (file)
index 0000000..aaa70bb
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TF_DA_COLOR {
+       public int type;
+       public int cr;
+       public static final int sizeof = OS.TF_DA_COLOR_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TF_DISPLAYATTRIBUTE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TF_DISPLAYATTRIBUTE.java
new file mode 100644 (file)
index 0000000..09a91bd
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TF_DISPLAYATTRIBUTE {
+       public TF_DA_COLOR crText = new TF_DA_COLOR();
+       public TF_DA_COLOR crBk = new TF_DA_COLOR();
+       public int lsStyle;
+       public boolean fBoldLine;
+       public TF_DA_COLOR crLine = new TF_DA_COLOR();
+       public int bAttr;
+       public static final int sizeof = OS.TF_DISPLAYATTRIBUTE_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TOOLINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TOOLINFO.java
new file mode 100644 (file)
index 0000000..e14f703
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TOOLINFO {
+       public int cbSize;
+       public int uFlags;
+       /** @field cast=(HWND) */
+       public long hwnd;
+       public long uId;
+//     public RECT rect;
+       /** @field accessor=rect.left */
+       public int left;
+       /** @field accessor=rect.top */
+       public int top;
+       /** @field accessor=rect.right */
+       public int right;
+       /** @field accessor=rect.bottom */
+       public int bottom;
+       /** @field cast=(HINSTANCE) */
+       public long hinst;
+       /** @field cast=(LPTSTR) */
+       public long lpszText;
+       public long lParam;
+       /** @field cast=(void *) */
+       public long lpReserved;
+       public static int sizeof = OS.TOOLINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TOUCHINPUT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TOUCHINPUT.java
new file mode 100644 (file)
index 0000000..84c3093
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TOUCHINPUT {
+       public int x;
+       public int y;
+       /** @field cast=(HWND) */
+       public long    hSource;
+       public int dwID;
+       public int dwFlags;
+       public int dwMask;
+       public int dwTime;
+       public long dwExtraInfo;
+       public int cxContact;
+       public int cyContact;
+       public static final int sizeof = OS.TOUCHINPUT_sizeof();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TRACKMOUSEEVENT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TRACKMOUSEEVENT.java
new file mode 100644 (file)
index 0000000..b56fa1f
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TRACKMOUSEEVENT {
+       public int cbSize;
+       public int dwFlags;
+       /** @field cast=(HWND) */
+       public long hwndTrack;
+       public int dwHoverTime;
+       public static final int sizeof = OS.TRACKMOUSEEVENT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TRIVERTEX.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TRIVERTEX.java
new file mode 100644 (file)
index 0000000..66bab8a
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TRIVERTEX {
+       public int x;
+       public int y;
+       public short Red;
+       public short Green;
+       public short Blue;
+       public short Alpha;
+       public static final int sizeof = OS.TRIVERTEX_sizeof ();
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVHITTESTINFO.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVHITTESTINFO.java
new file mode 100644 (file)
index 0000000..0d3b85e
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TVHITTESTINFO {
+//     POINT pt;
+       /** @field accessor=pt.x */
+       public int x;
+       /** @field accessor=pt.y */
+       public int y;
+       public int flags;
+       /** @field cast=(HTREEITEM) */
+       public long hItem;
+       public static int sizeof = OS.TVHITTESTINFO_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVINSERTSTRUCT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVINSERTSTRUCT.java
new file mode 100644 (file)
index 0000000..59a332a
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TVINSERTSTRUCT {
+       /** @field cast=(HTREEITEM) */
+       public long hParent;
+       /** @field cast=(HTREEITEM) */
+       public long hInsertAfter;
+//     public TVITEMEX item;
+       /** @field accessor=item.mask */
+       public int mask;
+       /** @field accessor=item.hItem,cast=(HTREEITEM) */
+       public long hItem;
+       /** @field accessor=item.state */
+       public int state;
+       /** @field accessor=item.stateMask */
+       public int stateMask;
+       /** @field accessor=item.pszText,cast=(LPTSTR) */
+       public long pszText;
+       /** @field accessor=item.cchTextMax */
+       public int cchTextMax;
+       /** @field accessor=item.iImage */
+       public int iImage;
+       /** @field accessor=item.iSelectedImage */
+       public int iSelectedImage;
+       /** @field accessor=item.cChildren */
+       public int cChildren;
+       /** @field accessor=item.lParam */
+       public long lParam;
+       /** @field accessor=itemex.iIntegral */
+       public int iIntegral;
+       public static final int sizeof = OS.TVINSERTSTRUCT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVITEM.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVITEM.java
new file mode 100644 (file)
index 0000000..8952603
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TVITEM {
+       public int mask;
+       /** @field cast=(HTREEITEM) */
+       public long hItem;
+       public int state;
+       public int stateMask;
+       /** @field cast=(LPTSTR) */
+       public long pszText;
+       public int cchTextMax;
+       public int iImage;
+       public int iSelectedImage;
+       public int cChildren;
+       public long lParam;
+       public static final int sizeof = OS.TVITEM_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVITEMEX.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVITEMEX.java
new file mode 100644 (file)
index 0000000..9a3a813
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TVITEMEX extends TVITEM {
+       public int iIntegral;
+       public static final int sizeof = OS.TVITEMEX_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVSORTCB.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/TVSORTCB.java
new file mode 100644 (file)
index 0000000..fd9ff29
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class TVSORTCB {
+       /** @field cast=(HTREEITEM) */
+       public long hParent;
+       /** @field cast=(PFNTVCOMPARE) */
+       public long lpfnCompare;
+       /** @field cast=(LPARAM) */
+       public long lParam;
+       public static final int sizeof = OS.TVSORTCB_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/UDACCEL.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/UDACCEL.java
new file mode 100644 (file)
index 0000000..438b264
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class UDACCEL {
+       public int nSec;
+       public int nInc;
+       public static final int sizeof = OS.UDACCEL_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WINDOWPLACEMENT.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WINDOWPLACEMENT.java
new file mode 100644 (file)
index 0000000..281c71f
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class WINDOWPLACEMENT {
+       public int length;
+       public int flags;
+       public int showCmd;
+//     POINT ptMinPosition;
+       /** @field accessor=ptMinPosition.x */
+       public int ptMinPosition_x;
+       /** @field accessor=ptMinPosition.y */
+       public int ptMinPosition_y;
+//     POINT ptMaxPosition;
+       /** @field accessor=ptMaxPosition.x */
+       public int ptMaxPosition_x;
+       /** @field accessor=ptMaxPosition.y */
+       public int ptMaxPosition_y;
+//     RECT  rcNormalPosition;
+       /** @field accessor=rcNormalPosition.left */
+       public int left;
+       /** @field accessor=rcNormalPosition.top */
+       public int top;
+       /** @field accessor=rcNormalPosition.right */
+       public int right;
+       /** @field accessor=rcNormalPosition.bottom */
+       public int bottom;
+       public static final int sizeof = OS.WINDOWPLACEMENT_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WINDOWPOS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WINDOWPOS.java
new file mode 100644 (file)
index 0000000..cb9d336
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class WINDOWPOS {
+       /** @field cast=(HWND) */
+       public long hwnd;
+       /** @field cast=(HWND) */
+       public long hwndInsertAfter;
+       public int x;
+       public int y;
+       public int cx;
+       public int cy;
+       public int flags;
+       public static final int sizeof = OS.WINDOWPOS_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WNDCLASS.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/WNDCLASS.java
new file mode 100644 (file)
index 0000000..0299807
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+public class WNDCLASS {
+       public int style;
+       /** @field cast=(WNDPROC) */
+       public long lpfnWndProc;
+       public int cbClsExtra;
+       public int cbWndExtra;
+       /** @field cast=(HINSTANCE) */
+       public long hInstance;
+       /** @field cast=(HICON) */
+       public long hIcon;
+       /** @field cast=(HCURSOR) */
+       public long hCursor;
+       /** @field cast=(HBRUSH) */
+       public long hbrBackground;
+       /** @field cast=(LPCTSTR) */
+       public long lpszMenuName;
+       /** @field cast=(LPCTSTR) */
+       public long lpszClassName;
+       public static final int sizeof = OS.WNDCLASS_sizeof ();
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/win32/package.html
new file mode 100644 (file)
index 0000000..1ee56b6
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT internal Win32 implementation classes.
+<h2>
+Package Specification</h2>
+This package contains the classes which represent the Microsoft 
+Win32 platform interface that the win32 variant of SWT is built
+from.
+<p>
+Referencing any of the classes in this package directly guarantees
+that the code is platform specific. Applications should not need to
+reference the classes in this package directly.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FillData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FillData.java
new file mode 100644 (file)
index 0000000..cb1dc26
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+class FillData {
+
+       int defaultWidth = -1, defaultHeight = -1;
+       int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+
+Point computeSize (Control control, int wHint, int hHint, boolean flushCache) {
+       if (flushCache) flushCache();
+       if (wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
+               if (defaultWidth == -1 || defaultHeight == -1) {
+                       Point size = control.computeSize (wHint, hHint, flushCache);
+                       defaultWidth = size.x;
+                       defaultHeight = size.y;
+               }
+               return new Point(defaultWidth, defaultHeight);
+       }
+       if (currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FillLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FillLayout.java
new file mode 100644 (file)
index 0000000..f66f280
--- /dev/null
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * <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.
+ * </p>
+ * <pre>
+ *             FillLayout fillLayout = new FillLayout();
+ *             fillLayout.type = SWT.VERTICAL;
+ *             shell.setLayout(fillLayout);
+ * </pre>
+ *
+ * @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 extends 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 points 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 points 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 points 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 FillLayout () {
+}
+
+/**
+ * Constructs a new instance of this class given the type.
+ *
+ * @param type the type of fill layout
+ *
+ * @since 2.0
+ */
+public FillLayout (int type) {
+       this.type = type;
+}
+
+@Override
+protected Point computeSize (Composite composite, int wHint, int hHint, boolean 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 == SWT.HORIZONTAL && wHint != SWT.DEFAULT) {
+                               w = Math.max (0, (wHint - (count - 1) * spacing) / count);
+                       }
+                       if (type == SWT.VERTICAL && hHint != 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 == SWT.HORIZONTAL) {
+               width = count * maxWidth;
+               if (count != 0) width += (count - 1) * spacing;
+               height = maxHeight;
+       } else {
+               width = maxWidth;
+               height = count * maxHeight;
+               if (count != 0) height += (count - 1) * spacing;
+       }
+       width += marginWidth * 2;
+       height += marginHeight * 2;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       return new Point (width, height);
+}
+
+Point computeChildSize (Control control, int wHint, int hHint, boolean flushCache) {
+       FillData data = (FillData)control.getLayoutData ();
+       if (data == null) {
+               data = new FillData ();
+               control.setLayoutData (data);
+       }
+       Point size = null;
+       if (wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
+               size = data.computeSize (control, wHint, hHint, flushCache);
+       } else {
+               // TEMPORARY CODE
+               int trimX, trimY;
+               if (control instanceof Scrollable) {
+                       Rectangle rect = ((Scrollable) control).computeTrim (0, 0, 0, 0);
+                       trimX = rect.width;
+                       trimY = rect.height;
+               } else {
+                       trimX = trimY = control.getBorderWidth () * 2;
+               }
+               int w = wHint == SWT.DEFAULT ? wHint : Math.max (0, wHint - trimX);
+               int h = hHint == SWT.DEFAULT ? hHint : Math.max (0, hHint - trimY);
+               size = data.computeSize (control, w, h, flushCache);
+       }
+       return size;
+}
+
+@Override
+protected boolean flushCache (Control control) {
+       Object data = control.getLayoutData();
+       if (data != null) ((FillData)data).flushCache();
+       return true;
+}
+
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (index + 1, string.length ());
+}
+
+@Override
+protected void layout (Composite composite, boolean flushCache) {
+       Rectangle rect = composite.getClientArea ();
+       Control [] children = composite.getChildren ();
+       int count = children.length;
+       if (count == 0) return;
+       int width = rect.width - marginWidth * 2;
+       int height = rect.height - marginHeight * 2;
+       if (type == 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 == 0) {
+                               childWidth += extra / 2;
+                       } else {
+                               if (i == 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 == 0) {
+                               childHeight += extra / 2;
+                       } else {
+                               if (i == 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 == SWT.VERTICAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL")+" ";
+       if (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
+       if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
+       if (spacing != 0) string += "spacing="+spacing+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormAttachment.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormAttachment.java
new file mode 100644 (file)
index 0000000..c7bc0ef
--- /dev/null
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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:
+ * </p>
+ * <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>
+ * 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
+ * points, from the attachment position. For example:</p>
+ * <pre>
+ *             FormAttachment attach = new FormAttachment (20, -5);
+ * </pre>
+ * <p>
+ * specifies that the side to which the <code>FormAttachment</code>
+ * object belongs will lie at 20% of the parent composite, minus 5 points.
+ * </p>
+ * <p>
+ * Control sides can also be attached to another control.
+ * For example:</p>
+ * <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 points. 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.
+ *
+ * @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 points, 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 FormAttachment () {
+}
+
+/**
+ * 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 FormAttachment (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 FormAttachment (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 FormAttachment (int numerator, int denominator, int offset) {
+       if (denominator == 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 FormAttachment (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 FormAttachment (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 FormAttachment (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 != 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 == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
+       return ((numerator * value) / denominator) + offset;
+}
+
+int solveY (int value) {
+       if (numerator == 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
+ */
+@Override
+public String toString () {
+       String string = control != null ? control.toString () : numerator + "/" + denominator;
+       return "{y = (" + string + (offset >= 0 ? ")x + " + offset: ")x - " + (-offset))+"}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormData.java
new file mode 100644 (file)
index 0000000..56100f8
--- /dev/null
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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:
+ * </p>
+ * <pre>
+ *             FormData data = new FormData();
+ *             data.left = new FormAttachment(0,5);
+ *             data.right = new FormAttachment(100,-5);
+ *             button.setLayoutData(formData);
+ * </pre>
+ * <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 points. This value
+        * is the wHint passed into Control.computeSize(int, int, boolean)
+        * to determine the preferred size of the control.
+        *
+        * The default value is SWT.DEFAULT.
+        *
+        * @see Control#computeSize(int, int, boolean)
+        */
+       public int width = SWT.DEFAULT;
+       /**
+        * height specifies the preferred height in points. This value
+        * is the hHint passed into Control.computeSize(int, int, boolean)
+        * to determine the preferred size of the control.
+        *
+        * The default value is SWT.DEFAULT.
+        *
+        * @see Control#computeSize(int, int, boolean)
+        */
+       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;
+       boolean isVisited, needed;
+
+/**
+ * Constructs a new instance of FormData using
+ * default values.
+ */
+public FormData () {
+}
+
+/**
+ * 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 FormData (int width, int height) {
+       this.width = width;
+       this.height = height;
+}
+
+void computeSize (Control control, int wHint, int hHint, boolean flushCache) {
+       if (cacheWidth != -1 && cacheHeight != -1) return;
+       if (wHint == this.width && hHint == this.height) {
+               if (defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != 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 == -1 || currentHeight == -1 || wHint != currentWhint || hHint != 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, boolean flushCache) {
+       needed = true;
+       computeSize (control, width, height, flushCache);
+       return cacheWidth;
+}
+
+int getHeight (Control control, boolean flushCache) {
+       computeSize (control, width, height, flushCache);
+       return cacheHeight;
+}
+
+FormAttachment getBottomAttachment (Control control, int spacing, boolean flushCache) {
+       if (cacheBottom != null) return cacheBottom;
+       if (isVisited) return cacheBottom = new FormAttachment (0, getHeight (control, flushCache));
+       if (bottom == null) {
+               if (top == 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 != null) {
+               if (bottomControl.isDisposed ()) {
+                       bottom.control = bottomControl = null;
+               } else {
+                       if (bottomControl.getParent () != control.getParent ()) {
+                               bottomControl = null;
+                       }
+               }
+       }
+       if (bottomControl == null) return cacheBottom = bottom;
+       isVisited = true;
+       FormData bottomData = (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, boolean flushCache) {
+       if (cacheLeft != null) return cacheLeft;
+       if (isVisited) return cacheLeft = new FormAttachment (0, 0);
+       if (left == null) {
+               if (right == null) return cacheLeft = new FormAttachment (0, 0);
+               return cacheLeft = getRightAttachment (control, spacing, flushCache).minus (getWidth (control, flushCache));
+       }
+       Control leftControl = left.control;
+       if (leftControl != null) {
+               if (leftControl.isDisposed ()) {
+                       left.control = leftControl = null;
+               } else {
+                       if (leftControl.getParent () != control.getParent ()) {
+                               leftControl = null;
+                       }
+               }
+       }
+       if (leftControl == null) return cacheLeft = left;
+       isVisited = true;
+       FormData leftData = (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 = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (index + 1, string.length ());
+}
+
+FormAttachment getRightAttachment (Control control, int spacing, boolean flushCache) {
+       if (cacheRight != null) return cacheRight;
+       if (isVisited) return cacheRight = new FormAttachment (0, getWidth (control, flushCache));
+       if (right == null) {
+               if (left == 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 != null) {
+               if (rightControl.isDisposed ()) {
+                       right.control = rightControl = null;
+               } else {
+                       if (rightControl.getParent () != control.getParent ()) {
+                               rightControl = null;
+                       }
+               }
+       }
+       if (rightControl == null) return cacheRight = right;
+       isVisited = true;
+       FormData rightData = (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, boolean flushCache) {
+       if (cacheTop != null) return cacheTop;
+       if (isVisited) return cacheTop = new FormAttachment (0, 0);
+       if (top == null) {
+               if (bottom == null) return cacheTop = new FormAttachment (0, 0);
+               return cacheTop = getBottomAttachment (control, spacing, flushCache).minus (getHeight (control, flushCache));
+       }
+       Control topControl = top.control;
+       if (topControl != null) {
+               if (topControl.isDisposed ()) {
+                       top.control = topControl = null;
+               } else {
+                       if (topControl.getParent () != control.getParent ()) {
+                               topControl = null;
+                       }
+               }
+       }
+       if (topControl == null) return cacheTop = top;
+       isVisited = true;
+       FormData topData = (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 != SWT.DEFAULT) string += "width="+width+" ";
+       if (height != SWT.DEFAULT) string += "height="+height+" ";
+       if (left != null) string += "left="+left+" ";
+       if (right != null) string += "right="+right+" ";
+       if (top != null) string += "top="+top+" ";
+       if (bottom != null) string += "bottom="+bottom+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/FormLayout.java
new file mode 100644 (file)
index 0000000..92272b0
--- /dev/null
@@ -0,0 +1,392 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>:
+ * </p>
+ * <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>
+ * 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:
+ * </p>
+ * <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>
+ * 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:
+ * </p>
+ * <pre>
+ *             FormData data2 = new FormData();
+ *             data2.left = new FormAttachment(button1);
+ *             data2.right = new FormAttachment(100, 0);
+ *             button2.setLayoutData(data2);
+ * </pre>
+ * <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 extends Layout {
+
+       /**
+        * marginWidth specifies the number of points 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 points 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 points 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 points 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 points 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 points 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 points 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 FormLayout () {
+}
+
+/*
+ * 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 != 0, C != 0 and A != 1, C != 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, boolean flushCache) {
+       FormAttachment top = data.getTopAttachment (control, spacing, flushCache);
+       FormAttachment bottom = data.getBottomAttachment (control, spacing, flushCache);
+       FormAttachment height = bottom.minus (top);
+       if (height.numerator == 0) {
+               if (bottom.numerator == 0) return bottom.offset;
+               if (bottom.numerator == 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, boolean flushCache) {
+       Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache);
+       if (wHint != SWT.DEFAULT) size.x = wHint;
+       if (hHint != SWT.DEFAULT) size.y = hHint;
+       return size;
+}
+
+@Override
+protected boolean flushCache (Control control) {
+       Object data = control.getLayoutData ();
+       if (data != null) ((FormData) data).flushCache ();
+       return true;
+}
+
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (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, boolean flushCache) {
+       FormAttachment left = data.getLeftAttachment (control, spacing, flushCache);
+       FormAttachment right = data.getRightAttachment (control, spacing, flushCache);
+       FormAttachment width = right.minus (left);
+       if (width.numerator == 0) {
+               if (right.numerator == 0) return right.offset;
+               if (right.numerator == 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, boolean 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, boolean move, int x, int y, int width, int height, boolean flushCache) {
+       Control [] children = composite.getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               FormData data = (FormData) child.getLayoutData ();
+               if (data == null) child.setLayoutData (data = new FormData ());
+               if (flushCache) data.flushCache ();
+               data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
+       }
+       boolean [] flush = null;
+       Rectangle [] bounds = null;
+       int w = 0, h = 0;
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               FormData data = (FormData) child.getLayoutData ();
+               if (width != 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 == SWT.DEFAULT && !data.needed) {
+                               int trim = 0;
+                               //TEMPORARY CODE
+                               if (child instanceof Scrollable) {
+                                       Rectangle rect = ((Scrollable) child).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 == null) flush = new boolean [children.length];
+                               flush [i] = true;
+                       }
+                       w = Math.max (x2, w);
+                       if (move) {
+                               if (bounds == 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 = (FormData) child.getLayoutData ();
+               if (height != 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 = (FormData) child.getLayoutData ();
+               if (flush != 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 != 0) string += "marginWidth="+marginWidth+" ";
+       if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
+       if (marginLeft != 0) string += "marginLeft="+marginLeft+" ";
+       if (marginRight != 0) string += "marginRight="+marginRight+" ";
+       if (marginTop != 0) string += "marginTop="+marginTop+" ";
+       if (marginBottom != 0) string += "marginBottom="+marginBottom+" ";
+       if (spacing != 0) string += "spacing="+spacing+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/GridData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/GridData.java
new file mode 100644 (file)
index 0000000..6d5da5c
--- /dev/null
@@ -0,0 +1,577 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * <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:</p>
+ * <pre>
+ *             GridData gridData = new GridData();
+ *             gridData.horizontalAlignment = GridData.FILL;
+ *             gridData.grabExcessHorizontalSpace = true;
+ *             button1.setLayoutData(gridData);
+ *
+ *             gridData = new GridData();
+ *             gridData.horizontalAlignment = GridData.FILL;
+ *             gridData.verticalAlignment = GridData.FILL;
+ *             gridData.grabExcessHorizontalSpace = true;
+ *             gridData.grabExcessVerticalSpace = true;
+ *             gridData.horizontalSpan = 2;
+ *             button2.setLayoutData(gridData);
+ * </pre>
+ * The second is to take advantage of <code>GridData</code> convenience constructors, for example:
+ * <pre>
+ *      button1.setLayoutData(new GridData (SWT.FILL, SWT.CENTER, true, false));
+ *      button2.setLayoutData(new GridData (SWT.FILL, SWT.FILL, true, true, 2, 1));
+ * </pre>
+ * <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 points. This value
+        * is the wHint passed into Control.computeSize(int, int, boolean)
+        * to determine the preferred size of the control.
+        *
+        * The default value is SWT.DEFAULT.
+        *
+        * @see Control#computeSize(int, int, boolean)
+        */
+       public int widthHint = SWT.DEFAULT;
+
+       /**
+        * heightHint specifies the preferred height in points. This value
+        * is the hHint passed into Control.computeSize(int, int, boolean)
+        * to determine the preferred size of the control.
+        *
+        * The default value is SWT.DEFAULT.
+        *
+        * @see Control#computeSize(int, int, boolean)
+        */
+       public int heightHint = SWT.DEFAULT;
+
+       /**
+        * horizontalIndent specifies the number of points 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 points 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 boolean 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 boolean grabExcessVerticalSpace = false;
+
+       /**
+        * minimumWidth specifies the minimum width in points.  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, boolean) where wHint is
+        * determined by GridData.widthHint.
+        *
+        * The default value is 0.
+        *
+        * @since 3.1
+        * @see Control#computeSize(int, int, boolean)
+        * @see GridData#widthHint
+        */
+       public int minimumWidth = 0;
+
+       /**
+        * minimumHeight specifies the minimum height in points.  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, boolean) where hHint is
+        * determined by GridData.heightHint.
+        *
+        * The default value is 0.
+        *
+        * @since 3.1
+        * @see Control#computeSize(int, int, boolean)
+        * @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 boolean 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 final 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 final 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 final 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 final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean)</code>
+        * instead.
+        */
+       public static final 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, boolean, true)</code>
+        * instead.
+        */
+       public static final 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, boolean, true)</code>
+        * instead.
+        */
+       public static final 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, boolean)</code>
+        * instead.
+        */
+       public static final 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 final 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 GridData () {
+       super ();
+}
+
+/**
+ * Constructs a new instance based on the GridData style.
+ * This constructor is not recommended.
+ *
+ * @param style the GridData style
+ */
+public GridData (int style) {
+       super ();
+       if ((style & VERTICAL_ALIGN_BEGINNING) != 0) verticalAlignment = BEGINNING;
+       if ((style & VERTICAL_ALIGN_CENTER) != 0) verticalAlignment = CENTER;
+       if ((style & VERTICAL_ALIGN_FILL) != 0) verticalAlignment = FILL;
+       if ((style & VERTICAL_ALIGN_END) != 0) verticalAlignment = END;
+       if ((style & HORIZONTAL_ALIGN_BEGINNING) != 0) horizontalAlignment = BEGINNING;
+       if ((style & HORIZONTAL_ALIGN_CENTER) != 0) horizontalAlignment = CENTER;
+       if ((style & HORIZONTAL_ALIGN_FILL) != 0) horizontalAlignment = FILL;
+       if ((style & HORIZONTAL_ALIGN_END) != 0) horizontalAlignment = END;
+       grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) != 0;
+       grabExcessVerticalSpace = (style & GRAB_VERTICAL) != 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 GridData (int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean 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 GridData (int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
+       super ();
+       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 GridData (int width, int height) {
+       super ();
+       this.widthHint = width;
+       this.heightHint = height;
+}
+
+void computeSize (Control control, int wHint, int hHint, boolean flushCache) {
+       if (cacheWidth != -1 && cacheHeight != -1) return;
+       if (wHint == this.widthHint && hHint == this.heightHint) {
+               if (defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != 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 == -1 || currentHeight == -1 || wHint != currentWhint || hHint != 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 = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (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 "+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 "+verticalAlignment; break;
+       }
+       String string = getName()+" {";
+       string += "horizontalAlignment="+hAlign+" ";
+       if (horizontalIndent != 0) string += "horizontalIndent="+horizontalIndent+" ";
+       if (horizontalSpan != 1) string += "horizontalSpan="+horizontalSpan+" ";
+       if (grabExcessHorizontalSpace) string += "grabExcessHorizontalSpace="+grabExcessHorizontalSpace+" ";
+       if (widthHint != SWT.DEFAULT) string += "widthHint="+widthHint+" ";
+       if (minimumWidth != 0) string += "minimumWidth="+minimumWidth+" ";
+       string += "verticalAlignment="+vAlign+" ";
+       if (verticalIndent != 0) string += "verticalIndent="+verticalIndent+" ";
+       if (verticalSpan != 1) string += "verticalSpan="+verticalSpan+" ";
+       if (grabExcessVerticalSpace) string += "grabExcessVerticalSpace="+grabExcessVerticalSpace+" ";
+       if (heightHint != SWT.DEFAULT) string += "heightHint="+heightHint+" ";
+       if (minimumHeight != 0) string += "minimumHeight="+minimumHeight+" ";
+       if (exclude) string += "exclude="+exclude+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/GridLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/GridLayout.java
new file mode 100644 (file)
index 0000000..d0bb2c6
--- /dev/null
@@ -0,0 +1,754 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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:</p>
+ * <pre>
+ *             Display display = new Display();
+ *             Shell shell = new Shell(display);
+ *             GridLayout gridLayout = new GridLayout();
+ *             gridLayout.numColumns = 3;
+ *             shell.setLayout(gridLayout);
+ * </pre>
+ * <p>
+ * 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 extends 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 boolean makeColumnsEqualWidth = false;
+
+       /**
+        * marginWidth specifies the number of points 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 points 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 points 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 points 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 points 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 points 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 points 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 points 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
+ * with a single column.
+ */
+public GridLayout () {}
+
+/**
+ * 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 GridLayout (int numColumns, boolean makeColumnsEqualWidth) {
+       this.numColumns = numColumns;
+       this.makeColumnsEqualWidth = makeColumnsEqualWidth;
+}
+
+@Override
+protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
+       Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache);
+       if (wHint != SWT.DEFAULT) size.x = wHint;
+       if (hHint != SWT.DEFAULT) size.y = hHint;
+       return size;
+}
+
+@Override
+protected boolean flushCache (Control control) {
+       Object data = control.getLayoutData ();
+       if (data != null) ((GridData) data).flushCache ();
+       return true;
+}
+
+GridData getData (Control [][] grid, int row, int column, int rowCount, int columnCount, boolean first) {
+       Control control = grid [row] [column];
+       if (control != null) {
+               GridData data = (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 == grid [i][j]) return data;
+                       }
+               }
+       }
+       return null;
+}
+
+@Override
+protected void layout (Composite composite, boolean flushCache) {
+       Rectangle rect = composite.getClientArea ();
+       layout (composite, true, rect.x, rect.y, rect.width, rect.height, flushCache);
+}
+
+Point layout (Composite composite, boolean move, int x, int y, int width, int height, boolean 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 = (GridData) control.getLayoutData ();
+               if (data == null || !data.exclude) {
+                       children [count++] = children [i];
+               }
+       }
+       if (count == 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 = (GridData) child.getLayoutData ();
+               if (data == 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 (child instanceof Scrollable) {
+                                       Rectangle rect = ((Scrollable) child).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 = (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];
+                               System.arraycopy (grid, 0, newGrid, 0, grid.length);
+                               grid = newGrid;
+                       }
+                       if (grid [row] == null) {
+                               grid [row] = new Control [columnCount];
+                       }
+                       while (column < columnCount && grid [row] [column] != null) {
+                               column++;
+                       }
+                       int endCount = column + hSpan;
+                       if (endCount <= columnCount) {
+                               int index = column;
+                               while (index < endCount && grid [row] [index] == null) {
+                                       index++;
+                               }
+                               if (index == endCount) break;
+                               column = index;
+                       }
+                       if (column + hSpan >= columnCount) {
+                               column = 0;
+                               row++;
+                       }
+               }
+               for (int j=0; j<vSpan; j++) {
+                       if (grid [row + j] == 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];
+       boolean [] expandColumn = new boolean [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 != null) {
+                               int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                               if (hSpan == 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 != 0) {
+                                               w = !data.grabExcessHorizontalSpace || data.minimumWidth == 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 != 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 == 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 == 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 != 0) {
+                                               w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+                                               w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing;
+                                               if (w > 0) {
+                                                       if (spanExpandCount == 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 == SWT.DEFAULT || expandCount == 0 ? columnWidth : Math.max (minColumnWidth, availableWidth / columnCount);
+               for (int i=0; i<columnCount; i++) {
+                       expandColumn [i] = expandCount > 0;
+                       widths [i] = columnWidth;
+               }
+       } else {
+               if (width != 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 != 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 != null) {
+                                                       int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                                                       if (hSpan > 1) {
+                                                               if (!data.grabExcessHorizontalSpace || data.minimumWidth != 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 == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+                                                                       w += data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing;
+                                                                       if (w > 0) {
+                                                                               if (spanExpandCount == 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 == 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 != 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 != null) {
+                                       if (data.heightHint == 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 != data.cacheWidth && data.horizontalAlignment == SWT.FILL) || (data.cacheWidth > currentWidth)) {
+                                                       int trim = 0;
+                                                       if (child instanceof Scrollable) {
+                                                               Rectangle rect = ((Scrollable) child).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 == 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];
+       boolean [] expandRow = new boolean [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 != null) {
+                               int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount));
+                               if (vSpan == 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 != 0) {
+                                               h = !data.grabExcessVerticalSpace || data.minimumHeight == 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 != 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 == 0) {
+                                               expandCount++;
+                                               expandRow [i] = true;
+                                       }
+                                       int h = data.cacheHeight + data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing;
+                                       if (h > 0) {
+                                               if (spanExpandCount == 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 != 0) {
+                                               h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+                                               h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing;
+                                               if (h > 0) {
+                                                       if (spanExpandCount == 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 != 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 != 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 != null) {
+                                               int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount));
+                                               if (vSpan > 1) {
+                                                       if (!data.grabExcessVerticalSpace || data.minimumHeight != 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 == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+                                                               h += data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing;
+                                                               if (h > 0) {
+                                                                       if (spanExpandCount == 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 == 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 != 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;
+                                       }
+                                       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;
+                                       }
+                                       Control child = grid [i][j];
+                                       if (child != 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 = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (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 != 1) string += "numColumns="+numColumns+" ";
+       if (makeColumnsEqualWidth) string += "makeColumnsEqualWidth="+makeColumnsEqualWidth+" ";
+       if (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
+       if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
+       if (marginLeft != 0) string += "marginLeft="+marginLeft+" ";
+       if (marginRight != 0) string += "marginRight="+marginRight+" ";
+       if (marginTop != 0) string += "marginTop="+marginTop+" ";
+       if (marginBottom != 0) string += "marginBottom="+marginBottom+" ";
+       if (horizontalSpacing != 0) string += "horizontalSpacing="+horizontalSpacing+" ";
+       if (verticalSpacing != 0) string += "verticalSpacing="+verticalSpacing+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowData.java
new file mode 100644 (file)
index 0000000..755917f
--- /dev/null
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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>:
+ * </p>
+ * <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>
+ *
+ * @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 points. This value
+        * is the wHint passed into Control.computeSize(int, int, boolean)
+        * to determine the preferred size of the control.
+        *
+        * The default value is SWT.DEFAULT.
+        *
+        * @see org.eclipse.swt.widgets.Control#computeSize(int, int, boolean)
+        */
+       public int width = SWT.DEFAULT;
+       /**
+        * height specifies the preferred height in points. This value
+        * is the hHint passed into Control.computeSize(int, int, boolean)
+        * to determine the preferred size of the control.
+        *
+        * The default value is SWT.DEFAULT.
+        *
+        * @see org.eclipse.swt.widgets.Control#computeSize(int, int, boolean)
+        */
+       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 boolean exclude = false;
+
+/**
+ * Constructs a new instance of RowData using
+ * default values.
+ */
+public RowData () {
+}
+
+/**
+ * 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 RowData (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 RowData (Point point) {
+       this (point.x, point.y);
+}
+
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (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 != SWT.DEFAULT) string += "width="+width+" ";
+       if (height != SWT.DEFAULT) string += "height="+height+" ";
+       if (exclude) string += "exclude="+exclude+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowLayout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowLayout.java
new file mode 100644 (file)
index 0000000..cb21fcd
--- /dev/null
@@ -0,0 +1,522 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.layout;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>.</p>
+ * <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>
+ *
+ * @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 extends 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 points 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 points 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 points 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 boolean 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 boolean 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 boolean 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 boolean 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 boolean justify = false;
+
+       /**
+        * marginLeft specifies the number of points 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 points 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 points 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 points 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 with type HORIZONTAL.
+ */
+public RowLayout () {
+}
+
+/**
+ * Constructs a new instance of this class given the type.
+ *
+ * @param type the type of row layout
+ *
+ * @since 2.0
+ */
+public RowLayout (int type) {
+       this.type = type;
+}
+
+@Override
+protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
+       Point extent;
+       if (type == SWT.HORIZONTAL) {
+               extent = layoutHorizontal (composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache);
+       } else {
+               extent = layoutVertical (composite, false, (hHint != SWT.DEFAULT) && wrap, hHint, flushCache);
+       }
+       if (wHint != SWT.DEFAULT) extent.x = wHint;
+       if (hHint != SWT.DEFAULT) extent.y = hHint;
+       return extent;
+}
+
+Point computeSize (Control control, boolean flushCache) {
+       int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
+       RowData data = (RowData) control.getLayoutData ();
+       if (data != null) {
+               wHint = data.width;
+               hHint = data.height;
+       }
+       return control.computeSize (wHint, hHint, flushCache);
+}
+
+@Override
+protected boolean flushCache (Control control) {
+       return true;
+}
+
+String getName () {
+       String string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (index + 1, string.length ());
+}
+
+@Override
+protected void layout (Composite composite, boolean flushCache) {
+       Rectangle clientArea = composite.getClientArea ();
+       if (type == SWT.HORIZONTAL) {
+               layoutHorizontal (composite, true, wrap, clientArea.width, flushCache);
+       } else {
+               layoutVertical (composite, true, wrap, clientArea.height, flushCache);
+       }
+}
+
+Point layoutHorizontal (Composite composite, boolean move, boolean wrap, int width, boolean flushCache) {
+       Control [] children = composite.getChildren ();
+       int count = 0;
+       for (int i=0; i<children.length; i++) {
+               Control control = children [i];
+               RowData data = (RowData) control.getLayoutData ();
+               if (data == null || !data.exclude) {
+                       children [count++] = children [i];
+               }
+       }
+       if (count == 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);
+                       if (width > SWT.DEFAULT && width < size.x && wrap) {
+                               size = child.computeSize (width, child.getLayoutData() == null ? SWT.DEFAULT : ((RowData) child.getLayoutData()).height, 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;
+       boolean 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);
+                       if (width > SWT.DEFAULT && width < size.x && wrap) {
+                               size = child.computeSize (width, child.getLayoutData() == null ? SWT.DEFAULT : ((RowData) child.getLayoutData()).height, flushCache);
+                       }
+                       childWidth = size.x;
+                       childHeight = size.y;
+               }
+               if (wrap && (i != 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] != 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, boolean move, boolean wrap, int height, boolean flushCache) {
+       Control [] children = composite.getChildren ();
+       int count = 0;
+       for (int i=0; i<children.length; i++) {
+               Control control = children [i];
+               RowData data = (RowData) control.getLayoutData ();
+               if (data == null || !data.exclude) {
+                       children [count++] = children [i];
+               }
+       }
+       if (count == 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);
+                       if(height>SWT.DEFAULT && height<size.y && wrap)
+                               size=child.computeSize(child.getLayoutData()==null?SWT.DEFAULT:((RowData)child.getLayoutData()).width,height,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;
+       boolean 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);
+                       if(height>SWT.DEFAULT && height<size.y && wrap)
+                               size=child.computeSize(child.getLayoutData()==null?SWT.DEFAULT:((RowData)child.getLayoutData()).width,height,flushCache);
+                       childWidth = size.x;
+                       childHeight = size.y;
+               }
+               if (wrap && (i != 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] != 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 != SWT.HORIZONTAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL")+" ";
+       if (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
+       if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
+       if (marginLeft != 0) string += "marginLeft="+marginLeft+" ";
+       if (marginTop != 0) string += "marginTop="+marginTop+" ";
+       if (marginRight != 0) string += "marginRight="+marginRight+" ";
+       if (marginBottom != 0) string += "marginBottom="+marginBottom+" ";
+       if (spacing != 0) string += "spacing="+spacing+" ";
+       string += "wrap="+wrap+" ";
+       string += "pack="+pack+" ";
+       string += "fill="+fill+" ";
+       string += "justify="+justify+" ";
+       string = string.trim();
+       string += "}";
+       return string;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/package.html
new file mode 100644 (file)
index 0000000..3da06c4
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT layout classes.
+<h2>
+Package Specification</h2>
+This package contains several standard layout classes which provide
+automated positioning and sizing support for SWT widgets.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OLE.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OLE.java
new file mode 100644 (file)
index 0000000..c10f62a
--- /dev/null
@@ -0,0 +1,442 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+import org.eclipse.swt.*;
+import java.io.File;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.win32.TCHAR;
+
+
+/**
+ *
+ * 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 extends SWT {
+
+       public static final int S_FALSE = 1; // Used for functions that semantically return a Boolean FALSE result to indicate that the function succeeded.
+       public static final int S_OK    = 0; // Function succeeded.
+       public static final int E_FAIL = -2147467259;  // Unspecified failure.
+       public static final int E_INVALIDARG = -2147024809; // Invalid argument
+       public static final int E_NOINTERFACE = -2147467262;  // QueryInterface did not recognize the requested interface.
+       public static final int E_NOTIMPL = -2147467263; // Not implemented
+
+       public static final String IID_IUNKNOWN = "{00000000-0000-0000-C000-000000000046}"; //$NON-NLS-1$
+       public static final String IID_IDISPATCH = "{00020400-0000-0000-C000-000000000046}"; //$NON-NLS-1$
+
+       // Verbs that can be invoked on this client
+       public static final int OLEIVERB_DISCARDUNDOSTATE = -6; // close the OLE object and discard the undo state
+       public static final int OLEIVERB_HIDE             = -3; // hide the OLE object
+       public static final int OLEIVERB_INPLACEACTIVATE  = -5; // open the OLE for editing in-place
+       public static final int OLEIVERB_OPEN             = -2; // open the OLE object for editing in a separate window
+       public static final int OLEIVERB_PRIMARY          =  0; // opens the OLE object for editing
+       public static final int OLEIVERB_PROPERTIES       = -7; // request the OLE object properties dialog
+       public static final int OLEIVERB_SHOW             = -1; // show the OLE object
+       public static final int OLEIVERB_UIACTIVATE       = -4; // activate the UI for the OLE object
+
+       public static final int PROPERTY_CHANGING = 0;
+       public static final int PROPERTY_CHANGED = 1;
+
+       /**
+        * Error code for OleError - No specific error information available
+        */
+       public static final int HRESULT_UNSPECIFIED       = 0;
+       /**
+        * Error code for OleError - Failed to create file
+        */
+       public static final int ERROR_CANNOT_CREATE_FILE = 1000;
+       /**
+        * Error code for OleError - Failed to create Ole Client
+        */
+       public static final 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 final int ERROR_CANNOT_OPEN_FILE = 1002;
+       /**
+        * Error code for OleError - Failed to find requested interface on OLE Object
+        */
+       public static final int ERROR_INTERFACE_NOT_FOUND = 1003;
+       /**
+        * Error code for OleError - Class ID not found in registry
+        */
+       public static final int ERROR_INVALID_CLASSID = 1004;
+       /**
+        * Error code for OleError - Failed to get the class factory for the specified classID
+        */
+       public static final int ERROR_CANNOT_ACCESS_CLASSFACTORY = 1005;
+       /**
+        * Error code for OleError - Failed to create Licensed instance
+        */
+       public static final int ERROR_CANNOT_CREATE_LICENSED_OBJECT = 1006;
+       /**
+        * Error code for OleError - Out of Memory
+        */
+       public static final int ERROR_OUT_OF_MEMORY = 1007;
+       /**
+        * Error code for OleError - Failed to change Variant type
+        */
+       public static final int ERROR_CANNOT_CHANGE_VARIANT_TYPE = 1010;
+       /**
+        * Error code for OleError - Invalid address received for Ole Interface
+        */
+       public static final int ERROR_INVALID_INTERFACE_ADDRESS = 1011;
+       /**
+        * Error code for OleError - Unable to find Application
+        */
+       public static final int ERROR_APPLICATION_NOT_FOUND = 1013;
+       /**
+        * Error code for OleError - Action can not be performed
+        */
+       public static final int ERROR_ACTION_NOT_PERFORMED = 1014;
+
+       public static final int OLECMDF_SUPPORTED    = 1;
+       public static final int OLECMDF_ENABLED      = 2;
+       public static final int OLECMDF_LATCHED      = 4;
+       public static final int OLECMDF_NINCHED      = 8;
+
+       public static final int OLECMDTEXTF_NONE      = 0;
+       public static final int OLECMDTEXTF_NAME      = 1;
+       public static final int OLECMDTEXTF_STATUS    = 2;
+
+       public static final int OLECMDEXECOPT_DODEFAULT        = 0;
+       public static final int OLECMDEXECOPT_PROMPTUSER       = 1;
+       public static final int OLECMDEXECOPT_DONTPROMPTUSER   = 2;
+       public static final int OLECMDEXECOPT_SHOWHELP         = 3;
+
+       public static final int OLECMDID_OPEN              = 1;
+       public static final int OLECMDID_NEW               = 2;
+       public static final int OLECMDID_SAVE              = 3;
+       public static final int OLECMDID_SAVEAS            = 4;
+       public static final int OLECMDID_SAVECOPYAS        = 5;
+       public static final int OLECMDID_PRINT             = 6;
+       public static final int OLECMDID_PRINTPREVIEW      = 7;
+       public static final int OLECMDID_PAGESETUP         = 8;
+       public static final int OLECMDID_SPELL             = 9;
+       public static final int OLECMDID_PROPERTIES        = 10;
+       public static final int OLECMDID_CUT               = 11;
+       public static final int OLECMDID_COPY              = 12;
+       public static final int OLECMDID_PASTE             = 13;
+       public static final int OLECMDID_PASTESPECIAL      = 14;
+       public static final int OLECMDID_UNDO              = 15;
+       public static final int OLECMDID_REDO              = 16;
+       public static final int OLECMDID_SELECTALL         = 17;
+       public static final int OLECMDID_CLEARSELECTION    = 18;
+       public static final int OLECMDID_ZOOM              = 19;
+       public static final int OLECMDID_GETZOOMRANGE      = 20;
+       public static final int OLECMDID_UPDATECOMMANDS    = 21;
+       public static final int OLECMDID_REFRESH           = 22;
+       public static final int OLECMDID_STOP              = 23;
+       public static final int OLECMDID_HIDETOOLBARS      = 24;
+       public static final int OLECMDID_SETPROGRESSMAX    = 25;
+       public static final int OLECMDID_SETPROGRESSPOS    = 26;
+       public static final int OLECMDID_SETPROGRESSTEXT   = 27;
+       public static final int OLECMDID_SETTITLE          = 28;
+       public static final int OLECMDID_SETDOWNLOADSTATE  = 29;
+       public static final 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 final short VT_BOOL = 11;     // Boolean; True=-1, False=0.
+       public static final short VT_BSTR = 8;      // Binary String.
+       public static final short VT_BYREF = 16384; // By reference - must be combined with one of the other VT values
+       public static final short VT_CY = 6;        // Currency.
+       public static final short VT_DATE = 7;      // Date.
+       public static final short VT_DISPATCH = 9;  // IDispatch
+       public static final short VT_EMPTY = 0;     // Not specified.
+       public static final short VT_ERROR = 10;    // Scodes.
+       public static final short VT_I2 = 2;        // 2-byte signed int.
+       public static final short VT_I4 = 3;        // 4-byte signed int.
+       public static final short VT_NULL = 1;      // Null.
+       public static final short VT_R4 = 4;        // 4-byte real.
+       public static final short VT_R8 = 5;        // 8-byte real.
+       public static final short VT_UI1 = 17;      // Unsigned char.
+       public static final short VT_UI4 = 19;      // Unsigned int.
+       public static final short VT_UNKNOWN = 13;  // IUnknown FAR*.
+       public static final short VT_VARIANT = 12;  // VARIANT FAR*.
+       public static final short VT_PTR = 26;
+       public static final short VT_USERDEFINED = 29;
+       public static final short VT_HRESULT = 25;
+       public static final short VT_DECIMAL = 14;
+       public static final short VT_I1 = 16;
+       public static final short VT_UI2 = 18;
+       public static final short VT_I8 = 20;
+       public static final short VT_UI8 = 21;
+       public static final short VT_INT = 22;
+       public static final short VT_UINT = 23;
+       public static final short VT_VOID = 24;
+       public static final short VT_SAFEARRAY = 27;
+       public static final short VT_CARRAY = 28;
+       public static final short VT_LPSTR = 30;
+       public static final short VT_LPWSTR = 31;
+       public static final short VT_RECORD = 36;
+       public static final short VT_FILETIME = 64;
+       public static final short VT_BLOB = 65;
+       public static final short VT_STREAM = 66;
+       public static final short VT_STORAGE = 67;
+       public static final short VT_STREAMED_OBJECT = 68;
+       public static final short VT_STORED_OBJECT = 69;
+       public static final short VT_BLOB_OBJECT = 70;
+       public static final short VT_CF = 71;
+       public static final short VT_CLSID = 72;
+       public static final short VT_VERSIONED_STREAM = 73;
+       public static final short VT_BSTR_BLOB = 0xfff;
+       public static final short VT_VECTOR = 0x1000;
+       public static final short VT_ARRAY = 0x2000;
+
+       /* Ole Function Description Invoke Kind values */
+       public static final int INVOKE_FUNC = 1;
+       public static final int INVOKE_PROPERTYGET = 2;
+       public static final int INVOKE_PROPERTYPUT = 4;
+       public static final int INVOKE_PROPERTYPUTREF = 8;
+
+       /* Ole Function Description function kind */
+       public static final int FUNC_VIRTUAL = 0;
+       public static final int FUNC_PUREVIRTUAL = 1;
+       public static final int FUNC_NONVIRTUAL = 2;
+       public static final int FUNC_STATIC = 3;
+       public static final int FUNC_DISPATCH = 4;
+
+       /* Ole Function Description function flags */
+       public static final short FUNCFLAG_FRESTRICTED = 1;
+       public static final short FUNCFLAG_FSOURCE = 0x2;
+       public static final short FUNCFLAG_FBINDABLE = 0x4;
+       public static final short FUNCFLAG_FREQUESTEDIT = 0x8;
+       public static final short FUNCFLAG_FDISPLAYBIND = 0x10;
+       public static final short FUNCFLAG_FDEFAULTBIND = 0x20;
+       public static final short FUNCFLAG_FHIDDEN = 0x40;
+       public static final short FUNCFLAG_FUSESGETLASTERROR = 0x80;
+       public static final short FUNCFLAG_FDEFAULTCOLLELEM = 0x100;
+       public static final short FUNCFLAG_FUIDEFAULT = 0x200;
+       public static final short FUNCFLAG_FNONBROWSABLE = 0x400;
+       public static final short FUNCFLAG_FREPLACEABLE = 0x800;
+       public static final short FUNCFLAG_FIMMEDIATEBIND = 0x1000;
+
+       /* Ole Function Description calling convention */
+       public static final int CC_FASTCALL = 0;
+       public static final int CC_CDECL = 1;
+       public static final int CC_MSCPASCAL = 2;
+       public static final int CC_PASCAL = 2;
+       public static final int CC_MACPASCAL = 3;
+       public static final int CC_STDCALL = 4;
+       public static final int CC_FPFASTCALL = 5;
+       public static final int CC_SYSCALL = 6;
+       public static final int CC_MPWCDECL = 7;
+       public static final int CC_MPWPASCAL = 8;
+       public static final int CC_MAX = 9;
+
+       static final String ERROR_NOT_IMPLEMENTED_MSG = "Required functionality not currently supported.";//$NON-NLS-1$
+       static final String ERROR_CANNOT_CREATE_FILE_MSG = "Failed to create file.";//$NON-NLS-1$
+       static final String ERROR_CANNOT_CREATE_OBJECT_MSG = "Failed to create Ole Client.";//$NON-NLS-1$
+       static final 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 final String ERROR_INTERFACE_NOT_FOUND_MSG = "Failed to find requested interface on OLE Object.";//$NON-NLS-1$
+       static final String ERROR_INVALID_CLASSID_MSG = "Class ID not found in registry";//$NON-NLS-1$
+       static final String ERROR_CANNOT_ACCESS_CLASSFACTORY_MSG = "Failed to get the class factory for the specified classID";//$NON-NLS-1$
+       static final String ERROR_CANNOT_CREATE_LICENSED_OBJECT_MSG = "Failed to create Licensed instance";//$NON-NLS-1$
+       static final String ERROR_OUT_OF_MEMORY_MSG = "Out of Memory";//$NON-NLS-1$
+       static final String ERROR_CANNOT_CHANGE_VARIANT_TYPE_MSG = "Failed to change Variant type";//$NON-NLS-1$
+       static final String ERROR_INVALID_INTERFACE_ADDRESS_MSG = "Invalid address received for Ole Interface.";//$NON-NLS-1$
+       static final String ERROR_APPLICATION_NOT_FOUND_MSG = "Unable to find Application.";//$NON-NLS-1$
+       static final String ERROR_ACTION_NOT_PERFORMED_MSG = "Action can not be performed.";//$NON-NLS-1$
+
+
+public static void error (int code) {
+       error (code, 0);
+}
+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 != 0) msg += " result = "+hresult;//$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+               case ERROR_CANNOT_CREATE_OBJECT : {
+                       String msg = ERROR_CANNOT_CREATE_OBJECT_MSG;
+                       if (hresult != 0) msg += " result = "+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 != 0) msg += " result = "+hresult;//$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+               case ERROR_INTERFACE_NOT_FOUND : {
+                       String msg = ERROR_INTERFACE_NOT_FOUND_MSG;
+                       if (hresult != 0) msg += " result = "+hresult;//$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+               case ERROR_INVALID_CLASSID : {
+                       String msg = ERROR_INVALID_CLASSID_MSG;
+                       if (hresult != 0) msg += " result = "+hresult;//$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+               case ERROR_CANNOT_ACCESS_CLASSFACTORY : {
+                       String msg = ERROR_CANNOT_ACCESS_CLASSFACTORY_MSG;
+                       if (hresult != 0) msg += " result = "+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 != 0) msg += " result = "+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 != 0) msg += " result = "+hresult;//$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+               case ERROR_APPLICATION_NOT_FOUND : {
+                       String msg = ERROR_APPLICATION_NOT_FOUND_MSG;
+                       if (hresult != 0) msg += " result = "+hresult;//$NON-NLS-1$
+                       throw new SWTException (code, msg);
+               }
+               case ERROR_ACTION_NOT_PERFORMED : {
+                       String msg = ERROR_ACTION_NOT_PERFORMED_MSG;
+                       if (hresult != 0) msg += " result = "+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 != 0) msg += " result = "+hresult; //$NON-NLS-1$
+                       throw new SWTError (code, msg);
+               }
+       }
+
+       /* 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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (extension.length () == 0) return ""; //$NON-NLS-1$
+
+       if (extension.charAt (0) != '.') extension = "." + extension; //$NON-NLS-1$
+
+       /* Use the character encoding for the default locale */
+       TCHAR extensionKey = new TCHAR(0, extension, true);
+       String result = getKeyValue(extensionKey);
+       if (result != null) {
+               // look for "<programID>\NotInsertable"
+               TCHAR notInsertableKey = new TCHAR(0, result+"\\NotInsertable", true); //$NON-NLS-1$
+               if (getKeyExists(notInsertableKey)) return ""; //$NON-NLS-1$
+               // look for "<programID>\Insertable"
+               TCHAR insertableKey = new TCHAR(0, result+"\\Insertable", true); //$NON-NLS-1$
+               if (getKeyExists(insertableKey)) return result;
+               // look for "<programID>\protocol\StdFileEditing\server"
+               TCHAR serverKey = new TCHAR(0, result+"\\protocol\\StdFileEditing\\server", true); //$NON-NLS-1$
+               if (getKeyExists(serverKey)) return result;
+       }
+
+       return ""; //$NON-NLS-1$
+}
+static String getKeyValue (TCHAR key) {
+       long [] phkResult = new long [1];
+       if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) != 0) {
+               return null;
+       }
+       String result = null;
+       int [] lpcbData = new int [1];
+       if (OS.RegQueryValueEx (phkResult [0], (TCHAR) null, 0, null, (TCHAR) null, lpcbData) == 0) {
+               int length = lpcbData [0] / TCHAR.sizeof;
+               if (length == 0) {
+                       result = "";
+               } else {
+                       /* Use the character encoding for the default locale */
+                       TCHAR lpData = new TCHAR (0, length);
+                       if (OS.RegQueryValueEx (phkResult [0], null, 0, null, lpData, lpcbData) == 0) {
+                               length = Math.max(0, lpData.length () - 1);
+                               result = lpData.toString (0, length);
+                       }
+               }
+       }
+       if (phkResult [0] != 0) OS.RegCloseKey (phkResult [0]);
+       return result;
+}
+private static boolean getKeyExists (TCHAR key) {
+       long [] phkResult = new long [1];
+       if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) != 0) {
+               return false;
+       }
+       if (phkResult [0] != 0) 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 boolean isOleFile(File file) {
+       if (file == null || !file.exists() || file.isDirectory())
+               return false;
+
+       return (COM.StgIsStorageFile((file.getAbsolutePath()+"\0").toCharArray()) == COM.S_OK);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleAutomation.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleAutomation.java
new file mode 100644 (file)
index 0000000..5bf1444
--- /dev/null
@@ -0,0 +1,744 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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:
+ *
+ * <pre><code>
+ *     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 != 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 == null || pVarResult.getInt() != OLE.S_OK){
+ *             System.out.println("Failed to add file "+fileName);
+ *     }
+ *
+ *     automation.dispose();
+ *
+ * </code></pre>
+ *
+ * @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 IUnknown objIUnknown;
+       private IDispatch objIDispatch;
+       private String exceptionDescription;
+       private ITypeInfo objITypeInfo;
+
+OleAutomation(IDispatch idispatch) {
+       if (idispatch == null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+       objIDispatch = idispatch;
+       objIDispatch.AddRef();
+
+       long[] ppv = new long[1];
+       /* GetTypeInfo([in] iTInfo, [in] lcid, [out] ppTInfo)
+        * AddRef has already been called on ppTInfo by the callee and must be released by the caller.
+        */
+       int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppv);
+       if (result == OLE.S_OK) {
+               objITypeInfo = new ITypeInfo(ppv[0]);
+       }
+}
+/**
+ * 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 OleAutomation(OleClientSite clientSite) {
+       if (clientSite == null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+       objIDispatch = clientSite.getAutomationObject();
+
+       long[] ppv = new long[1];
+       /* GetTypeInfo([in] iTInfo, [in] lcid, [out] ppTInfo)
+        * AddRef has already been called on ppTInfo by the callee and must be released by the caller.
+        */
+       int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppv);
+       if (result == OLE.S_OK) {
+               objITypeInfo = new ITypeInfo(ppv[0]);
+       }
+}
+/**
+ * Creates an OleAutomation object for the specified <code>progID</code>.
+ *
+ * @param progId the unique program identifier of an 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 SWTException
+ * <ul><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_INTERFACE_NOT_FOUND when the OLE object specified does not implement IDispatch
+ * </ul>
+ *
+ * @since 3.6
+ */
+public OleAutomation(String progId) {
+       try {
+               OS.OleInitialize(0);
+               GUID appClsid = getClassID(progId);
+               if (appClsid == null) {
+                       OS.OleUninitialize();
+                       OLE.error(OLE.ERROR_INVALID_CLASSID);
+               }
+               int flags = COM.CLSCTX_INPROC_SERVER | COM.CLSCTX_LOCAL_SERVER;
+               long[] ppvObject = new long[1];
+               int result = COM.CoCreateInstance(appClsid, 0, flags, COM.IIDIUnknown, ppvObject);
+               if (result != COM.S_OK) {
+                       OS.OleUninitialize();
+                       OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+               }
+               objIUnknown = new IUnknown(ppvObject[0]);
+
+               ppvObject[0] = 0;
+               result = objIUnknown.QueryInterface(COM.IIDIDispatch, ppvObject);
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND);
+               objIDispatch = new IDispatch(ppvObject[0]);
+
+               ppvObject[0] = 0;
+               result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppvObject);
+               if (result == OLE.S_OK) {
+                       objITypeInfo = new ITypeInfo(ppvObject[0]);
+               }
+       } catch (SWTException e) {
+               dispose();
+               throw e;
+       }
+}
+/**
+ * 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 != null){
+               objIDispatch.Release();
+       }
+       objIDispatch = null;
+
+       if (objITypeInfo != null){
+               objITypeInfo.Release();
+       }
+       objITypeInfo = null;
+
+       if (objIUnknown != null){
+               objIUnknown.Release();
+               OS.OleUninitialize();
+       }
+       objIUnknown = null;
+}
+long getAddress() {
+       return objIDispatch.getAddress();
+}
+GUID getClassID(String clientName) {
+       // create a GUID struct to hold the result
+       GUID guid = new GUID();
+
+       // create a null terminated array of char
+       char[] buffer = null;
+       if (clientName != null) {
+               int count = clientName.length();
+               buffer = new char[count + 1];
+               clientName.getChars(0, count, buffer, 0);
+       }
+       if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK){
+               int result = COM.CLSIDFromString(buffer, guid);
+               if (result != COM.S_OK) return null;
+       }
+       return guid;
+}
+/**
+ * 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 == null) return null;
+       String[] file = new String[1];
+       int rc = objITypeInfo.GetDocumentation(dispId, null, null, null, file );
+       if (rc == OLE.S_OK) return file[0];
+       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 == null) return null;
+       String[] doc = new String[1];
+       int rc = objITypeInfo.GetDocumentation(dispId, null, doc, null, null );
+       if (rc == OLE.S_OK) return doc[0];
+       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 == null) return null;
+       long[] ppVarDesc = new long[1];
+       int rc = objITypeInfo.GetVarDesc(index, ppVarDesc);
+       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];
+               OS.MoveMemory(vt, vardesc.elemdescVar_tdesc_union + C.PTR_SIZEOF, 2);
+               data.type = vt[0];
+       }
+       data.flags = vardesc.wVarFlags;
+       data.kind = vardesc.varkind;
+       data.description = getDocumentation(vardesc.memid);
+       data.helpFile = getHelpFile(vardesc.memid);
+
+       objITypeInfo.ReleaseVarDesc(ppVarDesc[0]);
+       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 == null) return null;
+       long[] ppFuncDesc = new long[1];
+       int rc = objITypeInfo.GetFuncDesc(index, ppFuncDesc);
+       if (rc != OLE.S_OK) return null;
+       FUNCDESC funcdesc = new FUNCDESC();
+       COM.MoveMemory(funcdesc, ppFuncDesc[0], FUNCDESC.sizeof);
+
+       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];
+               }
+               //TODO 0- use structures
+               short[] vt = new short[1];
+               OS.MoveMemory(vt, funcdesc.lprgelemdescParam + i * COM.ELEMDESC_sizeof() + C.PTR_SIZEOF, 2);
+               if (vt[0] == OLE.VT_PTR) {
+                       long [] pTypedesc = new long [1];
+                       OS.MoveMemory(pTypedesc, funcdesc.lprgelemdescParam + i * COM.ELEMDESC_sizeof(), C.PTR_SIZEOF);
+                       short[] vt2 = new short[1];
+                       OS.MoveMemory(vt2, pTypedesc[0] + C.PTR_SIZEOF, 2);
+                       vt[0] = (short)(vt2[0] | COM.VT_BYREF);
+               }
+               data.args[i].type = vt[0];
+               short[] wParamFlags = new short[1];
+               OS.MoveMemory(wParamFlags, funcdesc.lprgelemdescParam + i * COM.ELEMDESC_sizeof() + COM.TYPEDESC_sizeof () + C.PTR_SIZEOF, 2);
+               data.args[i].flags = wParamFlags[0];
+       }
+
+       data.returnType = funcdesc.elemdescFunc_tdesc_vt;
+       if (data.returnType == OLE.VT_PTR) {
+               short[] vt = new short[1];
+               OS.MoveMemory(vt, funcdesc.elemdescFunc_tdesc_union + C.PTR_SIZEOF, 2);
+               data.returnType = vt[0];
+       }
+
+       objITypeInfo.ReleaseFuncDesc(ppFuncDesc[0]);
+       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 == null) return null;
+       long [] ppTypeAttr = new long [1];
+       int rc = objITypeInfo.GetTypeAttr(ppTypeAttr);
+       if (rc != OLE.S_OK) return null;
+       TYPEATTR typeattr = new TYPEATTR();
+       COM.MoveMemory(typeattr, ppTypeAttr[0], TYPEATTR.sizeof);
+       objITypeInfo.ReleaseTypeAttr(ppTypeAttr[0]);
+       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 == null) return null;
+       String[] name = new String[1];
+       int rc = objITypeInfo.GetDocumentation(dispId, name, null, null, null );
+       if (rc == OLE.S_OK) return name[0];
+       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 == null) return new String[0];
+       String[] names = new String[maxSize];
+       int[] count = new int[1];
+       int rc = objITypeInfo.GetNames(dispId, names, maxSize, count);
+       if (rc == OLE.S_OK) {
+               String[] newNames = new String[count[0]];
+               System.arraycopy(names, 0, newNames, 0, count[0]);
+               return newNames;
+       }
+       return new String[0];
+}
+/**
+ * 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[] rgdispid = new int[names.length];
+       int result = objIDispatch.GetIDsOfNames(new GUID(), names, names.length, COM.LOCALE_USER_DEFAULT, rgdispid);
+       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();
+       int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, null, null, pVarResult);
+       return (result == 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();
+       int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, null, pVarResult);
+       return (result == 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();
+       int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, rgdispidNamedArgs, pVarResult);
+       return (result == OLE.S_OK) ? pVarResult : null;
+}
+@Override
+public boolean equals(Object object) {
+       if (object == this) return true;
+       if (object instanceof OleAutomation) {
+               if (objIDispatch == null) return false;
+               OleAutomation oleAutomation = ((OleAutomation) object);
+               if (oleAutomation.objIDispatch == null) return false;
+               long address1 = objIDispatch.getAddress();
+               long address2 = oleAutomation.objIDispatch.getAddress();
+               return address1 == address2;
+       }
+       return false;
+}
+/**
+ * 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();
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, pVarResult);
+       return (result == 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();
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, pVarResult);
+       return (result == 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();
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, pVarResult);
+       return (result == COM.S_OK) ? pVarResult : null;
+}
+private int invoke(int dispIdMember, int wFlags, Variant[] rgvarg, int[] rgdispidNamedArgs, Variant pVarResult) {
+
+       // get the IDispatch interface for the control
+       if (objIDispatch == null) return COM.E_FAIL;
+
+       // create a DISPPARAMS structure for the input parameters
+       DISPPARAMS pDispParams = new DISPPARAMS();
+       // store arguments in rgvarg
+       if (rgvarg != null && rgvarg.length > 0) {
+               pDispParams.cArgs = rgvarg.length;
+               pDispParams.rgvarg = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, VARIANT.sizeof * rgvarg.length);
+               int offset = 0;
+               for (int i = rgvarg.length - 1; i >= 0 ; i--) {
+                       rgvarg[i].getData(pDispParams.rgvarg + offset);
+                       offset += VARIANT.sizeof;
+               }
+       }
+
+       // if arguments have ids, store the ids in rgdispidNamedArgs
+       if (rgdispidNamedArgs != null && rgdispidNamedArgs.length > 0) {
+               pDispParams.cNamedArgs = rgdispidNamedArgs.length;
+               pDispParams.rgdispidNamedArgs = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, 4 * rgdispidNamedArgs.length);
+               int offset = 0;
+               for (int i = rgdispidNamedArgs.length; i > 0; i--) {
+                       OS.MoveMemory(pDispParams.rgdispidNamedArgs + offset, new int[] {rgdispidNamedArgs[i-1]}, 4);
+                       offset += 4;
+               }
+       }
+
+       // invoke the method
+       EXCEPINFO excepInfo = new EXCEPINFO();
+       int[] pArgErr = new int[1];
+       long pVarResultAddress = 0;
+       if (pVarResult != null) pVarResultAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+       int result = objIDispatch.Invoke(dispIdMember, new GUID(), COM.LOCALE_USER_DEFAULT, wFlags, pDispParams, pVarResultAddress, excepInfo, pArgErr);
+
+       if (pVarResultAddress != 0){
+               pVarResult.setData(pVarResultAddress);
+               COM.VariantClear(pVarResultAddress);
+               OS.GlobalFree(pVarResultAddress);
+       }
+
+       // free the Dispparams resources
+       if (pDispParams.rgdispidNamedArgs != 0){
+               OS.GlobalFree(pDispParams.rgdispidNamedArgs);
+       }
+       if (pDispParams.rgvarg != 0) {
+               int offset = 0;
+               for (int i = 0, length = rgvarg.length; i < length; i++){
+                       COM.VariantClear(pDispParams.rgvarg + offset);
+                       offset += VARIANT.sizeof;
+               }
+               OS.GlobalFree(pDispParams.rgvarg);
+       }
+
+       // 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) {
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, null);
+       if (result != COM.S_OK)
+               OLE.error(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 != COM.S_OK)
+               OLE.error(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) {
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, null);
+       if (result != COM.S_OK)
+               OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+private void manageExcepinfo(int hResult, EXCEPINFO excepInfo) {
+
+       if (hResult == COM.S_OK){
+               exceptionDescription = "No Error"; //$NON-NLS-1$
+               return;
+       }
+
+       // extract exception info
+       if (hResult == COM.DISP_E_EXCEPTION) {
+               if (excepInfo.bstrDescription != 0){
+                       int size = COM.SysStringByteLen(excepInfo.bstrDescription);
+                       char[] buffer = new char[(size + 1) /2];
+                       OS.MoveMemory(buffer, excepInfo.bstrDescription, size);
+                       exceptionDescription = new String(buffer);
+               } else {
+                       exceptionDescription = "OLE Automation Error Exception "; //$NON-NLS-1$
+                       if (excepInfo.wCode != 0){
+                               exceptionDescription += "code = "+excepInfo.wCode; //$NON-NLS-1$
+                       } else if (excepInfo.scode != 0){
+                               exceptionDescription += "code = "+excepInfo.scode; //$NON-NLS-1$
+                       }
+               }
+       } else {
+               exceptionDescription = "OLE Automation Error HResult : " + hResult; //$NON-NLS-1$
+       }
+
+       // cleanup EXCEPINFO struct
+       if (excepInfo.bstrDescription != 0)
+               COM.SysFreeString(excepInfo.bstrDescription);
+       if (excepInfo.bstrHelpFile != 0)
+               COM.SysFreeString(excepInfo.bstrHelpFile);
+       if (excepInfo.bstrSource != 0)
+               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 boolean setProperty(int dispIdMember, Variant rgvarg) {
+       Variant[] rgvarg2 = new Variant[] {rgvarg};
+       int[] rgdispidNamedArgs = new int[] {COM.DISPID_PROPERTYPUT};
+       int dwFlags = COM.DISPATCH_PROPERTYPUT;
+       if ((rgvarg.getType() & COM.VT_BYREF) == COM.VT_BYREF)
+               dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+       Variant pVarResult = new Variant();
+       int 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 boolean setProperty(int dispIdMember, Variant[] rgvarg) {
+       int[] rgdispidNamedArgs = new int[] {COM.DISPID_PROPERTYPUT};
+       int 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();
+       int result = invoke(dispIdMember, dwFlags, rgvarg, rgdispidNamedArgs, pVarResult);
+       return (result == COM.S_OK);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleClientSite.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleClientSite.java
new file mode 100644 (file)
index 0000000..0cc24ac
--- /dev/null
@@ -0,0 +1,1523 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+/**
+ * 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>
+ * <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 extends Composite {
+
+       // Interfaces for this Ole Client Container
+       COMObject  iOleClientSite;
+       private COMObject  iAdviseSink;
+       private COMObject  iOleInPlaceSite;
+       private COMObject  iOleDocumentSite;
+
+       protected GUID appClsid;
+       private GUID objClsid;
+       private int  refCount;
+
+       // References to the associated Frame.
+       protected 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 boolean isStatic;  // Indicates item's display is static, i.e., a bitmap, metafile, etc.
+       boolean isActivated;
+
+       private RECT borderWidths = new RECT();
+       private RECT indent = new RECT();
+       private boolean inUpdate = false;
+       private boolean inInit = true;
+       private boolean inDispose = false;
+
+       private static final String WORDPROGID = "Word.Document"; //$NON-NLS-1$
+
+       private Listener listener;
+
+       static final int STATE_NONE = 0;
+       static final int STATE_RUNNING = 1;
+       static final int STATE_INPLACEACTIVE = 2;
+       static final int STATE_UIACTIVE = 3;
+       static final int STATE_ACTIVE = 4;
+       int state = STATE_NONE;
+
+protected OleClientSite(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 != null) {
+               if (parent instanceof OleFrame){
+                       frame = (OleFrame)parent;
+                       break;
+               }
+               parent = parent.getParent();
+       }
+       if (frame == null) OLE.error(SWT.ERROR_INVALID_ARGUMENT);
+       frame.AddRef();
+
+       aspect   = COM.DVASPECT_CONTENT;
+       type     = COM.OLEEMBEDDED;
+       isStatic = false;
+
+       listener = new Listener() {
+               private int nestedFocusEvents = 0;
+               @Override
+               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:
+                               nestedFocusEvents++;
+                               boolean hasFocus = isFocusControl();
+                               onFocusIn(e);
+                               nestedFocusEvents--;
+                               /*
+                                * Added additional check below to avoid calling OleFrame#onFocusIn() twice,
+                                * which other wise lead to Main Menu refresh problem as seen in bug 527268
+                                */
+                               if (nestedFocusEvents == 0 && hasFocus == isFocusControl())
+                                       frame.onFocusIn(e);
+                               break;
+                       case SWT.FocusOut:
+                               nestedFocusEvents++;
+                               onFocusOut(e);
+                               nestedFocusEvents--;
+                               if (nestedFocusEvents == 0)
+                                       frame.onFocusOut(e);
+                               break;
+                       case SWT.Paint:    onPaint(e); break;
+                       case SWT.Traverse: onTraverse(e); break;
+                       case SWT.KeyDown: /* required for traversal */ break;
+                       case SWT.Activate: isActivated = true; break;
+                       case SWT.Deactivate: isActivated = false; break;
+                       default :
+                               OLE.error(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);
+       addListener(SWT.Activate, listener);
+       addListener(SWT.Deactivate, 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 OleClientSite(Composite parent, int style, File file) {
+       this(parent, style);
+       try {
+
+               if (file == null || file.isDirectory() || !file.exists())
+                       OLE.error(SWT.ERROR_INVALID_ARGUMENT);
+
+               // Is there an associated CLSID?
+               GUID fileClsid = new GUID();
+               char[] fileName = (file.getAbsolutePath()+"\0").toCharArray();
+               int result = COM.GetClassFile(fileName, fileClsid);
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_INVALID_CLASSID, result);
+               // associated CLSID may not be installed on this machine
+               String progID = getProgID(fileClsid);
+               if (progID == null)     OLE.error(OLE.ERROR_INVALID_CLASSID, result);
+
+               appClsid = fileClsid;
+               OleCreate(appClsid, fileClsid, fileName, file);
+       } 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 an 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 OleClientSite(Composite parent, int style, String progId) {
+       this(parent, style);
+       try {
+               appClsid = getClassID(progId);
+               if (appClsid == null)
+                       OLE.error(OLE.ERROR_INVALID_CLASSID);
+
+               // Open a temporary storage object
+               tempStorage = createTempStorage();
+
+               // Create ole object with storage object
+               long[] address = new long[1];
+               /*
+               * Bug in ICA Client 2.7. The creation of the IOleObject fails if the client
+               * site is provided to OleCreate().  The fix is to detect that the program
+               * id is an ICA Client and do not pass a client site to OleCreate().
+               * IOleObject.SetClientSite() is called later on.
+               */
+               long clientSite = isICAClient() ? 0 : iOleClientSite.getAddress();
+               int result = COM.OleCreate(appClsid, COM.IIDIUnknown, COM.OLERENDER_DRAW, null, clientSite, tempStorage.getAddress(), address);
+               if (result != COM.S_OK)
+                       OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+               objIUnknown = new IUnknown(address[0]);
+
+               // Init sinks
+               addObjectReferences();
+
+               if (COM.OleRun(objIUnknown.getAddress()) == 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public OleClientSite(Composite parent, int style, String progId, File file) {
+       this(parent, style);
+       try {
+               if (file == null || file.isDirectory() || !file.exists()) OLE.error(SWT.ERROR_INVALID_ARGUMENT);
+               appClsid = getClassID(progId);
+               if (appClsid == null) OLE.error(OLE.ERROR_INVALID_CLASSID);
+
+               // Are we opening this file with the preferred OLE object?
+               char[] fileName = (file.getAbsolutePath()+"\0").toCharArray();
+               GUID fileClsid = new GUID();
+               COM.GetClassFile(fileName, fileClsid);
+
+               OleCreate(appClsid, fileClsid, fileName, file);
+       } catch (SWTException e) {
+               dispose();
+               disposeCOMInterfaces();
+               throw e;
+       }
+}
+
+void OleCreate(GUID appClsid, GUID fileClsid, char[] fileName, File file) {
+
+       /* Bug in Windows. In some machines running Windows Vista and
+        * Office 2007, OleCreateFromFile() fails to open files from
+        * Office Word 97 - 2003 and in some other cases it fails to
+        * save files due to a lock. The fix is to detect this case and
+        * create the activeX using CoCreateInstance().
+        */
+       boolean isOffice2007 = isOffice2007(true);
+       if (!isOffice2007 && COM.IsEqualGUID(appClsid, fileClsid)){
+               // Using the same application that created file, therefore, use default mechanism.
+               tempStorage = createTempStorage();
+               // Create ole object with storage object
+               long[] address = new long[1];
+               int result = COM.OleCreateFromFile(appClsid, fileName, COM.IIDIUnknown, COM.OLERENDER_DRAW, null, iOleClientSite.getAddress(), tempStorage.getAddress(), address);
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+               objIUnknown = new IUnknown(address[0]);
+       } 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) == COM.S_OK) {
+                       long[] address = new long[1];
+                       int mode = COM.STGM_READ | COM.STGM_TRANSACTED | COM.STGM_SHARE_EXCLUSIVE;
+                       int result = COM.StgOpenStorage(fileName, 0, mode, 0, 0, address); //Does an AddRef if successful
+                       if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
+                       storage = new IStorage(address[0]);
+               } else {
+                       // Original file is not a Storage file so copy contents to a stream in a new storage file
+                       long[] address = new long[1];
+                       int mode = COM.STGM_READWRITE | COM.STGM_DIRECT | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
+                       int result = COM.StgCreateDocfile(null, mode | COM.STGM_DELETEONRELEASE, 0, address); // Increments ref count if successful
+                       if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
+                       storage = new IStorage(address[0]);
+                       // 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
+                       String streamName = "CONTENTS"; //$NON-NLS-1$
+                       GUID wordGUID = getClassID(WORDPROGID);
+                       if (wordGUID != null && COM.IsEqualGUID(appClsid, wordGUID)) streamName = "WordDocument"; //$NON-NLS-1$
+                       if (isOffice2007) streamName = "Package"; //$NON-NLS-1$
+                       address = new long[1];
+                       result = storage.CreateStream(streamName, mode, 0, 0, address); // Increments ref count if successful
+                       if (result != COM.S_OK) {
+                               storage.Release();
+                               OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
+                       }
+                       IStream stream = new IStream(address[0]);
+                       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){
+                                       long pv = OS.CoTaskMemAlloc(count);
+                                       OS.MoveMemory(pv, buffer, count);
+                                       result = stream.Write(pv, count, null) ;
+                                       OS.CoTaskMemFree(pv);
+                                       if (result != COM.S_OK) {
+                                               fileInput.close();
+                                               stream.Release();
+                                               storage.Release();
+                                               OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
+                                       }
+                               }
+                               fileInput.close();
+                               stream.Commit(COM.STGC_DEFAULT);
+                               stream.Release();
+                       } catch (IOException err) {
+                               stream.Release();
+                               storage.Release();
+                               OLE.error(OLE.ERROR_CANNOT_OPEN_FILE);
+                       }
+               }
+
+               // Open a temporary storage object
+               tempStorage = createTempStorage();
+               // Copy over contents of file
+               int result = storage.CopyTo(0, null, null, tempStorage.getAddress());
+               storage.Release();
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_OPEN_FILE, result);
+
+               // create ole client
+               long[] ppv = new long[1];
+               result = COM.CoCreateInstance(appClsid, 0, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, COM.IIDIUnknown, ppv);
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+               objIUnknown = new IUnknown(ppv[0]);
+               // get the persistent storage of the ole client
+               ppv = new long[1];
+               result = objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv);
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+               IPersistStorage iPersistStorage = new IPersistStorage(ppv[0]);
+               // load the contents of the file into the ole client site
+               result = iPersistStorage.Load(tempStorage.getAddress());
+               iPersistStorage.Release();
+               if (result != COM.S_OK)OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+       }
+
+       // Init sinks
+       addObjectReferences();
+
+       if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK) state = STATE_RUNNING;
+}
+protected void addObjectReferences() {
+       //
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIPersist, ppvObject) == COM.S_OK) {
+               IPersist objIPersist = new IPersist(ppvObject[0]);
+               GUID tempid = new GUID();
+               if (objIPersist.GetClassID(tempid) == COM.S_OK)
+                       objClsid = tempid;
+               objIPersist.Release();
+       }
+
+       //
+       ppvObject = new long[1];
+       int result = objIUnknown.QueryInterface(COM.IIDIViewObject2, ppvObject);
+       if (result != COM.S_OK)
+               OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
+       objIViewObject2 = new IViewObject2(ppvObject[0]);
+       objIViewObject2.SetAdvise(aspect, 0, iAdviseSink.getAddress());
+
+       //
+       ppvObject = new long[1];
+       result = objIUnknown.QueryInterface(COM.IIDIOleObject, ppvObject);
+       if (result != COM.S_OK)
+               OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND, result);
+       objIOleObject = new IOleObject(ppvObject[0]);
+       /*
+        * Feature in Windows. Despite the fact that the clientSite was provided during the
+        * creation of the OleObject (which is required by WMP11 - see bug 173556),
+        * some applications choose to ignore this optional parameter (see bug 211663)
+        * during OleCreate. The fix is to check whether the clientSite has already been set
+        * and set it. Note that setting it twice can result in assert failures.
+        */
+       long[] ppvClientSite = new long[1];
+       result = objIOleObject.GetClientSite(ppvClientSite);
+       if (ppvClientSite[0] == 0) {
+               objIOleObject.SetClientSite(iOleClientSite.getAddress());
+       } else {
+               Release(); // GetClientSite performs an AddRef so we must release it.
+       }
+       int[] pdwConnection = new int[1];
+       objIOleObject.Advise(iAdviseSink.getAddress(), 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.getAddress(), true);
+
+       // Is OLE object linked or embedded?
+       ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIOleLink, ppvObject) == COM.S_OK) {
+               IOleLink objIOleLink = new IOleLink(ppvObject[0]);
+               long[] ppmk = new long[1];
+               if (objIOleLink.GetSourceMoniker(ppmk) == COM.S_OK) {
+                       new IUnknown(ppmk[0]).Release();
+                       type = COM.OLELINKED;
+                       objIOleLink.BindIfRunning();
+               } else {
+                       isStatic = true;
+               }
+               objIOleLink.Release();
+       }
+}
+protected int AddRef() {
+       refCount++;
+       return refCount;
+}
+private int CanInPlaceActivate() {
+       if (aspect == COM.DVASPECT_CONTENT && type == COM.OLEEMBEDDED)
+               return COM.S_OK;
+
+       return COM.S_FALSE;
+}
+private int ContextSensitiveHelp(int fEnterMode) {
+       return COM.S_OK;
+}
+protected void createCOMInterfaces() {
+
+       iOleClientSite = new COMObject(new int[]{2, 0, 0, 0, 3, 1, 0, 1, 0}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return SaveObject();}
+               // method4 GetMoniker - not implemented
+               @Override
+               public long method5(long[] args) {return GetContainer(args[0]);}
+               @Override
+               public long method6(long[] args) {return ShowObject();}
+               @Override
+               public long method7(long[] args) {return OnShowWindow((int)args[0]);}
+               // method8 RequestNewObjectLayout - not implemented
+       };
+
+       iAdviseSink = new COMObject(new int[]{2, 0, 0, 2, 2, 1, 0, 0}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return OnDataChange(args[0], args[1]);}
+               @Override
+               public long method4(long[] args) {return OnViewChange((int)args[0], (int)args[1]);}
+               //method5 OnRename - not implemented
+               @Override
+               public long method6(long[] args) {OnSave();return 0;}
+               @Override
+               public long method7(long[] args) {return OnClose();}
+       };
+
+       iOleInPlaceSite = new COMObject(new int[]{2, 0, 0, 1, 1, 0, 0, 0, 5, 1, 1, 0, 0, 0, 1}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return GetWindow(args[0]);}
+               @Override
+               public long method4(long[] args) {return ContextSensitiveHelp((int)args[0]);}
+               @Override
+               public long method5(long[] args) {return CanInPlaceActivate();}
+               @Override
+               public long method6(long[] args) {return OnInPlaceActivate();}
+               @Override
+               public long method7(long[] args) {return OnUIActivate();}
+               @Override
+               public long method8(long[] args) {return GetWindowContext(args[0], args[1], args[2], args[3], args[4]);}
+               @Override
+               public long method9(long[] args) {return Scroll(args[0]);}
+               @Override
+               public long method10(long[] args) {return OnUIDeactivate((int)args[0]);}
+               @Override
+               public long method11(long[] args) {return OnInPlaceDeactivate();}
+               // method12 DiscardUndoState - not implemented
+               // method13 DeactivateAndUndoChange - not implemented
+               @Override
+               public long method14(long[] args) {return OnPosRectChange(args[0]);}
+       };
+
+       iOleDocumentSite = new COMObject(new int[]{2, 0, 0, 1}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return ActivateMe(args[0]);}
+       };
+}
+protected IStorage createTempStorage() {
+       long[] tempStorage = new long[1];
+       int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_DELETEONRELEASE;
+       int result = COM.StgCreateDocfile(null, grfMode, 0, tempStorage);
+       if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_FILE, result);
+       return new IStorage(tempStorage[0]);
+}
+/**
+ * Deactivates an active in-place object and discards the object's undo state.
+ */
+public void deactivateInPlaceClient() {
+       if (objIOleInPlaceObject != null) {
+               objIOleInPlaceObject.InPlaceDeactivate();
+       }
+}
+private void deleteTempStorage() {
+       //Destroy this item's contents in the temp root IStorage.
+       if (tempStorage != null){
+               tempStorage.Release();
+       }
+       tempStorage = null;
+}
+protected void disposeCOMInterfaces() {
+       if (iOleClientSite != null)
+               iOleClientSite.dispose();
+       iOleClientSite = null;
+
+       if (iAdviseSink != null)
+               iAdviseSink.dispose();
+       iAdviseSink = null;
+
+       if (iOleInPlaceSite != null)
+               iOleInPlaceSite.dispose();
+       iOleInPlaceSite = null;
+
+       if (iOleDocumentSite != null)
+               iOleDocumentSite.dispose();
+       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 == STATE_NONE) {
+               if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK) state = STATE_RUNNING;
+       }
+       if (state == STATE_NONE || isStatic)
+               return COM.E_FAIL;
+
+       // See PR: 1FV9RZW
+       RECT rect = new RECT();
+       OS.GetClientRect(handle, rect);
+       int result = objIOleObject.DoVerb(verb, null, iOleClientSite.getAddress(), 0, handle, rect);
+
+       if (state != 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 in, Variant out) {
+
+       if (objIOleCommandTarget == null) {
+               long[] address = new long[1];
+               if (objIUnknown.QueryInterface(COM.IIDIOleCommandTarget, address) != COM.S_OK)
+                       return OLE.ERROR_INTERFACE_NOT_FOUND;
+               objIOleCommandTarget = new IOleCommandTarget(address[0]);
+       }
+
+       long inAddress = 0;
+       if (in != null){
+               inAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+               in.getData(inAddress);
+       }
+       long outAddress = 0;
+       if (out != null){
+               outAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+               out.getData(outAddress);
+       }
+
+       int result = objIOleCommandTarget.Exec(null, cmdID, options, inAddress, outAddress);
+
+       if (inAddress != 0){
+               COM.VariantClear(inAddress);
+               OS.GlobalFree(inAddress);
+       }
+       if (outAddress != 0) {
+               out.setData(outAddress);
+               COM.VariantClear(outAddress);
+               OS.GlobalFree(outAddress);
+       }
+
+       return result;
+}
+IDispatch getAutomationObject() {
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIDispatch, ppvObject) != COM.S_OK)
+               return null;
+       return new IDispatch(ppvObject[0]);
+}
+protected GUID getClassID(String clientName) {
+       // create a GUID struct to hold the result
+       GUID guid = new GUID();
+
+       // create a null terminated array of char
+       char[] buffer = null;
+       if (clientName != null) {
+               int count = clientName.length();
+               buffer = new char[count + 1];
+               clientName.getChars(0, count, buffer, 0);
+       }
+       if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK){
+               int result = COM.CLSIDFromString(buffer, guid);
+               if (result != COM.S_OK) return null;
+       }
+       return guid;
+}
+private int GetContainer(long 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 != 0)
+               OS.MoveMemory(ppContainer, new long[]{0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+private SIZE getExtent() {
+       SIZE sizel = new SIZE();
+       // get the current size of the embedded OLENatives object
+       if (objIOleObject != null) {
+               if ( objIViewObject2 != null && !COM.OleIsRunning(objIOleObject.getAddress())) {
+                       objIViewObject2.GetExtent(aspect, -1, 0, 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(){
+       return getProgID(appClsid);
+}
+String getProgID(GUID clsid) {
+       if (clsid != null){
+               long[] lplpszProgID = new long[1];
+               if (COM.ProgIDFromCLSID(clsid, lplpszProgID) == COM.S_OK) {
+                       long hMem = lplpszProgID[0];
+                       int length = OS.GlobalSize(hMem);
+                       long ptr = OS.GlobalLock(hMem);
+                       char[] buffer = new char[length];
+                       OS.MoveMemory(buffer, ptr, length);
+                       OS.GlobalUnlock(hMem);
+                       OS.GlobalFree(hMem);
+
+                       String result = new String(buffer);
+                       // remove null terminator
+                       int index = result.indexOf("\0");
+                       return result.substring(0, index);
+               }
+       }
+       return null;
+}
+int ActivateMe(long pViewToActivate) {
+       if (pViewToActivate == 0) {
+               long[] ppvObject = new long[1];
+               if (objIUnknown.QueryInterface(COM.IIDIOleDocument, ppvObject) != COM.S_OK) return COM.E_FAIL;
+               IOleDocument objOleDocument = new IOleDocument(ppvObject[0]);
+               if (objOleDocument.CreateView(iOleInPlaceSite.getAddress(), 0, 0, ppvObject) != COM.S_OK) return COM.E_FAIL;
+               objOleDocument.Release();
+               objDocumentView = new IOleDocumentView(ppvObject[0]);
+       } else {
+               objDocumentView = new IOleDocumentView(pViewToActivate);
+               objDocumentView.AddRef();
+               objDocumentView.SetInPlaceSite(iOleInPlaceSite.getAddress());
+       }
+       objDocumentView.UIActivate(1);//TRUE
+       RECT rect = getRect();
+       objDocumentView.SetRect(rect);
+       objDocumentView.Show(1);//TRUE
+       return COM.S_OK;
+}
+protected int GetWindow(long phwnd) {
+       if (phwnd == 0)
+               return COM.E_INVALIDARG;
+       if (frame == null) {
+               OS.MoveMemory(phwnd, new long[] {0}, C.PTR_SIZEOF);
+               return COM.E_NOTIMPL;
+       }
+
+       // Copy the Window's handle into the memory passed in
+       OS.MoveMemory(phwnd, new long[] {handle}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+RECT getRect() {
+       Rectangle area = DPIUtil.autoScaleUp(getClientArea()); // To Pixels
+       RECT rect = new RECT();
+       rect.left   = area.x;
+       rect.top    = area.y;
+       rect.right  = area.x + area.width;
+       rect.bottom = area.y + area.height;
+       return rect;
+}
+private int GetWindowContext(long ppFrame, long ppDoc, long lprcPosRect, long lprcClipRect, long lpFrameInfo) {
+       if (frame == null || ppFrame == 0)
+               return COM.E_NOTIMPL;
+
+       // fill in frame handle
+       long iOleInPlaceFrame = frame.getIOleInPlaceFrame();
+       OS.MoveMemory(ppFrame, new long[] {iOleInPlaceFrame}, C.PTR_SIZEOF);
+       frame.AddRef();
+
+       // null out document handle
+       if (ppDoc != 0) OS.MoveMemory(ppDoc, new long[] {0}, C.PTR_SIZEOF);
+
+       // fill in position and clipping info
+       RECT rect = getRect();
+       if (lprcPosRect != 0) OS.MoveMemory(lprcPosRect, rect, RECT.sizeof);
+       if (lprcClipRect != 0) 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 != null && !menubar.isDisposed()) {
+               long hwnd = shell.handle;
+               int cAccel = (int)OS.SendMessage(hwnd, OS.WM_APP, 0, 0);
+               if (cAccel != 0) {
+                       long hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+                       if (hAccel != 0) {
+                               frameInfo.cAccelEntries = cAccel;
+                               frameInfo.haccel = hAccel;
+                       }
+               }
+       }
+       COM.MoveMemory(lpFrameInfo, frameInfo, OLEINPLACEFRAMEINFO.sizeof);
+
+       return COM.S_OK;
+}
+boolean isICAClient() {
+       return getProgramID().startsWith("Citrix.ICAClient"); //$NON-NLS-1$
+}
+/**
+ * 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 boolean 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
+       long[] address = new long[1];
+       if (objIOleObject.QueryInterface(COM.IIDIPersistFile, address) != COM.S_OK)
+               return true;
+       IPersistFile permStorage = new IPersistFile(address[0]);
+       // Are the contents of the permanent storage different from the file?
+       int result = permStorage.IsDirty();
+       permStorage.Release();
+       if (result == COM.S_FALSE) return false;
+       return true;
+}
+@Override
+public boolean isFocusControl () {
+       checkWidget ();
+       long focusHwnd = OS.GetFocus();
+       if (objIOleInPlaceObject == null) return (handle == focusHwnd);
+       long[] phwnd = new long[1];
+       objIOleInPlaceObject.GetWindow(phwnd);
+       while (focusHwnd != 0) {
+               if (phwnd[0] == focusHwnd) return true;
+               focusHwnd = OS.GetParent(focusHwnd);
+       }
+       return false;
+}
+private boolean isOffice2007(boolean program) {
+       String programID = getProgramID();
+       if (programID == null) return false;
+       if (program) {
+               int lastDot = programID.lastIndexOf('.');
+               if (lastDot != -1) {
+                       programID = programID.substring(0, lastDot);
+                       GUID guid = getClassID(programID);
+                       programID = getProgID(guid);
+                       if (programID == null) return false;
+               }
+       }
+       if (programID.equals("Word.Document.12")) return true; //$NON-NLS-1$
+       if (programID.equals("Excel.Sheet.12")) return true; //$NON-NLS-1$
+       if (programID.equals("PowerPoint.Show.12")) return true; //$NON-NLS-1$
+       return false;
+}
+private int OnClose() {
+       return COM.S_OK;
+}
+private int OnDataChange(long pFormatetc, long pStgmed) {
+       return COM.S_OK;
+}
+private void onDispose(Event e) {
+       inDispose = true;
+
+       // remove listeners
+       removeListener(SWT.Dispose, listener);
+       removeListener(SWT.FocusIn, listener);
+       removeListener(SWT.FocusOut, listener);
+       removeListener(SWT.Paint, listener);
+       removeListener(SWT.Traverse, listener);
+       removeListener(SWT.KeyDown, listener);
+
+       if (state != STATE_NONE)
+               doVerb(OLE.OLEIVERB_DISCARDUNDOSTATE);
+       deactivateInPlaceClient();
+       releaseObjectInterfaces(); // Note, must release object interfaces before releasing frame
+       deleteTempStorage();
+
+       frame.removeListener(SWT.Resize, listener);
+       frame.removeListener(SWT.Move, listener);
+
+       frame.Release();
+       frame = null;
+}
+void onFocusIn(Event e) {
+       if (inDispose) return;
+       if (state != STATE_UIACTIVE) {
+               long[] ppvObject = new long[1];
+               if (objIUnknown.QueryInterface(COM.IIDIOleInPlaceObject, ppvObject) == COM.S_OK) {
+                       IOleInPlaceObject objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
+                       objIOleInPlaceObject.Release();
+                       doVerb(OLE.OLEIVERB_SHOW);
+               }
+       }
+       if (objIOleInPlaceObject == null) return;
+       if (isFocusControl()) return;
+       long[] phwnd = new long[1];
+       objIOleInPlaceObject.GetWindow(phwnd);
+       if (phwnd[0] == 0) return;
+       OS.SetFocus(phwnd[0]);
+}
+void onFocusOut(Event e) {
+}
+private int OnInPlaceActivate() {
+       state = STATE_INPLACEACTIVE;
+       frame.setCurrentDocument(this);
+       if (objIOleObject == null)
+               return COM.S_OK;
+       long[] ppvObject = new long[1];
+       if (objIOleObject.QueryInterface(COM.IIDIOleInPlaceObject, ppvObject) == COM.S_OK) {
+               objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
+       }
+       return COM.S_OK;
+}
+private int OnInPlaceDeactivate() {
+       if (objIOleInPlaceObject != 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(long lprcPosRect) {
+       Point size = DPIUtil.autoScaleUp(getSize()); // To Pixels
+       setExtent(size.x, size.y);
+       return COM.S_OK;
+}
+private void onPaint(Event e) {
+       if (state == STATE_RUNNING || state == STATE_INPLACEACTIVE) {
+               SIZE size = getExtent();
+               Rectangle area = DPIUtil.autoScaleUp(getClientArea()); // To Pixels
+               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;
+               }
+
+               long pArea = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, RECT.sizeof);
+               OS.MoveMemory(pArea, rect, RECT.sizeof);
+               COM.OleDraw(objIUnknown.getAddress(), aspect, e.gc.handle, pArea);
+               OS.GlobalFree(pArea);
+       }
+}
+private void onResize(Event e) {
+       setBounds();
+}
+private void OnSave() {
+}
+private int OnShowWindow(int fShow) {
+       return COM.S_OK;
+}
+private int OnUIActivate() {
+       if (objIOleInPlaceObject == null) return COM.E_FAIL;
+       state = STATE_UIACTIVE;
+       long[] phwnd = new long[1];
+       if (objIOleInPlaceObject.GetWindow(phwnd) == COM.S_OK) {
+               OS.SetWindowPos(phwnd[0], OS.HWND_TOP, 0, 0, 0, 0, OS.SWP_NOSIZE | OS.SWP_NOMOVE);
+       }
+       return COM.S_OK;
+}
+int OnUIDeactivate(int fUndoable) {
+       // currently, we are ignoring the fUndoable flag
+       if (frame == null || frame.isDisposed()) return COM.S_OK;
+       state = STATE_INPLACEACTIVE;
+       frame.SetActiveObject(0,0);
+       redraw();
+       Shell shell = getShell();
+       if (isFocusControl() || frame.isFocusControl()) {
+               shell.traverse(SWT.TRAVERSE_TAB_NEXT);
+       }
+       Menu menubar = shell.getMenuBar();
+       if (menubar == null || menubar.isDisposed())
+               return COM.S_OK;
+
+       long shellHandle = shell.handle;
+       OS.SetMenu(shellHandle, menubar.handle);
+       return COM.OleSetMenuDescriptor(0, shellHandle, 0, 0, 0);
+}
+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;
+       }
+}
+private int OnViewChange(int dwAspect, int lindex) {
+       return COM.S_OK;
+}
+protected int QueryInterface(long riid, long ppvObject) {
+
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_NOINTERFACE;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+
+       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) {
+               OS.MoveMemory(ppvObject, new long[] {iOleClientSite.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) {
+               OS.MoveMemory(ppvObject, new long[] {iAdviseSink.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) {
+               OS.MoveMemory(ppvObject, new long[] {iOleInPlaceSite.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite )) {
+               String progID = getProgramID();
+               if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$
+                       OS.MoveMemory(ppvObject, new long[] {iOleDocumentSite.getAddress()}, C.PTR_SIZEOF);
+                       AddRef();
+                       return COM.S_OK;
+               }
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       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 == null) {
+               long[] address = new long[1];
+               if (objIUnknown.QueryInterface(COM.IIDIOleCommandTarget, address) != COM.S_OK)
+                       return 0;
+               objIOleCommandTarget = new IOleCommandTarget(address[0]);
+       }
+
+       OLECMD olecmd = new OLECMD();
+       olecmd.cmdID = cmd;
+
+       int result = objIOleCommandTarget.QueryStatus(null, 1, olecmd, 0);
+
+       if (result != COM.S_OK) return 0;
+
+       return olecmd.cmdf;
+}
+protected int Release() {
+       refCount--;
+
+       if (refCount == 0) {
+               disposeCOMInterfaces();
+       }
+       return refCount;
+}
+protected void releaseObjectInterfaces() {
+
+       if (objIOleInPlaceObject!= null)
+               objIOleInPlaceObject.Release();
+       objIOleInPlaceObject = null;
+
+       if (objIOleObject != null) {
+               objIOleObject.Close(COM.OLECLOSE_NOSAVE);
+               objIOleObject.Release();
+       }
+       objIOleObject = null;
+
+       if (objDocumentView != null){
+               objDocumentView.Release();
+       }
+       objDocumentView = null;
+
+       if (objIViewObject2 != null) {
+               objIViewObject2.SetAdvise(aspect, 0, 0);
+               objIViewObject2.Release();
+       }
+       objIViewObject2 = null;
+
+       if (objIOleCommandTarget != null)
+               objIOleCommandTarget.Release();
+       objIOleCommandTarget = null;
+
+       if (objIUnknown != null){
+               objIUnknown.Release();
+       }
+       objIUnknown = null;
+
+       if (COM.FreeUnusedLibraries) {
+               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 boolean save(File file, boolean includeOleInfo) {
+       /*
+       * Bug in Office 2007. Saving Office 2007 documents to compound file storage object
+       * causes the output file to be corrupted. The fix is to detect Office 2007 documents
+       * using the program ID and save only the content of the 'Package' stream.
+       */
+       if (isOffice2007(false)) {
+               return saveOffice2007(file);
+       }
+       if (includeOleInfo)
+               return saveToStorageFile(file);
+       return saveToTraditionalFile(file);
+}
+private boolean saveFromContents(long address, File file) {
+
+       boolean success = false;
+
+       IStream tempContents = new IStream(address);
+       tempContents.AddRef();
+
+       try {
+               FileOutputStream writer = new FileOutputStream(file);
+
+               int increment = 1024 * 4;
+               long pv = OS.CoTaskMemAlloc(increment);
+               int[] pcbWritten = new int[1];
+               while (tempContents.Read(pv, increment, pcbWritten) == COM.S_OK && pcbWritten[0] > 0) {
+                       byte[] buffer = new byte[ pcbWritten[0]];
+                       OS.MoveMemory(buffer, pv, pcbWritten[0]);
+                       writer.write(buffer); // Note: if file does not exist, this will create the file the
+                                             // first time it is called
+                       success = true;
+               }
+               OS.CoTaskMemFree(pv);
+
+               writer.close();
+
+       } catch (IOException err) {
+       }
+
+       tempContents.Release();
+
+       return success;
+}
+private boolean saveFromOle10Native(long address, File file) {
+
+       boolean success = false;
+
+       IStream tempContents = new IStream(address);
+       tempContents.AddRef();
+
+       // The "\1Ole10Native" stream contains a DWORD header whose value is the length
+       // of the native data that follows.
+       long pv = OS.CoTaskMemAlloc(4);
+       int[] size = new int[1];
+       int rc = tempContents.Read(pv, 4, null);
+       OS.MoveMemory(size, pv, 4);
+       OS.CoTaskMemFree(pv);
+       if (rc == COM.S_OK && size[0] > 0) {
+
+               // Read the data
+               byte[] buffer = new byte[size[0]];
+               pv = OS.CoTaskMemAlloc(size[0]);
+               rc = tempContents.Read(pv, size[0], null);
+               OS.MoveMemory(buffer, pv, size[0]);
+               OS.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;
+}
+private boolean saveOffice2007(File file) {
+       if (file == null || file.isDirectory()) return false;
+       if (!updateStorage()) return false;
+       boolean result = false;
+
+       /* Excel fails to open the package stream when the PersistStorage is not in hands off mode */
+       long[] ppv = new long[1];
+       IPersistStorage iPersistStorage = null;
+       if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) == COM.S_OK) {
+               iPersistStorage = new IPersistStorage(ppv[0]);
+               tempStorage.AddRef();
+               iPersistStorage.HandsOffStorage();
+       }
+       long[] address = new long[1];
+       int grfMode = COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE;
+       if (tempStorage.OpenStream("Package", 0, grfMode, 0, address) == COM.S_OK) { //$NON-NLS-1$
+               result = saveFromContents(address[0], file);
+       }
+       if (iPersistStorage != null) {
+               iPersistStorage.SaveCompleted(tempStorage.getAddress());
+               tempStorage.Release();
+               iPersistStorage.Release();
+       }
+       return result;
+}
+/**
+ * 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 boolean 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 == null || file.isDirectory()) return false;
+       if (!updateStorage()) return false;
+
+       // get access to the persistent storage mechanism
+       long[] address = new long[1];
+       if (objIOleObject.QueryInterface(COM.IIDIPersistStorage, address) != COM.S_OK) return false;
+       IPersistStorage permStorage = new IPersistStorage(address[0]);
+       try {
+               address = new long[1];
+               char[] path = (file.getAbsolutePath()+"\0").toCharArray();
+               int mode = COM.STGM_TRANSACTED | COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
+               int result = COM.StgCreateDocfile(path, mode, 0, address); //Does an AddRef if successful
+               if (result != COM.S_OK) return false;
+               IStorage storage =  new IStorage(address[0]);
+               try {
+                       if (COM.OleSave(permStorage.getAddress(), storage.getAddress(), false) == COM.S_OK) {
+                               if (storage.Commit(COM.STGC_DEFAULT) == 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 boolean 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 == null || file.isDirectory())
+               return false;
+       if (!updateStorage())
+               return false;
+
+       long[] address = new long[1];
+       // Look for a CONTENTS stream
+       if (tempStorage.OpenStream("CONTENTS", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$
+               return saveFromContents(address[0], file);
+
+       // Look for Ole 1.0 object stream
+       if (tempStorage.OpenStream("\1Ole10Native", 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, address) == COM.S_OK) //$NON-NLS-1$
+               return saveFromOle10Native(address[0], file);
+
+       return false;
+}
+private int Scroll(long scrollExtent) {
+       return COM.S_OK;
+}
+void setBorderSpace(RECT newBorderwidth) {
+       borderWidths = newBorderwidth;
+       // readjust size and location of client site
+       setBounds();
+}
+void setBounds() {
+       Rectangle area = DPIUtil.autoScaleUp(frame.getClientArea()); // To Pixels
+       setBounds(DPIUtil.autoScaleDown(borderWidths.left),
+                         DPIUtil.autoScaleDown(borderWidths.top),
+                         DPIUtil.autoScaleDown(area.width - borderWidths.left - borderWidths.right),
+                         DPIUtil.autoScaleDown(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 == null || isStatic || inUpdate) return;
+       SIZE currentExtent = getExtent();
+       if (width == currentExtent.cx && height == 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
+       boolean alreadyRunning = COM.OleIsRunning(objIOleObject.getAddress());
+       if (!alreadyRunning)
+               COM.OleRun(objIOleObject.getAddress());
+
+       if (objIOleObject.SetExtent(aspect, newExtent) == 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 = new RECT();
+       indent.left = newIndent.x;
+       indent.right = newIndent.width;
+       indent.top = newIndent.y;
+       indent.bottom = newIndent.height;
+}
+private void setObjectRects() {
+       if (objIOleInPlaceObject == 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.
+        */
+       setBounds();
+       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
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDISpecifyPropertyPages, ppvObject) != COM.S_OK) return;
+       ISpecifyPropertyPages objISPP = new ISpecifyPropertyPages(ppvObject[0]);
+       CAUUID caGUID = new CAUUID();
+       int result = objISPP.GetPages(caGUID);
+       objISPP.Release();
+       if (result != COM.S_OK) return;
+
+       // create a frame in which to display the pages
+       char[] chTitle = null;
+       if (title != null) {
+               chTitle = new char[title.length()];
+               title.getChars(0, title.length(), chTitle, 0);
+       }
+       result = COM.OleCreatePropertyFrame(frame.handle, 10, 10, chTitle, 1, new long[] {objIUnknown.getAddress()}, caGUID.cElems, caGUID.pElems, COM.LOCALE_USER_DEFAULT, 0, 0);
+
+       // free the property page information
+       OS.CoTaskMemFree(caGUID.pElems);
+}
+private boolean updateStorage() {
+
+       if (tempStorage == null) return false;
+
+       long[] ppv = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppv) != COM.S_OK) return false;
+       IPersistStorage iPersistStorage = new IPersistStorage(ppv[0]);
+
+       int result = COM.OleSave(iPersistStorage.getAddress(), tempStorage.getAddress(), true);
+
+       if (result != COM.S_OK){
+               // OleSave will fail for static objects, so do what OleSave does.
+               COM.WriteClassStg(tempStorage.getAddress(), objClsid);
+               result = iPersistStorage.Save(tempStorage.getAddress(), true);
+       }
+
+       tempStorage.Commit(COM.STGC_DEFAULT);
+       result = iPersistStorage.SaveCompleted(0);
+       iPersistStorage.Release();
+
+       return true;
+}
+private SIZE xFormHimetricToPixels(SIZE aSize) {
+       // Return a new Size which is the pixel transformation of a
+       // size in HIMETRIC units.
+
+       long hDC = OS.GetDC(0);
+       int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
+       int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
+       OS.ReleaseDC(0, 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.
+
+       long hDC = OS.GetDC(0);
+       int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
+       int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
+       OS.ReleaseDC(0, 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleControlSite.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleControlSite.java
new file mode 100644 (file)
index 0000000..3d3d0da
--- /dev/null
@@ -0,0 +1,1018 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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>
+ * <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 extends OleClientSite
+{
+       // interfaces for this container
+       private COMObject iOleControlSite;
+       private COMObject iDispatch;
+
+       // supporting Property Change attributes
+       private OlePropertyChangeSink olePropertyChangeSink;
+
+       // supporting Event Sink attributes
+       private OleEventSink[] oleEventSink = new OleEventSink[0];
+       private GUID[] oleEventSinkGUID = new GUID[0];
+       private long[] oleEventSinkIUnknown = new long[0];
+
+       // supporting information for the Control COM object
+       private CONTROLINFO currentControlInfo;
+       private int[] sitePropertyIds = new int[0];
+       private Variant[] sitePropertyValues = new Variant[0];
+
+       private Font font;
+
+       // work around for IE destroying the caret
+       static int SWT_RESTORECARET;
+
+       static final String SHELL_PROG_ID = "Shell.Explorer";   //$NON-NLS-1$
+
+/**
+ * Create an OleControlSite 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>
+ *
+ * @since 3.5
+ */
+public OleControlSite(Composite parent, int style, File file) {
+       super(parent, style, file);
+
+       // Init site properties
+       setSiteProperty(COM.DISPID_AMBIENT_USERMODE, new Variant(true));
+       setSiteProperty(COM.DISPID_AMBIENT_UIDEAD, new Variant(false));
+}
+/**
+ * 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 OleControlSite(Composite parent, int style, String progId) {
+       super(parent, style);
+       try {
+
+               // check for licensing
+               appClsid = getClassID(progId);
+               if (appClsid == null) OLE.error(OLE.ERROR_INVALID_CLASSID);
+
+               long licinfo = getLicenseInfo(appClsid);
+               if (licinfo == 0) {
+
+                       // Open a storage object
+                       tempStorage = createTempStorage();
+
+                       // Create ole object with storage object
+                       long[] address = new long[1];
+                       /*
+                       * Bug in ICA Client 2.7. The creation of the IOleObject fails if the client
+                       * site is provided to OleCreate().  The fix is to detect that the program
+                       * id is an ICA Client and do not pass a client site to OleCreate().
+                       * IOleObject.SetClientSite() is called later on.
+                       */
+                       long clientSite = isICAClient() ? 0 : iOleClientSite.getAddress();
+                       int result = COM.OleCreate(appClsid, COM.IIDIUnknown, COM.OLERENDER_DRAW, null, clientSite, tempStorage.getAddress(), address);
+                       if (result != COM.S_OK)
+                               OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+                       objIUnknown = new IUnknown(address[0]);
+
+               } else {
+                       // Prepare the ClassFactory
+                       long[] ppvObject = new long[1];
+                       try {
+                               int result = COM.CoGetClassObject(appClsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, 0, COM.IIDIClassFactory2, ppvObject);
+                               if (result != COM.S_OK) {
+                                       OLE.error(OLE.ERROR_CANNOT_ACCESS_CLASSFACTORY, result);
+                               }
+                               IClassFactory2 classFactory = new IClassFactory2(ppvObject[0]);
+                               // Create Com Object
+                               ppvObject = new long[1];
+                               result = classFactory.CreateInstanceLic(0, 0, COM.IIDIUnknown, licinfo, ppvObject);
+                               classFactory.Release();
+                               if (result != COM.S_OK)
+                                       OLE.error(OLE.ERROR_CANNOT_CREATE_LICENSED_OBJECT, result);
+                       } finally {
+                               COM.SysFreeString(licinfo);
+                       }
+
+                       objIUnknown = new IUnknown(ppvObject[0]);
+
+                       // Prepare a storage medium
+                       ppvObject = new long[1];
+                       if (objIUnknown.QueryInterface(COM.IIDIPersistStorage, ppvObject) == COM.S_OK) {
+                               IPersistStorage persist = new IPersistStorage(ppvObject[0]);
+                               tempStorage = createTempStorage();
+                               persist.InitNew(tempStorage.getAddress());
+                               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.getAddress()) == OLE.S_OK) state= STATE_RUNNING;
+
+       } catch (SWTError 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.5
+ */
+public OleControlSite(Composite parent, int style, String progId, File file) {
+       super(parent, style, progId, file);
+
+       // Init site properties
+       setSiteProperty(COM.DISPID_AMBIENT_USERMODE, new Variant(true));
+       setSiteProperty(COM.DISPID_AMBIENT_UIDEAD, new Variant(false));
+}
+/**
+ * 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 == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       GUID riid = getDefaultEventSinkGUID(objIUnknown);
+       if (riid != null) {
+               addEventListener(objIUnknown.getAddress(), riid, eventID, listener);
+       }
+
+}
+static GUID getDefaultEventSinkGUID(IUnknown unknown) {
+       // get Event Sink I/F from IProvideClassInfo2
+       long[] ppvObject = new long[1];
+       if (unknown.QueryInterface(COM.IIDIProvideClassInfo2, ppvObject) == COM.S_OK) {
+               IProvideClassInfo2 pci2 = new IProvideClassInfo2(ppvObject[0]);
+               GUID riid = new GUID();
+               int result = pci2.GetGUID(COM.GUIDKIND_DEFAULT_SOURCE_DISP_IID, riid);
+               pci2.Release();
+               if (result == COM.S_OK) return riid;
+       }
+
+       // get Event Sink I/F from IProvideClassInfo
+       if (unknown.QueryInterface(COM.IIDIProvideClassInfo, ppvObject) == COM.S_OK) {
+               IProvideClassInfo pci = new IProvideClassInfo(ppvObject[0]);
+               long[] ppTI = new long[1];
+               long[] ppEI = new long[1];
+               int result = pci.GetClassInfo(ppTI);
+               pci.Release();
+
+               if (result == COM.S_OK && ppTI[0] != 0) {
+                       ITypeInfo classInfo = new ITypeInfo(ppTI[0]);
+                       long[] ppTypeAttr = new long[1];
+                       result = classInfo.GetTypeAttr(ppTypeAttr);
+                       if (result == COM.S_OK  && ppTypeAttr[0] != 0) {
+                               TYPEATTR typeAttribute = new TYPEATTR();
+                               COM.MoveMemory(typeAttribute, ppTypeAttr[0], TYPEATTR.sizeof);
+                               classInfo.ReleaseTypeAttr(ppTypeAttr[0]);
+                               int implMask = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE | COM.IMPLTYPEFLAG_FRESTRICTED;
+                               int implBits = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE;
+
+                               for (int i = 0; i < typeAttribute.cImplTypes; i++) {
+                                       int[] pImplTypeFlags = new int[1];
+                                       if (classInfo.GetImplTypeFlags(i, pImplTypeFlags) == COM.S_OK) {
+                                               if ((pImplTypeFlags[0] & implMask) == implBits) {
+                                                       int[] pRefType = new int[1];
+                                                       if (classInfo.GetRefTypeOfImplType(i, pRefType) == COM.S_OK) {
+                                                               classInfo.GetRefTypeInfo(pRefType[0], ppEI);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       classInfo.Release();
+
+                       if (ppEI[0] != 0) {
+                               ITypeInfo eventInfo = new ITypeInfo(ppEI[0]);
+                               ppTypeAttr = new long[1];
+                               result = eventInfo.GetTypeAttr(ppTypeAttr);
+                               GUID riid = null;
+                               if (result == COM.S_OK && ppTypeAttr[0] != 0) {
+                                       riid = new GUID();
+                                       COM.MoveMemory(riid, ppTypeAttr[0], GUID.sizeof);
+                                       eventInfo.ReleaseTypeAttr(ppTypeAttr[0]);
+                               }
+                               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 == null || automation == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       long address = automation.getAddress();
+       IUnknown unknown = new IUnknown(address);
+       GUID riid = getDefaultEventSinkGUID(unknown);
+       if (riid != null) {
+               addEventListener(address, 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 == null || automation == null || eventSinkId == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       long address = automation.getAddress();
+       if (address == 0) return;
+       char[] buffer = (eventSinkId +"\0").toCharArray();
+       GUID guid = new GUID();
+       if (COM.IIDFromString(buffer, guid) != COM.S_OK) return;
+       addEventListener(address, guid, eventID, listener);
+}
+
+void addEventListener(long iunknown, GUID guid, int eventID, OleListener listener) {
+       if (listener == null || iunknown == 0 || guid == null) OLE.error (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 == oleEventSinkIUnknown[i]) {
+                               index = i;
+                               break;
+                       }
+               }
+       }
+       if (index != -1) {
+               oleEventSink[index].addListener(eventID, listener);
+       } else {
+               int oldLength = oleEventSink.length;
+               OleEventSink[] newOleEventSink = new OleEventSink[oldLength + 1];
+               GUID[] newOleEventSinkGUID = new GUID[oldLength + 1];
+               long[] newOleEventSinkIUnknown = new long[oldLength + 1];
+               System.arraycopy(oleEventSink, 0, newOleEventSink, 0, oldLength);
+               System.arraycopy(oleEventSinkGUID, 0, newOleEventSinkGUID, 0, oldLength);
+               System.arraycopy(oleEventSinkIUnknown, 0, newOleEventSinkIUnknown, 0, oldLength);
+               oleEventSink = newOleEventSink;
+               oleEventSinkGUID = newOleEventSinkGUID;
+               oleEventSinkIUnknown = newOleEventSinkIUnknown;
+
+               oleEventSink[oldLength] = new OleEventSink(this, iunknown, guid);
+               oleEventSinkGUID[oldLength] = guid;
+               oleEventSinkIUnknown[oldLength] = iunknown;
+               oleEventSink[oldLength].AddRef();
+               oleEventSink[oldLength].connect();
+               oleEventSink[oldLength].addListener(eventID, listener);
+
+       }
+}
+@Override
+protected void addObjectReferences() {
+
+       super.addObjectReferences();
+
+       // Get property change notification from control
+       connectPropertyChangeSink();
+
+       // Get access to the Control object
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIOleControl, ppvObject) == COM.S_OK) {
+               IOleControl objIOleControl = new IOleControl(ppvObject[0]);
+               // 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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       olePropertyChangeSink.addListener(propertyID, listener);
+}
+
+private void connectPropertyChangeSink() {
+       olePropertyChangeSink = new OlePropertyChangeSink(this);
+       olePropertyChangeSink.AddRef();
+       olePropertyChangeSink.connect(objIUnknown);
+}
+@Override
+protected void createCOMInterfaces () {
+       super.createCOMInterfaces();
+
+       // register each of the interfaces that this object implements
+       iOleControlSite = new COMObject(new int[]{2, 0, 0, 0, 1, 1, 3, 2, 1, 0}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return OnControlInfoChanged();}
+               // method4 LockInPlaceActive - not implemented
+               // method5 GetExtendedControl - not implemented
+               // method6 TransformCoords - not implemented
+               // method7 Translate Accelerator - not implemented
+               @Override
+               public long method8(long[] args) {return OnFocus((int)args[0]);}
+               // method9 ShowPropertyFrame - not implemented
+       };
+
+       iDispatch = new COMObject(new int[]{2, 0, 0, 1, 3, 5, 8}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               // method3 GetTypeInfoCount - not implemented
+               // method4 GetTypeInfo - not implemented
+               // method5 GetIDsOfNames - not implemented
+               @Override
+               public long method6(long[] args) {return Invoke((int)args[0], args[1], (int)args[2], (int)args[3], args[4], args[5], args[6], args[7]);}
+       };
+}
+private void disconnectEventSinks() {
+
+       for (int i = 0; i < oleEventSink.length; i++) {
+               OleEventSink sink = oleEventSink[i];
+               sink.disconnect();
+               sink.Release();
+       }
+       oleEventSink = new OleEventSink[0];
+       oleEventSinkGUID = new GUID[0];
+       oleEventSinkIUnknown = new long[0];
+}
+private void disconnectPropertyChangeSink() {
+
+       if (olePropertyChangeSink != null) {
+               olePropertyChangeSink.disconnect(objIUnknown);
+               olePropertyChangeSink.Release();
+       }
+       olePropertyChangeSink = null;
+}
+@Override
+protected void disposeCOMInterfaces() {
+       super.disposeCOMInterfaces();
+
+       if (iOleControlSite != null)
+               iOleControlSite.dispose();
+       iOleControlSite = null;
+
+       if (iDispatch != null)
+               iDispatch.dispose();
+       iDispatch = null;
+}
+@Override
+public Color getBackground () {
+
+       if (objIUnknown != 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 != null){
+                       int[] colorRef = new int[1];
+                       if (COM.OleTranslateColor(varBackColor.getInt(), 0, colorRef) == COM.S_OK)
+                               return Color.win32_new(getDisplay(), colorRef[0]);
+               }
+       }
+
+       return super.getBackground();
+}
+@Override
+public Font getFont () {
+       if (font != null && !font.isDisposed()) return font;
+       if (objIUnknown != null) {
+               OleAutomation oleObject= new OleAutomation(this);
+               Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
+               oleObject.dispose();
+
+               if (varDispFont != 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 != null &&
+                               lfHeight != null &&
+                               lfItalic != null &&
+                               lfBold != null){
+                               int style = 3 * lfBold.getInt() + 2 * lfItalic.getInt();
+                               font = new Font(getShell().getDisplay(), lfFaceName.getString(), lfHeight.getInt(), style);
+                               return font;
+                       }
+               }
+       }
+
+       return super.getFont();
+}
+@Override
+public Color getForeground () {
+
+       if (objIUnknown != 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 != null){
+                       int[] colorRef = new int[1];
+                       if (COM.OleTranslateColor(varForeColor.getInt(), 0, colorRef) == COM.S_OK)
+                               return Color.win32_new(getDisplay(), colorRef[0]);
+               }
+       }
+
+       return super.getForeground();
+}
+protected long getLicenseInfo(GUID clsid) {
+       long[] ppvObject = new long[1];
+       if (COM.CoGetClassObject(clsid, COM.CLSCTX_INPROC_HANDLER
+                               | COM.CLSCTX_INPROC_SERVER, 0, COM.IIDIClassFactory, ppvObject) != COM.S_OK) {
+               return 0;
+       }
+       long result = 0;
+       IUnknown unknown = new IUnknown(ppvObject[0]);
+       if (unknown.QueryInterface(COM.IIDIClassFactory2, ppvObject) == COM.S_OK) {
+               IClassFactory2 classFactory = new IClassFactory2(ppvObject[0]);
+               LICINFO licinfo = new LICINFO();
+               if (classFactory.GetLicInfo(licinfo) == COM.S_OK) {
+                       long[] pBstrKey = new long[1];
+                       if (licinfo != null && licinfo.fRuntimeKeyAvail) {
+                               if (classFactory.RequestLicKey(0, pBstrKey) == COM.S_OK) {
+                                       result = pBstrKey[0];
+                               }
+                       }
+               }
+               classFactory.Release();
+       }
+       unknown.Release();
+       return result;
+}
+/**
+ *
+ * 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] == dispId) {
+                       return sitePropertyValues[i];
+               }
+       }
+       return null;
+}
+@Override
+protected int GetWindow(long phwnd) {
+
+       if (phwnd == 0)
+               return COM.E_INVALIDARG;
+       if (frame == null) {
+               OS.MoveMemory(phwnd, new long[] {0}, C.PTR_SIZEOF);
+               return COM.E_NOTIMPL;
+       }
+
+       // Copy the Window's handle into the memory passed in
+       OS.MoveMemory(phwnd, new long[] {handle}, C.PTR_SIZEOF);
+       return COM.S_OK;
+}
+private int Invoke(int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr) {
+       if (pVarResult == 0 || dwFlags != COM.DISPATCH_PROPERTYGET) {
+               if (pExcepInfo != 0) OS.MoveMemory(pExcepInfo, new long [] {0}, C.PTR_SIZEOF);
+               if (pArgErr != 0) OS.MoveMemory(pArgErr, new int[] {0}, 4);
+               return COM.DISP_E_MEMBERNOTFOUND;
+       }
+       Variant result = getSiteProperty(dispIdMember);
+       if (result != null) {
+               if (pVarResult != 0) 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 != 0) OS.MoveMemory(pVarResult, new long [] {0}, C.PTR_SIZEOF);
+                       if (pExcepInfo != 0) OS.MoveMemory(pExcepInfo, new long [] {0}, C.PTR_SIZEOF);
+                       if (pArgErr != 0) OS.MoveMemory(pArgErr, new int[] {0}, 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 != 0) OS.MoveMemory(pVarResult, new long [] {0}, C.PTR_SIZEOF);
+                       if (pExcepInfo != 0) OS.MoveMemory(pExcepInfo, new long [] {0}, C.PTR_SIZEOF);
+                       if (pArgErr != 0) OS.MoveMemory(pArgErr, new int[] {0}, 4);
+                       return COM.E_NOTIMPL;
+
+               default :
+                       if (pVarResult != 0) OS.MoveMemory(pVarResult, new long [] {0}, C.PTR_SIZEOF);
+                       if (pExcepInfo != 0) OS.MoveMemory(pExcepInfo,new long [] {0}, C.PTR_SIZEOF);
+                       if (pArgErr != 0) OS.MoveMemory(pArgErr, new int[] {0}, 4);
+                       return COM.DISP_E_MEMBERNOTFOUND;
+       }
+}
+private int OnControlInfoChanged() {
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIOleControl, ppvObject) == COM.S_OK) {
+               IOleControl objIOleControl = new IOleControl(ppvObject[0]);
+               // 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;
+}
+@Override
+protected int OnUIDeactivate(int fUndoable) {
+       return super.OnUIDeactivate(fUndoable);
+}
+@Override
+void onFocusIn(Event e) {
+       String progID = getProgramID();
+       if (progID == null) return;
+       if (!progID.startsWith(SHELL_PROG_ID)) {
+               super.onFocusIn(e);
+               return;
+       }
+       if (objIOleInPlaceObject == null) return;
+       if (!isActivated) doVerb(OLE.OLEIVERB_UIACTIVATE);
+       if (isFocusControl()) return;
+       long[] phwnd = new long[1];
+       objIOleInPlaceObject.GetWindow(phwnd);
+       if (phwnd[0] == 0) return;
+       OS.SetFocus(phwnd[0]);
+}
+@Override
+void onFocusOut(Event e) {
+       if (objIOleInPlaceObject == null) return;
+       String progID = getProgramID();
+       if (progID == null) return;
+       if (!progID.startsWith(SHELL_PROG_ID)) {
+               super.onFocusOut(e);
+               return;
+       }
+
+       /*
+       * FocusOut is received when focus is reassigned between handles within
+       * our site.  In such cases the site should not be UIDeactivated.
+       */
+       if (isFocusControl()) return;
+
+       /*
+       * 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.
+       */
+       int threadId = OS.GetCurrentThreadId();
+       GUITHREADINFO lpgui1 = new GUITHREADINFO();
+       lpgui1.cbSize = GUITHREADINFO.sizeof;
+       OS.GetGUIThreadInfo(threadId, lpgui1);
+       objIOleInPlaceObject.UIDeactivate();
+       if (SWT_RESTORECARET == 0) {
+               SWT_RESTORECARET = OS.RegisterWindowMessage (new TCHAR (0, "SWT_RESTORECARET", true));
+       }
+       if (lpgui1.hwndCaret != 0) {
+               GUITHREADINFO lpgui2 = new GUITHREADINFO();
+               lpgui2.cbSize = GUITHREADINFO.sizeof;
+               OS.GetGUIThreadInfo(threadId, lpgui2);
+               if (lpgui2.hwndCaret == 0 && lpgui1.hwndCaret == OS.GetFocus()) {
+                       /*
+                       * 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) == 0) {
+                               int width = lpgui1.right - lpgui1.left;
+                               int height = lpgui1.bottom - lpgui1.top;
+                               OS.CreateCaret (lpgui1.hwndCaret, 0, width, height);
+                               OS.SetCaretPos (lpgui1.left, lpgui1.top);
+                               OS.ShowCaret (lpgui1.hwndCaret);
+                       }
+               }
+       } else if (lpgui1.hwndFocus != 0 && lpgui1.hwndFocus == OS.GetFocus()) {
+               OS.SendMessage (lpgui1.hwndFocus, SWT_RESTORECARET, 0, 0);
+       }
+}
+private int OnFocus(int fGotFocus) {
+       return COM.S_OK;
+}
+@Override
+protected int QueryInterface(long riid, long ppvObject) {
+       int result = super.QueryInterface(riid, ppvObject);
+       if (result == COM.S_OK)
+               return result;
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIOleControlSite)) {
+               OS.MoveMemory(ppvObject, new long[] {iOleControlSite.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) {
+               OS.MoveMemory(ppvObject, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+@Override
+protected int Release() {
+       int result = super.Release();
+       if (result == 0) {
+               for (int i = 0; i < sitePropertyIds.length; i++) {
+                       sitePropertyValues[i].dispose();
+               }
+               sitePropertyIds = new int[0];
+               sitePropertyValues = new Variant[0];
+       }
+       return result;
+}
+@Override
+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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+
+       GUID riid = getDefaultEventSinkGUID(objIUnknown);
+       if (riid != null) {
+               removeEventListener(objIUnknown.getAddress(), 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>
+ */
+@Deprecated
+public void removeEventListener(OleAutomation automation, GUID guid, int eventID, OleListener listener) {
+       checkWidget();
+       if (automation == null || listener == null || guid == null) SWT.error (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 == null || listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       long address = automation.getAddress();
+       IUnknown unknown = new IUnknown(address);
+       GUID riid = getDefaultEventSinkGUID(unknown);
+       if (riid != null) {
+               removeEventListener(address, riid, eventID, listener);
+       }
+}
+void removeEventListener(long iunknown, GUID guid, int eventID, OleListener listener) {
+       if (listener == null || guid == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i = 0; i < oleEventSink.length; i++) {
+               if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
+                       if (iunknown == 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 == 1) {
+                                               oleEventSink = new OleEventSink[0];
+                                               oleEventSinkGUID = new GUID[0];
+                                               oleEventSinkIUnknown = new long[0];
+                                       } 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];
+                                               System.arraycopy(oleEventSinkGUID, 0, newOleEventSinkGUID, 0, i);
+                                               System.arraycopy(oleEventSinkGUID, i + 1, newOleEventSinkGUID, i, oldLength - i - 1);
+                                               oleEventSinkGUID = newOleEventSinkGUID;
+
+                                               long[] newOleEventSinkIUnknown = new long[oldLength - 1];
+                                               System.arraycopy(oleEventSinkIUnknown, 0, newOleEventSinkIUnknown, 0, i);
+                                               System.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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       olePropertyChangeSink.removeListener(propertyID, listener);
+}
+@Override
+public void setBackground (Color color) {
+
+       super.setBackground(color);
+
+       //set the background of the ActiveX Control
+       if (objIUnknown != null) {
+               OleAutomation oleObject= new OleAutomation(this);
+               oleObject.setProperty(COM.DISPID_BACKCOLOR, new Variant(color.handle));
+               oleObject.dispose();
+       }
+}
+@Override
+public void setFont (Font font) {
+
+       super.setFont(font);
+
+       //set the font of the ActiveX Control
+       if (objIUnknown != null) {
+
+               OleAutomation oleObject= new OleAutomation(this);
+               Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
+               oleObject.dispose();
+
+               if (varDispFont != 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();
+               }
+       }
+       this.font = font;
+       return;
+}
+@Override
+public void setForeground (Color color) {
+
+       super.setForeground(color);
+
+       //set the foreground of the ActiveX Control
+       if (objIUnknown != null) {
+               OleAutomation oleObject= new OleAutomation(this);
+               oleObject.setProperty(COM.DISPID_FORECOLOR, new Variant(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] == dispId) {
+                       if (sitePropertyValues[i] != null) {
+                               sitePropertyValues[i].dispose();
+                       }
+                       if (value != 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEvent.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEvent.java
new file mode 100644 (file)
index 0000000..cb08f6e
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+import org.eclipse.swt.widgets.Widget;
+
+public class OleEvent {
+       public int type;
+       public Widget widget;
+       public int detail;
+       public boolean doit = true;
+       public Variant[] arguments;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventSink.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventSink.java
new file mode 100644 (file)
index 0000000..cb3e57c
--- /dev/null
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+final class OleEventSink
+{
+       private OleControlSite widget;
+
+       private COMObject iDispatch;
+       private int refCount;
+
+       private IUnknown objIUnknown;
+       private int  eventCookie;
+       private GUID eventGuid;
+
+       private OleEventTable eventTable;
+
+OleEventSink(OleControlSite widget, long iUnknown, GUID riid) {
+
+       this.widget = widget;
+       this.eventGuid = riid;
+       this.objIUnknown = new IUnknown(iUnknown);
+
+       createCOMInterfaces();
+}
+
+void connect () {
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
+               IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
+               long[] ppCP = new long[1];
+               if (cpc.FindConnectionPoint(eventGuid, ppCP) == COM.S_OK) {
+                       IConnectionPoint cp = new IConnectionPoint(ppCP[0]);
+                       int[] pCookie = new int[1];
+                       if (cp.Advise(iDispatch.getAddress(), pCookie) == COM.S_OK)
+                               eventCookie = pCookie[0];
+                       cp.Release();
+               }
+               cpc.Release();
+       }
+}
+void addListener(int eventID, OleListener listener) {
+       if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) eventTable = new OleEventTable ();
+       eventTable.hook(eventID, listener);
+}
+int AddRef() {
+       refCount++;
+       return refCount;
+}
+private void createCOMInterfaces() {
+       iDispatch = new COMObject(new int[]{2, 0, 0, 1, 3, 4, 8}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               // method3 GetTypeInfoCount - not implemented
+               // method4 GetTypeInfo - not implemented
+               // method5 GetIDsOfNames - not implemented
+               @Override
+               public long method6(long[] args) {return Invoke((int)args[0], args[1], (int)args[2], (int)args[3], args[4], args[5], args[6], args[7]);}
+       };
+}
+void disconnect() {
+       // disconnect event sink
+       if (eventCookie != 0 && objIUnknown != null) {
+               long[] ppvObject = new long[1];
+               if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
+                       IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
+                       if (cpc.FindConnectionPoint(eventGuid, ppvObject) == COM.S_OK) {
+                               IConnectionPoint cp = new IConnectionPoint(ppvObject[0]);
+                               if (cp.Unadvise(eventCookie) == COM.S_OK) {
+                                       eventCookie = 0;
+                               }
+                               cp.Release();
+                       }
+                       cpc.Release();
+               }
+       }
+}
+private void disposeCOMInterfaces() {
+       if (iDispatch != null)
+               iDispatch.dispose();
+       iDispatch = null;
+
+}
+private int Invoke(int dispIdMember, long riid, int lcid, int dwFlags, long pDispParams, long pVarResult, long pExcepInfo, long pArgErr)
+{
+       if (eventTable == 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 != 0) {
+               DISPPARAMS dispParams = new DISPPARAMS();
+               COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof);
+               eventInfo = new Variant[dispParams.cArgs];
+               int size = VARIANT.sizeof;
+               long 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);
+
+       if (eventInfo != null) {
+               for (int j = 0; j < eventInfo.length; j++){
+                       eventInfo[j].dispose();
+               }
+       }
+
+       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 == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       event.type = eventType;
+       event.widget = widget;
+       eventTable.sendEvent (event);
+}
+private int QueryInterface(long riid, long ppvObject) {
+
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+
+       if ( COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) ||
+                       COM.IsEqualGUID(guid, eventGuid)) {
+               OS.MoveMemory(ppvObject, new long[] {iDispatch.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return OLE.S_OK;
+       }
+
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+int Release() {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces();
+       }
+
+       return refCount;
+}
+void removeListener(int eventID, OleListener listener) {
+       if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (eventID, listener);
+}
+boolean hasListeners() {
+       return eventTable.hasEntries();
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventTable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleEventTable.java
new file mode 100644 (file)
index 0000000..41947f4
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+/**
+* 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 == null) types = new int [4];
+       if (handlers == null) handlers = new OleListener [4];
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == 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);
+       System.arraycopy (handlers, 0, newHandlers, 0, size);
+       types = newTypes;  handlers = newHandlers;
+       types [size] = eventType;  handlers [size] = handler;
+}
+boolean hooks (int eventType) {
+       if (handlers == null) return false;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == eventType) return true;
+       }
+       return false;
+}
+void sendEvent (OleEvent event) {
+       if (handlers == null) return;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == event.type) {
+                       OleListener listener = handlers [i];
+                       if (listener != null) listener.handleEvent (event);
+               }
+       }
+}
+void unhook (int eventType, OleListener handler) {
+       if (handlers == null) return;
+       for (int i=0; i<types.length; i++) {
+               if ((types [i] == eventType) && (handlers [i] == handler)) {
+                       types [i] = 0;
+                       handlers [i] = null;
+                       return;
+               }
+       }
+}
+boolean hasEntries() {
+       for (int i=0; i<types.length; i++) {
+               if (types[i] != 0) return true;
+       }
+       return false;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleFrame.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleFrame.java
new file mode 100644 (file)
index 0000000..b6bd46c
--- /dev/null
@@ -0,0 +1,823 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ *
+ * 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 extends Composite
+{
+       // Interfaces for this Ole Client Container
+       private COMObject 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 long shellHandle;
+       private long oldMenuHandle;
+       private long newMenuHandle;
+       private static long lastActivatedMenuHandle;
+
+       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 boolean ignoreNextKey;
+       private static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
+
+       private static final String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
+       private static final String ACCEL_KEY_HIT = "org.eclipse.swt.internal.win32.accelKeyHit"; //$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 OleFrame(Composite parent, int style) {
+       super(parent, style);
+
+       createCOMInterfaces();
+
+       // setup cleanup proc
+       listener = 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 (final Display display) {
+       if (display.getData(CHECK_FOCUS) != null) return;
+       display.setData(CHECK_FOCUS, CHECK_FOCUS);
+       final int time = 50;
+       final Runnable[] timer = new Runnable[1];
+       final Control[] lastFocus = new Control[1];
+       timer[0] = () -> {
+               if (lastFocus[0] instanceof OleClientSite && !lastFocus[0].isDisposed()) {
+                       // ignore popup menus and dialogs
+                       long hwnd = OS.GetFocus();
+                       while (hwnd != 0) {
+                               long ownerHwnd = OS.GetWindow(hwnd, OS.GW_OWNER);
+                               if (ownerHwnd != 0) {
+                                       display.timerExec(time, timer[0]);
+                                       return;
+                               }
+                               hwnd = OS.GetParent(hwnd);
+                       }
+               }
+               if (lastFocus[0] == null || lastFocus[0].isDisposed() || !lastFocus[0].isFocusControl()) {
+                       Control currentFocus = display.getFocusControl();
+                       if (currentFocus instanceof OleFrame) {
+                               OleFrame frame = (OleFrame) currentFocus;
+                               currentFocus = frame.getCurrentDocument();
+                       }
+                       if (lastFocus[0] != currentFocus) {
+                               Event event = new Event();
+                               if (lastFocus[0] instanceof OleClientSite && !lastFocus[0].isDisposed()) {
+                                       lastFocus[0].notifyListeners (SWT.FocusOut, event);
+                               }
+                               if (currentFocus instanceof OleClientSite && !currentFocus.isDisposed()) {
+                                       currentFocus.notifyListeners(SWT.FocusIn, event);
+                               }
+                       }
+                       lastFocus[0] = currentFocus;
+               }
+               display.timerExec(time, timer[0]);
+       };
+       display.timerExec(time, timer[0]);
+}
+private static void initMsgHook(Display display) {
+       if (display.getData(HHOOK) != null) return;
+       final Callback callback = new Callback(OleFrame.class, "getMsgProc", 3); //$NON-NLS-1$
+       long address = callback.getAddress();
+       if (address == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+       int threadId = OS.GetCurrentThreadId();
+       final long hHook = OS.SetWindowsHookEx(OS.WH_GETMESSAGE, address, 0, threadId);
+       if (hHook == 0) {
+               callback.dispose();
+               return;
+       }
+       display.setData(HHOOK, new LONG(hHook));
+       display.setData(HHOOKMSG, new MSG());
+       display.disposeExec(() -> {
+               if (hHook != 0) OS.UnhookWindowsHookEx(hHook);
+               if (callback != null) callback.dispose();
+       });
+}
+static long getMsgProc(long code, long wParam, long lParam) {
+       Display display = Display.getCurrent();
+       if (display == null) return 0;
+       LONG hHook = (LONG)display.getData(HHOOK);
+       if (hHook == null) return 0;
+       if (code < 0 || (wParam & OS.PM_REMOVE) == 0) {
+               return OS.CallNextHookEx(hHook.value, (int)code, wParam, lParam);
+       }
+       MSG msg = (MSG)display.getData(HHOOKMSG);
+       OS.MoveMemory(msg, lParam, MSG.sizeof);
+       int message = msg.message;
+       if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
+               if (display != null) {
+                       Widget widget = null;
+                       long hwnd = msg.hwnd;
+                       while (hwnd != 0) {
+                               widget = display.findWidget (hwnd);
+                               if (widget != null) break;
+                               hwnd = OS.GetParent (hwnd);
+                       }
+                       if (widget != null && widget instanceof OleClientSite) {
+                               OleClientSite site = (OleClientSite)widget;
+                               if (site.handle == hwnd) {
+                                       boolean 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;
+                                       boolean rc = OS.GetGUIThreadInfo(thread, lpgui);
+                                       int mask = OS.GUI_INMENUMODE | OS.GUI_INMOVESIZE | OS.GUI_POPUPMENUMODE | OS.GUI_SYSTEMMENUMODE;
+                                       if (!rc || (lpgui.flags & mask) == 0) {
+                                               OleFrame frame = site.frame;
+                                               frame.setData(CONSUME_KEY, null);
+                                               display.setData(ACCEL_KEY_HIT, Boolean.TRUE);
+                                               consumed = frame.translateOleAccelerator(msg);
+                                               /* translateOleAccelerator() may send client events, ensure that the frame and display are still valid */
+                                               if (display.isDisposed()) return 0;
+                                               display.setData(ACCEL_KEY_HIT, Boolean.FALSE);
+                                               if (frame.isDisposed()) return 0;
+                                               String value = (String)frame.getData(CONSUME_KEY);
+                                               if (value != null) consumed = value.equals("true"); //$NON-NLS-1$
+                                               frame.setData(CONSUME_KEY, null);
+                                       }
+                                       boolean accentKey = false;
+                                       switch (msg.message) {
+                                               case OS.WM_KEYDOWN:
+                                               case OS.WM_SYSKEYDOWN: {
+                                                       switch ((int)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: {
+                                                                       int mapKey = OS.MapVirtualKey ((int)msg.wParam, 2);
+                                                                       if (mapKey != 0) {
+                                                                               accentKey = (mapKey & 0x80000000) != 0;
+                                                                               if (!accentKey) {
+                                                                                       for (int i=0; i<ACCENTS.length; i++) {
+                                                                                               int value = OS.VkKeyScan (ACCENTS [i]);
+                                                                                               if (value != -1 && (value & 0xFF) == msg.wParam) {
+                                                                                                       int state = value >> 8;
+                                                                                                       if ((OS.GetKeyState (OS.VK_SHIFT) < 0) == ((state & 0x1) != 0) &&
+                                                                                                               (OS.GetKeyState (OS.VK_CONTROL) < 0) == ((state & 0x2) != 0) &&
+                                                                                                               (OS.GetKeyState (OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
+                                                                                                                       if ((state & 0x7) != 0) accentKey = true;
+                                                                                                                       break;
+                                                                                                       }
+                                                                                               }
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                                       break;
+                                                               }
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                                       /* Allow OleClientSite to process key events before activeX control */
+                                       if (!consumed && !accentKey && !ignoreNextKey) {
+                                               long hwndOld = msg.hwnd;
+                                               msg.hwnd = site.handle;
+                                               consumed = OS.DispatchMessage (msg) == 1;
+                                               msg.hwnd = hwndOld;
+                                       }
+                                       switch (msg.message) {
+                                               case OS.WM_KEYDOWN:
+                                               case OS.WM_SYSKEYDOWN: {
+                                                       switch ((int)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;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       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, (int)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 COMObject(new int[]{2, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 1, 1, 1, 2}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return GetWindow(args[0]);}
+               @Override
+               public long method4(long[] args) {return ContextSensitiveHelp((int)args[0]);}
+               @Override
+               public long method5(long[] args) {return GetBorder(args[0]);}
+               @Override
+               public long method6(long[] args) {return RequestBorderSpace(args[0]);}
+               @Override
+               public long method7(long[] args) {return SetBorderSpace(args[0]);}
+               @Override
+               public long method8(long[] args) {return SetActiveObject(args[0], args[1]);}
+               @Override
+               public long method9(long[] args) {return InsertMenus(args[0], args[1]);}
+               @Override
+               public long method10(long[] args) {return SetMenu(args[0], args[1], args[2]);}
+               @Override
+               public long method11(long[] args) {return RemoveMenus(args[0]);}
+               // method12 SetStatusText - not implemented
+               // method13 EnableModeless - not implemented
+               @Override
+               public long method14(long[] args) {return TranslateAccelerator(args[0], (int)args[1]);}
+       };
+}
+private void disposeCOMInterfaces () {
+       if (iOleInPlaceFrame != null)
+               iOleInPlaceFrame.dispose();
+       iOleInPlaceFrame = null;
+}
+private int GetBorder(long 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 == 0) return COM.E_INVALIDARG;
+       RECT rectBorder = new RECT();
+       // Coordinates must be relative to the window
+       OS.GetClientRect(handle, rectBorder);
+       OS.MoveMemory(lprectBorder, rectBorder, RECT.sizeof);
+       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;
+}
+long getIOleInPlaceFrame() {
+       return iOleInPlaceFrame.getAddress();
+}
+private long getMenuItemID(long hMenu, int index) {
+       long id = 0;
+       MENUITEMINFO lpmii = new MENUITEMINFO();
+       lpmii.cbSize = 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) == OS.MF_POPUP) {
+               id = lpmii.hSubMenu;
+       } else {
+               id = lpmii.wID;
+       }
+       return id;
+}
+private int GetWindow(long phwnd) {
+       if (phwnd != 0) {
+               OS.MoveMemory(phwnd, new long[] {handle}, C.PTR_SIZEOF);
+       }
+       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 int InsertMenus(long hmenuShared, long lpMenuWidths) {
+       // locate menu bar
+       Menu menubar = getShell().getMenuBar();
+       if (menubar == null || menubar.isDisposed()) {
+               OS.MoveMemory(lpMenuWidths, new int[] {0}, 4);
+               return COM.S_OK;
+       }
+       long 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 = new MENUITEMINFO();
+       long hHeap = OS.GetProcessHeap();
+       int cch = 128;
+       int byteCount = cch * TCHAR.sizeof;
+       long pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       lpmii.cbSize = 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 != null) {
+               for (int i = 0; i < this.fileMenuItems.length; i++) {
+                       MenuItem item = this.fileMenuItems[i];
+                       if (item != 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
+       OS.MoveMemory(lpMenuWidths, new int[] {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 != null) {
+               for (int i = 0; i < this.containerMenuItems.length; i++) {
+                       MenuItem item = this.containerMenuItems[i];
+                       if (item != 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
+       OS.MoveMemory(lpMenuWidths + 8, new int[] {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 != null) {
+               for (int i = 0; i < this.windowMenuItems.length; i++) {
+                       MenuItem item = this.windowMenuItems[i];
+                       if (item != 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
+       OS.MoveMemory(lpMenuWidths + 16, new int[] {windowMenuCount}, 4);
+
+       // free resources used in querying the OS
+       if (pszText != 0)
+               OS.HeapFree(hHeap, 0, pszText);
+       return COM.S_OK;
+}
+void onActivate(Event e) {
+       if (objIOleInPlaceActiveObject != null) {
+               objIOleInPlaceActiveObject.OnFrameWindowActivate(true);
+       }
+}
+void onDeactivate(Event e) {
+       if (objIOleInPlaceActiveObject != null) {
+               objIOleInPlaceActiveObject.OnFrameWindowActivate(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);
+}
+void onFocusIn(Event e) {
+       if (lastActivatedMenuHandle != newMenuHandle)
+               currentdoc.doVerb(OLE.OLEIVERB_SHOW);
+       if (OS.GetMenu(shellHandle) != newMenuHandle)
+               OS.SetMenu(shellHandle, newMenuHandle);
+}
+void onFocusOut(Event e) {
+       Control control = getDisplay().getFocusControl();
+       if (OS.GetMenu(shellHandle) != oldMenuHandle && control != null && control.handle != shellHandle)
+               OS.SetMenu(shellHandle, oldMenuHandle);
+}
+private void onResize(Event e) {
+       if (objIOleInPlaceActiveObject != null) {
+               RECT lpRect = new RECT();
+               OS.GetClientRect(handle, lpRect);
+               objIOleInPlaceActiveObject.ResizeBorder(lpRect, iOleInPlaceFrame.getAddress(), true);
+       }
+}
+private int QueryInterface(long riid, long ppvObject) {
+//     implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame) ) {
+               OS.MoveMemory(ppvObject, new long [] {iOleInPlaceFrame.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+
+       OS.MoveMemory(ppvObject, new long [] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+/**
+ * Decrement the count of references to this instance
+ *
+ * @return the current reference count
+ */
+int Release() {
+       refCount--;
+       if (refCount == 0){
+               disposeCOMInterfaces();
+               if (COM.FreeUnusedLibraries) {
+                       COM.CoFreeUnusedLibraries();
+               }
+       }
+       return refCount;
+}
+private void releaseObjectInterfaces() {
+       if (objIOleInPlaceActiveObject != null) {
+               objIOleInPlaceActiveObject.Release();
+       }
+       objIOleInPlaceActiveObject = null;
+}
+private int RemoveMenus(long hmenuShared) {
+
+       Menu menubar = getShell().getMenuBar();
+       if (menubar == null || menubar.isDisposed()) return COM.S_FALSE;
+
+       long hMenu = menubar.handle;
+
+       List<LONG> ids = new ArrayList<>();
+       if (this.fileMenuItems != null) {
+               for (int i = 0; i < this.fileMenuItems.length; i++) {
+                       MenuItem item = this.fileMenuItems[i];
+                       if (item != null && !item.isDisposed()) {
+                               int index = item.getParent().indexOf(item);
+                               // get Id from original menubar
+                               long id = getMenuItemID(hMenu, index);
+                               ids.add(new LONG(id));
+                       }
+               }
+       }
+       if (this.containerMenuItems != null) {
+               for (int i = 0; i < this.containerMenuItems.length; i++) {
+                       MenuItem item = this.containerMenuItems[i];
+                       if (item != null && !item.isDisposed()) {
+                               int index = item.getParent().indexOf(item);
+                               long id = getMenuItemID(hMenu, index);
+                               ids.add(new LONG(id));
+                       }
+               }
+       }
+       if (this.windowMenuItems != null) {
+               for (int i = 0; i < this.windowMenuItems.length; i++) {
+                       MenuItem item = this.windowMenuItems[i];
+                       if (item != null && !item.isDisposed()) {
+                               int index = item.getParent().indexOf(item);
+                               long id = getMenuItemID(hMenu, index);
+                               ids.add(new LONG(id));
+                       }
+               }
+       }
+       int index = OS.GetMenuItemCount(hmenuShared) - 1;
+       for (int i = index; i >= 0; i--) {
+               long id = getMenuItemID(hmenuShared, i);
+               if (ids.contains(new LONG(id))){
+                       OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION);
+               }
+       }
+       return COM.S_OK;
+}
+private int RequestBorderSpace(long pborderwidths) {
+       return COM.S_OK;
+}
+int SetActiveObject(long pActiveObject, long pszObjName) {
+       if (objIOleInPlaceActiveObject != null) {
+               objIOleInPlaceActiveObject.Release();
+               objIOleInPlaceActiveObject = null;
+       }
+       if (pActiveObject != 0) {
+               objIOleInPlaceActiveObject = new IOleInPlaceActiveObject(pActiveObject);
+               objIOleInPlaceActiveObject.AddRef();
+       }
+
+       return COM.S_OK;
+}
+private int SetBorderSpace(long 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 == null) return COM.S_OK;
+       RECT borderwidth = new RECT();
+       if (pborderwidths == 0 || currentdoc == 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 != null && objIOleInPlaceActiveObject != null) {
+               RECT lpRect = new RECT();
+               OS.GetClientRect(handle, lpRect);
+               objIOleInPlaceActiveObject.ResizeBorder(lpRect, iOleInPlaceFrame.getAddress(), 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;
+}
+private int SetMenu(long hmenuShared, long holemenu, long hwndActiveObject) {
+       long inPlaceActiveObject = 0;
+       if (objIOleInPlaceActiveObject != null)
+               inPlaceActiveObject = objIOleInPlaceActiveObject.getAddress();
+
+       Menu menubar = getShell().getMenuBar();
+       if (menubar == null || menubar.isDisposed()){
+               return COM.OleSetMenuDescriptor(0, getShell().handle, hwndActiveObject, iOleInPlaceFrame.getAddress(), inPlaceActiveObject);
+       }
+
+       long handle = menubar.getShell().handle;
+
+       if (hmenuShared == 0 && holemenu == 0) {
+               // re-instate the original menu - this occurs on deactivation
+               hmenuShared = menubar.handle;
+       }
+       if (hmenuShared == 0) return COM.E_FAIL;
+
+       shellHandle = handle;
+       oldMenuHandle = menubar.handle;
+       newMenuHandle = hmenuShared;
+       lastActivatedMenuHandle = newMenuHandle;
+
+       return COM.OleSetMenuDescriptor(holemenu, handle, hwndActiveObject, iOleInPlaceFrame.getAddress(), 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 boolean translateOleAccelerator(MSG msg) {
+       if (objIOleInPlaceActiveObject == null) return false;
+       int result = objIOleInPlaceActiveObject.TranslateAccelerator(msg);
+       return (result != COM.S_FALSE && result != COM.E_NOTIMPL);
+}
+private int TranslateAccelerator(long lpmsg, int wID){
+       Menu menubar = getShell().getMenuBar();
+       if (menubar == null || menubar.isDisposed() || !menubar.isEnabled()) return COM.S_FALSE;
+       if (wID < 0) return COM.S_FALSE;
+
+       Shell shell = menubar.getShell();
+       long hwnd = shell.handle;
+       long hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+       if (hAccel == 0) return COM.S_FALSE;
+
+       MSG msg = new MSG();
+       OS.MoveMemory(msg, lpmsg, MSG.sizeof);
+       int result = OS.TranslateAccelerator(hwnd, hAccel, msg);
+       return result == 0 ? COM.S_FALSE : COM.S_OK;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleFunctionDescription.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleFunctionDescription.java
new file mode 100644 (file)
index 0000000..5f9678c
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+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;
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleListener.java
new file mode 100644 (file)
index 0000000..455af5a
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+/**
+ * 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleParameterDescription.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleParameterDescription.java
new file mode 100644 (file)
index 0000000..582467d
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+public class OleParameterDescription {
+       public String name;
+       public short flags;
+       public short type;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.java
new file mode 100644 (file)
index 0000000..917dd2c
--- /dev/null
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+final class OlePropertyChangeSink {
+
+       private OleControlSite controlSite;
+       //private IUnknown objIUnknown;
+
+       private COMObject iPropertyNotifySink;
+
+       private int refCount;
+
+       private int propertyCookie;
+
+       private OleEventTable eventTable;
+
+OlePropertyChangeSink(OleControlSite controlSite) {
+
+       this.controlSite = controlSite;
+
+       createCOMInterfaces();
+}
+void addListener(int propertyID, OleListener listener) {
+       if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) eventTable = new OleEventTable ();
+       eventTable.hook(propertyID, listener);
+}
+int AddRef() {
+       refCount++;
+       return refCount;
+}
+void connect(IUnknown objIUnknown) {
+
+       // Set up property change notification sink
+       long[] ppvObject = new long[1];
+       if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
+               IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
+               if (cpc.FindConnectionPoint(COM.IIDIPropertyNotifySink, ppvObject) == COM.S_OK) {
+                       IConnectionPoint cp = new IConnectionPoint(ppvObject[0]);
+                       int[] cookie = new int[1];
+                       if (cp.Advise(iPropertyNotifySink.getAddress(), cookie) == COM.S_OK) {
+                               propertyCookie = cookie[0];
+                       }
+                       cp.Release();
+               }
+               cpc.Release();
+       }
+}
+private void createCOMInterfaces() {
+       iPropertyNotifySink = new COMObject(new int[]{2, 0, 0, 1, 1}){
+               @Override
+               public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
+               @Override
+               public long method1(long[] args) {return AddRef();}
+               @Override
+               public long method2(long[] args) {return Release();}
+               @Override
+               public long method3(long[] args) {return OnChanged((int)args[0]);}
+               @Override
+               public long method4(long[] args) {return OnRequestEdit((int)args[0]);}
+       };
+}
+void disconnect(IUnknown objIUnknown) {
+
+       // disconnect property notification sink
+       if (propertyCookie != 0 && objIUnknown != null) {
+               long[] ppvObject = new long[1];
+               if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) {
+                       IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]);
+                       if (cpc.FindConnectionPoint(COM.IIDIPropertyNotifySink, ppvObject) == COM.S_OK) {
+                               IConnectionPoint cp = new IConnectionPoint(ppvObject[0]);
+                               if (cp.Unadvise(propertyCookie) == COM.S_OK) {
+                                       propertyCookie = 0;
+                               }
+                               cp.Release();
+                       }
+                       cpc.Release();
+               }
+       }
+}
+private void disposeCOMInterfaces() {
+       if (iPropertyNotifySink != null) iPropertyNotifySink.dispose();
+       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 == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       event.type = eventType;
+       event.widget = controlSite;
+       eventTable.sendEvent (event);
+}
+private int OnChanged(int dispID) {
+       if (eventTable == null || !eventTable.hooks(dispID)) return COM.S_OK;
+       OleEvent event = new OleEvent();
+       event.detail = OLE.PROPERTY_CHANGED;
+       notifyListener(dispID,event);
+       return COM.S_OK;
+}
+private int OnRequestEdit(int dispID) {
+       if (eventTable == 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;
+}
+private int QueryInterface(long riid, long ppvObject) {
+       if (riid == 0 || ppvObject == 0)
+               return COM.E_INVALIDARG;
+       GUID guid = new GUID();
+       COM.MoveMemory(guid, riid, GUID.sizeof);
+       if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIPropertyNotifySink)) {
+               OS.MoveMemory(ppvObject, new long[] {iPropertyNotifySink.getAddress()}, C.PTR_SIZEOF);
+               AddRef();
+               return COM.S_OK;
+       }
+       OS.MoveMemory(ppvObject, new long[] {0}, C.PTR_SIZEOF);
+       return COM.E_NOINTERFACE;
+}
+int Release() {
+       refCount--;
+       if (refCount == 0) {
+               disposeCOMInterfaces();
+       }
+       return refCount;
+}
+void removeListener(int propertyID, OleListener listener) {
+       if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (propertyID, listener);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OlePropertyDescription.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OlePropertyDescription.java
new file mode 100644 (file)
index 0000000..9a710fc
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+public class OlePropertyDescription {
+       public int id;
+       public String name;
+       public int type;
+       public int flags;
+       public int kind;
+       public String description;
+       public String helpFile;
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/Variant.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/Variant.java
new file mode 100644 (file)
index 0000000..c75a3bc
--- /dev/null
@@ -0,0 +1,1074 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+/**
+ *
+ * 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.
+       */
+       public static final int sizeof = VARIANT.sizeof;
+
+       private short type; // OLE.VT_* type
+       private boolean booleanData;
+       private byte    byteData;
+       private short   shortData;
+       private char    charData;
+       private int     intData;
+       private long    longData;
+       private float   floatData;
+       private double  doubleData;
+       private String  stringData;
+       private long     byRefPtr;
+       private IDispatch dispatchData;
+       private IUnknown unknownData;
+
+       /**
+        * A shared Variant instance with type VT_NULL.
+        *
+        * @since 3.7
+        */
+       public static final Variant NULL;
+       static {
+               NULL = new Variant ();
+               NULL.type = COM.VT_NULL;
+       }
+
+/**
+ * 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.3
+ */
+public static void win32_copy (long 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.3
+ */
+public static Variant win32_new (long pVariant) {
+       Variant variant = new Variant ();
+       variant.setData (pVariant);
+       return variant;
+}
+
+/**
+ * Create an empty Variant object with type VT_EMPTY.
+ *
+ * @since 2.0
+ */
+public Variant() {
+       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 Variant(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 Variant(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 Variant(int 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 Variant(long ptr, short 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 Variant(OleAutomation automation) {
+       type = COM.VT_DISPATCH;
+       dispatchData = new IDispatch(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 Variant(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 Variant(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 Variant(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 Variant(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 Variant(short val) {
+       type = COM.VT_I2;
+       shortData = val;
+}
+/**
+ * Create a Variant object which represents a Java boolean as a VT_BOOL.
+ *
+ * @param val the Java boolean value that this Variant represents
+ *
+ */
+public Variant(boolean 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) == COM.VT_BYREF) {
+               return;
+       }
+
+       switch (type) {
+               case COM.VT_DISPATCH :
+                       dispatchData.Release();
+                       break;
+               case COM.VT_UNKNOWN :
+                       unknownData.Release();
+                       break;
+       }
+
+}
+/**
+ * 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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_DISPATCH) {
+               return new OleAutomation(dispatchData);
+       }
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_DISPATCH);
+               if (result != COM.S_OK)
+                       OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+               Variant autoVar = new Variant();
+               autoVar.setData(newPtr);
+               return autoVar.getAutomation();
+       } finally {
+               COM.VariantClear(oldPtr);
+               OS.GlobalFree(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
+               OS.GlobalFree(newPtr);
+       }
+}
+/**
+ * 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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_DISPATCH) {
+               return dispatchData;
+       }
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_DISPATCH);
+               if (result != COM.S_OK)
+                       OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+               Variant autoVar = new Variant();
+               autoVar.setData(newPtr);
+               return autoVar.getDispatch();
+       } finally {
+               COM.VariantClear(oldPtr);
+               OS.GlobalFree(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
+               OS.GlobalFree(newPtr);
+       }
+}
+/**
+ * Returns the Java boolean represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java boolean, an attempt is made to
+ * coerce the Variant type into a Java boolean.  If this fails, an error is thrown.
+ *
+ * @return the Java boolean represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a boolean</li>
+ * </ul>
+ *
+ */
+public boolean getBoolean() {
+       if (type == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_BOOL) {
+               return booleanData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_BOOL);
+               if (result != COM.S_OK)
+                       OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+               Variant boolVar = new Variant();
+               boolVar.setData(newPtr);
+               return boolVar.getBoolean();
+       } finally {
+               COM.VariantClear(oldPtr);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 long getByRef() {
+       if (type == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if ((type & COM.VT_BYREF)== COM.VT_BYREF) {
+               return byRefPtr;
+       }
+
+       return 0;
+}
+/**
+ * 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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_I1) {
+               return byteData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I1);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 char getChar() {
+       if (type == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_UI2) {
+               return charData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_UI2);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(newPtr);
+       }
+}
+void getData(long pData){
+       if (pData == 0) OLE.error(OLE.ERROR_OUT_OF_MEMORY);
+
+       COM.VariantInit(pData);
+
+       if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
+               //TODO - use VARIANT structure
+               OS.MoveMemory(pData, new short[] {type}, 2);
+               OS.MoveMemory(pData + 8, new long[]{byRefPtr}, C.PTR_SIZEOF);
+               return;
+       }
+
+       switch (type) {
+               case COM.VT_EMPTY :
+               case COM.VT_NULL :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       break;
+               case COM.VT_BOOL :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new short[]{(booleanData) ? OS.VARIANT_TRUE : OS.VARIANT_FALSE}, 2);
+                       break;
+               case COM.VT_I1 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new byte[]{byteData}, 1);
+                       break;
+               case COM.VT_I2 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new short[]{shortData}, 2);
+                       break;
+               case COM.VT_UI2 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new char[]{charData}, 2);
+                       break;
+               case COM.VT_I4 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new int[]{intData}, 4);
+                       break;
+               case COM.VT_I8 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new long[]{longData}, 8);
+                       break;
+               case COM.VT_R4 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new float[]{floatData}, 4);
+                       break;
+               case COM.VT_R8 :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new double[]{doubleData}, 8);
+                       break;
+               case COM.VT_DISPATCH :
+                       dispatchData.AddRef();
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new long[]{dispatchData.getAddress()}, C.PTR_SIZEOF);
+                       break;
+               case COM.VT_UNKNOWN :
+                       unknownData.AddRef();
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       OS.MoveMemory(pData + 8, new long[]{unknownData.getAddress()}, C.PTR_SIZEOF);
+                       break;
+               case COM.VT_BSTR :
+                       OS.MoveMemory(pData, new short[] {type}, 2);
+                       char[] data = (stringData+"\0").toCharArray();
+                       long ptr = COM.SysAllocString(data);
+                       OS.MoveMemory(pData + 8, new long[] {ptr}, C.PTR_SIZEOF);
+                       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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_R8) {
+               return doubleData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_R8);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_R4) {
+               return floatData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_R4);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_I4) {
+               return intData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I4);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_I8) {
+               return longData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I8);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_I2) {
+               return shortData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I2);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_BSTR) {
+               return stringData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_BSTR);
+               if (result != 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);
+               OS.GlobalFree(oldPtr);
+               COM.VariantClear(newPtr);
+               OS.GlobalFree(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 == COM.VT_EMPTY) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+       }
+       if (type == COM.VT_UNKNOWN) {
+               return unknownData;
+       }
+
+       // try to coerce the value to the desired type
+       long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
+       try {
+               getData(oldPtr);
+               int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_UNKNOWN);
+               if (result != 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);
+               OS.GlobalFree(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
+               OS.GlobalFree(newPtr);
+       }
+}
+/**
+ * Update the by reference value of this variant with a new boolean value.
+ *
+ * @param val the new boolean 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(boolean val) {
+       if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_BOOL) == 0) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+       }
+       OS.MoveMemory(byRefPtr, new short[]{val ? OS.VARIANT_TRUE : OS.VARIANT_FALSE}, 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) == 0 || (type & COM.VT_R4) == 0) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+       }
+       OS.MoveMemory(byRefPtr, new float[]{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(long val) {
+       if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I8) == 0) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+       }
+       OS.MoveMemory(byRefPtr, new long[]{val}, C.PTR_SIZEOF);
+}
+/**
+ * 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) == 0 || (type & COM.VT_I2) == 0) {
+               OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+       }
+       OS.MoveMemory(byRefPtr, new short[]{val}, 2);
+}
+void setData(long pData){
+       if (pData == 0) OLE.error(SWT.ERROR_INVALID_ARGUMENT);
+
+       //TODO - use VARIANT structure
+       short[] dataType = new short[1];
+       OS.MoveMemory(dataType, pData, 2);
+       type = dataType[0];
+
+       if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
+               long[] newByRefPtr = new long[1];
+               OS.MoveMemory(newByRefPtr, pData + 8, C.PTR_SIZEOF);
+               byRefPtr = newByRefPtr[0];
+               return;
+       }
+
+       switch (type) {
+               case COM.VT_EMPTY :
+               case COM.VT_NULL :
+                       break;
+               case COM.VT_BOOL :
+                       short[] newBooleanData = new short[1];
+                       OS.MoveMemory(newBooleanData, pData + 8, 2);
+                       booleanData = (newBooleanData[0] != OS.VARIANT_FALSE);
+                       break;
+               case COM.VT_I1 :
+                       byte[] newByteData = new byte[1];
+                       OS.MoveMemory(newByteData, pData + 8, 1);
+                       byteData = newByteData[0];
+                       break;
+               case COM.VT_I2 :
+                       short[] newShortData = new short[1];
+                       OS.MoveMemory(newShortData, pData + 8, 2);
+                       shortData = newShortData[0];
+                       break;
+               case COM.VT_UI2 :
+                       char[] newCharData = new char[1];
+                       OS.MoveMemory(newCharData, pData + 8, 2);
+                       charData = newCharData[0];
+                       break;
+               case COM.VT_I4 :
+                       int[] newIntData = new int[1];
+                       OS.MoveMemory(newIntData, pData + 8, 4);
+                       intData = newIntData[0];
+                       break;
+               case COM.VT_I8 :
+                       long[] newLongData = new long[1];
+                       OS.MoveMemory(newLongData, pData + 8, 8);
+                       longData = newLongData[0];
+                       break;
+               case COM.VT_R4 :
+                       float[] newFloatData = new float[1];
+                       OS.MoveMemory(newFloatData, pData + 8, 4);
+                       floatData = newFloatData[0];
+                       break;
+               case COM.VT_R8 :
+                       double[] newDoubleData = new double[1];
+                       OS.MoveMemory(newDoubleData, pData + 8, 8);
+                       doubleData = newDoubleData[0];
+                       break;
+               case COM.VT_DISPATCH : {
+                       long[] ppvObject = new long[1];
+                       OS.MoveMemory(ppvObject, pData + 8, C.PTR_SIZEOF);
+                       if (ppvObject[0] == 0) {
+                               type = COM.VT_EMPTY;
+                               break;
+                       }
+                       dispatchData = new IDispatch(ppvObject[0]);
+                       dispatchData.AddRef();
+                       break;
+               }
+               case COM.VT_UNKNOWN : {
+                       long[] ppvObject = new long[1];
+                       OS.MoveMemory(ppvObject, pData + 8, C.PTR_SIZEOF);
+                       if (ppvObject[0] == 0) {
+                               type = COM.VT_EMPTY;
+                               break;
+                       }
+                       unknownData = new IUnknown(ppvObject[0]);
+                       unknownData.AddRef();
+                       break;
+               }
+               case COM.VT_BSTR :
+                       // get the address of the memory in which the string resides
+                       long[] hMem = new long[1];
+                       OS.MoveMemory(hMem, pData + 8, C.PTR_SIZEOF);
+                       if (hMem[0] == 0) {
+                               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
+                               char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
+                               OS.MoveMemory(buffer, hMem[0], size);
+                               stringData = new String(buffer);
+                       } else {
+                               stringData = ""; //$NON-NLS-1$
+                       }
+                       break;
+
+               default :
+                       // try coercing it into one of the known forms
+                       long newPData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, sizeof);
+                       if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_R8) == COM.S_OK) {
+                               setData(newPData);
+                       } else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_I8) == COM.S_OK) {
+                               setData(newPData);
+                       } else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_BSTR) == 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
+ */
+@Override
+public String toString () {
+       switch (type) {
+               case COM.VT_BOOL :
+                       return "VT_BOOL{"+booleanData+"}";
+               case COM.VT_I1 :
+                       return "VT_I1{"+byteData+"}";
+               case COM.VT_I2 :
+                       return "VT_I2{"+shortData+"}";
+               case COM.VT_UI2 :
+                       return "VT_UI2{"+charData+"}";
+               case COM.VT_I4 :
+                       return "VT_I4{"+intData+"}";
+               case COM.VT_I8 :
+                       return "VT_I8{"+longData+"}";
+               case COM.VT_R4 :
+                       return "VT_R4{"+floatData+"}";
+               case COM.VT_R8 :
+                       return "VT_R8{"+doubleData+"}";
+               case COM.VT_BSTR :
+                       return "VT_BSTR{"+stringData+"}";
+               case COM.VT_DISPATCH :
+                       return "VT_DISPATCH{"+(dispatchData == null ? 0 : dispatchData.getAddress())+"}";
+               case COM.VT_UNKNOWN :
+                       return "VT_UNKNOWN{"+(unknownData == null ? 0 : unknownData.getAddress())+"}";
+               case COM.VT_EMPTY :
+                       return "VT_EMPTY";
+               case COM.VT_NULL :
+                       return "VT_NULL";
+       }
+       if ((type & COM.VT_BYREF) != 0) {
+               return "VT_BYREF|"+(type & ~COM.VT_BYREF)+"{"+byRefPtr+"}";
+       }
+       return "Unsupported Type "+type;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/package.html
new file mode 100644 (file)
index 0000000..93c5fd1
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Win32 OLE implementation classes.
+<h2>
+Package Specification</h2>
+This package contains the classes which provide the public API to the
+the Microsoft Win32 Object Linking and Embedding mechanism
+that the win32 variant of SWT is capable of using.
+<p>
+Referencing any of the classes in this package directly guarantees
+that the code is platform specific.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/GLCanvas.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/GLCanvas.java
new file mode 100644 (file)
index 0000000..95fdee3
--- /dev/null
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.opengl;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.opengl.win32.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 extends Canvas {
+       long context;
+       int pixelFormat;
+       static final String USE_OWNDC_KEY = "org.eclipse.swt.internal.win32.useOwnDC"; //$NON-NLS-1$
+/**
+ * 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>
+ *     <li>ERROR_UNSUPPORTED_DEPTH when the requested attributes cannot be provided</li>
+ * </ul>
+ */
+public GLCanvas (Composite parent, int style, GLData data) {
+       super (parent, checkStyle (parent, style));
+       parent.getDisplay ().setData (USE_OWNDC_KEY, false);
+       if (data == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR ();
+       pfd.nSize = (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 = (byte) WGL.PFD_TYPE_RGBA;
+       if (data.doubleBuffer) pfd.dwFlags |= WGL.PFD_DOUBLEBUFFER;
+       if (data.stereo) pfd.dwFlags |= WGL.PFD_STEREO;
+       pfd.cRedBits = (byte) data.redSize;
+       pfd.cGreenBits = (byte) data.greenSize;
+       pfd.cBlueBits = (byte) data.blueSize;
+       pfd.cAlphaBits = (byte) data.alphaSize;
+       pfd.cDepthBits = (byte) data.depthSize;
+       pfd.cStencilBits = (byte) data.stencilSize;
+       pfd.cAccumRedBits = (byte) data.accumRedSize;
+       pfd.cAccumGreenBits = (byte) data.accumGreenSize;
+       pfd.cAccumBlueBits = (byte) data.accumBlueSize;
+       pfd.cAccumAlphaBits = (byte) data.accumAlphaSize;
+       pfd.cAccumBits = (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;
+//     }
+
+       long hDC = OS.GetDC (handle);
+       pixelFormat = WGL.ChoosePixelFormat (hDC, pfd);
+       if (pixelFormat == 0 || !WGL.SetPixelFormat (hDC, pixelFormat, pfd)) {
+               OS.ReleaseDC (handle, hDC);
+               dispose ();
+               SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+       }
+       context = WGL.wglCreateContext (hDC);
+       if (context == 0) {
+               OS.ReleaseDC (handle, hDC);
+               SWT.error (SWT.ERROR_NO_HANDLES);
+       }
+       OS.ReleaseDC (handle, hDC);
+       if (data.shareContext != null) {
+               WGL.wglShareLists (data.shareContext.context, context);
+       }
+
+       Listener listener = event -> {
+               switch (event.type) {
+                       case SWT.Dispose:
+                               WGL.wglDeleteContext (context);
+                               break;
+               }
+       };
+       addListener (SWT.Dispose, listener);
+}
+
+static int checkStyle(Composite parent, int style) {
+       if (parent != null) {
+               parent.getDisplay ().setData (USE_OWNDC_KEY, true);
+       }
+       return style;
+}
+
+/**
+ * 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 = new PIXELFORMATDESCRIPTOR ();
+       pfd.nSize = (short) PIXELFORMATDESCRIPTOR.sizeof;
+       long hDC = OS.GetDC (handle);
+       WGL.DescribePixelFormat (hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, pfd);
+       OS.ReleaseDC (handle, hDC);
+       data.doubleBuffer = (pfd.dwFlags & WGL.PFD_DOUBLEBUFFER) != 0;
+       data.stereo = (pfd.dwFlags & WGL.PFD_STEREO) != 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 boolean 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 boolean isCurrent () {
+       checkWidget ();
+       return WGL.wglGetCurrentContext () == 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 () == context) return;
+       long 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 ();
+       long hDC = OS.GetDC (handle);
+       WGL.SwapBuffers (hDC);
+       OS.ReleaseDC (handle, hDC);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/GLData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/GLData.java
new file mode 100644 (file)
index 0000000..5a5ecc7
--- /dev/null
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.opengl;
+
+/**
+ * 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 boolean doubleBuffer;
+
+       /**
+        * Specifies a stereo surface.  During context creation,
+        * only stereo formats are considered when set to true.
+        */
+       public boolean 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;
+
+       /**
+        * Another GLCanvas whose texture namespace and display lists
+        * should be shared.
+        *
+        * @since 3.5
+        */
+       public GLCanvas shareContext;
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the data
+ */
+@Override
+public String toString() {
+       return (doubleBuffer ? "doubleBuffer," : "") +
+               (stereo ? "stereo," : "") +
+               "r:" + redSize + " g:" + greenSize + " b:" + blueSize + " a:" + alphaSize + "," +
+               "depth:" + depthSize + ",stencil:" + stencilSize +
+               ",accum r:" + accumRedSize + "g:" + accumGreenSize + "b:" + accumBlueSize + "a:" + accumAlphaSize +
+               ",sampleBuffers:" + sampleBuffers + ",samples:" + samples;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/opengl/package.html
new file mode 100644 (file)
index 0000000..3ad94ae
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT OpenGL support.
+<h2>
+Package Specification</h2>
+This package contains widgets for integrating OpenGL graphics
+into SWT applications.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/package.html
new file mode 100644 (file)
index 0000000..31459b9
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT constants and error handling support.
+<h2>
+Package Specification</h2>
+This package provides the class <code>SWT</code> which contains all of the
+constants used by SWT as well as a small selection of error handling routines
+and queries such as <code>getPlatform</code> and <code>getVersion</code>.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/PrintDialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/PrintDialog.java
new file mode 100644 (file)
index 0000000..38af0a7
--- /dev/null
@@ -0,0 +1,544 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.printing;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class PrintDialog extends Dialog {
+       static final TCHAR DialogClass = new TCHAR (0, "#32770", true);
+       PrinterData printerData = new PrinterData();
+
+/**
+ * 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 PrintDialog (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 PrintDialog (Shell parent, int style) {
+       super (parent, checkStyle(parent, style));
+       checkSubclass ();
+}
+
+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) == 0) style |= int0;
+       if ((style & int0) != 0) style = (style & ~mask) | int0;
+       if ((style & int1) != 0) style = (style & ~mask) | int1;
+       if ((style & int2) != 0) style = (style & ~mask) | int2;
+       if ((style & int3) != 0) style = (style & ~mask) | int3;
+       if ((style & int4) != 0) style = (style & ~mask) | int4;
+       if ((style & int5) != 0) style = (style & ~mask) | int5;
+       return style;
+}
+
+static int checkStyle (Shell parent, int style) {
+       int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+       if ((style & SWT.SHEET) != 0) {
+               style &= ~SWT.SHEET;
+               if ((style & mask) == 0) {
+                       style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
+               }
+       }
+       if ((style & mask) == 0) {
+               style |= SWT.APPLICATION_MODAL;
+       }
+       style &= ~SWT.MIRRORED;
+       if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
+               if (parent != null) {
+                       if ((parent.getStyle () & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT;
+                       if ((parent.getStyle () & SWT.RIGHT_TO_LEFT) != 0) style |= SWT.RIGHT_TO_LEFT;
+               }
+       }
+       return checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
+}
+
+/**
+ * Sets the printer data that will be used when the dialog
+ * is opened.
+ * <p>
+ * Setting the printer data to null is equivalent to
+ * resetting all data fields to their default values.
+ * </p>
+ *
+ * @param data the data that will be used when the dialog is opened or null to use default data
+ *
+ * @since 3.4
+ */
+public void setPrinterData(PrinterData data) {
+       if (data == null) data = new PrinterData();
+       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 printerData.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) {
+       printerData.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 printerData.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) {
+       printerData.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 printerData.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) {
+       printerData.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 boolean getPrintToFile() {
+       return printerData.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(boolean printToFile) {
+       printerData.printToFile = printToFile;
+}
+
+@Override
+protected void checkSubclass() {
+       String name = getClass().getName();
+       String validName = PrintDialog.class.getName();
+       if (!validName.equals(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,
+ *         or null if the dialog was canceled, no printers were found, 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 PrinterData open() {
+       /* Get the owner HWND for the dialog */
+       Control parent = getParent();
+       int style = getStyle();
+       long hwndOwner = parent.handle;
+       long hwndParent = parent.handle;
+
+       /*
+       * Feature in Windows.  There is no API to set the BIDI orientation
+       * of a print 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.
+       */
+       boolean enabled = false;
+       int dialogOrientation = style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+       int parentOrientation = parent.getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+       if (dialogOrientation != parentOrientation) {
+               int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+               if (dialogOrientation == SWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+               hwndOwner = OS.CreateWindowEx (
+                       exStyle,
+                       DialogClass,
+                       null,
+                       0,
+                       OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                       hwndParent,
+                       0,
+                       OS.GetModuleHandle (null),
+                       null);
+               enabled = OS.IsWindowEnabled (hwndParent);
+               if (enabled) OS.EnableWindow (hwndParent, false);
+       }
+
+       PrinterData data = null;
+       PRINTDLG pd = new PRINTDLG();
+       pd.lStructSize = PRINTDLG.sizeof;
+       pd.hwndOwner = hwndOwner;
+
+       boolean success = false;
+       if (printerData.name != null) {
+               /* Ensure that the printer name is in the current list of printers. */
+               PrinterData printerList[] = Printer.getPrinterList();
+               if (printerList.length > 0) {
+                       for (int p = 0; p < printerList.length; p++) {
+                               if (printerList[p].name.equals(printerData.name)) {
+                                       success = true;
+                                       break;
+                               }
+                       }
+               }
+               if (success) {
+                       /* Initialize PRINTDLG DEVNAMES for the specified printer. */
+                       TCHAR buffer = new TCHAR(0, printerData.name, true);
+                       int size = buffer.length() * TCHAR.sizeof;
+                       short[] offsets = new short[4]; // DEVNAMES (4 offsets)
+                       int offsetsSize = offsets.length * 2; // 2 bytes each
+                       offsets[1] = (short) offsets.length; // offset 1 points to wDeviceOffset
+                       long hMem = OS.GlobalAlloc(OS.GMEM_MOVEABLE | OS.GMEM_ZEROINIT, offsetsSize + size);
+                       long ptr = OS.GlobalLock(hMem);
+                       OS.MoveMemory(ptr, offsets, offsetsSize);
+                       OS.MoveMemory(ptr + offsetsSize, buffer, size);
+                       OS.GlobalUnlock(hMem);
+                       pd.hDevNames = hMem;
+               }
+       }
+       Display display = parent.getDisplay();
+       String externalLoopKey = "org.eclipse.swt.internal.win32.externalEventLoop";
+       if (!success) {
+               /* Initialize PRINTDLG fields, including DEVMODE, for the default printer. */
+               pd.Flags = OS.PD_RETURNDEFAULT;
+               display.setData(externalLoopKey, Boolean.TRUE);
+               display.sendPreExternalEventDispatchEvent ();
+               success = OS.PrintDlg(pd);
+               display.setData(externalLoopKey, Boolean.FALSE);
+               display.sendPostExternalEventDispatchEvent ();
+               if (success) {
+                       if (pd.hDevNames != 0) {
+                               OS.GlobalFree(pd.hDevNames);
+                               pd.hDevNames = 0;
+                       }
+               }
+       }
+
+       if (success) {
+               /*
+                * If user setup info from a previous print dialog was specified,
+                * then restore the previous DEVMODE struct.
+                */
+               byte devmodeData [] = printerData.otherData;
+               if (devmodeData != null && devmodeData.length != 0) {
+                       long hMem = OS.GlobalAlloc(OS.GMEM_MOVEABLE | OS.GMEM_ZEROINIT, devmodeData.length);
+                       long ptr = OS.GlobalLock(hMem);
+                       OS.MoveMemory(ptr, devmodeData, devmodeData.length);
+                       OS.GlobalUnlock(hMem);
+                       if (pd.hDevMode != 0) OS.GlobalFree(pd.hDevMode);
+                       pd.hDevMode = hMem;
+               }
+
+               /* Initialize the DEVMODE struct's fields from the printerData. */
+               long hMem = pd.hDevMode;
+               if (hMem == 0) {
+                       hMem = OS.GlobalAlloc(OS.GMEM_MOVEABLE | OS.GMEM_ZEROINIT, DEVMODE.sizeof);
+                       pd.hDevMode = hMem;
+               }
+               long ptr = OS.GlobalLock(hMem);
+               DEVMODE devmode = new DEVMODE ();
+               OS.MoveMemory(devmode, ptr, DEVMODE.sizeof);
+               if (printerData.name != null) {
+                       /* Copy PRINTDLG DEVNAMES into DEVMODE dmDeviceName (truncate if necessary). */
+                       int max = Math.min(printerData.name.length(), OS.CCHDEVICENAME - 1);
+                       for (int i = 0; i < max; i++) {
+                               devmode.dmDeviceName[i] = printerData.name.charAt(i);
+                       }
+               }
+               devmode.dmFields |= OS.DM_ORIENTATION;
+               devmode.dmOrientation = printerData.orientation == PrinterData.PORTRAIT ? OS.DMORIENT_PORTRAIT : OS.DMORIENT_LANDSCAPE;
+               if (printerData.copyCount != 1) {
+                       devmode.dmFields |= OS.DM_COPIES;
+                       devmode.dmCopies = (short)printerData.copyCount;
+               }
+               if (printerData.collate != false) {
+                       devmode.dmFields |= OS.DM_COLLATE;
+                       devmode.dmCollate = OS.DMCOLLATE_TRUE;
+               }
+               if (printerData.duplex != SWT.DEFAULT) {
+                       devmode.dmFields |= OS.DM_DUPLEX;
+                       switch (printerData.duplex) {
+                               case PrinterData.DUPLEX_SHORT_EDGE: devmode.dmDuplex = OS.DMDUP_HORIZONTAL; break;
+                               case PrinterData.DUPLEX_LONG_EDGE: devmode.dmDuplex = OS.DMDUP_VERTICAL; break;
+                               default: devmode.dmDuplex = OS.DMDUP_SIMPLEX;
+                       }
+               }
+               OS.MoveMemory(ptr, devmode, DEVMODE.sizeof);
+               OS.GlobalUnlock(hMem);
+
+               pd.Flags = OS.PD_USEDEVMODECOPIESANDCOLLATE;
+               if (printerData.printToFile) pd.Flags |= OS.PD_PRINTTOFILE;
+               switch (printerData.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 = -1;
+               pd.nFromPage = (short) Math.min (0xFFFF, Math.max (1, printerData.startPage));
+               pd.nToPage = (short) Math.min (0xFFFF, Math.max (1, printerData.endPage));
+
+               Shell [] shells = display.getShells();
+               if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+                       for (int i=0; i<shells.length; i++) {
+                               if (shells[i].isEnabled() && shells[i] != parent) {
+                                       shells[i].setEnabled(false);
+                               } else {
+                                       shells[i] = null;
+                               }
+                       }
+               }
+               String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+               Object oldValue = display.getData(key);
+               display.setData(key, Boolean.TRUE);
+               display.setData(externalLoopKey, Boolean.TRUE);
+               display.sendPreExternalEventDispatchEvent ();
+               success = OS.PrintDlg(pd);
+               display.setData(externalLoopKey, Boolean.FALSE);
+               display.sendPostExternalEventDispatchEvent ();
+               display.setData(key, oldValue);
+               if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+                       for (int i=0; i<shells.length; i++) {
+                               if (shells[i] != null && !shells[i].isDisposed ()) {
+                                       shells[i].setEnabled(true);
+                               }
+                       }
+               }
+
+               if (success) {
+                       /* Get driver and device from the DEVNAMES struct */
+                       hMem = pd.hDevNames;
+                       /* Ensure size is a multiple of 2 bytes on UNICODE platforms */
+                       int size = OS.GlobalSize(hMem) / TCHAR.sizeof * TCHAR.sizeof;
+                       ptr = OS.GlobalLock(hMem);
+                       short[] offsets = new short[4];
+                       OS.MoveMemory(offsets, ptr, 2 * offsets.length);
+                       char [] buffer = new char [size];
+                       OS.MoveMemory(buffer, ptr, size);
+                       OS.GlobalUnlock(hMem);
+
+                       int driverOffset = offsets[0];
+                       int i = 0;
+                       while (driverOffset + i < size) {
+                               if (buffer [driverOffset + i] == 0) break;
+                               i++;
+                       }
+                       String driver = new String(buffer, driverOffset, i);
+
+                       int deviceOffset = offsets[1];
+                       i = 0;
+                       while (deviceOffset + i < size) {
+                               if (buffer [deviceOffset + i] == 0) break;
+                               i++;
+                       }
+                       String device = new String(buffer, deviceOffset, i);
+
+                       /* Create PrinterData object and set fields from PRINTDLG */
+                       data = new PrinterData(driver, device);
+                       if ((pd.Flags & OS.PD_PAGENUMS) != 0) {
+                               data.scope = PrinterData.PAGE_RANGE;
+                               data.startPage = pd.nFromPage & 0xFFFF;
+                               data.endPage = pd.nToPage & 0xFFFF;
+                       } else if ((pd.Flags & OS.PD_SELECTION) != 0) {
+                               data.scope = PrinterData.SELECTION;
+                       }
+                       data.printToFile = (pd.Flags & OS.PD_PRINTTOFILE) != 0;
+                       if (data.printToFile) data.fileName = printerData.fileName;
+                       data.copyCount = pd.nCopies;
+                       data.collate = (pd.Flags & OS.PD_COLLATE) != 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, size);
+
+                       /* Set PrinterData fields from DEVMODE */
+                       devmode = new DEVMODE ();
+                       OS.MoveMemory(devmode, ptr, DEVMODE.sizeof);
+                       if ((devmode.dmFields & OS.DM_ORIENTATION) != 0) {
+                               int dmOrientation = devmode.dmOrientation;
+                               data.orientation = dmOrientation == OS.DMORIENT_LANDSCAPE ? PrinterData.LANDSCAPE : PrinterData.PORTRAIT;
+                       }
+                       if ((devmode.dmFields & OS.DM_DUPLEX) != 0) {
+                               short dmDuplex = devmode.dmDuplex;
+                               data.duplex = dmDuplex == OS.DMDUP_SIMPLEX ? PrinterData.DUPLEX_NONE : dmDuplex == OS.DMDUP_HORIZONTAL ? PrinterData.DUPLEX_SHORT_EDGE : PrinterData.DUPLEX_LONG_EDGE;
+                       }
+
+                       OS.GlobalUnlock(hMem);
+                       printerData = data;
+               }
+       }
+       if (pd.hDevNames != 0) {
+               OS.GlobalFree(pd.hDevNames);
+               pd.hDevNames = 0;
+       }
+       if (pd.hDevMode != 0) {
+               OS.GlobalFree(pd.hDevMode);
+               pd.hDevMode = 0;
+       }
+       /* Destroy the BIDI orientation window */
+       if (hwndParent != hwndOwner) {
+               if (enabled) OS.EnableWindow (hwndParent, true);
+               OS.SetActiveWindow (hwndParent);
+               OS.DestroyWindow (hwndOwner);
+       }
+       return data;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/Printer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/Printer.java
new file mode 100644 (file)
index 0000000..4e68b8b
--- /dev/null
@@ -0,0 +1,617 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.printing;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+       /**
+        * the printer data describing this printer
+        */
+       PrinterData data;
+
+       /**
+        * whether or not a GC was created for this printer
+        */
+       boolean isGCCreated = false;
+
+       /**
+        * strings used to access the Windows registry
+        */
+       static TCHAR profile;
+       static TCHAR appName;
+       static TCHAR keyName;
+       static {
+               profile = new TCHAR(0, "PrinterPorts", true); //$NON-NLS-1$
+               appName = new TCHAR(0, "windows", true); //$NON-NLS-1$
+               keyName = new TCHAR(0, "device", true); //$NON-NLS-1$
+       }
+
+/**
+ * Returns an array of <code>PrinterData</code> objects
+ * representing all available printers.  If there are no
+ * printers, the array will be empty.
+ *
+ * @return an array of PrinterData objects representing the available printers
+ */
+public static PrinterData[] getPrinterList() {
+       int length = 1024;
+       /* Use the character encoding for the default locale */
+       TCHAR buf = new TCHAR(0, length);
+       TCHAR nullBuf = new TCHAR(0, 1);
+       int n = OS.GetProfileString(profile, null, nullBuf, buf, length);
+       if (n == 0) return new PrinterData[0];
+       String[] deviceNames = new String[5];
+       int nameCount = 0;
+       int index = 0;
+       for (int i = 0; i < n; i++) {
+               if (buf.tcharAt(i) == 0) {
+                       if (nameCount == deviceNames.length) {
+                               String[] newNames = new String[deviceNames.length + 5];
+                               System.arraycopy(deviceNames, 0, newNames, 0, deviceNames.length);
+                               deviceNames = newNames;
+                       }
+                       deviceNames[nameCount] = buf.toString(index, i - index);
+                       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(profile, new TCHAR(0, device, true), nullBuf, buf, length) > 0) {
+                       int commaIndex = 0;
+                       while (buf.tcharAt(commaIndex) != ',' && commaIndex < length) commaIndex++;
+                       if (commaIndex < length) {
+                               driver = buf.toString(0, commaIndex);
+                       }
+               }
+               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
+ * default printer.
+ *
+ * @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 */
+       TCHAR buf = new TCHAR(0, length);
+       TCHAR nullBuf = new TCHAR(0, 1);
+       int n = OS.GetProfileString(appName, keyName, nullBuf, buf, length);
+       if (n == 0) return null;
+       int commaIndex = 0;
+       while(buf.tcharAt(commaIndex) != ',' && commaIndex < length) commaIndex++;
+       if (commaIndex < length) {
+               deviceName = buf.toString(0, commaIndex);
+       }
+       if (deviceName == null) return null;
+       String driver = ""; //$NON-NLS-1$
+       if (OS.GetProfileString(profile, new TCHAR(0, deviceName, true), nullBuf, buf, length) > 0) {
+               commaIndex = 0;
+               while (buf.tcharAt(commaIndex) != ',' && commaIndex < length) commaIndex++;
+               if (commaIndex < length) {
+                       driver = buf.toString(0, commaIndex);
+               }
+       }
+       return new PrinterData(driver, deviceName);
+}
+
+static DeviceData checkNull (PrinterData data) {
+       if (data == null) data = new PrinterData();
+       if (data.driver == null || data.name == null) {
+               PrinterData defaultPrinter = getDefaultPrinterData();
+               if (defaultPrinter == 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>
+ * Note: You must dispose the printer when it is no longer required.
+ * </p>
+ *
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if there is no valid default printer
+ * </ul>
+ *
+ * @see Device#dispose
+ */
+public Printer() {
+       this(null);
+}
+
+/**
+ * Constructs a new printer given a <code>PrinterData</code>
+ * object representing the desired printer. If the argument
+ * is null, then the default printer will be used.
+ * <p>
+ * Note: You must dispose the printer when it is no longer required.
+ * </p>
+ *
+ * @param data the printer data for the specified printer, or null to use the default 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 Printer(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
+ */
+@Override
+protected void create(DeviceData deviceData) {
+       data = (PrinterData)deviceData;
+       /* Use the character encoding for the default locale */
+       TCHAR driver = new TCHAR(0, data.driver, true);
+       TCHAR device = new TCHAR(0, data.name, true);
+       long lpInitData = 0;
+       byte devmodeData [] = data.otherData;
+       long hHeap = OS.GetProcessHeap();
+       if (devmodeData != null && devmodeData.length != 0) {
+               /* If user setup info from a print dialog was specified, restore the DEVMODE struct. */
+               lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, devmodeData.length);
+               OS.MoveMemory(lpInitData, devmodeData, devmodeData.length);
+       } else {
+               long [] hPrinter = new long [1];
+               OS.OpenPrinter(device, hPrinter, 0);
+               if (hPrinter[0] != 0) {
+                       int dwNeeded = OS.DocumentProperties(0, hPrinter[0], device, 0, 0, 0);
+                       if (dwNeeded >= 0) {
+                               lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, dwNeeded);
+                               int rc = OS.DocumentProperties(0, hPrinter[0], device, lpInitData, 0, OS.DM_OUT_BUFFER);
+                               if (rc != OS.IDOK) {
+                                       OS.HeapFree(hHeap, 0, lpInitData);
+                                       lpInitData = 0;
+                               }
+                       }
+                       OS.ClosePrinter(hPrinter[0]);
+               }
+       }
+
+       /* Initialize DEVMODE struct fields from the printerData. */
+       if (lpInitData != 0) {
+               DEVMODE devmode = new DEVMODE ();
+               OS.MoveMemory(devmode, lpInitData, DEVMODE.sizeof);
+               devmode.dmFields |= OS.DM_ORIENTATION;
+               devmode.dmOrientation = data.orientation == PrinterData.LANDSCAPE ? OS.DMORIENT_LANDSCAPE : OS.DMORIENT_PORTRAIT;
+               if (data.copyCount != 1) {
+                       devmode.dmFields |= OS.DM_COPIES;
+                       devmode.dmCopies = (short)data.copyCount;
+               }
+               if (data.collate != false) {
+                       devmode.dmFields |= OS.DM_COLLATE;
+                       devmode.dmCollate = OS.DMCOLLATE_TRUE;
+               }
+               if (data.duplex != SWT.DEFAULT) {
+                       devmode.dmFields |= OS.DM_DUPLEX;
+                       switch (data.duplex) {
+                               case PrinterData.DUPLEX_SHORT_EDGE: devmode.dmDuplex = OS.DMDUP_HORIZONTAL; break;
+                               case PrinterData.DUPLEX_LONG_EDGE: devmode.dmDuplex = OS.DMDUP_VERTICAL; break;
+                               default: devmode.dmDuplex = OS.DMDUP_SIMPLEX;
+                       }
+               }
+               OS.MoveMemory(lpInitData, devmode, DEVMODE.sizeof);
+       }
+       handle = OS.CreateDC(driver, device, 0, lpInitData);
+       if (lpInitData != 0) OS.HeapFree(hHeap, 0, lpInitData);
+       if (handle == 0) 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public long internal_new_GC(GCData data) {
+       if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       if (data != null) {
+               if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+               int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+               if ((data.style & mask) != 0) {
+                       data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void internal_dispose_GC(long hDC, GCData data) {
+       if (data != null) isGCCreated = false;
+}
+
+/**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public boolean isAutoScalable() {
+       return 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 boolean startJob(String jobName) {
+       checkDevice();
+       DOCINFO di = new DOCINFO();
+       di.cbSize = DOCINFO.sizeof;
+       long hHeap = OS.GetProcessHeap();
+       long lpszDocName = 0;
+       if (jobName != null && jobName.length() != 0) {
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR(0, jobName, true);
+               int byteCount = buffer.length() * TCHAR.sizeof;
+               lpszDocName = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory(lpszDocName, buffer, byteCount);
+               di.lpszDocName = lpszDocName;
+       }
+       long lpszOutput = 0;
+       if (data.printToFile) {
+               if (data.fileName == null) {
+                       /* Prompt the user for a file name. */
+                       data.fileName = "FILE:"; //$NON-NLS-1$
+               }
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR(0, data.fileName, true);
+               int byteCount = buffer.length() * TCHAR.sizeof;
+               lpszOutput = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory(lpszOutput, buffer, byteCount);
+               di.lpszOutput = lpszOutput;
+       }
+       int rc = OS.StartDoc(handle, di);
+       if (lpszDocName != 0) OS.HeapFree(hHeap, 0, lpszDocName);
+       if (lpszOutput != 0) 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 boolean 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>
+ */
+@Override
+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
+ */
+@Override
+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
+ */
+@Override
+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 &lt;= 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:
+ * </p>
+ * <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>
+ *
+ * @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>
+ */
+@Override
+protected void checkDevice() {
+       if (handle == 0) 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.
+ */
+@Override
+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.
+ */
+@Override
+protected void destroy() {
+       if (handle != 0) OS.DeleteDC(handle);
+       handle = 0;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/PrinterData.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/PrinterData.java
new file mode 100644 (file)
index 0000000..3f8ce5f
--- /dev/null
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.printing;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 extends 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 = 1;
+
+       /**
+        * 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 = 1;
+
+       /**
+        * whether or not the print job should go to a file
+        */
+       public boolean 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 boolean collate = false;
+
+       /**
+        * The orientation of the paper, which can be either PORTRAIT
+        * or LANDSCAPE.
+        *
+        * @since 3.5
+        */
+       public int orientation = PORTRAIT;
+
+       /**
+        * Single-sided or double-sided printing, expressed as one of the
+        * following values:
+        * <dl>
+        * <dt><code>SWT.DEFAULT</code></dt>
+        * <dd>the default duplex value for the printer</dd>
+        * <dt><code>DUPLEX_NONE</code></dt>
+        * <dd>single-sided printing</dd>
+        * <dt><code>DUPLEX_LONG_EDGE</code></dt>
+        * <dd>double-sided printing as if bound on the long edge</dd>
+        * <dt><code>DUPLEX_SHORT_EDGE</code></dt>
+        * <dd>double-sided printing as if bound on the short edge</dd>
+        * </dl>
+        * <p>
+        * The default value is <code>SWT.DEFAULT</code>, meaning do not set a value;
+        * use the printer's default duplex setting.
+        * A printer's default value is typically single-sided,
+        * however it can default to double-sided in order to save paper.
+        * </p>
+        *
+        * @since 3.7
+        */
+       public int duplex = SWT.DEFAULT;
+
+       /**
+        * <code>scope</code> field value indicating that
+        * all pages should be printed
+        */
+       public static final 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 final int PAGE_RANGE = 1;
+
+       /**
+        * <code>scope</code> field value indicating that
+        * the current selection should be printed
+        */
+       public static final int SELECTION = 2;
+
+       /**
+        * <code>orientation</code> field value indicating
+        * portrait paper orientation
+        *
+        * @since 3.5
+        */
+       public static final int PORTRAIT = 1;
+
+       /**
+        * <code>orientation</code> field value indicating
+        * landscape paper orientation
+        *
+        * @since 3.5
+        */
+       public static final int LANDSCAPE = 2;
+
+       /**
+        * <code>duplex</code> field value indicating
+        * single-sided printing.
+        * <p>
+        * This is also known as simplex printing.
+        * </p>
+        *
+        * @since 3.7
+        */
+       public static final int DUPLEX_NONE = 0;
+
+       /**
+        * <code>duplex</code> field value indicating
+        * double-sided printing for binding on the long edge.
+        * <p>
+        * For portrait orientation, the long edge is vertical.
+        * For landscape orientation, the long edge is horizontal.
+        * </p><p>
+        * This is also known as duplex printing.
+        * </p>
+        *
+        * @since 3.7
+        */
+       public static final int DUPLEX_LONG_EDGE = 1;
+
+       /**
+        * <code>duplex</code> field value indicating
+        * double-sided printing for binding on the short edge.
+        * <p>
+        * For portrait orientation, the short edge is horizontal.
+        * For landscape orientation, the short edge is vertical.
+        * </p><p>
+        * This is also known as duplex tumble printing.
+        * </p>
+        *
+        * @since 3.7
+        */
+       public static final int DUPLEX_SHORT_EDGE = 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 Cocoa, 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 PrinterData() {
+       }
+
+       /**
+        * 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 PrinterData(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
+        */
+       @Override
+       public String toString() {
+               return "PrinterData {" + "driver = " + driver + ", name = " + name + "}";  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+       }
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/printing/package.html
new file mode 100644 (file)
index 0000000..4de0891
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Printing support classes.
+<h2>
+Package Specification</h2>
+This package contains the classes which provide printing support for SWT.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/program/Program.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/program/Program.java
new file mode 100644 (file)
index 0000000..dd39098
--- /dev/null
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.program;
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 final String [] ARGUMENTS = new String [] {"%1", "%l", "%L"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Program () {
+}
+
+static String assocQueryString (int assocStr, TCHAR key, boolean expand) {
+       TCHAR pszOut = new TCHAR(0, 1024);
+       int[] pcchOut = new int[1];
+       pcchOut[0] = pszOut.length();
+       int flags = OS.ASSOCF_NOTRUNCATE | OS.ASSOCF_INIT_IGNOREUNKNOWN;
+       int result = OS.AssocQueryString (flags, assocStr, key, null, pszOut, pcchOut);
+       if (result == OS.E_POINTER) {
+               pszOut = new TCHAR(0, pcchOut [0]);
+               result = OS.AssocQueryString (flags, assocStr, key, null, pszOut, pcchOut);
+       }
+       if (result == 0) {
+               if (expand) {
+                       int length = OS.ExpandEnvironmentStrings (pszOut, null, 0);
+                       if (length != 0) {
+                               TCHAR lpDst = new TCHAR (0, length);
+                               OS.ExpandEnvironmentStrings (pszOut, lpDst, length);
+                               return lpDst.toString (0, Math.max (0, length - 1));
+                       } else {
+                               return "";
+                       }
+               } else {
+                       return pszOut.toString (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>
+ *
+ * @exception IllegalArgumentException <ul>
+ *             <li>ERROR_NULL_ARGUMENT when extension is null</li>
+ *     </ul>
+ */
+public static Program findProgram (String extension) {
+       if (extension == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       if (extension.length () == 0) return null;
+       if (extension.charAt (0) != '.') extension = "." + extension; //$NON-NLS-1$
+       /* Use the character encoding for the default locale */
+       TCHAR key = new TCHAR (0, extension, true);
+       Program program = null;
+       String command = assocQueryString (OS.ASSOCSTR_COMMAND, key, true);
+       if (command != null) {
+               String name = null;
+               if (name == null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYDOCNAME, key, false);
+               if (name == null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYAPPNAME, key, false);
+               if (name == null) name = "";
+               String iconName = assocQueryString (OS.ASSOCSTR_DEFAULTICON, key, true);
+               if (iconName == 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];
+       char [] lpName = new char [1024];
+       int [] lpcName = {lpName.length};
+       FILETIME ft = new FILETIME ();
+       int dwIndex = 0, count = 0;
+       while (OS.RegEnumKeyEx (OS.HKEY_CLASSES_ROOT, dwIndex, lpName, lpcName, null, null, null, ft) != OS.ERROR_NO_MORE_ITEMS) {
+               String extension = new String (lpName, 0, lpcName [0]);
+               lpcName [0] = lpName.length;
+               if (extension.length () > 0 && extension.charAt (0) == '.') {
+                       if (count == 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 != extensions.length) {
+               String [] newExtension = new String [count];
+               System.arraycopy (extensions, 0, newExtension, 0, count);
+               extensions = newExtension;
+       }
+       return extensions;
+}
+
+static String getKeyValue (String string, boolean expand) {
+       /* Use the character encoding for the default locale */
+       TCHAR key = new TCHAR (0, string, true);
+       long [] phkResult = new long [1];
+       if (OS.RegOpenKeyEx (OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) != 0) {
+               return null;
+       }
+       String result = null;
+       int [] lpcbData = new int [1];
+       if (OS.RegQueryValueEx (phkResult [0], (TCHAR) null, 0, null, (TCHAR) null, lpcbData) == 0) {
+               result = "";
+               int length = lpcbData [0] / TCHAR.sizeof;
+               /*
+                * Crash is seen when the size of REG_SZ entry in HKEY_CLASSES_ROOT
+                * is not multiple of a Unicode byte length. The REG_SZ entry in
+                * Windows registry may not have been stored with the proper
+                * terminating null characters: e.g. non null terminated string or a
+                * single byte null terminated. Refer below MSDN article on this:
+                * https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884
+                * %28v=vs.85%29.aspx Hence solution is to adjust the buffer length
+                * accordingly. Refer Bug 157010 for more details.
+                */
+               if (lpcbData [0] % TCHAR.sizeof != 0) {
+                       length++;
+               }
+               if (length != 0) {
+                       char [] lpData = new char [length];
+                       if (OS.RegQueryValueEx (phkResult [0], null, 0, null, lpData, lpcbData) == 0) {
+                               if (expand) {
+                                       length = OS.ExpandEnvironmentStrings (lpData, null, 0);
+                                       if (length != 0) {
+                                               char [] lpDst = new char [length];
+                                               OS.ExpandEnvironmentStrings (lpData, lpDst, length);
+                                               result = new String (lpDst, 0, length - 1);
+                                       }
+                               } else {
+                                       result = new String (lpData, 0, length - 1);
+                               }
+                       }
+               }
+       }
+       if (phkResult [0] != 0) OS.RegCloseKey (phkResult [0]);
+       return result;
+}
+
+static Program getProgram (String key, String extension) {
+
+       /* Name */
+       String name = getKeyValue (key, false);
+       if (name == null || name.length () == 0) {
+               name = key;
+       }
+
+       /* Command */
+       String DEFAULT_COMMAND = "\\shell"; //$NON-NLS-1$
+       String defaultCommand = getKeyValue (key + DEFAULT_COMMAND, true);
+       if (defaultCommand == null || defaultCommand.length() == 0) defaultCommand = "open"; //$NON-NLS-1$
+       String COMMAND = "\\shell\\" + defaultCommand + "\\command"; //$NON-NLS-1$
+       String command = getKeyValue (key + COMMAND, true);
+       if (command == null || command.length () == 0) return null;
+
+       /* Icon */
+       String DEFAULT_ICON = "\\DefaultIcon"; //$NON-NLS-1$
+       String iconName = getKeyValue (key + DEFAULT_ICON, true);
+       if (iconName == 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 () {
+       LinkedHashSet<Program> programs = new LinkedHashSet<>(1024);
+       char [] lpName = new char [1024];
+       int [] lpcName = new int [] {lpName.length};
+       FILETIME ft = new FILETIME ();
+       int dwIndex = 0;
+       while (OS.RegEnumKeyEx (OS.HKEY_CLASSES_ROOT, dwIndex, lpName, lpcName, null, null, null, ft) != OS.ERROR_NO_MORE_ITEMS) {
+               String path = new String (lpName, 0, lpcName [0]);
+               lpcName [0] = lpName.length;
+               Program program = getProgram (path, null);
+               if (program != null) {
+                       programs.add(program);
+               }
+               dwIndex++;
+       }
+       return programs.toArray(new Program[programs.size()]);
+}
+
+/**
+ * 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 boolean launch (String fileName) {
+       return launch(fileName, null);
+}
+
+/**
+ * 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. The program is launched with the specified
+ * working directory only when the <code>workingDir</code> exists and
+ * <code>fileName</code> is an executable.
+ * Note that a <code>Display</code> must already exist to guarantee
+ * that this method returns an appropriate result.
+ *
+ * @param fileName the file name or program name or URL (http:// or https://)
+ * @param workingDir the name of the working directory or null
+ * @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>
+ *
+ * @since 3.6
+ */
+public static boolean launch (String fileName, String workingDir) {
+       if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+
+       /* Use the character encoding for the default locale */
+       long hHeap = OS.GetProcessHeap ();
+       TCHAR buffer = new TCHAR (0, fileName, true);
+       int byteCount = buffer.length () * TCHAR.sizeof;
+       long lpFile = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (lpFile, buffer, byteCount);
+
+       long lpDirectory = 0;
+       if (workingDir != null && OS.PathIsExe(lpFile)) {
+               TCHAR buffer1 = new TCHAR (0, workingDir, true);
+               byteCount = buffer1.length () * TCHAR.sizeof;
+               lpDirectory = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory (lpDirectory, buffer1, byteCount);
+       }
+
+       SHELLEXECUTEINFO info = new SHELLEXECUTEINFO ();
+       info.cbSize = SHELLEXECUTEINFO.sizeof;
+       info.lpFile = lpFile;
+       info.lpDirectory = lpDirectory;
+       info.nShow = OS.SW_SHOW;
+       boolean result = OS.ShellExecuteEx (info);
+       if (lpFile != 0) OS.HeapFree (hHeap, 0, lpFile);
+       if (lpDirectory != 0) OS.HeapFree (hHeap, 0, lpDirectory);
+       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 boolean execute (String fileName) {
+       if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       int index = 0;
+       boolean append = true;
+       String prefix = command, suffix = ""; //$NON-NLS-1$
+       while (index < ARGUMENTS.length) {
+               int i = command.indexOf (ARGUMENTS [index]);
+               if (i != -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;
+       long hHeap = OS.GetProcessHeap ();
+       /* Use the character encoding for the default locale */
+       TCHAR buffer = new TCHAR (0, commandLine, true);
+       int byteCount = buffer.length () * TCHAR.sizeof;
+       long lpCommandLine = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (lpCommandLine, buffer, byteCount);
+       STARTUPINFO lpStartupInfo = new STARTUPINFO ();
+       lpStartupInfo.cb = STARTUPINFO.sizeof;
+       PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION ();
+       boolean success = OS.CreateProcess (0, lpCommandLine, 0, 0, false, 0, 0, 0, lpStartupInfo, lpProcessInformation);
+       if (lpCommandLine != 0) OS.HeapFree (hHeap, 0, lpCommandLine);
+       if (lpProcessInformation.hProcess != 0) OS.CloseHandle (lpProcessInformation.hProcess);
+       if (lpProcessInformation.hThread != 0) 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 != null) {
+               SHFILEINFO shfi = new SHFILEINFO ();
+               int flags = OS.SHGFI_ICON | OS.SHGFI_SMALLICON | OS.SHGFI_USEFILEATTRIBUTES;
+               TCHAR pszPath = new TCHAR (0, extension, true);
+               OS.SHGetFileInfo (pszPath.chars, OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags);
+               if (shfi.hIcon != 0) {
+                       Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon);
+                       /* Fetch the ImageData at 100% zoom and return */
+                       ImageData imageData = image.getImageData ();
+                       image.dispose ();
+                       return imageData;
+               }
+       }
+       int nIconIndex = 0;
+       String fileName = iconName;
+       int index = iconName.indexOf (',');
+       if (index != -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 > 1 && fileName.charAt (0) == '\"') {
+               if (fileName.charAt (length - 1) == '\"') {
+                       fileName = fileName.substring (1, length - 1);
+               }
+       }
+       /* Use the character encoding for the default locale */
+       TCHAR lpszFile = new TCHAR (0, fileName, true);
+       long [] phiconSmall = new long[1], phiconLarge = null;
+       OS.ExtractIconEx (lpszFile, nIconIndex, phiconLarge, phiconSmall, 1);
+       if (phiconSmall [0] == 0) return null;
+       Image image = Image.win32_new (null, SWT.ICON, phiconSmall [0]);
+       /* Fetch the ImageData at 100% zoom and return */
+       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()
+ */
+@Override
+public boolean equals(Object other) {
+       if (this == other) return true;
+       if (other instanceof Program) {
+               final Program program = (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)
+ */
+@Override
+public int hashCode() {
+       return name.hashCode() ^ command.hashCode() ^ iconName.hashCode();
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the program
+ */
+@Override
+public String toString () {
+       return "Program {" + name + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/program/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/program/package.html
new file mode 100644 (file)
index 0000000..99d6556
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT Program support class.
+<h2>
+Package Specification</h2>
+This package contains class <code>Program</code> which provides access to facilities for
+discovering operating system specific aspects of external program launching.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Button.java
new file mode 100644 (file)
index 0000000..feb543a
--- /dev/null
@@ -0,0 +1,1493 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Conrad Groth - Bug 23837 [FEEP] Button, do not respect foreground and background color on Windows
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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, WRAP</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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Button extends Control {
+       String text = "", message = "";
+       Image image, image2, disabledImage;
+       ImageList imageList;
+       boolean ignoreMouse, grayed;
+       int buttonBackground = -1;
+       // we need our own field, because setting Control.background causes two colored pixels around the button.
+       int buttonBackgroundAlpha = 255;
+       static final int MARGIN = 4;
+       static final int CHECK_WIDTH, CHECK_HEIGHT;
+       static final int ICON_WIDTH = 128, ICON_HEIGHT = 128;
+       static /*final*/ boolean COMMAND_LINK = false;
+       static final long ButtonProc;
+       static final TCHAR ButtonClass = new TCHAR (0, "BUTTON", true);
+       static {
+               long hBitmap = OS.LoadBitmap (0, OS.OBM_CHECKBOXES);
+               if (hBitmap == 0) {
+                       CHECK_WIDTH = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+                       CHECK_HEIGHT = OS.GetSystemMetrics (OS.SM_CYVSCROLL);
+               } else {
+                       BITMAP bitmap = new BITMAP ();
+                       OS.GetObject (hBitmap, BITMAP.sizeof, bitmap);
+                       OS.DeleteObject (hBitmap);
+                       CHECK_WIDTH = bitmap.bmWidth / 4;
+                       CHECK_HEIGHT =  bitmap.bmHeight / 3;
+               }
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ButtonClass, lpWndClass);
+               ButtonProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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#UP
+ * @see SWT#DOWN
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Button (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+void _setImage (Image image) {
+       if ((style & SWT.COMMAND) != 0) return;
+       if (imageList != null) imageList.dispose ();
+       imageList = null;
+       if (image != null) {
+               imageList = new ImageList (style & SWT.RIGHT_TO_LEFT);
+               if (OS.IsWindowEnabled (handle)) {
+                       imageList.add (image);
+               } else {
+                       if (disabledImage != null) disabledImage.dispose ();
+                       disabledImage = new Image (display, image, SWT.IMAGE_DISABLE);
+                       imageList.add (disabledImage);
+               }
+               BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST ();
+               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) != 0) newBits |= OS.BS_LEFT;
+               if ((style & SWT.CENTER) != 0) newBits |= OS.BS_CENTER;
+               if ((style & SWT.RIGHT) != 0) newBits |= OS.BS_RIGHT;
+               if (text.length () == 0) {
+                       if ((style & SWT.LEFT) != 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                       if ((style & SWT.CENTER) != 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+                       if ((style & SWT.RIGHT) != 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 != 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);
+}
+
+void _setText (String text) {
+       int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+       newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+       if ((style & SWT.LEFT) != 0) newBits |= OS.BS_LEFT;
+       if ((style & SWT.CENTER) != 0) newBits |= OS.BS_CENTER;
+       if ((style & SWT.RIGHT) != 0) newBits |= OS.BS_RIGHT;
+       if (imageList != null) {
+               BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST ();
+               buttonImageList.himl = imageList.getHandle ();
+               if (text.length () == 0) {
+                       if ((style & SWT.LEFT) != 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                       if ((style & SWT.CENTER) != 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+                       if ((style & SWT.RIGHT) != 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 != 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 append a space to the text.
+       */
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               if (!OS.IsAppThemed ()) {
+                       text = OS.IsWindowEnabled (handle) ? text : text + " ";
+               }
+       }
+       TCHAR buffer = new TCHAR (getCodePage (), text, true);
+       OS.SetWindowText (handle, buffer);
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+}
+
+/**
+ * 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>
+ * <p>
+ * When the <code>SWT.RADIO</code> style bit is set, the <code>widgetSelected</code> method is
+ * also called when the receiver loses selection because another item in the same radio group
+ * was selected by the user. During <code>widgetSelected</code> the application can use
+ * <code>getSelection()</code> to determine the current selected state of the receiver.
+ * </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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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)) != 0) {
+               return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0);
+       }
+       if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
+               return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
+       }
+       if ((style & SWT.ARROW) != 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;
+}
+
+// TODO: this method ignores the style LEFT, CENTER or RIGHT
+int computeLeftMargin () {
+       if ((style & (SWT.PUSH | SWT.TOGGLE)) == 0) return MARGIN;
+       int margin = 0;
+       if (image != null && text.length () != 0) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               margin += bounds.width + MARGIN * 2;
+               long oldFont = 0;
+               long hDC = OS.GetDC (handle);
+               long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               char [] buffer = text.toCharArray ();
+               RECT rect = new RECT ();
+               int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+               OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+               margin += rect.right - rect.left;
+               if (newFont != 0) 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width = 0, height = 0, border = getBorderWidthInPixels ();
+       if ((style & SWT.ARROW) != 0) {
+               if ((style & (SWT.UP | SWT.DOWN)) != 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) != 0) {
+                       SIZE size = new SIZE ();
+                       if (wHint != 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 != height) {
+                                       size.cx = width++;
+                                       size.cy = 0;
+                                       OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, size);
+                               }
+                       }
+               } else {
+                       int extra = 0;
+                       boolean hasImage = image != null, hasText = true;
+                       if (hasImage) {
+                               if (image != null) {
+                                       Rectangle rect = image.getBoundsInPixels ();
+                                       width = rect.width;
+                                       if (hasText && text.length () != 0) {
+                                               width += MARGIN * 2;
+                                       }
+                                       height = rect.height;
+                                       extra = MARGIN * 2;
+                               }
+                       }
+                       if (hasText) {
+                               long oldFont = 0;
+                               long hDC = OS.GetDC (handle);
+                               long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+                               TEXTMETRIC lptm = new TEXTMETRIC ();
+                               OS.GetTextMetrics (hDC, lptm);
+                               int length = text.length ();
+                               if (length == 0) {
+                                       height = Math.max (height, lptm.tmHeight);
+                               } else {
+                                       extra = Math.max (MARGIN * 2, lptm.tmAveCharWidth);
+                                       char [] buffer = text.toCharArray ();
+                                       RECT rect = new RECT ();
+                                       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+                                       if ((style & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) {
+                                               flags = OS.DT_CALCRECT | OS.DT_WORDBREAK;
+                                               rect.right = wHint - width - 2 * border;
+                                               if (isRadioOrCheck()) {
+                                                       rect.right -= CHECK_WIDTH + 3;
+                                               } else {
+                                                       rect.right -= 6;
+                                               }
+                                               if (!OS.IsAppThemed ()) {
+                                                       rect.right -= 2;
+                                                       if (isRadioOrCheck()) {
+                                                               rect.right -= 2;
+                                                       }
+                                               }
+                                       }
+                                       OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+                                       width += rect.right - rect.left;
+                                       height = Math.max (height, rect.bottom - rect.top);
+                               }
+                               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+                               OS.ReleaseDC (handle, hDC);
+                       }
+                       if (isRadioOrCheck()) {
+                               width += CHECK_WIDTH + extra;
+                               height = Math.max (height, CHECK_HEIGHT + 3);
+                       }
+                       if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+                               width += 12;  height += 10;
+                       }
+               }
+       }
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != 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;
+
+       if (OS.IsAppThemed ()) {
+               /* Set the theme background.
+               *
+               * 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 ((style & (SWT.PUSH | SWT.TOGGLE)) == 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 ((style & SWT.RADIO) != 0) {
+                       state |= DRAW_BACKGROUND;
+               }
+       }
+}
+
+private boolean customBackgroundDrawing() {
+       return buttonBackground != -1 && !isRadioOrCheck();
+}
+
+private boolean customDrawing() {
+       return customBackgroundDrawing() || customForegroundDrawing();
+}
+
+private boolean customForegroundDrawing() {
+       return foreground != -1 && !text.isEmpty() && OS.IsWindowEnabled(handle);
+}
+
+@Override
+int defaultBackground () {
+       if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+               return OS.GetSysColor (OS.COLOR_BTNFACE);
+       }
+       return super.defaultBackground ();
+}
+
+@Override
+int defaultForeground () {
+       return OS.GetSysColor (OS.COLOR_BTNTEXT);
+}
+
+@Override
+void enableWidget (boolean 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 append a space to the text.
+       */
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               if (!OS.IsAppThemed ()) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       boolean hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) != 0;
+                       if (!hasImage) {
+                               String string = enabled ? text : text + " ";
+                               TCHAR buffer = new TCHAR (getCodePage (), string, true);
+                               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.
+       */
+       updateImageList ();
+}
+
+/**
+ * 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) != 0) {
+               if ((style & SWT.UP) != 0) return SWT.UP;
+               if ((style & SWT.DOWN) != 0) return SWT.DOWN;
+               if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+               if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+               return SWT.UP;
+       }
+       if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+       if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+       if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+       return SWT.LEFT;
+}
+
+@Override
+public Color getBackground () {
+       if (isRadioOrCheck()) {
+               return super.getBackground();
+       }
+       checkWidget ();
+       if (buttonBackground != -1) {
+               return Color.win32_new (display, buttonBackground, buttonBackgroundAlpha);
+       }
+       return Color.win32_new (display, defaultBackground());
+}
+
+boolean getDefault () {
+       if ((style & SWT.PUSH) == 0) return false;
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       return (bits & OS.BS_DEFPUSHBUTTON) != 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 boolean getGrayed () {
+       checkWidget();
+       if ((style & SWT.CHECK) == 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 boolean getSelection () {
+       checkWidget ();
+       if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return false;
+       return isChecked();
+}
+
+/**
+ * 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) != 0) return "";
+       return text;
+}
+
+private boolean isChecked() {
+       long flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+       return flags != OS.BST_UNCHECKED;
+}
+
+private boolean isRadioOrCheck() {
+       return (style & (SWT.RADIO | SWT.CHECK)) != 0;
+}
+
+@Override
+boolean isTabItem () {
+       if ((style & SWT.PUSH) != 0) return isTabGroup ();
+       return super.isTabItem ();
+}
+
+@Override
+boolean mnemonicHit (char 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) == 0) click ();
+       return true;
+}
+
+@Override
+boolean mnemonicMatch (char key) {
+       char mnemonic = findMnemonic (getText ());
+       if (mnemonic == '\0') return false;
+       return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (imageList != null) imageList.dispose ();
+       imageList = null;
+       if (disabledImage != null) disabledImage.dispose ();
+       disabledImage = null;
+       if (image2 != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+@Override
+int resolveTextDirection() {
+       return (style & SWT.ARROW) != 0 ? SWT.NONE : BidiUtil.resolveTextDirection(text);
+}
+
+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] != 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 != 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) != 0) {
+               if ((style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) == 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)) == 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) != 0) newBits |= OS.BS_LEFT;
+       if ((style & SWT.CENTER) != 0) newBits |= OS.BS_CENTER;
+       if ((style & SWT.RIGHT) != 0) newBits |= OS.BS_RIGHT;
+       if (imageList != null) {
+               BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST ();
+               buttonImageList.himl = imageList.getHandle ();
+               if (text.length () == 0) {
+                       if ((style & SWT.LEFT) != 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                       if ((style & SWT.CENTER) != 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+                       if ((style & SWT.RIGHT) != 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 != oldBits) {
+               OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+               OS.InvalidateRect (handle, null, true);
+       }
+}
+
+/**
+ * Sets the button'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 is custom paint operation and only affects {@link SWT#PUSH} and {@link SWT#TOGGLE} buttons. If the native button
+ * has a 3D look an feel (e.g. Windows 7), this method will cause the button to look FLAT irrespective of the state of the
+ * {@link SWT#FLAT} style.
+ * For {@link SWT#CHECK} and {@link SWT#RADIO} buttons, this method delegates to {@link Control#setBackground(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>
+ */
+@Override
+public void setBackground (Color color) {
+       checkWidget ();
+       if (isRadioOrCheck()) {
+               super.setBackground(color);
+       } else {
+               setButtonBackground (color);
+       }
+}
+
+private void setButtonBackground (Color color) {
+       int pixel = -1;
+       int alpha = 255;
+       if (color != null) {
+               if (color.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+               alpha = color.getAlpha();
+       }
+       if (pixel == buttonBackground && alpha == buttonBackgroundAlpha) return;
+       buttonBackground = pixel;
+       buttonBackgroundAlpha = alpha;
+       updateBackgroundColor ();
+}
+
+void setDefault (boolean value) {
+       if ((style & SWT.PUSH) == 0) return;
+       long 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
+public boolean setFocus () {
+       checkWidget ();
+       /*
+       * 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) != 0 && !isChecked () && display.fixFocus) return false;
+       return super.setFocus ();
+}
+
+/**
+ * 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 != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       if ((style & SWT.ARROW) != 0) return;
+       this.image = image;
+       /* This code is intentionally commented */
+//     if (OS.COMCTL32_MAJOR < 6) {
+//             if (image == null || text.length () != 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 (boolean grayed) {
+       checkWidget ();
+       if ((style & SWT.CHECK) == 0) return;
+       this.grayed = grayed;
+       long flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+       if (grayed) {
+               if (flags == OS.BST_CHECKED) updateSelection (OS.BST_INDETERMINATE);
+       } else {
+               if (flags == 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 ();
+       if (message == null) error (SWT.ERROR_NULL_ARGUMENT);
+       this.message = message;
+       if ((style & SWT.COMMAND) != 0) {
+               int length = message.length ();
+               char [] chars = new char [length + 1];
+               message.getChars(0, length, chars, 0);
+               OS.SendMessage (handle, OS.BCM_SETNOTE, 0, chars);
+       }
+}
+
+@Override
+boolean setRadioFocus (boolean tabbing) {
+       if ((style & SWT.RADIO) == 0 || !getSelection ()) return false;
+       return tabbing ? setTabItemFocus () : setFocus ();
+}
+
+@Override
+boolean setRadioSelection (boolean value) {
+       if ((style & SWT.RADIO) == 0) return false;
+       if (getSelection () != value) {
+               setSelection (value);
+               sendSelectionEvent (SWT.Selection);
+       }
+       return true;
+}
+
+/**
+ * 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 (boolean selected) {
+       checkWidget ();
+       if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return;
+       int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED;
+       if ((style & SWT.CHECK) != 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><p>
+ * Also note, if control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if ((style & SWT.ARROW) != 0) return;
+       text = string;
+       /* This code is intentionally commented */
+//     if (OS.COMCTL32_MAJOR < 6) {
+//             if (text.length () == 0 && image != null) {
+//                     _setImage (image);
+//                     return;
+//             }
+//     }
+       _setText (string);
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+// TODO: Keep for now, to follow up
+//             int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+//             style &= ~SWT.MIRRORED;
+//             style &= ~flags;
+//             style |= textDirection & flags;
+//             updateOrientation ();
+//             checkMirrored ();
+               return true;
+       }
+       return false;
+}
+
+void updateImageList () {
+       if (imageList != null) {
+               BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST ();
+               OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, buttonImageList);
+               if (imageList != null) imageList.dispose ();
+               imageList = new ImageList (style & SWT.RIGHT_TO_LEFT);
+               if (OS.IsWindowEnabled (handle)) {
+                       imageList.add (image);
+               } else {
+                       if (disabledImage != 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);
+       }
+}
+
+@Override
+void updateOrientation () {
+       super.updateOrientation ();
+       updateImageList ();
+}
+
+void updateSelection (int flags) {
+       if (flags != 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 WS_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) != 0) {
+                       if (flags == OS.BST_INDETERMINATE) {
+                               bits &= ~OS.BS_CHECKBOX;
+                               bits |= OS.BS_3STATE;
+                       } else {
+                               bits |= OS.BS_CHECKBOX;
+                               bits &= ~OS.BS_3STATE;
+                       }
+                       if (bits != OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+                               OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+                       }
+               }
+               OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
+               if (bits != OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+                       OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+               }
+       }
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle ();
+       if ((style & SWT.FLAT) != 0) bits |= OS.BS_FLAT;
+       if ((style & SWT.ARROW) != 0) return bits | OS.BS_OWNERDRAW;
+       if ((style & SWT.LEFT) != 0) bits |= OS.BS_LEFT;
+       if ((style & SWT.CENTER) != 0) bits |= OS.BS_CENTER;
+       if ((style & SWT.RIGHT) != 0) bits |= OS.BS_RIGHT;
+       if ((style & SWT.WRAP) != 0) bits |= OS.BS_MULTILINE;
+       if ((style & SWT.PUSH) != 0) return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+       if ((style & SWT.CHECK) != 0) return bits | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+       if ((style & SWT.RADIO) != 0) return bits | OS.BS_RADIOBUTTON;
+       if ((style & SWT.TOGGLE) != 0) return bits | OS.BS_PUSHLIKE | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+       if ((style & SWT.COMMAND) != 0) return bits | OS.BS_COMMANDLINK | OS.WS_TABSTOP;
+       return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+}
+
+@Override
+TCHAR windowClass () {
+       return ButtonClass;
+}
+
+@Override
+long windowProc () {
+       return ButtonProc;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+       if (result != null) return result;
+       if ((style & SWT.ARROW) != 0) {
+               return new LRESULT (OS.DLGC_STATIC);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETOBJECT (long wParam, long lParam) {
+       /*
+       * Ensure that there is an accessible object created for this
+       * control because support for radio button position in group
+       * accessibility is implemented in the accessibility package.
+       */
+       if ((style & SWT.RADIO) != 0) {
+               if (accessible == null) accessible = new_Accessible (this);
+       }
+       return super.WM_GETOBJECT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+       if ((style & SWT.PUSH) != 0 && getDefault ()) {
+               menuShell ().setDefaultButton (null, false);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       if (ignoreMouse) return null;
+       return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+@Override
+LRESULT WM_LBUTTONUP (long wParam, long lParam) {
+       if (ignoreMouse) return null;
+       return super.WM_LBUTTONUP (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       /*
+       * Feature in Windows. When Windows sets focus to
+       * a radio button, it sets the WS_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) != 0) {
+               bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       }
+       LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+       if ((style & SWT.RADIO) != 0) {
+               OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+       }
+       if ((style & SWT.PUSH) != 0) {
+               menuShell ().setDefaultButton (this, false);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       if (result != null) return result;
+       if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+               if (imageList != null && text.length () != 0) {
+                       BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST ();
+                       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 (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+       if (result != null) return result;
+       if (image2 != null) _setImage (image);
+       return result;
+}
+
+@Override
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+       if (result != 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 ((style & (SWT.RADIO | SWT.CHECK | SWT.TOGGLE)) != 0) {
+               boolean redraw = findImageControl () != null;
+               if (!redraw) {
+                       if ((state & THEME_BACKGROUND) != 0) {
+                               if (OS.IsAppThemed ()) {
+                                       redraw = findThemeControl () != null;
+                               }
+                       }
+                       if (!redraw) redraw = findBackgroundControl () != null;
+               }
+               if (redraw) {
+                       OS.InvalidateRect (handle, null, false);
+                       long code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+                       return new LRESULT (code);
+               }
+       }
+       /*
+       * Feature in Windows.  Push and toggle buttons draw directly
+       * in WM_UPDATEUISTATE rather than damaging and drawing later
+       * in WM_PAINT.  This means that clients who hook WM_PAINT
+       * expecting to get all the drawing will not.  The fix is to
+       * redraw the control when paint events are hooked.
+       */
+       if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+               if (hooks (SWT.Paint) || filters (SWT.Paint) || customDrawing()) {
+                       OS.InvalidateRect (handle, null, true);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT wmCommandChild (long wParam, long lParam) {
+       int code = OS.HIWORD (wParam);
+       switch (code) {
+               case OS.BN_CLICKED:
+               case OS.BN_DOUBLECLICKED:
+                       if ((style & (SWT.CHECK | SWT.TOGGLE)) != 0) {
+                               setSelection (!getSelection ());
+                       } else {
+                               if ((style & SWT.RADIO) != 0) {
+                                       if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) {
+                                               setSelection (!getSelection ());
+                                       } else {
+                                               selectRadio ();
+                                       }
+                               }
+                       }
+                       sendSelectionEvent (SWT.Selection);
+       }
+       return super.wmCommandChild (wParam, lParam);
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.NM_CUSTOMDRAW:
+                       // this message will not appear for owner-draw buttons (currently the ARROW button).
+
+                       NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
+                       OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
+
+                       switch (nmcd.dwDrawStage) {
+                               case OS.CDDS_PREPAINT: {
+                                       // buttons are ignoring SetBkColor, SetBkMode and SetTextColor
+                                       if (customBackgroundDrawing()) {
+                                               int pixel = buttonBackground;
+                                               if ((nmcd.uItemState & OS.CDIS_SELECTED) != 0) {
+                                                       pixel = getDifferentColor(buttonBackground);
+                                               } else if ((nmcd.uItemState & OS.CDIS_HOT) != 0) {
+                                                       pixel = getSlightlyDifferentColor(buttonBackground);
+                                               }
+                                               if ((style & SWT.TOGGLE) != 0 && isChecked()) {
+                                                       pixel = getDifferentColor(buttonBackground);
+                                               }
+                                               RECT rect = new RECT ();
+                                               OS.SetRect (rect, nmcd.left+2, nmcd.top+2, nmcd.right-2, nmcd.bottom-2);
+                                               long brush = OS.CreateSolidBrush(pixel);
+                                               OS.FillRect(nmcd.hdc, rect, brush);
+                                               OS.DeleteObject(brush);
+                                       }
+                                       if (customForegroundDrawing()) {
+                                               /*
+                                                * Check-box/Radio buttons are native widget which honors
+                                                * the Win OS zoom level for both 'Square' and 'Text' part
+                                                * [Note: By-design SWT doesn't control native auto-scaling]
+                                                * Hence, custom fore-ground draw logic should auto-scale
+                                                * text-padding as per OS Native DPI level to fix bug 506371
+                                                */
+                                               int radioOrCheckTextPadding = DPIUtil.autoScaleUpUsingNativeDPI(16);
+                                               int border = isRadioOrCheck() ? 0 : 3;
+                                               int left = nmcd.left + border;
+                                               int right = nmcd.right - border;
+                                               if (image != null) {
+                                                       GCData data = new GCData();
+                                                       data.device = display;
+                                                       GC gc = GC.win32_new (nmcd.hdc, data);
+
+                                                       int margin = computeLeftMargin();
+                                                       int imageWidth = image.getBoundsInPixels().width;
+                                                       left += (imageWidth + (isRadioOrCheck() ? 2 * MARGIN : MARGIN)); // for SWT.RIGHT_TO_LEFT right and left are inverted
+
+                                                       int x = margin + (isRadioOrCheck() ? radioOrCheckTextPadding : 3);
+                                                       int y = Math.max (0, (nmcd.bottom - image.getBoundsInPixels().height) / 2);
+                                                       gc.drawImage (image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y));
+                                                       gc.dispose ();
+                                               }
+
+                                               left += isRadioOrCheck() ? radioOrCheckTextPadding : 0;
+                                               RECT textRect = new RECT ();
+                                               OS.SetRect (textRect, left, nmcd.top + border, right, nmcd.bottom - border);
+
+                                               // draw text
+                                               char [] buffer = text.toCharArray ();
+                                               int flags = 0;
+                                               if ((style & SWT.WRAP) != 0) {
+                                                       flags |= OS.DT_WORDBREAK;
+                                                       if (!isRadioOrCheck() && image != null) {
+                                                               textRect.right -= MARGIN;
+                                                       }
+                                               } else {
+                                                       flags |= OS.DT_SINGLELINE; // TODO: this always draws the prefix
+                                               }
+                                               OS.DrawText(nmcd.hdc, buffer, buffer.length, textRect, flags | OS.DT_CALCRECT);
+                                               OS.OffsetRect(textRect, 0, Math.max(0, (nmcd.bottom  - textRect.bottom - border) / 2));
+                                               if (image != null) {
+                                                       // The default button with an image doesn't respect the text alignment. So we do the same for styled buttons.
+                                                       flags |= OS.DT_LEFT;
+                                                       if (!isRadioOrCheck()) {
+                                                               OS.OffsetRect(textRect, Math.max(MARGIN, (right - textRect.right) / 2 + 1), 0);
+                                                       }
+                                               } else if ((style & SWT.LEFT) != 0) {
+                                                       flags |= OS.DT_LEFT;
+                                               } else if ((style & SWT.RIGHT) != 0) {
+                                                       flags |= OS.DT_RIGHT;
+                                                       OS.OffsetRect(textRect, right - textRect.right, 0);
+                                               } else {
+                                                       flags |= OS.DT_CENTER;
+                                                       OS.OffsetRect(textRect, (right - textRect.right) / 2, 0);
+                                               }
+                                               OS.SetBkMode(nmcd.hdc, OS.TRANSPARENT);
+                                               OS.SetTextColor(nmcd.hdc, foreground);
+                                               OS.DrawText(nmcd.hdc, buffer, buffer.length, textRect, flags);
+
+                                               // draw focus rect
+                                               if ((nmcd.uItemState & OS.CDIS_FOCUS) != 0) {
+                                                       RECT focusRect = new RECT ();
+                                                       if (isRadioOrCheck()) {
+                                                               if (text.length() > 0) {
+                                                                       OS.SetRect(focusRect, textRect.left-1, textRect.top, Math.min(nmcd.right, textRect.right+1), Math.min(nmcd.bottom, textRect.bottom+1));
+                                                               } else {
+                                                                       /*
+                                                                        * With custom foreground, draw focus rectangle for CheckBox
+                                                                        * and Radio buttons considering the native text padding
+                                                                        * value(which is DPI aware). See bug 508141 for details.
+                                                                        */
+                                                                       OS.SetRect (focusRect, nmcd.left+1+radioOrCheckTextPadding, nmcd.top, nmcd.right-2, nmcd.bottom-1);
+                                                               }
+                                                       } else {
+                                                               OS.SetRect (focusRect, nmcd.left+2, nmcd.top+3, nmcd.right-2, nmcd.bottom-3);
+                                                       }
+                                                       OS.DrawFocusRect(nmcd.hdc, focusRect);
+                                               }
+                                               return new LRESULT (OS.CDRF_SKIPDEFAULT);
+                                       }
+                                       return new LRESULT (OS.CDRF_DODEFAULT);
+                               }
+                       }
+                       break;
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+@Override
+LRESULT wmDrawChild (long wParam, long lParam) {
+       if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam);
+       DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+       RECT rect = new RECT ();
+       OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom);
+       if (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;
+               }
+               /*
+               * Feature in Windows.  DrawThemeBackground() does not mirror the drawing.
+               * The fix is switch left to right and right to left.
+               */
+               if ((style & SWT.MIRRORED) != 0) {
+                       if ((style & (SWT.LEFT | SWT.RIGHT)) != 0) {
+                               iStateId = iStateId == OS.ABS_RIGHTNORMAL ? OS.ABS_LEFTNORMAL : OS.ABS_RIGHTNORMAL;
+                       }
+               }
+               /*
+               * 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) != 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;
+               }
+               if (!getEnabled ()) uState |= OS.DFCS_INACTIVE;
+               if ((style & SWT.FLAT) == SWT.FLAT) uState |= OS.DFCS_FLAT;
+               if ((struct.itemState & OS.ODS_SELECTED) != 0) uState |= OS.DFCS_PUSHED;
+               OS.DrawFrameControl (struct.hDC, rect, OS.DFC_SCROLL, uState);
+       }
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Canvas.java
new file mode 100644 (file)
index 0000000..f7b8fb9
--- /dev/null
@@ -0,0 +1,489 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 extends Composite {
+       Caret caret;
+       IME ime;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Canvas () {
+}
+
+/**
+ * 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#getStyle
+ */
+public Canvas (Composite parent, int style) {
+       super (parent, style);
+}
+
+void clearArea (int x, int y, int width, int height) {
+       checkWidget ();
+       if (OS.IsWindowVisible (handle)) {
+               RECT rect = new RECT ();
+               OS.SetRect (rect, x, y, x + width, y + height);
+               long hDC = OS.GetDCEx (handle, 0, 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) {
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       drawBackgroundInPixels(gc, x, y, width, height, 0, 0);
+}
+
+/**
+ * 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;
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (caret != null) {
+               caret.release (false);
+               caret = null;
+       }
+       if (ime != null) {
+               ime.release (false);
+               ime = null;
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (caret != null) caret.reskin (flags);
+       if (ime != null)  ime.reskin (flags);
+       super.reskinChildren (flags);
+}
+
+/**
+ * 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, all 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, boolean all) {
+       checkWidget ();
+       destX = DPIUtil.autoScaleUp(destX);
+       destY = DPIUtil.autoScaleUp(destY);
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       scrollInPixels(destX, destY, x, y, width, height, all);
+}
+
+void scrollInPixels (int destX, int destY, int x, int y, int width, int height, boolean all) {
+       forceResize ();
+       boolean isFocus = caret != null && caret.isFocusCaret ();
+       if (isFocus) caret.killFocus ();
+       RECT sourceRect = new RECT ();
+       OS.SetRect (sourceRect, x, y, x + width, y + height);
+       RECT clientRect = new RECT ();
+       OS.GetClientRect (handle, clientRect);
+       if (OS.IntersectRect (clientRect, sourceRect, clientRect)) {
+               int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+               OS.RedrawWindow (handle, null, 0, flags);
+       }
+       int deltaX = destX - x, deltaY = destY - y;
+       if (findImageControl () != null) {
+               int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+               if (all) flags |= OS.RDW_ALLCHILDREN;
+               OS.RedrawWindow (handle, sourceRect, 0, flags);
+               OS.OffsetRect (sourceRect, deltaX, deltaY);
+               OS.RedrawWindow (handle, sourceRect, 0, 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, 0, null, flags);
+       }
+       if (all) {
+               Control [] children = _getChildren ();
+               for (int i=0; i<children.length; i++) {
+                       Control child = children [i];
+                       Rectangle rect = child.getBoundsInPixels ();
+                       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.setLocationInPixels (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 != null) oldCaret.killFocus ();
+               if (newCaret != null) {
+                       if (newCaret.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+                       newCaret.setFocus ();
+               }
+       }
+}
+
+@Override
+public void setFont (Font font) {
+       checkWidget ();
+       if (caret != 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 != null && ime.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       this.ime = ime;
+}
+
+@Override
+TCHAR windowClass () {
+       if (display.useOwnDC) return display.windowOwnDCClass;
+       return super.windowClass ();
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (msg == Display.SWT_RESTORECARET) {
+               if ((state & CANVAS) != 0) {
+                       if (caret != null) {
+                               caret.killFocus ();
+                               caret.setFocus ();
+                               return 1;
+                       }
+               }
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != null) return result;
+       if (caret != null) {
+               switch ((int)wParam) {
+                       case SWT.DEL:
+                       case SWT.BS:
+                       case SWT.ESC:
+                               break;
+                       default: {
+                               if (OS.GetKeyState (OS.VK_CONTROL) >= 0) {
+                                       int [] value = new int [1];
+                                       if (OS.SystemParametersInfo (OS.SPI_GETMOUSEVANISH, 0, value, 0)) {
+                                               if (value [0] != 0) OS.SetCursor (0);
+                                       }
+                               }
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_IME_COMPOSITION (long wParam, long lParam) {
+       if (ime != null) {
+               LRESULT result = ime.WM_IME_COMPOSITION (wParam, lParam);
+               if (result != null) return result;
+       }
+       return super.WM_IME_COMPOSITION (wParam, lParam);
+}
+
+@Override
+LRESULT WM_IME_COMPOSITION_START (long wParam, long lParam) {
+       if (ime != null) {
+               LRESULT result = ime.WM_IME_COMPOSITION_START (wParam, lParam);
+               if (result != null) return result;
+       }
+       return super.WM_IME_COMPOSITION_START (wParam, lParam);
+}
+
+@Override
+LRESULT WM_IME_ENDCOMPOSITION (long wParam, long lParam) {
+       if (ime != null) {
+               LRESULT result = ime.WM_IME_ENDCOMPOSITION (wParam, lParam);
+               if (result != null) return result;
+       }
+       return super.WM_IME_ENDCOMPOSITION (wParam, lParam);
+}
+
+@Override
+LRESULT WM_INPUTLANGCHANGE (long wParam, long lParam) {
+       LRESULT result  = super.WM_INPUTLANGCHANGE (wParam, lParam);
+       if (caret != null && caret.isFocusCaret ()) {
+               caret.setIMEFont ();
+               caret.resizeIME ();
+       }
+       return result;
+}
+
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       if (ime != null) {
+               ime.WM_KEYDOWN (wParam, lParam);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       if (ime != null) {
+               LRESULT result = ime.WM_KILLFOCUS (wParam, lParam);
+               if (result != null) return result;
+       }
+       Caret caret = this.caret;
+       LRESULT result  = super.WM_KILLFOCUS (wParam, lParam);
+       if (caret != null) caret.killFocus ();
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       if (ime != null) {
+               LRESULT result = ime.WM_LBUTTONDOWN (wParam, lParam);
+               if (result != null) return result;
+       }
+       return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       LRESULT result  = super.WM_SETFOCUS (wParam, lParam);
+       if (caret != null && caret.isFocusCaret ()) caret.setFocus ();
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result  = super.WM_SIZE (wParam, lParam);
+       if (caret != null && caret.isFocusCaret ()) caret.resizeIME ();
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGED (long wParam, long lParam) {
+       LRESULT result  = super.WM_WINDOWPOSCHANGED (wParam, lParam);
+       //if (result != 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.
+       */
+       boolean isFocus = (style & SWT.RIGHT_TO_LEFT) != 0 && caret != null && caret.isFocusCaret ();
+       if (isFocus) caret.setFocus ();
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
+       LRESULT result  = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+       if (result != 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.
+       */
+       boolean isFocus = (style & SWT.RIGHT_TO_LEFT) != 0 && caret != null && caret.isFocusCaret ();
+       if (isFocus) caret.killFocus ();
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Caret.java
new file mode 100644 (file)
index 0000000..bc0f470
--- /dev/null
@@ -0,0 +1,635 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Caret extends Widget {
+       Canvas parent;
+       int x, y, width, height;
+       boolean moved, resized;
+       boolean 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 Caret (Canvas parent, int style) {
+       super (parent, style);
+       this.parent = parent;
+       createWidget ();
+}
+
+void createWidget () {
+       isVisible = true;
+       if (parent.getCaret () == null) {
+               parent.setCaret (this);
+       }
+}
+
+long defaultFont () {
+       long hwnd = parent.handle;
+       long hwndIME = OS.ImmGetDefaultIMEWnd (hwnd);
+       long hFont = 0;
+       if (hwndIME != 0) {
+               hFont = OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0);
+       }
+       if (hFont == 0) {
+               hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+       }
+       if (hFont == 0) 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();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels () {
+       if (image != null) {
+               Rectangle rect = image.getBoundsInPixels ();
+               return new Rectangle (x, y, rect.width, rect.height);
+       }
+       if (width == 0) {
+               int [] buffer = new int [1];
+               if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
+                       return new Rectangle (x, y, buffer [0], 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 == null) {
+               long 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 DPIUtil.autoScaleDown(getLocationInPixels());
+}
+
+Point getLocationInPixels () {
+       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();
+       return DPIUtil.autoScaleDown(getSizeInPixels());
+}
+
+Point getSizeInPixels () {
+       if (image != null) {
+               Rectangle rect = image.getBoundsInPixels ();
+               return new Point (rect.width, rect.height);
+       }
+       if (width == 0) {
+               int [] buffer = new int [1];
+               if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
+                       return new Point (buffer [0], 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 boolean getVisible () {
+       checkWidget();
+       return isVisible;
+}
+
+boolean hasFocus () {
+       return parent.handle == OS.GetFocus ();
+}
+
+boolean isFocusCaret () {
+       return parent.caret == 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 boolean 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 = new POINT ();
+       if (!OS.GetCaretPos (ptCurrentPos)) return;
+       long hwnd = parent.handle;
+       long hIMC = OS.ImmGetContext (hwnd);
+       IME ime = parent.getIME ();
+       if (ime != null && ime.isInlineEnabled ()) {
+               Point size = getSizeInPixels ();
+               CANDIDATEFORM lpCandidate = new CANDIDATEFORM ();
+               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 = new RECT ();
+               OS.GetClientRect (hwnd, rect);
+               COMPOSITIONFORM lpCompForm = new COMPOSITIONFORM ();
+               lpCompForm.dwStyle = OS.CFS_RECT;
+               lpCompForm.x = ptCurrentPos.x;
+               lpCompForm.y = ptCurrentPos.y;
+               lpCompForm.left = rect.left;
+               lpCompForm.right = rect.right;
+               lpCompForm.top = rect.top;
+               lpCompForm.bottom = rect.bottom;
+               OS.ImmSetCompositionWindow (hIMC, lpCompForm);
+       }
+       OS.ImmReleaseContext (hwnd, hIMC);
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (parent != null && this == parent.caret) {
+               if (!parent.isDisposed()) parent.setCaret (null);
+               else parent.caret = null;
+       }
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       parent = null;
+       image = null;
+       font = null;
+       oldFont = null;
+}
+
+void resize () {
+       resized = false;
+       long hwnd = parent.handle;
+       OS.DestroyCaret ();
+       long hBitmap = image != null ? image.handle : 0;
+       int width = this.width;
+       if (image == null && width == 0) {
+               int [] buffer = new int [1];
+               if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
+                       width = buffer [0];
+               }
+       }
+       OS.CreateCaret (hwnd, hBitmap, width, height);
+       OS.SetCaretPos (x, y);
+       OS.ShowCaret (hwnd);
+       move ();
+}
+
+void restoreIMEFont () {
+       if (!OS.IsDBLocale) return;
+       if (oldFont == null) return;
+       long hwnd = parent.handle;
+       long 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();
+       setBoundsInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void setBoundsInPixels (int x, int y, int width, int height) {
+       boolean samePosition = this.x == x && this.y == y;
+       boolean sameExtent = this.width == width && this.height == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       setBoundsInPixels(DPIUtil.autoScaleUp(rect));
+}
+
+void setBoundsInPixels (Rectangle rect) {
+       setBoundsInPixels (rect.x, rect.y, rect.width, rect.height);
+}
+
+void setFocus () {
+       long hwnd = parent.handle;
+       long hBitmap = 0;
+       if (image != null) hBitmap = image.handle;
+       int width = this.width;
+       if (image == null && width == 0) {
+               int [] buffer = new int [1];
+               if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
+                       width = buffer [0];
+               }
+       }
+       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 != 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 != null && image.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       this.image = image;
+       if (isVisible && hasFocus ()) resize ();
+}
+
+void setIMEFont () {
+       if (!OS.IsDBLocale) return;
+       long hFont = 0;
+       if (font != null) hFont = font.handle;
+       if (hFont == 0) hFont = defaultFont ();
+       long hwnd = parent.handle;
+       long hIMC = OS.ImmGetContext (hwnd);
+       /* Save the current IME font */
+       if (oldFont == null) {
+               oldFont = new LOGFONT ();
+               if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null;
+       }
+       /* Set new IME font */
+       LOGFONT logFont = new LOGFONT ();
+       if (OS.GetObject (hFont, LOGFONT.sizeof, logFont) != 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();
+       setLocationInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+void setLocationInPixels (int x, int y) {
+       if (this.x == x && this.y == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       location = DPIUtil.autoScaleUp(location);
+       setLocationInPixels(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();
+       setSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void setSizeInPixels (int width, int height) {
+       if (this.width == width && this.height == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       size = DPIUtil.autoScaleUp(size);
+       setSizeInPixels(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 (boolean visible) {
+       checkWidget();
+       if (visible == isVisible) return;
+       isVisible = visible;
+       long hwnd = parent.handle;
+       if (OS.GetFocus () != hwnd) return;
+       if (!isVisible) {
+               OS.HideCaret (hwnd);
+       } else {
+               if (resized) {
+                       resize ();
+               } else {
+                       if (moved) move ();
+               }
+               OS.ShowCaret (hwnd);
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ColorDialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ColorDialog.java
new file mode 100644 (file)
index 0000000..01f6882
--- /dev/null
@@ -0,0 +1,362 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ColorDialog extends Dialog {
+       static final int CUSTOM_COLOR_COUNT = 16; // from the MS spec for CHOOSECOLOR.lpCustColors
+       Display display;
+       int width, height;
+       RGB rgb;
+       RGB [] rgbs;
+       int [] colors = new int [CUSTOM_COLOR_COUNT];
+
+/**
+ * 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 ColorDialog (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 ColorDialog (Shell parent, int style) {
+       super (parent, checkStyle (parent, style));
+       checkSubclass ();
+}
+
+long CCHookProc (long hdlg, long uiMsg, long lParam, long lpData) {
+       switch ((int)uiMsg) {
+               case OS.WM_INITDIALOG: {
+                       RECT rect = new RECT ();
+                       OS.GetWindowRect (hdlg, rect);
+                       width = rect.right - rect.left;
+                       height = rect.bottom - rect.top;
+                       if (title != null && title.length () != 0) {
+                               /* Use the character encoding for the default locale */
+                               TCHAR buffer = new TCHAR (0, title, true);
+                               OS.SetWindowText (hdlg, buffer);
+                       }
+                       break;
+               }
+               case OS.WM_DESTROY: {
+                       RECT rect = new 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;
+               }
+       }
+       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;
+}
+
+/**
+ * Returns an array of <code>RGB</code>s which are the list of
+ * custom colors selected by the user in the receiver, or null
+ * if no custom colors were selected.
+ *
+ * @return the array of RGBs, which may be null
+ *
+ * @since 3.8
+ */
+public RGB[] getRGBs() {
+       return rgbs;
+}
+
+/**
+ * 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 */
+       long hwndOwner = parent.handle;
+       long 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.
+       */
+       boolean enabled = false;
+       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 != parentOrientation) {
+               int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+               if (dialogOrientation == SWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+               hwndOwner = OS.CreateWindowEx (
+                       exStyle,
+                       Shell.DialogClass,
+                       null,
+                       0,
+                       OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                       hwndParent,
+                       0,
+                       OS.GetModuleHandle (null),
+                       null);
+               enabled = OS.IsWindowEnabled (hwndParent);
+               if (enabled) OS.EnableWindow (hwndParent, false);
+       }
+
+       /* Create the CCHookProc */
+       Callback callback = new Callback (this, "CCHookProc", 4); //$NON-NLS-1$
+       long lpfnHook = callback.getAddress ();
+       if (lpfnHook == 0) error(SWT.ERROR_NO_MORE_CALLBACKS);
+
+       /* Allocate the Custom Colors and initialize to white */
+       display = parent.display;
+       if (display.lpCustColors == 0) {
+               long hHeap = OS.GetProcessHeap ();
+               display.lpCustColors = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, CUSTOM_COLOR_COUNT * 4);
+               for (int i=0; i < CUSTOM_COLOR_COUNT; i++) {
+                       colors[i] = 0x00FFFFFF;
+               }
+               OS.MoveMemory (display.lpCustColors, colors, CUSTOM_COLOR_COUNT * 4);
+       }
+
+       /* Set the Custom Colors (if any) into the dialog */
+       if (rgbs != null) {
+               int length = rgbs.length > CUSTOM_COLOR_COUNT ? CUSTOM_COLOR_COUNT : rgbs.length;
+               for (int i=0; i<length; i++) {
+                       RGB rgb = rgbs [i];
+                       int red = rgb.red & 0xFF;
+                       int green = (rgb.green << 8) & 0xFF00;
+                       int blue = (rgb.blue << 16) & 0xFF0000;
+                       colors[i] = red | green | blue;
+               }
+               for (int i=length; i < CUSTOM_COLOR_COUNT; i++) {
+                       colors[i] = 0x00FFFFFF;
+               }
+               OS.MoveMemory (display.lpCustColors, colors, CUSTOM_COLOR_COUNT * 4);
+       }
+
+       /* Open the dialog */
+       CHOOSECOLOR lpcc = new CHOOSECOLOR ();
+       lpcc.lStructSize = CHOOSECOLOR.sizeof;
+       lpcc.Flags = OS.CC_ANYCOLOR | OS.CC_ENABLEHOOK;
+       //if (display.fullOpen) lpcc.Flags |= OS.CC_FULLOPEN;
+       lpcc.lpfnHook = lpfnHook;
+       lpcc.hwndOwner = hwndOwner;
+       lpcc.lpCustColors = display.lpCustColors;
+       if (rgb != 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)) != 0) {
+               oldModal = display.getModalDialog ();
+               display.setModalDialog (this);
+       }
+
+       display.externalEventLoop = true;
+       display.sendPreExternalEventDispatchEvent ();
+       /* Open the dialog */
+       boolean success = OS.ChooseColor (lpcc);
+       display.externalEventLoop = false;
+       display.sendPostExternalEventDispatchEvent ();
+
+       /* Clear the temporary dialog modal parent */
+       if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+               display.setModalDialog (oldModal);
+       }
+
+       /* Get the Custom Colors (if the user defined any) from the dialog */
+       boolean customColor = false;
+       OS.MoveMemory (colors, display.lpCustColors, colors.length * 4);
+       for (int i=0; i<colors.length; i++) {
+               if (colors[i] != 0x00FFFFFF) {
+                       customColor = true;
+                       break;
+               }
+       }
+       if (customColor) {
+               rgbs = new RGB [CUSTOM_COLOR_COUNT];
+               for (int i=0; i<colors.length; i++) {
+                       int color = colors[i];
+                       int red = color & 0xFF;
+                       int green = (color >> 8) & 0xFF;
+                       int blue = (color >> 16) & 0xFF;
+                       rgbs[i] = new RGB (red, green, blue);
+               }
+       }
+
+       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 != 0) OS.HeapFree (hHeap, 0, lpCustColors);
+
+       /* Destroy the BIDI orientation window */
+       if (hwndParent != 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 != 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;
+}
+
+/**
+ * Sets the receiver's list of custom colors to be the given array
+ * of <code>RGB</code>s, which may be null to let the platform select
+ * a default when open() is called.
+ *
+ * @param rgbs the array of RGBs, which may be null
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if an RGB in the rgbs array is null</li>
+ * </ul>
+ *
+ * @since 3.8
+ */
+public void setRGBs(RGB[] rgbs) {
+       if (rgbs != null) {
+               for (int i=0; i<rgbs.length; i++) {
+                       if (rgbs [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       this.rgbs = rgbs;
+}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Combo.java
new file mode 100644 (file)
index 0000000..8f065ee
--- /dev/null
@@ -0,0 +1,3393 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 483540
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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, OrientationChange</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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Combo extends Composite {
+       boolean noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify, ignoreResize, lockText;
+       int scrollWidth, visibleCount;
+       long cbtHook;
+       String [] items = new String [0];
+       int[] segments;
+       int clearSegmentsCount = 0;
+       boolean stateFlagsUsable;
+
+       static final char LTR_MARK = '\u200e';
+       static final char RTL_MARK = '\u200f';
+       static final int VISIBLE_COUNT = 5;
+
+       /**
+        * the operating system limit for the number of characters
+        * that the text field in an instance of this class can hold
+        */
+       public static final 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 {
+               LIMIT = 0x7FFFFFFF;
+       }
+
+       /*
+        * 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 final int CBID_LIST = 1000;
+       static final int CBID_EDIT = 1001;
+       static /*final*/ long EditProc, ListProc;
+
+       static final long ComboProc;
+       static final TCHAR ComboClass = new TCHAR (0, "COMBOBOX", true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ComboClass, lpWndClass);
+               ComboProc = lpWndClass.lpfnWndProc;
+       }
+
+       /* Undocumented values. Remained the same at least between Win7 and Win10 */
+       static final int stateFlagsOffset = (C.PTR_SIZEOF == 8) ? 0x68 : 0x54;
+       static final int stateFlagsFirstPaint = 0x02000000;
+
+       /**
+ * 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 Combo (Composite parent, int style) {
+       super (parent, checkStyle (style));
+       /* This code is intentionally commented */
+       //if ((style & SWT.H_SCROLL) != 0) this.style |= SWT.H_SCROLL;
+       this.style |= SWT.H_SCROLL;
+}
+
+/**
+ * Adds the argument to the end of the receiver's list.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new item
+ *
+ * @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>
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       int result = (int)OS.SendMessage (handle, OS.CB_ADDSTRING, 0, buffer);
+       if (result == OS.CB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+       if (result == OS.CB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+       if ((style & SWT.H_SCROLL) != 0) setScrollWidth (buffer.chars, 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><p>
+ * Also note, if control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ *    <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 ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int count = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+       if (!(0 <= index && index <= count)) {
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       int result = (int)OS.SendMessage (handle, OS.CB_INSERTSTRING, index, buffer);
+       if (result == OS.CB_ERRSPACE || result == OS.CB_ERR) {
+               error (SWT.ERROR_ITEM_NOT_ADDED);
+       }
+       if ((style & SWT.H_SCROLL) != 0) setScrollWidth (buffer.chars, 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds a segment listener.
+ * <p>
+ * A <code>SegmentEvent</code> is sent whenever text content is being modified or
+ * a segment listener is added or removed. You can
+ * customize the appearance of text by indicating certain characters to be inserted
+ * at certain text offsets. This may be used for bidi purposes, e.g. 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>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows.
+ * <code>SegmentEvent</code>s won't be sent on GTK and Cocoa.
+ * </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 SegmentEvent
+ * @see SegmentListener
+ * @see #removeSegmentListener
+ *
+ * @since 3.103
+ */
+public void addSegmentListener (SegmentListener listener) {
+       checkWidget ();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       addListener (SWT.Segments, new TypedListener (listener));
+       int selection = OS.CB_ERR;
+       if (!noSelection) {
+               selection = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+       }
+       clearSegments (true);
+       applyEditSegments ();
+       applyListSegments ();
+       if (selection != OS.CB_ERR) {
+               OS.SendMessage (handle, OS.CB_SETCURSEL, selection, 0);
+       }
+}
+
+/**
+ * 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 == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Verify, typedListener);
+}
+
+void applyEditSegments () {
+       if (--clearSegmentsCount != 0) return;
+       if (!hooks (SWT.Segments) && !filters (SWT.Segments) && (state & HAS_AUTO_DIRECTION) == 0) return;
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       int length = OS.GetWindowTextLength (hwndText);
+       char [] buffer = new char [length + 1];
+       if (length > 0) OS.GetWindowText (hwndText, buffer, length + 1);
+       String string = new String (buffer, 0, length);
+       /* Get segments */
+       segments = null;
+       Event event = getSegments (string);
+       if (event == null || event.segments == null) return;
+       segments = event.segments;
+       int nSegments = segments.length;
+       if (nSegments == 0) return;
+       char [] segmentsChars = event.segmentsChars;
+       int limit = (int)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
+       OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, limit + Math.min (nSegments, LIMIT - limit), 0);
+       length += nSegments;
+       char [] newChars = new char [length + 1];
+       int charCount = 0, segmentCount = 0;
+       char defaultSeparator = getOrientation () == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
+       while (charCount < length) {
+               if (segmentCount < nSegments && charCount - segmentCount == segments [segmentCount]) {
+                       char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
+                       newChars [charCount++] = separator;
+                       segmentCount++;
+               } else if (string != null) {
+                       newChars [charCount] = string.charAt (charCount++ - segmentCount);
+               }
+       }
+       while (segmentCount < nSegments) {
+               segments [segmentCount] = charCount - segmentCount;
+               char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
+               newChars [charCount++] = separator;
+               segmentCount++;
+       }
+       /* Get the current selection */
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+       boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify;
+       ignoreCharacter = ignoreModify = true;
+       /*
+        * SetWindowText empties the undo buffer and disables undo menu item.
+        * Sending OS.EM_REPLACESEL message instead.
+        */
+       newChars [length] = 0;
+       OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
+       long undo = OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0);
+       OS.SendMessage (hwndText, OS.EM_REPLACESEL, undo, newChars);
+       /* Restore selection */
+       start [0] = translateOffset (start [0]);
+       end [0] = translateOffset (end [0]);
+       if (segmentsChars != null && segmentsChars.length > 0) {
+               /*
+                * In addition to enforcing the required direction by prepending a UCC (LRE
+                * or RLE), also set the direction through a Window style.
+                * This is to ensure correct caret movement, and makes sense even when the
+                * UCC was added by an authentic SegmentListener.
+                */
+               int auto = state & HAS_AUTO_DIRECTION;
+               if (segmentsChars[0] == RLE) {
+                       super.updateTextDirection(SWT.RIGHT_TO_LEFT);
+               } else if (segmentsChars[0] == LRE) {
+                       super.updateTextDirection(SWT.LEFT_TO_RIGHT);
+               }
+               state |= auto;
+       }
+       OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+       ignoreCharacter = oldIgnoreCharacter;
+       ignoreModify = oldIgnoreModify;
+}
+
+void applyListSegments () {
+       int count = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+       if (count == OS.CB_ERR) return;
+       boolean add = items.length != count;
+       if (add) items = new String [count];
+       int index = items.length;
+       int selection = OS.CB_ERR;
+       int cp = getCodePage ();
+       String string;
+       TCHAR buffer;
+       if (!noSelection) {
+               selection = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+       }
+       while (index-- > 0) {
+               buffer = null;
+               if (add) {
+                       int length = (int)OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
+                       if (length == OS.CB_ERR) error (SWT.ERROR);
+                       buffer = new TCHAR (cp, length + 1);
+                       if (OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer) == OS.CB_ERR) return;
+                       items [index] = string = buffer.toString (0, length);
+               } else {
+                       string = items [index];
+               }
+               if (OS.SendMessage (handle, OS.CB_DELETESTRING, index, 0) == OS.CB_ERR) return;
+               if (buffer == null) buffer = new TCHAR (cp, string, true);
+               if (OS.SendMessage (handle, OS.CB_INSERTSTRING, index, buffer) == OS.CB_ERR) return;
+       }
+       if (selection != OS.CB_ERR) {
+               OS.SendMessage (handle, OS.CB_SETCURSEL, selection, 0);
+       }
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if (hwnd == handle) {
+               switch (msg) {
+                       case OS.WM_SIZE: {
+                               ignoreResize = true;
+                               boolean oldLockText = lockText;
+                               if ((style & SWT.READ_ONLY) == 0) lockText = true;
+                               long result = OS.CallWindowProc (ComboProc, hwnd, msg, wParam, lParam);
+                               if ((style & SWT.READ_ONLY) == 0) lockText = oldLockText;
+                               ignoreResize = false;
+                               return result;
+                       }
+               }
+               return OS.CallWindowProc (ComboProc, hwnd, msg, wParam, lParam);
+       }
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwnd == hwndText) {
+               if (lockText && msg == OS.WM_SETTEXT) {
+                       long hHeap = OS.GetProcessHeap ();
+                       int length = OS.GetWindowTextLength (handle);
+                       char [] buffer = new char [length + 1];
+                       OS.GetWindowText (handle, buffer, length + 1);
+                       int byteCount = buffer.length * TCHAR.sizeof;
+                       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                       OS.MoveMemory (pszText, buffer, byteCount);
+                       long code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText);
+                       OS.HeapFree (hHeap, 0, pszText);
+                       return code;
+               }
+               return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
+       }
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwnd == hwndList) {
+               return OS.CallWindowProc (ListProc, hwnd, msg, wParam, lParam);
+       }
+       return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+long CBTProc (long nCode, long wParam, long lParam) {
+       if ((int)nCode == OS.HCBT_CREATEWND) {
+               char [] buffer = new char [128];
+               int length = OS.GetClassName (wParam, buffer, buffer.length);
+               String className = new String (buffer, 0, length);
+               if (className.equals ("Edit") || className.equals ("EDIT")) { //$NON-NLS-1$  //$NON-NLS-2$
+                       int bits = OS.GetWindowLong (wParam, OS.GWL_STYLE);
+                       OS.SetWindowLong (wParam, OS.GWL_STYLE, bits & ~OS.ES_NOHIDESEL);
+               }
+       }
+       return OS.CallNextHookEx (cbtHook, (int)nCode, wParam, lParam);
+}
+
+@Override
+boolean checkHandle (long hwnd) {
+       return hwnd == handle || hwnd == OS.GetDlgItem (handle, CBID_EDIT) || hwnd == 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) != 0) return style & ~SWT.READ_ONLY;
+       return style;
+}
+
+void clearSegments (boolean applyText) {
+       if (clearSegmentsCount++ != 0) return;
+       if (segments == null) return;
+       int nSegments = segments.length;
+       if (nSegments == 0) return;
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       int limit = (int)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
+       if (limit < LIMIT) {
+               OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, Math.max (1, limit - nSegments), 0);
+       }
+       if (!applyText) {
+               segments = null;
+               return;
+       }
+       boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify;
+       ignoreCharacter = ignoreModify = true;
+       int length = OS.GetWindowTextLength (hwndText);
+       int cp = getCodePage ();
+       TCHAR buffer = new TCHAR (cp, length + 1);
+       if (length > 0) OS.GetWindowText (hwndText, buffer, length + 1);
+       buffer = deprocessText (buffer, 0, -1, true);
+       /* Get the current selection */
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+       start [0] = untranslateOffset (start [0]);
+       end [0] = untranslateOffset (end[0]);
+
+       segments = null;
+       /*
+        * SetWindowText empties the undo buffer and disables undo in the context
+        * menu. Sending OS.EM_REPLACESEL message instead.
+        */
+       OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
+       long undo = OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0);
+       OS.SendMessage (hwndText, OS.EM_REPLACESEL, undo, buffer);
+       OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+       ignoreCharacter = oldIgnoreCharacter;
+       ignoreModify = oldIgnoreModify;
+}
+
+/**
+ * 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width = 0, height = 0;
+       if (wHint == SWT.DEFAULT) {
+               long newFont, oldFont = 0;
+               long hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               int count = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+               RECT rect = new RECT ();
+               int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+               if ((style & SWT.READ_ONLY) == 0) flags |= OS.DT_EDITCONTROL;
+               int length = OS.GetWindowTextLength (handle);
+               char [] buffer = new char [length + 1];
+               OS.GetWindowText (handle, buffer, length + 1);
+               OS.DrawText (hDC, buffer, length, rect, flags);
+               width = Math.max (width, rect.right - rect.left);
+               if ((style & SWT.H_SCROLL) != 0) {
+                       width = Math.max (width, scrollWidth);
+               } else {
+                       for (int i=0; i<count; i++) {
+                               length = (int)OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, i, 0);
+                               if (length != OS.CB_ERR) {
+                                       if (length + 1 > buffer.length) buffer = new char [length + 1];
+                                       int result = (int)OS.SendMessage (handle, OS.CB_GETLBTEXT, i, buffer);
+                                       if (result != OS.CB_ERR) {
+                                               OS.DrawText (hDC, buffer, length, rect, flags);
+                                               width = Math.max (width, rect.right - rect.left);
+                                       }
+                               }
+                       }
+               }
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+       }
+       if (hHint == SWT.DEFAULT) {
+               if ((style & SWT.SIMPLE) != 0) {
+                       int count = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+                       int itemHeight = (int)OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+                       height = count * itemHeight;
+               }
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       if ((style & SWT.READ_ONLY) != 0) {
+               width += 8;
+       } else {
+               long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+               if (hwndText != 0) {
+                       long margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+                       int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
+                       width += marginWidth + 3;
+               }
+       }
+       COMBOBOXINFO pcbi = new COMBOBOXINFO ();
+       pcbi.cbSize = COMBOBOXINFO.sizeof;
+       if (((style & SWT.SIMPLE) == 0) && OS.GetComboBoxInfo (handle, pcbi)) {
+               width += pcbi.itemLeft + (pcbi.buttonRight - pcbi.buttonLeft);
+               height = (pcbi.buttonBottom - pcbi.buttonTop) + pcbi.buttonTop * 2;
+       } else {
+               int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
+               width += OS.GetSystemMetrics (OS.SM_CXVSCROLL) + border * 2;
+               int textHeight = (int)OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, -1, 0);
+               if ((style & SWT.DROP_DOWN) != 0) {
+                       height = textHeight + 6;
+               } else {
+                       height += textHeight + 10;
+               }
+       }
+       if ((style & SWT.SIMPLE) != 0 && (style & SWT.H_SCROLL) != 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 ((style & (SWT.READ_ONLY | SWT.SIMPLE)) != 0) {
+               super.createHandle ();
+       } else {
+               int threadId = OS.GetCurrentThreadId ();
+               Callback cbtCallback = new Callback (this, "CBTProc", 3); //$NON-NLS-1$
+               long cbtProc = cbtCallback.getAddress ();
+               if (cbtProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+               cbtHook = OS.SetWindowsHookEx (OS.WH_CBT, cbtProc, 0, threadId);
+               super.createHandle ();
+               if (cbtHook != 0) OS.UnhookWindowsHookEx (cbtHook);
+               cbtHook = 0;
+               cbtCallback.dispose ();
+       }
+       state &= ~(CANVAS | THEME_BACKGROUND);
+
+       stateFlagsUsable = stateFlagsTest();
+
+       /* Get the text and list window procs */
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0 && EditProc == 0) {
+               EditProc = OS.GetWindowLongPtr (hwndText, OS.GWLP_WNDPROC);
+       }
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0 && ListProc == 0) {
+               ListProc = 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) != 0) {
+               int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+               OS.SetWindowPos (handle, 0, 0, 0, 0x3FFF, 0x3FFF, flags);
+               OS.SetWindowPos (handle, 0, 0, 0, 0, 0, flags);
+       }
+}
+
+@Override
+void createWidget() {
+       super.createWidget();
+       visibleCount = VISIBLE_COUNT;
+       if ((style & SWT.SIMPLE) == 0) {
+               int itemHeight = (int)OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+               if (itemHeight != OS.CB_ERR && itemHeight != 0) {
+                       int maxHeight = 0;
+                       long hmonitor = OS.MonitorFromWindow (handle, OS.MONITOR_DEFAULTTONEAREST);
+                       MONITORINFO lpmi = new MONITORINFO ();
+                       lpmi.cbSize = MONITORINFO.sizeof;
+                       OS.GetMonitorInfo (hmonitor, lpmi);
+                       maxHeight = (lpmi.rcWork_bottom - lpmi.rcWork_top) / 3;
+                       visibleCount = Math.max(visibleCount, maxHeight / itemHeight);
+               }
+       }
+}
+
+/**
+ * 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) != 0) return;
+       OS.SendMessage (handle, OS.WM_CUT, 0, 0);
+}
+
+@Override
+int defaultBackground () {
+       return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+TCHAR deprocessText (TCHAR text, int start, int end, boolean terminate) {
+       if (text == null || segments == null) return text;
+       int length = text.length();
+       if (length == 0) return text;
+       int nSegments = segments.length;
+       if (nSegments == 0) return text;
+       char [] chars;
+       if (start < 0) start = 0;
+       chars = text.chars;
+       if (text.chars [length - 1] == 0) length--;
+       if (end == -1) end = length;
+       if (end > segments [0] && start <= segments [nSegments - 1]) {
+               int nLeadSegments = 0;
+               while (start - nLeadSegments > segments [nLeadSegments]) nLeadSegments++;
+               int segmentCount = nLeadSegments;
+               for (int i = start; i < end; i++) {
+                       if (segmentCount < nSegments && i - segmentCount == segments [segmentCount]) {
+                               ++segmentCount;
+                       } else {
+                               chars [i - segmentCount + nLeadSegments] = chars [i];
+                       }
+               }
+               length = end - start - segmentCount + nLeadSegments;
+       }
+       if (start != 0 || end != length) {
+               char [] newChars = new char [length];
+               System.arraycopy(chars, start, newChars, 0, length);
+               return new TCHAR (getCodePage (), newChars, terminate);
+       }
+       return text;
+}
+
+@Override
+void deregister () {
+       super.deregister ();
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) display.removeControl (hwndText);
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0) 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 = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+       if (index != selection) return;
+       OS.SendMessage (handle, OS.CB_SETCURSEL, -1, 0);
+       sendEvent (SWT.Modify);
+       // widget could be disposed at this point
+       clearSegments (false);
+       clearSegmentsCount--;
+}
+
+/**
+ * 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
+       clearSegments (false);
+       clearSegmentsCount--;
+}
+
+@Override
+boolean dragDetect (long hwnd, int x, int y, boolean filter, boolean [] detect, boolean [] consume) {
+       if (filter && (style & SWT.READ_ONLY) == 0) {
+               long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+               if (hwndText != 0) {
+                       int [] start = new int [1], end = new int [1];
+                       OS.SendMessage (handle, OS.CB_GETEDITSEL, start, end);
+                       if (start [0] != end [0]) {
+                               long lParam = OS.MAKELPARAM (x, y);
+                               int position = OS.LOWORD (OS.SendMessage (hwndText, OS.EM_CHARFROMPOS, 0, lParam));
+                               if (start [0] <= position && position < end [0]) {
+                                       if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
+                                               if (consume != null) consume [0] = true;
+                                               return true;
+                                       }
+                               }
+                       }
+                       return false;
+               }
+       }
+       return super.dragDetect (hwnd, x, y, filter, detect, consume);
+}
+
+/**
+ * Returns a point describing the location of the caret relative
+ * to the receiver.
+ *
+ * @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>
+ *
+ * @since 3.8
+ */
+public Point getCaretLocation () {
+       checkWidget ();
+       return DPIUtil.autoScaleDown(getCaretLocationInPixels());
+}
+
+Point getCaretLocationInPixels () {
+       /*
+       * 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 = translateOffset (getCaretPosition ());
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       long caretPos = OS.SendMessage (hwndText, OS.EM_POSFROMCHAR, position, 0);
+       if (caretPos == -1) {
+               caretPos = 0;
+               if (position >= OS.GetWindowTextLength (hwndText)) {
+                       int [] start = new int [1], end = new int [1];
+                       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+                       OS.SendMessage (hwndText, 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 (hwndText, OS.EM_REPLACESEL, 0, new char [] {' ', '\0'});
+                       caretPos = OS.SendMessage (hwndText, OS.EM_POSFROMCHAR, position, 0);
+                       OS.SendMessage (hwndText, OS.EM_SETSEL, position, position + 1);
+                       OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, new char [1]);
+                       ignoreCharacter = ignoreModify = false;
+                       OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], start [0]);
+                       OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+               }
+       }
+       POINT point = new POINT ();
+       point.x = OS.GET_X_LPARAM (caretPos);
+       point.y = OS.GET_Y_LPARAM (caretPos);
+       OS.MapWindowPoints (hwndText, handle, point, 1);
+       return new Point (point.x, point.y);
+}
+
+/**
+ * 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>
+ *
+ * @since 3.8
+ */
+public int getCaretPosition () {
+       checkWidget ();
+       int [] start = new int [1], end = new int [1];
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       OS.SendMessage (hwndText, 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 [0];
+       if (start [0] != end [0]) {
+               int idThread = OS.GetWindowThreadProcessId (hwndText, null);
+               GUITHREADINFO lpgui = new GUITHREADINFO ();
+               lpgui.cbSize = GUITHREADINFO.sizeof;
+               if (OS.GetGUIThreadInfo (idThread, lpgui)) {
+                       if (lpgui.hwndCaret == hwndText || lpgui.hwndCaret == 0) {
+                               POINT ptCurrentPos = new POINT ();
+                               if (OS.GetCaretPos (ptCurrentPos)) {
+                                       long endPos = OS.SendMessage (hwndText, OS.EM_POSFROMCHAR, end [0], 0);
+                                       if (endPos == -1) {
+                                               long startPos = OS.SendMessage (hwndText, OS.EM_POSFROMCHAR, start [0], 0);
+                                               int startX = OS.GET_X_LPARAM (startPos);
+                                               if (ptCurrentPos.x > startX) caret = end [0];
+                                       } else {
+                                               int endX = OS.GET_X_LPARAM (endPos);
+                                               if (ptCurrentPos.x >= endX) caret = end [0];
+                                       }
+                               }
+                       }
+               }
+       }
+       return untranslateOffset (caret);
+}
+
+/**
+ * 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 = (int)OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
+       if (length != OS.CB_ERR) {
+               if (hooks (SWT.Segments) || filters (SWT.Segments) || (state & HAS_AUTO_DIRECTION) != 0) return items [index];
+               char [] buffer = new char [length + 1];
+               int result = (int)OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer);
+               if (result != OS.CB_ERR) return new String (buffer, 0, length);
+       }
+       int count = (int)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 = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+       if (count == 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 ();
+       return DPIUtil.autoScaleDown(getItemHeightInPixels());
+}
+
+int getItemHeightInPixels () {
+       int result = (int)OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+       if (result == 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 ();
+       String [] result;
+       int count = getItemCount ();
+       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 boolean getListVisible () {
+       checkWidget ();
+       if ((style & SWT.DROP_DOWN) != 0) {
+               return OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 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 (boolean 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
+ */
+@Override
+public int getOrientation () {
+       return super.getOrientation ();
+}
+
+Event getSegments (String string) {
+       Event event = null;
+       if (hooks (SWT.Segments) || filters (SWT.Segments)) {
+               event = new Event ();
+               event.text = string;
+               sendEvent (SWT.Segments, event);
+               if (event != null && event.segments != null) {
+                       for (int i = 1, segmentCount = event.segments.length, lineLength = string == null ? 0 : string.length(); i < segmentCount; i++) {
+                               if (event.segments[i] < event.segments[i - 1] || event.segments[i] > lineLength) {
+                                       SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+                               }
+                       }
+               }
+       }
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               int direction = BidiUtil.resolveTextDirection(string);
+               if (direction == SWT.NONE) {
+                       /*
+                        * Force adding a UCC even when no strong characters are found.
+                        * Otherwise, the widget would keep the old direction, which might be
+                        * inappropriate for the new text.
+                        */
+                       direction = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+               }
+               int [] oldSegments = null;
+               char [] oldSegmentsChars = null;
+               if (event == null) {
+                       event = new Event ();
+               } else {
+                       oldSegments = event.segments;
+                       oldSegmentsChars = event.segmentsChars;
+               }
+               int nSegments = oldSegments == null ? 0 : oldSegments.length;
+               event.segments = new int [nSegments + 1];
+               event.segmentsChars = new char [nSegments + 1];
+               if (oldSegments != null) {
+                       System.arraycopy(oldSegments, 0, event.segments, 1, nSegments);
+               }
+               if (oldSegmentsChars != null) {
+                       System.arraycopy(oldSegmentsChars, 0, event.segmentsChars, 1, nSegments);
+               }
+               event.segments [0] = 0;
+               event.segmentsChars [0] = direction == SWT.RIGHT_TO_LEFT ? RLE : LRE;
+       }
+       return event;
+}
+
+String getSegmentsText (String text, Event event) {
+       if (text == null || event == null) return text;
+       int[] segments = event.segments;
+       if (segments == null) return text;
+       int nSegments = segments.length;
+       if (nSegments == 0) return text;
+       char[] segmentsChars = /*event == null ? this.segmentsChars : */event.segmentsChars;
+       int length = text.length();
+       char[] oldChars = new char[length];
+       text.getChars (0, length, oldChars, 0);
+       char[] newChars = new char[length + nSegments];
+       int charCount = 0, segmentCount = 0;
+       char defaultSeparator = getOrientation () == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
+       while (charCount < length) {
+               if (segmentCount < nSegments && charCount == segments[segmentCount]) {
+                       char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator;
+                       newChars[charCount + segmentCount++] = separator;
+               } else {
+                       newChars[charCount + segmentCount] = oldChars[charCount++];
+               }
+       }
+       while (segmentCount < nSegments) {
+               segments[segmentCount] = charCount;
+               char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator;
+               newChars[charCount + segmentCount++] = separator;
+       }
+       return new String(newChars, 0, newChars.length);
+}
+
+/**
+ * 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) != 0 && (style & SWT.READ_ONLY) != 0) {
+               return new Point (0, OS.GetWindowTextLength (handle));
+       }
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.CB_GETEDITSEL, start, end);
+       return new Point (untranslateOffset (start [0]), untranslateOffset (end [0]));
+}
+
+/**
+ * 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 (int)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 == 0) return "";
+       TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+       OS.GetWindowText (handle, buffer, length + 1);
+       if (segments != null) {
+               buffer = deprocessText (buffer, 0, -1, false);
+               return buffer.toString ();
+       }
+
+       return buffer.toString (0, length);
+}
+
+/**
+ * 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 DPIUtil.autoScaleDown(getTextHeightInPixels());
+}
+
+int getTextHeightInPixels () {
+       COMBOBOXINFO pcbi = new COMBOBOXINFO ();
+       pcbi.cbSize = COMBOBOXINFO.sizeof;
+       if (((style & SWT.SIMPLE) == 0) && OS.GetComboBoxInfo (handle, pcbi)) {
+               return (pcbi.buttonBottom - pcbi.buttonTop) + pcbi.buttonTop * 2;
+       }
+       int result = (int)OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, -1, 0);
+       if (result == OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+       return (style & SWT.DROP_DOWN) != 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 ();
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText == 0) return LIMIT;
+       int limit = (int)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+       if (segments != null && limit < LIMIT) limit = Math.max (1, limit - segments.length);
+       return limit;
+}
+
+/**
+ * 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
+boolean hasFocus () {
+       long hwndFocus = OS.GetFocus ();
+       if (hwndFocus == handle) return true;
+       if (hwndFocus == 0) return false;
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndFocus == hwndText) return true;
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndFocus == 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 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>
+ */
+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 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>
+ */
+public int indexOf (String string, int start) {
+       checkWidget ();
+       if (string == 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 () == 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 = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+       if (!(0 <= start && start < count)) return -1;
+       int index = start - 1, last = 0;
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       do {
+               index = (int)OS.SendMessage (handle, OS.CB_FINDSTRINGEXACT, last = index, buffer);
+               if (index == OS.CB_ERR || index <= last) return -1;
+       } while (!string.equals (getItem (index)));
+       return index;
+}
+
+/**
+ * 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) != 0) return;
+       OS.SendMessage (handle, OS.WM_PASTE, 0, 0);
+}
+
+void stateFlagsAdd(int flags) {
+       final long tagCBoxPtr = OS.GetWindowLongPtr(handle, 0);
+       /*
+        * Bug 550423: When non-XP-theme COMMCTL32.DLL gets loaded, undocumented
+        * internal data is not there. We do not support that and in such case
+        * GetWindowLongPtr function fails and return zero.
+        */
+       if (tagCBoxPtr == 0) return;
+       final long stateFlagsPtr = tagCBoxPtr + stateFlagsOffset;
+
+       int stateFlags[] = new int[1];
+       OS.MoveMemory(stateFlags, stateFlagsPtr, 4);
+       stateFlags[0] |= flags;
+       OS.MoveMemory(stateFlagsPtr, stateFlags, 4);
+}
+
+/*
+ * Verify that undocumented internal data is in expected location.
+ * The test is performed at creation time, when the value of state flags is predictable.
+ * For simplicity, only SWT.READ_ONLY combos are handled.
+ */
+boolean stateFlagsTest() {
+       final long tagCBoxPtr = OS.GetWindowLongPtr(handle, 0);
+       /*
+        * Bug 550423: When non-XP-theme COMMCTL32.DLL gets loaded, undocumented
+        * internal data is not there. We do not support that and in such case
+        * GetWindowLongPtr function fails and return zero.
+        */
+       if (tagCBoxPtr == 0) return false;
+       final long stateFlagsPtr = tagCBoxPtr + stateFlagsOffset;
+
+       int stateFlags[] = new int[1];
+       OS.MoveMemory(stateFlags, stateFlagsPtr, 4);
+
+       /*
+        * 0x00000002 is unknown
+        * 0x00002000 is set in WM_NCCREATE
+        * 0x00004000 means CBS_DROPDOWNLIST (SWT.READ_ONLY)
+        * 0x02000000 is set in WM_NCCREATE and reset after first WM_PAINT
+        */
+       return (stateFlags[0] == 0x02006002);
+}
+
+@Override
+void register () {
+       super.register ();
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) display.addControl (hwndText, this);
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0) 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, boolean notify) {
+       char [] buffer = null;
+       if ((style & SWT.H_SCROLL) != 0) {
+               int length = (int)OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
+               if (length == OS.CB_ERR) {
+                       int count = (int)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 char [length + 1];
+               int result = (int)OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer);
+               if (result == OS.CB_ERR) {
+                       int count = (int)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 = (int)OS.SendMessage (handle, OS.CB_DELETESTRING, index, 0);
+       if (code == OS.CB_ERR) {
+               int count = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+               if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       else if (code == 0) {
+               /*
+                * Bug in Windows, when combo had exactly one item, that was
+                * currently selected & is removed, the combo box does not clear the
+                * text area. The fix is to reset contents of the Combo. Bug#440671
+                */
+               OS.SendMessage (handle, OS.CB_RESETCONTENT, 0, 0);
+       }
+       if ((style & SWT.H_SCROLL) != 0) setScrollWidth (buffer, true);
+       if (notify && length != OS.GetWindowTextLength (handle)) {
+               sendEvent (SWT.Modify);
+               if (isDisposed ()) return;
+       }
+}
+
+/**
+ * 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 = (int)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 = null;
+       long hDC = 0, oldFont = 0, newFont = 0;
+       int newWidth = 0;
+       if ((style & SWT.H_SCROLL) != 0) {
+               rect = new RECT ();
+               hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       }
+       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+       for (int i=start; i<=end; i++) {
+               char [] buffer = null;
+               if ((style & SWT.H_SCROLL) != 0) {
+                       int length = (int)OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, start, 0);
+                       if (length == OS.CB_ERR) break;
+                       buffer = new char [length + 1];
+                       int result = (int)OS.SendMessage (handle, OS.CB_GETLBTEXT, start, buffer);
+                       if (result == OS.CB_ERR) break;
+               }
+               int result = (int)OS.SendMessage (handle, OS.CB_DELETESTRING, start, 0);
+               if (result == OS.CB_ERR) {
+                       error (SWT.ERROR_ITEM_NOT_REMOVED);
+               }
+               else if (result == 0) {
+                       /*
+                        * Bug in Windows, when combo had exactly one item, that was
+                        * currently selected & is removed, the combo box does not clear the
+                        * text area. The fix is to reset contents of the Combo. Bug#440671
+                        */
+                       OS.SendMessage (handle, OS.CB_RESETCONTENT, 0, 0);
+               }
+               if ((style & SWT.H_SCROLL) != 0) {
+                       OS.DrawText (hDC, buffer, -1, rect, flags);
+                       newWidth = Math.max (newWidth, rect.right - rect.left);
+               }
+       }
+       if ((style & SWT.H_SCROLL) != 0) {
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+               setScrollWidth (newWidth, false);
+       }
+       if (textLength != OS.GetWindowTextLength (handle)) {
+               sendEvent (SWT.Modify);
+               if (isDisposed ()) return;
+       }
+}
+
+/**
+ * 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_NULL_ARGUMENT - if the string is null</li>
+ *    <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 ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int index = indexOf (string, 0);
+       if (index == -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.
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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) != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * 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 SegmentEvent
+ * @see SegmentListener
+ * @see #addSegmentListener
+ *
+ * @since 3.103
+ */
+public void removeSegmentListener (SegmentListener listener) {
+       checkWidget ();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       eventTable.unhook (SWT.Segments, listener);
+       int selection = OS.CB_ERR;
+       if (!noSelection) {
+               selection = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+       }
+       clearSegments (true);
+       applyEditSegments ();
+       applyListSegments ();
+       if (selection != OS.CB_ERR) {
+               OS.SendMessage (handle, OS.CB_SETCURSEL, selection, 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Verify, listener);
+}
+
+@Override
+boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
+       if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+               return false;
+       }
+       if ((style & SWT.READ_ONLY) != 0) return true;
+       if (type != SWT.KeyDown) return true;
+       if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
+               return true;
+       }
+       if (event.character == 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 != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
+                       // FALL THROUGH
+               case OS.WM_KEYDOWN:
+                       if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
+                       break;
+       }
+
+       /*
+       * 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 (OS.GetDlgItem (handle, CBID_EDIT) == OS.GetCapture()) return true;
+       }
+
+       /* Verify the character */
+       String oldText = "";
+       int [] start = new int [1], end = new int [1];
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText == 0) return true;
+       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+       switch (key) {
+               case 0x08:      /* Bs */
+                       if (start [0] == end [0]) {
+                               if (start [0] == 0) return true;
+                               start [0] = start [0] - 1;
+                               start [0] = Math.max (start [0], 0);
+                       }
+                       break;
+               case 0x7F:      /* Del */
+                       if (start [0] == end [0]) {
+                               int length = OS.GetWindowTextLength (hwndText);
+                               if (start [0] == length) return true;
+                               end [0] = end [0] + 1;
+                               end [0] = Math.min (end [0], length);
+                       }
+                       break;
+               case '\r':      /* Return */
+                       return true;
+               default:        /* Tab and other characters */
+                       if (key != '\t' && key < 0x20) return true;
+                       oldText = new String (new char [] {key});
+                       break;
+       }
+       String newText = verifyText (oldText, start [0], end [0], event);
+       if (newText == null) return false;
+       if (newText == oldText) return true;
+       TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+       OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+       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 = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+       if (0 <= index && index < count) {
+               int selection = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+               //corner case for single elements combo boxes for Bug 222752
+               if (OS.WIN32_VERSION < OS.VERSION (6, 2) && getListVisible() && (style & SWT.READ_ONLY) != 0 && count==1 && selection == OS.CB_ERR) {
+                       OS.SendMessage (handle, OS.WM_KEYDOWN, OS.VK_DOWN, 0);
+                       sendEvent (SWT.Modify);
+                       return;
+               }
+               int code = (int)OS.SendMessage (handle, OS.CB_SETCURSEL, index, 0);
+               if (code != OS.CB_ERR && code != selection) {
+                       //Workaround for Bug 222752
+                       if (OS.WIN32_VERSION < OS.VERSION (6, 2) && getListVisible() && (style & SWT.READ_ONLY) != 0) {
+                               int firstKey = OS.VK_UP;
+                               int secondKey = OS.VK_DOWN;
+                               if (index == 0) {
+                                       firstKey = OS.VK_DOWN;
+                                       secondKey = OS.VK_UP;
+                               }
+                               OS.SendMessage (handle, OS.WM_KEYDOWN, firstKey, 0);
+                               OS.SendMessage (handle, OS.WM_KEYDOWN, secondKey, 0);
+                       }
+                       sendEvent (SWT.Modify);
+                       // widget could be disposed at this point
+               }
+       }
+}
+
+@Override
+void setBackgroundImage (long hBitmap) {
+       super.setBackgroundImage (hBitmap);
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) OS.InvalidateRect (hwndText, null, true);
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0) OS.InvalidateRect (hwndList, null, true);
+}
+
+@Override
+void setBackgroundPixel (int pixel) {
+       super.setBackgroundPixel (pixel);
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) OS.InvalidateRect (hwndText, null, true);
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0) OS.InvalidateRect (hwndList, null, true);
+}
+
+@Override
+void setBoundsInPixels (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) != 0) {
+               int visibleCount = getItemCount() == 0 ? VISIBLE_COUNT : this.visibleCount;
+               height = getTextHeightInPixels () + (getItemHeightInPixels () * 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 = new RECT ();
+               OS.GetWindowRect (handle, rect);
+               if (rect.right - rect.left != 0) {
+                       if (OS.SendMessage (handle, OS.CB_GETDROPPEDCONTROLRECT, 0, rect) != 0) {
+                               int oldWidth = rect.right - rect.left, oldHeight = rect.bottom - rect.top;
+                               if (oldWidth == width && oldHeight == height) flags |= OS.SWP_NOSIZE;
+                       }
+               }
+               OS.SetWindowPos (handle, 0, x, y, width, height, flags);
+       } else {
+               super.setBoundsInPixels (x, y, width, height, flags);
+       }
+}
+
+@Override
+public void setFont (Font font) {
+       checkWidget ();
+
+       /*
+       * Feature in Windows.  For some reason, in a editable combo box,
+       * when WM_SETFONT is used to set the font of the control
+       * and the current text does not match an item in the
+       * list, Windows selects the item that most closely matches the
+       * contents of the combo.  The fix is to lock the current text
+       * by ignoring all WM_SETTEXT messages during processing of
+       * WM_SETFONT.
+       */
+       boolean oldLockText = lockText;
+       if ((style & SWT.READ_ONLY) == 0) lockText = true;
+       super.setFont (font);
+       if ((style & SWT.READ_ONLY) == 0) lockText = oldLockText;
+       if ((style & SWT.H_SCROLL) != 0) setScrollWidth ();
+}
+
+@Override
+void setForegroundPixel (int pixel) {
+       super.setForegroundPixel (pixel);
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) OS.InvalidateRect (hwndText, null, true);
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0) 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>
+ *    <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>
+ */
+public void setItem (int index, String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int selection = getSelectionIndex ();
+       remove (index, false);
+       if (isDisposed ()) return;
+       add (string, index);
+       if (selection != -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_NULL_ARGUMENT - if the items array is null</li>
+ *    <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 ();
+       if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i=0; i<items.length; i++) {
+               if (items [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       RECT rect = null;
+       long hDC = 0, oldFont = 0, newFont = 0;
+       int newWidth = 0;
+       if ((style & SWT.H_SCROLL) != 0) {
+               rect = new RECT ();
+               hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) 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 = new TCHAR (codePage, string, true);
+               int code = (int)OS.SendMessage (handle, OS.CB_ADDSTRING, 0, buffer);
+               if (code == OS.CB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+               if (code == OS.CB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+               if ((style & SWT.H_SCROLL) != 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) != 0) {
+               if (newFont != 0) 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
+ */
+@Override
+public void setOrientation (int orientation) {
+       super.setOrientation (orientation);
+}
+
+void setScrollWidth () {
+       int newWidth = 0;
+       RECT rect = new RECT ();
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       int count = (int)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 = (int)OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, i, 0);
+               if (length != OS.CB_ERR) {
+                       char [] buffer = new char [length + 1];
+                       int result = (int)OS.SendMessage (handle, OS.CB_GETLBTEXT, i, buffer);
+                       if (result != OS.CB_ERR) {
+                               OS.DrawText (hDC, buffer, -1, rect, flags);
+                               newWidth = Math.max (newWidth, rect.right - rect.left);
+                       }
+               }
+       }
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       setScrollWidth (newWidth + 3);
+}
+
+void setScrollWidth (int scrollWidth) {
+       this.scrollWidth = scrollWidth;
+       if ((style & SWT.SIMPLE) != 0) {
+               OS.SendMessage (handle, OS.CB_SETHORIZONTALEXTENT, scrollWidth, 0);
+               return;
+       }
+       boolean scroll = false;
+       int count = (int)OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+       if (count > 3) {
+               long hmonitor = OS.MonitorFromWindow (handle, OS.MONITOR_DEFAULTTONEAREST);
+               MONITORINFO lpmi = new MONITORINFO ();
+               lpmi.cbSize = MONITORINFO.sizeof;
+               OS.GetMonitorInfo (hmonitor, lpmi);
+               int maxWidth = (lpmi.rcWork_right - lpmi.rcWork_left) / 4;
+               scroll = scrollWidth > maxWidth;
+       }
+       /*
+       * Feature in Windows.  For some reason, in a editable combo box,
+       * when CB_SETDROPPEDWIDTH is used to set the width of the drop
+       * down list and the current text does not match an item in the
+       * list, Windows selects the item that most closely matches the
+       * contents of the combo.  The fix is to lock the current text
+       * by ignoring all WM_SETTEXT messages during processing of
+       * CB_SETDROPPEDWIDTH.
+       */
+       boolean oldLockText = lockText;
+       if ((style & SWT.READ_ONLY) == 0) lockText = true;
+       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);
+       }
+       if ((style & SWT.READ_ONLY) == 0) lockText = oldLockText;
+}
+
+void setScrollWidth (char[] buffer, boolean grow) {
+       RECT rect = new RECT ();
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) 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 != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       setScrollWidth (rect.right - rect.left, grow);
+}
+
+void setScrollWidth (int newWidth, boolean 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int start = translateOffset (selection.x), end = translateOffset (selection.y);
+       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>
+ * This call is ignored when the receiver is read only and
+ * the given string is not in the receiver's list.
+ * </p>
+ * <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><p>
+ * Also note, if control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @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>
+ */
+public void setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if ((style & SWT.READ_ONLY) != 0) {
+               int index = indexOf (string);
+               if (index != -1) select (index);
+               return;
+       }
+       clearSegments (false);
+       int limit = LIMIT;
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) {
+               limit = (int)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+       }
+       if (string.length () > limit) string = string.substring (0, limit);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       if (OS.SetWindowText (handle, buffer)) {
+               applyEditSegments ();
+               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 == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+       if (segments != null && limit > 0) {
+               OS.SendMessage (handle, OS.CB_LIMITTEXT, limit + Math.min (segments.length, LIMIT - limit), 0);
+       } else {
+               OS.SendMessage (handle, OS.CB_LIMITTEXT, limit, 0);
+       }
+}
+
+@Override
+void setToolTipText (Shell shell, String string) {
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndText != 0) shell.setToolTipText (hwndText, string);
+       if (hwndList != 0) 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;
+       updateDropDownHeight ();
+}
+
+@Override
+void subclass () {
+       super.subclass ();
+       long newProc = display.windowProc;
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0) {
+               OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc);
+       }
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0) {
+               OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, newProc);
+       }
+}
+
+int translateOffset (int offset) {
+       if (segments == null) return offset;
+       for (int i = 0, nSegments = segments.length; i < nSegments && offset - i >= segments[i]; i++) {
+               offset++;
+       }
+       return offset;
+}
+
+@Override
+boolean 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 ((int)(msg.wParam)) {
+               case OS.VK_RETURN:
+               case OS.VK_ESCAPE:
+                       if ((style & SWT.DROP_DOWN) != 0) {
+                               if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) {
+                                       return false;
+                               }
+                       }
+       }
+       return super.translateTraversal (msg);
+}
+
+@Override
+boolean traverseEscape () {
+       if ((style & SWT.DROP_DOWN) != 0) {
+               if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) {
+                       OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, 0, 0);
+                       return true;
+               }
+       }
+       return super.traverseEscape ();
+}
+
+@Override
+boolean traverseReturn () {
+       if ((style & SWT.DROP_DOWN) != 0) {
+               if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) {
+                       OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, 0, 0);
+                       return true;
+               }
+       }
+       return super.traverseReturn ();
+}
+
+@Override
+void unsubclass () {
+       super.unsubclass ();
+       long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+       if (hwndText != 0 && EditProc != 0) {
+               OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, EditProc);
+       }
+       long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+       if (hwndList != 0 && ListProc != 0) {
+               OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, ListProc);
+       }
+}
+
+int untranslateOffset (int offset) {
+       if (segments == null) return offset;
+       for (int i = 0, nSegments = segments.length; i < nSegments && offset > segments[i]; i++) {
+               offset--;
+       }
+       return offset;
+}
+
+void updateDropDownHeight () {
+       /*
+       * 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.  See #setBounds() for more details.
+       */
+       if ((style & SWT.DROP_DOWN) != 0) {
+               RECT rect = new RECT ();
+               OS.SendMessage (handle, OS.CB_GETDROPPEDCONTROLRECT, 0, rect);
+               int visibleCount = getItemCount() == 0 ? VISIBLE_COUNT : this.visibleCount;
+               int height = getTextHeightInPixels () + (getItemHeightInPixels () * visibleCount) + 2;
+               if (height != (rect.bottom - rect.top)) {
+                       forceResize ();
+                       OS.GetWindowRect (handle, rect);
+                       int flags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+                       OS.SetWindowPos (handle, 0, 0, 0, rect.right - rect.left, height, flags);
+               }
+       }
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               clearSegments (true);
+               applyEditSegments ();
+               applyListSegments ();
+               return true;
+       }
+       return false;
+}
+
+@Override
+void updateOrientation () {
+       int bits  = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               bits |= OS.WS_EX_LAYOUTRTL;
+       } else {
+               bits &= ~OS.WS_EX_LAYOUTRTL;
+       }
+       bits &= ~OS.WS_EX_RTLREADING;
+       OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+       long hwndText = 0, hwndList = 0;
+       COMBOBOXINFO pcbi = new COMBOBOXINFO ();
+       pcbi.cbSize = COMBOBOXINFO.sizeof;
+       if (OS.GetComboBoxInfo (handle, pcbi)) {
+               hwndText = pcbi.hwndItem;
+               hwndList = pcbi.hwndList;
+       }
+       if (hwndText != 0) {
+               int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
+               int bits2 = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
+               if ((style & SWT.RIGHT_TO_LEFT) != 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 = new 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;
+               OS.SetWindowPos (hwndText, 0, 0, 0, width - 1, height - 1, uFlags);
+               OS.SetWindowPos (handle, 0, 0, 0, widthCombo - 1, heightCombo - 1, uFlags);
+               OS.SetWindowPos (hwndText, 0, 0, 0, width, height, uFlags);
+               OS.SetWindowPos (handle, 0, 0, 0, widthCombo, heightCombo, uFlags);
+               OS.InvalidateRect (handle, null, true);
+       }
+       if (hwndList != 0) {
+               int bits1 = OS.GetWindowLong (hwndList, OS.GWL_EXSTYLE);
+               if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                       bits1 |= OS.WS_EX_LAYOUTRTL;
+               } else {
+                       bits1 &= ~OS.WS_EX_LAYOUTRTL;
+               }
+               OS.SetWindowLong (hwndList, OS.GWL_EXSTYLE, bits1);
+       }
+}
+
+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 != null) {
+               event.character = keyEvent.character;
+               event.keyCode = keyEvent.keyCode;
+               event.stateMask = keyEvent.stateMask;
+       }
+       event.start = untranslateOffset (event.start);
+       event.end = untranslateOffset (event.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;
+}
+
+@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) != 0) return bits | OS.CBS_SIMPLE;
+       if ((style & SWT.READ_ONLY) != 0) return bits | OS.CBS_DROPDOWNLIST;
+       return bits | OS.CBS_DROPDOWN;
+}
+
+@Override
+TCHAR windowClass () {
+       return ComboClass;
+}
+
+@Override
+long windowProc () {
+       return ComboProc;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if (hwnd != handle) {
+               long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+               long hwndList = OS.GetDlgItem (handle, CBID_LIST);
+               if ((hwndText != 0 && hwnd == hwndText) || (hwndList != 0 && hwnd == hwndList)) {
+                       LRESULT result = null;
+                       boolean processSegments = false, redraw = false;
+                       switch (msg) {
+                               /* Keyboard messages */
+                               case OS.WM_CHAR:
+                                       processSegments = (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) && !ignoreCharacter && OS.GetKeyState (OS.VK_CONTROL) >= 0 && OS.GetKeyState (OS.VK_MENU) >= 0;
+                                       result = wmChar (hwnd, wParam, lParam);
+                                       break;
+                               case OS.WM_IME_CHAR:    result = wmIMEChar (hwnd, wParam, lParam); break;
+                               case OS.WM_KEYDOWN:
+                                       processSegments = wParam == OS.VK_DELETE && (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0));
+                                       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.EM_CANUNDO:
+                                       if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) return 0;
+                                       break;
+                               case OS.WM_UNDO:
+                               case OS.EM_UNDO:
+                                       if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) return 0;
+                               case OS.WM_COPY:
+                               case OS.WM_CLEAR:
+                               case OS.WM_CUT:
+                               case OS.WM_PASTE:
+                                       processSegments = hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0);
+                               case OS.WM_SETTEXT:
+                                       if (hwnd == hwndText) {
+                                               result = wmClipboard (hwnd, msg, wParam, lParam);
+                                       }
+                                       break;
+                       }
+                       if (result != null) return result.value;
+
+                       if (processSegments) {
+                               if (getDrawing () && OS.IsWindowVisible (hwndText)) {
+                                       redraw = true;
+                                       OS.DefWindowProc (hwndText, OS.WM_SETREDRAW, 0, 0);
+                               }
+                               clearSegments (true);
+                               long code = callWindowProc (hwnd, msg, wParam, lParam);
+                               applyEditSegments ();
+                               if (redraw) {
+                                       OS.DefWindowProc (hwndText, OS.WM_SETREDRAW, 1, 0);
+                                       OS.InvalidateRect (hwndText, null, true);
+                               }
+                               return code;
+                       }
+                       return callWindowProc (hwnd, msg, wParam, lParam);
+               }
+       }
+       switch (msg) {
+               case OS.CB_SETCURSEL: {
+                       long code = OS.CB_ERR;
+                       int index = (int) wParam;
+                       if ((style & SWT.READ_ONLY) != 0) {
+                               if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+                                       String oldText = getText (), newText = null;
+                                       if (wParam == -1) {
+                                               newText = "";
+                                       } else {
+                                               if (0 <= wParam && wParam < getItemCount ()) {
+                                                       newText = getItem ((int)wParam);
+                                               }
+                                       }
+                                       if (newText != null && !newText.equals (oldText)) {
+                                               int length = OS.GetWindowTextLength (handle);
+                                               oldText = newText;
+                                               newText = verifyText (newText, 0, length, null);
+                                               if (newText == null) return 0;
+                                               if (!newText.equals (oldText)) {
+                                                       index = indexOf (newText);
+                                                       if (index != -1 && index != wParam) {
+                                                               return callWindowProc (handle, OS.CB_SETCURSEL, index, lParam);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
+                               code = super.windowProc (hwnd, msg, wParam, lParam);
+                               if (!(code == OS.CB_ERR || code == OS.CB_ERRSPACE)) {
+                                       Event event = getSegments (items [index]);
+                                       segments = event != null ? event.segments : null;
+                                       if (event.segmentsChars != null) {
+                                               int auto = state & HAS_AUTO_DIRECTION;
+                                               if (event.segmentsChars[0] == RLE) {
+                                                       super.updateTextDirection(SWT.RIGHT_TO_LEFT);
+                                               } else if (event.segmentsChars[0] == LRE) {
+                                                       super.updateTextDirection(SWT.LEFT_TO_RIGHT);
+                                               }
+                                               state |= auto;
+                                       }
+                                       return code;
+                               }
+                       }
+                       break;
+               }
+               case OS.CB_ADDSTRING:
+               case OS.CB_INSERTSTRING:
+               case OS.CB_FINDSTRINGEXACT:
+                       if (lParam != 0 && (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0))) {
+                               long code = OS.CB_ERR;
+                               int length = OS.wcslen (lParam);
+                               TCHAR buffer = new TCHAR (getCodePage (), length);
+                               OS.MoveMemory (buffer, lParam, buffer.length () * TCHAR.sizeof);
+                               String string = buffer.toString (0, length);
+                               Event event = getSegments (string);
+                               if (event != null && event.segments != null) {
+                                       buffer = new TCHAR (getCodePage (), getSegmentsText (string, event), true);
+                                       long hHeap = OS.GetProcessHeap ();
+                                       length = buffer.length() * TCHAR.sizeof;
+                                       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, length);
+                                       OS.MoveMemory (pszText, buffer, length);
+                                       code = super.windowProc (hwnd, msg, wParam, pszText);
+                                       OS.HeapFree (hHeap, 0, pszText);
+                               }
+                               if (msg == OS.CB_ADDSTRING || msg == OS.CB_INSERTSTRING) {
+                                       int index = msg == OS.CB_ADDSTRING ? items.length : (int) wParam;
+                                       String [] newItems = new String [items.length + 1];
+                                       System.arraycopy (items, 0, newItems, 0, index);
+                                       newItems [index] = string;
+                                       System.arraycopy (items, index, newItems, index + 1, items.length - index);
+                                       items = newItems;
+                               }
+                               if (code != OS.CB_ERR && code != OS.CB_ERRSPACE) return code;
+                       }
+                       break;
+               case OS.CB_DELETESTRING: {
+                       if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
+                               long code = super.windowProc (hwnd, msg, wParam, lParam);
+                               if (code != OS.CB_ERR && code != OS.CB_ERRSPACE) {
+                                       int index = (int) wParam;
+                                       if (items.length == 1) {
+                                               items = new String[0];
+                                       } else if (items.length > 1) {
+                                               String [] newItems = new String [items.length - 1];
+                                               System.arraycopy (items, 0, newItems, 0, index);
+                                               System.arraycopy (items, index + 1, newItems, index, items.length - index - 1);
+                                               items = newItems;
+                                       }
+                                       if (!noSelection) {
+                                               index = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+                                               if (index == wParam) {
+                                                       clearSegments (false);
+                                                       applyEditSegments ();
+                                               }
+                                       }
+                               }
+                               return code;
+                       }
+                       break;
+               }
+               case OS.CB_RESETCONTENT: {
+                       if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
+                               if (items.length > 0) items = new String [0];
+                               clearSegments (false);
+                               applyEditSegments ();
+                       }
+                       break;
+               }
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT wmColorChild (long wParam, long lParam) {
+       LRESULT result = super.wmColorChild(wParam, lParam);
+
+       /*
+        * CBS_DROPDOWNLIST (SWT.READ_ONLY) comboboxes ignore results of WM_CTLCOLORxxx.
+        * This prevents SWT from setting custom background / text color.
+        * In Windows function 'comctl32!ComboBox_InternalUpdateEditWindow' there are two main branches:
+        * 'DrawThemeText' branch
+        *   Ignores any SetTextColor / SetBkColor.
+        *   Ignores brush returned from WM_CTLCOLORxxx.
+        *   Keeps any background that was painted during WM_CTLCOLORxxx.
+        * 'ExtTextOut' branch
+        *   Uses pre-selected SetTextColor / SetBkColor.
+        *   Ignores brush returned from WM_CTLCOLORxxx.
+        *   Overwrites background with color in SetBkColor.
+        * This undocumented hack forces combobox to use 'ExtTextOut' branch.
+        * The flag is reset after every WM_PAINT, so it's set in every WM_CTLCOLORxxx.
+        * Since 'ExtTextOut' always paints background, hack is not activated if not needed
+        * to avoid changes in visual appearance of comboboxes with default colors.
+        */
+       final boolean isReadonly = ((style & SWT.READ_ONLY) != 0);
+       final boolean isCustomColors = (result != null);
+       if (isReadonly && isCustomColors && stateFlagsUsable) {
+               stateFlagsAdd(stateFlagsFirstPaint);
+       }
+
+       return result;
+}
+
+@Override
+LRESULT WM_CTLCOLOR (long wParam, long lParam) {
+       return wmColorChild (wParam, lParam);
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       long code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+       return new LRESULT (code | OS.DLGC_WANTARROWS);
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long 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) != 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 (long wParam, long 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 = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+       LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+       if ((style & SWT.READ_ONLY) == 0) {
+               int newSelection = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+               if (oldSelection != newSelection) {
+                       sendEvent (SWT.Modify);
+                       if (isDisposed ()) return LRESULT.ZERO;
+                       sendSelectionEvent (SWT.Selection, null, true);
+                       if (isDisposed ()) return LRESULT.ZERO;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       /*
+       * Return NULL - Focus notification is
+       * done by WM_COMMAND with CBN_SETFOCUS.
+       */
+       return null;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long 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) != 0) {
+               LRESULT result = super.WM_SIZE (wParam, lParam);
+               if (OS.IsWindowVisible (handle)) {
+                       int uFlags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                       OS.RedrawWindow (handle, null, 0, 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 lock the current text
+       * by ignoring all WM_SETTEXT messages during processing of
+       * WM_SIZE.
+       */
+       boolean oldLockText = lockText;
+       if ((style & SWT.READ_ONLY) == 0) lockText = true;
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       if ((style & SWT.READ_ONLY) == 0) lockText = oldLockText;
+       /*
+       * 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) != 0) setScrollWidth (scrollWidth);
+
+       /*
+       * When setting selection, Combo automatically scrolls selection's end into view.
+       * We force it to do such scrolling after every resize to achieve multiple goals:
+       * 1) Text is no longer partially shown when there's free space after resizing
+       *    Without workaround, this happens when all of these are true:
+       *    a) Combo has focus
+       *    b) Combo can't fit all text
+       *    c) Caret is not at position 0
+       *    d) Combo is resized bigger.
+       * 2) Text is no longer partially shown after .setSelection() before its size was calculated
+       *    This is just another form of problem 1.
+       * 3) Caret no longer goes out of view when shrinking control.
+       */
+       if ((style & SWT.READ_ONLY) == 0) {
+               Point oldSelection = this.getSelection();
+               Point tmpSelection = new Point(0, 0);
+               if (!oldSelection.equals(tmpSelection)) {
+                       this.setSelection(tmpSelection);
+                       this.setSelection(oldSelection);
+               }
+       }
+
+       return result;
+}
+
+@Override
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+       if (result != null) return result;
+       OS.InvalidateRect (handle, null, true);
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
+       LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+       if (result != 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 (!getDrawing ()) return result;
+       if (!OS.IsWindowVisible (handle)) return result;
+       if (ignoreResize) {
+               WINDOWPOS lpwp = new WINDOWPOS ();
+               OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+               if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
+                       lpwp.flags |= OS.SWP_NOREDRAW;
+                       OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
+                       OS.InvalidateRect (handle, null, true);
+                       RECT rect = new RECT ();
+                       OS.GetWindowRect (handle, rect);
+                       int width = rect.right - rect.left;
+                       int height = rect.bottom - rect.top;
+                       if (width != 0 && height != 0) {
+                               long hwndParent = parent.handle;
+                               long hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD);
+                               OS.MapWindowPoints (0, hwndParent, rect, 2);
+                               long rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+                               while (hwndChild != 0) {
+                                       if (hwndChild != handle) {
+                                               OS.GetWindowRect (hwndChild, rect);
+                                               OS.MapWindowPoints (0, hwndParent, rect, 2);
+                                               long 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 (long hwnd, long wParam, long lParam) {
+       if (ignoreCharacter) return null;
+       LRESULT result = super.wmChar (hwnd, wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               /*
+               * 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.
+               */
+               case SWT.TAB: return LRESULT.ZERO;
+               case SWT.CR:
+                       if (!ignoreDefaultSelection) sendSelectionEvent (SWT.DefaultSelection);
+                       ignoreDefaultSelection = false;
+                       // when no value is selected in the dropdown
+                       if (getSelectionIndex() == -1) {
+                               if ((style & SWT.DROP_DOWN) != 0 && (style & SWT.READ_ONLY) == 0) {
+                                       // close the dropdown if open
+                                       if (OS.SendMessage(handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) {
+                                               OS.SendMessage(handle, OS.CB_SHOWDROPDOWN, 0, 0);
+                                       }
+                                       return LRESULT.ZERO;
+                               }
+                       }
+               case SWT.ESC:
+                       if ((style & SWT.DROP_DOWN) != 0) {
+                               if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) == 0) {
+                                       return LRESULT.ZERO;
+                               }
+                       }
+               /*
+               * Bug in Windows.  When the user types CTRL and BS
+               * in a combo control, a DEL character (0x08) 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.
+               */
+               case SWT.DEL:
+                       if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                               if ((style & SWT.READ_ONLY) != 0) return LRESULT.ZERO;
+                               Point selection = getSelection ();
+                               long hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+                               int x = selection.x;
+                               int y = selection.y;
+                               if (x == y) {
+                                       String actText = getText ().substring (0, x);
+                                       java.util.regex.Matcher m = CTRL_BS_PATTERN.matcher (actText);
+                                       if (m.find ()) {
+                                               x = m.start ();
+                                               y = m.end ();
+                                               OS.SendMessage (hwndText, OS.EM_SETSEL, x, y);
+                                       }
+                               }
+                               if (x < y) {
+                                       /*
+                                       * Instead of setting the new text directly we send the replace selection event to
+                                       * guarantee that the action is pushed to the undo buffer.
+                                       */
+                                       OS.SendMessage (hwndText, OS.EM_REPLACESEL, 1, 0);
+                               }
+                               return LRESULT.ZERO;
+                       }
+       }
+       return result;
+}
+
+LRESULT wmClipboard (long hwndText, int msg, long wParam, long lParam) {
+       if ((style & SWT.READ_ONLY) != 0) return null;
+       if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+       boolean call = false;
+       int [] start = new int [1], end = new int [1];
+       String newText = null;
+       switch (msg) {
+               case OS.WM_CLEAR:
+               case OS.WM_CUT:
+                       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+                       if (untranslateOffset (start [0]) != untranslateOffset (end [0])) {
+                               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) != 0) {
+                               ignoreModify = true;
+                               OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                               int length = OS.GetWindowTextLength (hwndText);
+                               int [] newStart = new int [1], newEnd = new int [1];
+                               OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
+                               if (length != 0 && newStart [0] != newEnd [0]) {
+                                       char [] buffer = new char [length + 1];
+                                       OS.GetWindowText (hwndText, buffer, length + 1);
+                                       newText = new String (buffer, newStart [0], newEnd [0] - newStart [0]);
+                               } else {
+                                       newText = "";
+                               }
+                               OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                               OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+                               ignoreModify = false;
+                       }
+                       break;
+               case OS.WM_SETTEXT:
+                       if (lockText) return null;
+                       end [0] = OS.GetWindowTextLength (hwndText);
+                       int length = OS.wcslen (lParam);
+                       TCHAR buffer = new TCHAR (getCodePage (), length);
+                       int byteCount = buffer.length () * TCHAR.sizeof;
+                       OS.MoveMemory (buffer, lParam, byteCount);
+                       newText = buffer.toString (0, length);
+                       break;
+       }
+       if (newText != null) {
+               String oldText = newText;
+               newText = verifyText (newText, start [0], end [0], null);
+               if (newText == null) return LRESULT.ZERO;
+               if (!newText.equals (oldText)) {
+                       if (call) {
+                               OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                       }
+                       TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+                       if (msg == OS.WM_SETTEXT) {
+                               long hHeap = OS.GetProcessHeap ();
+                               int byteCount = buffer.length () * TCHAR.sizeof;
+                               long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                               OS.MoveMemory (pszText, buffer, byteCount);
+                               long code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText);
+                               OS.HeapFree (hHeap, 0, pszText);
+                               return new LRESULT (code);
+                       } else {
+                               OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+                               return LRESULT.ZERO;
+                       }
+               }
+       }
+       return null;
+}
+
+@Override
+LRESULT wmCommandChild (long wParam, long 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 = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+                       if (index != 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;
+                       sendSelectionEvent (SWT.Selection);
+                       break;
+               case OS.CBN_SETFOCUS:
+                       sendFocusEvent (SWT.FocusIn);
+                       if (isDisposed ()) return LRESULT.ZERO;
+                       break;
+               case OS.CBN_DROPDOWN:
+                       setCursor ();
+                       updateDropDownHeight ();
+                       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) != 0) break;
+                       sendFocusEvent (SWT.FocusOut);
+                       if (isDisposed ()) return LRESULT.ZERO;
+                       break;
+               case OS.EN_ALIGN_LTR_EC:
+               case OS.EN_ALIGN_RTL_EC:
+                       Event event = new Event ();
+                       event.doit = true;
+                       sendEvent (SWT.OrientationChange, event);
+                       if (!event.doit) {
+                               long hwnd = lParam;
+                               int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                               int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+                               if (code == OS.EN_ALIGN_LTR_EC) {
+                                       bits1 |= (OS.WS_EX_RTLREADING | OS.WS_EX_RIGHT);
+                                       bits2 |= OS.ES_RIGHT;
+                               } else {
+                                       bits1 &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_RIGHT);
+                                       bits2 &= ~OS.ES_RIGHT;
+                               }
+                               OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits1);
+                               OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits2);
+                       }
+                       if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
+                               clearSegments(true);
+                               /*
+                                * Explicit LTR or RTL direction was set, so auto direction
+                                * should be deactivated.
+                                */
+                               state &= ~HAS_AUTO_DIRECTION;
+                               applyEditSegments();
+                       }
+                       break;
+       }
+       return super.wmCommandChild (wParam, lParam);
+}
+
+@Override
+LRESULT wmIMEChar (long hwnd, long wParam, long lParam) {
+
+       /* Process a DBCS character */
+       Display display = this.display;
+       display.lastKey = 0;
+       display.lastAscii = (int)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;
+       long result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam);
+       MSG msg = new 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 (long hwnd, long wParam, long lParam) {
+       if (ignoreCharacter) return null;
+       LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+       if (result != null) return result;
+       ignoreDefaultSelection = false;
+       switch ((int)wParam) {
+               case OS.VK_LEFT:
+               case OS.VK_UP:
+               case OS.VK_RIGHT:
+               case OS.VK_DOWN:
+                       if (segments != null) {
+                               long code = 0;
+                               int [] start = new int [1], end = new int [1], newStart = new int [1], newEnd = new int [1];
+                               OS.SendMessage (handle, OS.CB_GETEDITSEL, start, end);
+                               while (true) {
+                                       code = callWindowProc (hwnd, OS.WM_KEYDOWN, wParam, lParam);
+                                       OS.SendMessage (handle, OS.CB_GETEDITSEL, newStart, newEnd);
+                                       if (newStart [0] != start [0]) {
+                                               if (untranslateOffset (newStart [0]) != untranslateOffset (start [0])) break;
+                                       } else if (newEnd [0] != end [0]) {
+                                               if (untranslateOffset (newEnd [0]) != untranslateOffset (end [0]))  break;
+                                       } else {
+                                               break;
+                                       }
+                                       start [0] = newStart [0];
+                                       end [0] = newEnd [0];
+                               }
+                               result = code == 0 ? LRESULT.ZERO : new LRESULT (code);
+                       }
+                       break;
+               case OS.VK_RETURN:
+                       if ((style & SWT.DROP_DOWN) != 0) {
+                               if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) {
+                                       ignoreDefaultSelection = true;
+                               }
+                       }
+                       break;
+       }
+       return result;
+}
+
+@Override
+LRESULT wmSysKeyDown (long hwnd, long wParam, long 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 = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+       LRESULT result = super.wmSysKeyDown (hwnd, wParam, lParam);
+       if (result != null) return result;
+       if ((style & SWT.READ_ONLY) == 0) {
+               if (wParam == OS.VK_DOWN) {
+                       long code = callWindowProc (hwnd, OS.WM_SYSKEYDOWN, wParam, lParam);
+                       int newSelection = (int)OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+                       if (oldSelection != newSelection) {
+                               sendEvent (SWT.Modify);
+                               if (isDisposed ()) return LRESULT.ZERO;
+                               sendSelectionEvent (SWT.Selection, null, true);
+                               if (isDisposed ()) return LRESULT.ZERO;
+                       }
+                       return new LRESULT (code);
+               }
+       }
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java
new file mode 100644 (file)
index 0000000..8289d43
--- /dev/null
@@ -0,0 +1,1991 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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), this may cause
+ * the children of this composite to be obscured.
+ * </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 extends Scrollable {
+       Layout layout;
+       WINDOWPOS [] lpwp;
+       Control [] tabList;
+       int layoutCount, backgroundMode;
+
+       static final int TOOLTIP_LIMIT = 4096;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Composite () {
+}
+
+/**
+ * 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 SWT#EMBEDDED
+ * @see SWT#DOUBLE_BUFFERED
+ * @see Widget#getStyle
+ */
+public Composite (Composite parent, int style) {
+       super (parent, style);
+}
+
+Control [] _getChildren () {
+       int count = 0;
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       if (hwndChild == 0) return new Control [0];
+       while (hwndChild != 0) {
+               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 != 0) {
+               Control control = display.getControl (hwndChild);
+               if (control != null && control != this) {
+                       children [index++] = control;
+               }
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       if (count == index) return children;
+       Control [] newChildren = new Control [index];
+       System.arraycopy (children, 0, newChildren, 0, index);
+       return newChildren;
+}
+
+Control [] _getTabList () {
+       if (tabList == null) return tabList;
+       int count = 0;
+       for (int i=0; i<tabList.length; i++) {
+               if (!tabList [i].isDisposed ()) count++;
+       }
+       if (count == 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>
+ *
+ * @deprecated use {@link Composite#layout(Control[], int)} instead
+ * @since 3.1
+ */
+@Deprecated
+public void changed (Control[] changed) {
+       layout(changed, SWT.DEFER);
+}
+
+@Override
+void checkBuffered () {
+       if ((state & CANVAS) == 0) {
+               super.checkBuffered ();
+       }
+}
+
+@Override
+void checkComposited () {
+       if ((state & CANVAS) != 0) {
+               if ((style & SWT.TRANSPARENT) != 0) {
+                       long 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
+Widget [] computeTabList () {
+       Widget result [] = super.computeTabList ();
+       if (result.length == 0) return result;
+       Control [] list = tabList != null ? _getTabList () : _getChildren ();
+       for (int i=0; i<list.length; i++) {
+               Control child = list [i];
+               Widget  [] childList = child.computeTabList ();
+               if (childList.length != 0) {
+                       Widget [] newResult = new Widget [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
+Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       display.runSkin ();
+       Point size;
+       if (layout != null) {
+               if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+                       changed |= (state & LAYOUT_CHANGED) != 0;
+                       state &= ~LAYOUT_CHANGED;
+                       size = DPIUtil.autoScaleUp(layout.computeSize (this, DPIUtil.autoScaleDown(wHint), DPIUtil.autoScaleDown(hHint), changed));
+               } else {
+                       size = new Point (wHint, hHint);
+               }
+       } else {
+               size = minimumSize (wHint, hHint, changed);
+               if (size.x == 0) size.x = DEFAULT_WIDTH;
+               if (size.y == 0) size.y = DEFAULT_HEIGHT;
+       }
+       if (wHint != SWT.DEFAULT) size.x = wHint;
+       if (hHint != SWT.DEFAULT) size.y = hHint;
+       /*
+        * Since computeTrim can be overridden by subclasses, we cannot
+        * call computeTrimInPixels directly.
+        */
+       Rectangle trim = DPIUtil.autoScaleUp(computeTrim (0, 0, DPIUtil.autoScaleDown(size.x), DPIUtil.autoScaleDown(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 == 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?
+       long hDC = gc.handle;
+       int nSavedDC = OS.SaveDC (hDC);
+       OS.IntersectClipRect (hDC, 0, 0, width, height);
+
+       //WRONG PARENT
+       POINT lpPoint = new POINT ();
+       long hwndParent = OS.GetParent (handle);
+       OS.MapWindowPoints (handle, hwndParent, lpPoint, 1);
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       POINT lpPoint1 = new POINT (), lpPoint2 = new POINT ();
+       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) == 0) {
+               OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+       }
+       //NECESSARY?
+       OS.RedrawWindow (handle, null, 0, OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN);
+       OS.PrintWindow (handle, hDC, 0);//0x00000001);
+       if ((bits & OS.WS_VISIBLE) == 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)) == 0 || findThemeControl () == parent) {
+               state |= THEME_BACKGROUND;
+       }
+       if ((style & SWT.TRANSPARENT) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+               bits |= OS.WS_EX_TRANSPARENT;
+               OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+       }
+}
+
+@Override
+int applyThemeBackground () {
+       /*
+        * Composite with scrollbars would not inherit the theme because it was
+        * probably being used to implement a control similar to a Text, List,
+        * Table, or Tree, and those controls do not inherit the background theme.
+        * We assume that a Composite that did not have scrollbars was probably just
+        * being used to group some other controls, therefore it should inherit.
+        *
+        * But when Composite background is set to COLOR_TRANSPARENT (i.e.
+        * backgroundAlpha as '0') which means parent theme should be inherited, so
+        * enable the THEME_BACKGROUND in 'state' to support background transparent.
+        * Refer bug 463127 & related bug 234649.
+        */
+       return (backgroundAlpha == 0 || (style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0 || findThemeControl () == parent) ? 1 : 0;
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * with the receiver's background.
+ *
+ * <p>The <code>offsetX</code> and <code>offsetY</code> are used to map from
+ * the <code>gc</code> origin to the origin of the parent image background. This is useful
+ * to ensure proper alignment of the image background.</p>
+ *
+ * @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
+ * @param offsetX the image background x offset
+ * @param offsetY the image background y offset
+ *
+ * @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.6
+ */
+public void drawBackground (GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
+       checkWidget ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       offsetX = DPIUtil.autoScaleUp(offsetX);
+       offsetY = DPIUtil.autoScaleUp(offsetY);
+       drawBackgroundInPixels(gc, x, y, width, height, offsetX, offsetY);
+}
+
+void drawBackgroundInPixels(GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
+       if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       RECT rect = new RECT ();
+       OS.SetRect (rect, x, y, x + width, y + height);
+       long hDC = gc.handle;
+       int pixel = background == -1 ? gc.getBackground ().handle : -1;
+       drawBackground (hDC, rect, pixel, offsetX, offsetY);
+}
+
+Composite findDeferredControl () {
+       return layoutCount > 0 ? this : parent.findDeferredControl ();
+}
+
+@Override
+Menu [] findMenus (Control control) {
+       if (control == 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 != 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 == null) return;
+       int count = 0;
+       for (int i=0; i<tabList.length; i++) {
+               if (tabList [i] == control) count++;
+       }
+       if (count == 0) return;
+       Control [] newList = null;
+       int length = tabList.length - count;
+       if (length != 0) {
+               newList = new Control [length];
+               int index = 0;
+               for (int i=0; i<tabList.length; i++) {
+                       if (tabList [i] != 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>INHERIT_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;
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               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 == 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;
+}
+
+boolean 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(boolean)
+ * @see #isLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public boolean 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(boolean)
+ * @see #getLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public boolean isLayoutDeferred () {
+       checkWidget ();
+       return findDeferredControl () != 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>
+ * Use of this method is discouraged since it is the least-efficient
+ * way to trigger a layout. The use of <code>layout(true)</code>
+ * discards all cached layout information, even from controls which
+ * have not changed. It is much more efficient to invoke
+ * {@link Control#requestLayout()} on every control which has changed
+ * in the layout than it is to invoke this method on the layout itself.
+ * </p>
+ * <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>
+ * It is normally more efficient to invoke {@link Control#requestLayout()}
+ * on every control which has changed in the layout than it is to invoke
+ * this method on the layout itself. Clients are encouraged to use
+ * {@link Control#requestLayout()} where possible instead of calling
+ * this method.
+ * </p>
+ * <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 (boolean changed) {
+       checkWidget ();
+       if (layout == 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>
+ * It is normally more efficient to invoke {@link Control#requestLayout()}
+ * on every control which has changed in the layout than it is to invoke
+ * this method on the layout itself. Clients are encouraged to use
+ * {@link Control#requestLayout()} where possible instead of calling
+ * this method.
+ * </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 (boolean changed, boolean all) {
+       checkWidget ();
+       if (layout == null && !all) return;
+       markLayout (changed, all);
+       updateLayout (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>
+ * It is normally more efficient to invoke {@link Control#requestLayout()}
+ * on every control which has changed in the layout than it is to invoke
+ * this method on the layout itself. Clients are encouraged to use
+ * {@link Control#requestLayout()} where possible instead of calling
+ * this method.
+ * </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 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 == null) error (SWT.ERROR_INVALID_ARGUMENT);
+       layout (changed, SWT.NONE);
+}
+
+/**
+ * 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.
+ * <p>
+ * The parameter <code>flags</code> may be a combination of:
+ * </p>
+ * <dl>
+ * <dt><b>SWT.ALL</b></dt>
+ * <dd>all children in the receiver's widget tree should be laid out</dd>
+ * <dt><b>SWT.CHANGED</b></dt>
+ * <dd>the layout must flush its caches</dd>
+ * <dt><b>SWT.DEFER</b></dt>
+ * <dd>layout will be deferred</dd>
+ * </dl>
+ * <p>
+ * When the <code>changed</code> array is specified, the flags <code>SWT.ALL</code>
+ * and <code>SWT.CHANGED</code> have no effect. In this case, 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>
+ * <p>
+ * When the <code>changed</code> array is not specified, the flag <code>SWT.ALL</code>
+ * indicates that the whole widget tree should be laid out. And the flag
+ * <code>SWT.CHANGED</code> indicates that the layouts should flush any cached
+ * information for all controls that are laid out.
+ * </p>
+ * <p>
+ * The <code>SWT.DEFER</code> flag always causes the layout to be deferred by
+ * calling <code>Composite.setLayoutDeferred(true)</code> and scheduling a call
+ * to <code>Composite.setLayoutDeferred(false)</code>, which will happen when
+ * appropriate (usually before the next event is handled). When this flag is set,
+ * the application should not call <code>Composite.setLayoutDeferred(boolean)</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 a control that has had a state change which requires a recalculation of its size
+ * @param flags the flags specifying how the layout should happen
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if any of the controls in changed is null or has 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.6
+ */
+public void layout (Control [] changed, int flags) {
+       checkWidget ();
+       if (changed != null) {
+               for (int i=0; i<changed.length; i++) {
+                       Control control = changed [i];
+                       if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
+                       if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+                       boolean ancestor = false;
+                       Composite composite = control.parent;
+                       while (composite != null) {
+                               ancestor = composite == 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;
+                       // Update layout when the list of children has changed.
+                       // See bug 497812.
+                       child.markLayout(false, false);
+                       while (child != this) {
+                               if (composite.layout != null) {
+                                       composite.state |= LAYOUT_NEEDED;
+                                       if (!composite.layout.flushCache (child)) {
+                                               composite.state |= LAYOUT_CHANGED;
+                                       }
+                               }
+                               if (updateCount == 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;
+                       }
+               }
+               if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) {
+                       setLayoutDeferred (true);
+                       display.addLayoutDeferred (this);
+               }
+               for (int i=updateCount-1; i>=0; i--) {
+                       update [i].updateLayout (false);
+               }
+       } else {
+               if (layout == null && (flags & SWT.ALL) == 0) return;
+               markLayout ((flags & SWT.CHANGED) != 0, (flags & SWT.ALL) != 0);
+               if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) {
+                       setLayoutDeferred (true);
+                       display.addLayoutDeferred (this);
+               }
+               updateLayout ((flags & SWT.ALL) != 0);
+       }
+}
+
+@Override
+void markLayout (boolean changed, boolean all) {
+       if (layout != 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, boolean changed) {
+       Control [] children = _getChildren ();
+       /*
+        * Since getClientArea can be overridden by subclasses, we cannot
+        * call getClientAreaInPixels directly.
+        */
+       Rectangle clientArea = DPIUtil.autoScaleUp(getClientArea ());
+       int width = 0, height = 0;
+       for (int i=0; i<children.length; i++) {
+               Rectangle rect = DPIUtil.autoScaleUp(children [i].getBounds ());
+               width = Math.max (width, rect.x - clientArea.x + rect.width);
+               height = Math.max (height, rect.y - clientArea.y + rect.height);
+       }
+       return new Point (width, height);
+}
+
+@Override
+boolean 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) != 0) {
+               if ((style & SWT.TRANSPARENT) != 0) {
+                       long hwndParent = parent.handle;
+                       long hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD);
+                       while (hwndChild != 0) {
+                               if (hwndChild != handle) {
+                                       int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                                       if ((bits & OS.WS_EX_TRANSPARENT) != 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 (boolean destroy) {
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child != null && !child.isDisposed ()) {
+                       child.release (false);
+               }
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+               long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+               if (hwndChild != 0) {
+                       int threadId = OS.GetWindowThreadProcessId (hwndChild, null);
+                       if (threadId != OS.GetCurrentThreadId ()) {
+                               OS.ShowWindow (hwndChild, OS.SW_HIDE);
+                               OS.SetParent (hwndChild, 0);
+                       }
+               }
+       }
+       layout = null;
+       tabList = null;
+       lpwp = null;
+}
+
+void removeControl (Control control) {
+       fixTabList (control);
+       resizeChildren ();
+}
+
+@Override
+void reskinChildren (int flags) {
+       super.reskinChildren (flags);
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child != null) child.reskin (flags);
+       }
+}
+
+void resizeChildren () {
+       if (lpwp == null) return;
+       do {
+               WINDOWPOS [] currentLpwp = lpwp;
+               lpwp = null;
+               if (!resizeChildren (true, currentLpwp)) {
+                       resizeChildren (false, currentLpwp);
+               }
+       } while (lpwp != null);
+}
+
+boolean resizeChildren (boolean defer, WINDOWPOS [] pwp) {
+       if (pwp == null) return true;
+       long hdwp = 0;
+       if (defer) {
+               hdwp = OS.BeginDeferWindowPos (pwp.length);
+               if (hdwp == 0) return false;
+       }
+       for (int i=0; i<pwp.length; i++) {
+               WINDOWPOS wp = pwp [i];
+               if (wp != 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) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//                     }
+                       if (defer) {
+                               hdwp = OS.DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                               if (hdwp == 0) return false;
+                       } else {
+                               OS.SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                       }
+               }
+       }
+       if (defer) return OS.EndDeferWindowPos (hdwp);
+       return true;
+}
+
+void resizeEmbeddedHandle(long embeddedHandle, int width, int height) {
+       if (embeddedHandle == 0) return;
+       int [] processID = new int [1];
+       int threadId = OS.GetWindowThreadProcessId (embeddedHandle, processID);
+       if (threadId != OS.GetCurrentThreadId ()) {
+               if (processID [0] == OS.GetCurrentProcessId ()) {
+                       if (display.msgHook == 0) {
+                               display.getMsgCallback = new Callback (display, "getMsgProc", 3);
+                               display.getMsgProc = display.getMsgCallback.getAddress ();
+                               if (display.getMsgProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+                               display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, display.getMsgProc, 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, 0, 0, 0, width, height, flags);
+       }
+}
+
+@Override
+void sendResize () {
+       setResizeChildren (false);
+       super.sendResize ();
+       if (isDisposed ()) return;
+       if (layout != 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 setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
+       if (display.resizeCount > Display.RESIZE_LIMIT) {
+               defer = false;
+       }
+       if (!defer && (state & CANVAS) != 0) {
+               state &= ~(RESIZE_OCCURRED | MOVE_OCCURRED);
+               state |= RESIZE_DEFERRED | MOVE_DEFERRED;
+       }
+       super.setBoundsInPixels (x, y, width, height, flags, defer);
+       if (!defer && (state & CANVAS) != 0) {
+               boolean wasMoved = (state & MOVE_OCCURRED) != 0;
+               boolean wasResized = (state & RESIZE_OCCURRED) != 0;
+               state &= ~(RESIZE_DEFERRED | MOVE_DEFERRED);
+               if (wasMoved && !isDisposed ()) sendMove ();
+               if (wasResized && !isDisposed ()) sendResize ();
+       }
+}
+
+@Override
+public boolean setFocus () {
+       checkWidget ();
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child.setRadioFocus (false)) 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(boolean)
+ * @see #layout(Control[])
+ *
+ * @since 3.1
+ */
+public void setLayoutDeferred (boolean defer) {
+       checkWidget();
+       if (!defer) {
+               if (--layoutCount == 0) {
+                       if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) {
+                               updateLayout (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 != null) {
+               for (int i=0; i<tabList.length; i++) {
+                       Control control = tabList [i];
+                       if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
+                       if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+                       if (control.parent != 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 (boolean resize) {
+       if (resize) {
+               resizeChildren ();
+       } else {
+               if (display.resizeCount > Display.RESIZE_LIMIT) {
+                       return;
+               }
+               int count = getChildrenCount ();
+               if (count > 1 && lpwp == null) {
+                       lpwp = new WINDOWPOS [count];
+               }
+       }
+}
+
+@Override
+boolean setTabGroupFocus () {
+       if (isTabItem ()) return setTabItemFocus ();
+       boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
+       if ((state & CANVAS) != 0) {
+               takeFocus = hooksKeys ();
+               if ((style & SWT.EMBEDDED) != 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 (true)) 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;
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       super.updateTextDirection (textDirection);
+       /*
+        * Always continue, communicating the direction to the children since
+        * OS.WS_EX_RTLREADING doesn't propagate to them natively, and since
+        * the direction might need to be handled by each child individually.
+        */
+       Control[] children = _getChildren ();
+       int i = children.length;
+       while (i-- > 0) {
+               if (children[i] != null && !children[i].isDisposed ()) {
+                       children[i].updateTextDirection(textDirection);
+               }
+       }
+       /*
+        * Return value indicates whether or not to update derivatives, so in case
+        * of AUTO always return true regardless of the actual update.
+        */
+       return true;
+}
+
+String toolTipText (NMTTDISPINFO hdr) {
+       Shell shell = getShell ();
+       if ((hdr.uFlags & OS.TTF_IDISHWND) == 0) {
+               String string = null;
+               ToolTip toolTip = shell.findToolTip ((int)hdr.idFrom);
+               if (toolTip != null) {
+                       string = toolTip.message;
+                       if (string == null || string.length () == 0) string = " ";
+                       /*
+                       * Bug in Windows.  On Windows 7, tool tips hang when displaying large
+                       * unwrapped strings. The fix is to wrap the string ourselves.
+                       */
+                       if (string.length () > TOOLTIP_LIMIT / 4) {
+                               string = display.wrapText (string, handle, toolTip.getWidth ());
+                       }
+               }
+               return string;
+       }
+       shell.setToolTipTitle (hdr.hwndFrom, null, 0);
+       OS.SendMessage (hdr.hwndFrom, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+       Control control = display.getControl (hdr.idFrom);
+       return control != null ? control.toolTipText : null;
+}
+
+@Override
+boolean translateMnemonic (Event event, Control control) {
+       if (super.translateMnemonic (event, control)) return true;
+       if (control != 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
+boolean translateTraversal (MSG msg) {
+       if ((state & CANVAS) != 0 ) {
+               if ((style & SWT.EMBEDDED) != 0) return false;
+               switch ((int)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 = (int)OS.SendMessage (msg.hwnd, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((uiState & OS.UISF_HIDEFOCUS) != 0) {
+                                       OS.SendMessage (msg.hwnd, OS.WM_UPDATEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
+                               }
+                               break;
+               }
+       }
+       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) != 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) != 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);
+               }
+       }
+}
+
+void updateLayout (boolean all) {
+       updateLayout (true, all);
+}
+
+@Override
+void updateLayout (boolean resize, boolean all) {
+       Composite parent = findDeferredControl ();
+       if (parent != null) {
+               parent.state |= LAYOUT_CHILD;
+               return;
+       }
+       if ((state & LAYOUT_NEEDED) != 0) {
+               boolean changed = (state & LAYOUT_CHANGED) != 0;
+               state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
+               display.runSkin();
+               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);
+               }
+       }
+}
+
+@Override
+void updateOrientation () {
+       Control [] controls = _getChildren ();
+       RECT [] rects = new RECT [controls.length];
+       for (int i=0; i<controls.length; i++) {
+               Control control = controls [i];
+               RECT rect = rects [i] = new RECT();
+               control.forceResize ();
+               OS.GetWindowRect (control.topHandle (), rect);
+               OS.MapWindowPoints (0, handle, rect, 2);
+       }
+       int orientation = style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+       super.updateOrientation ();
+       for (int i=0; i<controls.length; i++) {
+               Control control = controls [i];
+               RECT rect = rects [i];
+               control.setOrientation (orientation);
+               int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
+               OS.SetWindowPos (control.topHandle (), 0, rect.left, rect.top, 0, 0, flags);
+       }
+}
+
+void updateUIState () {
+       long hwndShell = getShell ().handle;
+       int uiState = (int)OS.SendMessage (hwndShell, OS.WM_QUERYUISTATE, 0, 0);
+       if ((uiState & OS.UISF_HIDEFOCUS) != 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0) {
+               /* Return zero to indicate that the background was not erased */
+               if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) != 0) {
+                       return LRESULT.ZERO;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0) {
+               int flags = 0;
+               if (hooksKeys ()) {
+                       flags |= OS.DLGC_WANTALLKEYS | OS.DLGC_WANTARROWS | OS.DLGC_WANTTAB;
+               }
+               if ((style & SWT.NO_FOCUS) != 0) flags |= OS.DLGC_STATIC;
+               if (OS.GetWindow (handle, OS.GW_CHILD) != 0) flags |= OS.DLGC_STATIC;
+               if (flags != 0) return new LRESULT (flags);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETFONT (long wParam, long lParam) {
+       LRESULT result = super.WM_GETFONT (wParam, lParam);
+       if (result != null) return result;
+       long code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
+       if (code != 0) return new LRESULT (code);
+       return new LRESULT (font != null ? font.handle : defaultFont ());
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+
+       /* Set focus for a canvas with no children */
+       if ((state & CANVAS) != 0) {
+               if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
+                       if (OS.GetWindow (handle, OS.GW_CHILD) == 0) setFocus ();
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+       if (result != 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.IsAppThemed ()) {
+               if ((state & CANVAS)!= 0) {
+                       long code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+                       if (code == OS.HTCLIENT) {
+                               RECT rect = new RECT ();
+                               OS.GetClientRect (handle, rect);
+                               POINT pt = new POINT ();
+                               pt.x = OS.GET_X_LPARAM (lParam);
+                               pt.y = OS.GET_Y_LPARAM (lParam);
+                               OS.MapWindowPoints (0, handle, pt, 1);
+                               if (!OS.PtInRect (rect, pt)) {
+                                       int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
+                                       OS.RedrawWindow (handle, null, 0, flags);
+                               }
+                       }
+                       return new LRESULT (code);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_PARENTNOTIFY (long wParam, long lParam) {
+       if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+               if (OS.LOWORD (wParam) == OS.WM_CREATE) {
+                       RECT rect = new RECT ();
+                       OS.GetClientRect (handle, rect);
+                       resizeEmbeddedHandle (lParam, rect.right - rect.left, rect.bottom - rect.top);
+               }
+       }
+       return super.WM_PARENTNOTIFY (wParam, lParam);
+}
+
+@Override
+LRESULT WM_PAINT (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+       if ((state & CANVAS) == 0 || (state & FOREIGN_HANDLE) != 0) {
+               return super.WM_PAINT (wParam, lParam);
+       }
+
+       /* Set the clipping bits */
+       int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       int newBits = oldBits | OS.WS_CLIPSIBLINGS | OS.WS_CLIPCHILDREN;
+       if (newBits != oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+
+       /* Paint the control and the background */
+       PAINTSTRUCT ps = new PAINTSTRUCT ();
+       if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+
+               /* Use the buffered paint when possible */
+               boolean bufferedPaint = false;
+               if ((style & SWT.DOUBLE_BUFFERED) != 0) {
+                       if ((style & (SWT.NO_MERGE_PAINTS | SWT.RIGHT_TO_LEFT | SWT.TRANSPARENT)) == 0) {
+                               bufferedPaint = true;
+                       }
+               }
+               if (bufferedPaint) {
+                       long hDC = OS.BeginPaint (handle, ps);
+                       int width = ps.right - ps.left;
+                       int height = ps.bottom - ps.top;
+                       if (width != 0 && height != 0) {
+                               long [] phdc = new long [1];
+                               int flags = OS.BPBF_COMPATIBLEBITMAP;
+                               RECT prcTarget = new RECT ();
+                               OS.SetRect (prcTarget, ps.left, ps.top, ps.right, ps.bottom);
+                               long hBufferedPaint = OS.BeginBufferedPaint (hDC, prcTarget, flags, null, phdc);
+                               GCData data = new GCData ();
+                               data.device = display;
+                               data.foreground = getForegroundPixel ();
+                               Control control = findBackgroundControl ();
+                               if (control == null) control = this;
+                               data.background = control.getBackgroundPixel ();
+                               data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
+                               data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((style & SWT.NO_BACKGROUND) != 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 = new RECT ();
+                                       OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                       drawBackground (phdc [0], rect);
+                               }
+                               GC gc = GC.win32_new (phdc [0], data);
+                               Event event = new Event ();
+                               event.gc = gc;
+                               event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, 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 */
+                       long sysRgn = 0;
+                       if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0 || (style & SWT.NO_MERGE_PAINTS) != 0) {
+                               sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
+                               if (OS.GetRandomRgn (gc.handle, sysRgn, OS.SYSRGN) == 1) {
+                                       if ((OS.GetLayout (gc.handle) & OS.LAYOUT_RTL) != 0) {
+                                               int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                                               int [] lpRgnData = new int [nBytes / 4];
+                                               OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                                               long newSysRgn = OS.ExtCreateRegion (new float [] {-1, 0, 0, 1, 0, 0}, nBytes, lpRgnData);
+                                               OS.DeleteObject (sysRgn);
+                                               sysRgn = newSysRgn;
+                                       }
+                                       POINT pt = new POINT();
+                                       OS.MapWindowPoints (0, handle, pt, 1);
+                                       OS.OffsetRgn (sysRgn, pt.x, pt.y);
+                               }
+                       }
+
+                       /* Send the paint event */
+                       int width = ps.right - ps.left;
+                       int height = ps.bottom - ps.top;
+                       if (width != 0 && height != 0) {
+                               GC paintGC = null;
+                               Image image = null;
+                               if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 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) != 0) {
+                                               OS.BitBlt (gc.handle, 0, 0, width, height, paintGC.handle, ps.left, ps.top, OS.SRCCOPY);
+                                       }
+                                       OS.OffsetRgn (sysRgn, -ps.left, -ps.top);
+                                       OS.SelectClipRgn (gc.handle, sysRgn);
+                                       OS.OffsetRgn (sysRgn, ps.left, ps.top);
+                                       OS.SetMetaRgn (gc.handle);
+                                       OS.SetWindowOrgEx (gc.handle, ps.left, ps.top, null);
+                                       OS.SetBrushOrgEx (gc.handle, ps.left, ps.top, null);
+                                       if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) != 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 = new RECT ();
+                                               OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                               drawBackground (gc.handle, rect);
+                                       }
+                               }
+                               Event event = new Event ();
+                               event.gc = gc;
+                               RECT rect = null;
+                               if ((style & SWT.NO_MERGE_PAINTS) != 0 && OS.GetRgnBox (sysRgn, rect = new RECT ()) == OS.COMPLEXREGION) {
+                                       int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                                       int [] lpRgnData = new int [nBytes / 4];
+                                       OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                                       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)) == 0) {
+                                                       drawBackground (gc.handle, rect);
+                                               }
+                                               event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
+                                               event.count = count - 1 - i;
+                                               sendEvent (SWT.Paint, event);
+                                       }
+                               } else {
+                                       if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                                               if (rect == null) rect = new RECT ();
+                                               OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                               drawBackground (gc.handle, rect);
+                                       }
+                                       event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height));
+                                       sendEvent (SWT.Paint, event);
+                               }
+                               // widget could be disposed at this point
+                               event.gc = null;
+                               if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0) {
+                                       if (!gc.isDisposed ()) {
+                                               GCData gcData = gc.getGCData ();
+                                               if (gcData.focusDrawn && !isDisposed ()) updateUIState ();
+                                       }
+                                       gc.dispose();
+                                       if (!isDisposed ()) paintGC.drawImage (image, DPIUtil.autoScaleDown(ps.left), DPIUtil.autoScaleDown(ps.top));
+                                       image.dispose ();
+                                       gc = paintGC;
+                               }
+                       }
+                       if (sysRgn != 0) OS.DeleteObject (sysRgn);
+                       if (data.focusDrawn && !isDisposed ()) updateUIState ();
+
+                       /* Dispose the paint GC */
+                       gc.dispose ();
+               }
+       } else {
+               long hDC = OS.BeginPaint (handle, ps);
+               if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                       RECT rect = new RECT ();
+                       OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                       drawBackground (hDC, rect);
+               }
+               OS.EndPaint (handle, ps);
+       }
+
+       /* Restore the clipping bits */
+       if (!isDisposed ()) {
+               if (newBits != 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0) {
+               forceResize ();
+               int nSavedDC = OS.SaveDC (wParam);
+               RECT rect = new RECT ();
+               OS.GetClientRect (handle, rect);
+               if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                       drawBackground (wParam, rect);
+               }
+               if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+                       GCData data = new GCData ();
+                       data.device = display;
+                       data.foreground = getForegroundPixel ();
+                       Control control = findBackgroundControl ();
+                       if (control == null) control = this;
+                       data.background = control.getBackgroundPixel ();
+                       data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
+                       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                       GC gc = GC.win32_new (wParam, data);
+                       Event event = new Event ();
+                       event.gc = gc;
+                       event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
+                       sendEvent (SWT.Paint, event);
+                       event.gc = null;
+                       gc.dispose ();
+               }
+               OS.RestoreDC (wParam, nSavedDC);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETFONT (long wParam, long lParam) {
+       if (lParam != 0) OS.InvalidateRect (handle, null, true);
+       return super.WM_SETFONT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result = null;
+       if ((state & RESIZE_DEFERRED) != 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 != 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) != 0) {
+                       if ((style & SWT.NO_REDRAW_RESIZE) == 0) {
+                               if (hooks (SWT.Paint)) {
+                                       OS.InvalidateRect (handle, null, true);
+                               }
+                       }
+               }
+               if (OS.IsAppThemed ()) {
+                       if (findThemeControl () != null) redrawChildren ();
+               }
+       }
+
+       /* Resize the embedded window */
+       if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+               resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), OS.LOWORD (lParam), OS.HIWORD (lParam));
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+       if (result != null) return result;
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SYSCOMMAND (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+       if (result != 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) == 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.
+       */
+       int cmd = (int)wParam & 0xFFF0;
+       switch (cmd) {
+               case OS.SC_HSCROLL:
+               case OS.SC_VSCROLL:
+                       boolean showHBar = horizontalBar != null && horizontalBar.getVisible ();
+                       boolean showVBar = verticalBar != null && verticalBar.getVisible ();
+                       long code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
+                       if ((showHBar != (horizontalBar != null && horizontalBar.getVisible ())) ||
+                               (showVBar != (verticalBar != null && verticalBar.getVisible ()))) {
+                                       int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
+                                       OS.RedrawWindow (handle, null, 0, flags);
+                               }
+                       if (code == 0) return LRESULT.ZERO;
+                       return new LRESULT (code);
+       }
+
+       /* Return the result */
+       return result;
+}
+
+@Override
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0 && hooks (SWT.Paint)) {
+               OS.InvalidateRect (handle, null, true);
+       }
+       return result;
+}
+
+@Override
+LRESULT wmNCPaint (long hwnd, long wParam, long lParam) {
+       LRESULT result = super.wmNCPaint (hwnd, wParam, lParam);
+       if (result != null) return result;
+       long borderHandle = borderHandle ();
+       if ((state & CANVAS) != 0 || (hwnd == borderHandle && handle != borderHandle)) {
+               if (OS.IsAppThemed ()) {
+                       int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                       if ((bits1 & OS.WS_EX_CLIENTEDGE) != 0) {
+                               long code = 0;
+                               int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+                               if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) != 0) {
+                                       code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam);
+                               }
+                               long hDC = OS.GetWindowDC (hwnd);
+                               RECT rect = new 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, long wParam, long lParam) {
+       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.
+                       */
+                       long hwndParent = hdr.hwndFrom;
+                       do {
+                               hwndParent = OS.GetParent (hwndParent);
+                               if (hwndParent == 0) break;
+                               int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                               if ((bits & OS.WS_EX_TOPMOST) != 0) break;
+                       } while (true);
+                       if (hwndParent != 0) break;
+                       /*
+                        * Bug in Windows.  TTN_SHOW is sent for inactive shells.  When
+                        * SetWindowPos is called as a reaction, inactive shells can
+                        * wrongly end up on top.  The fix is to swallow such requests.
+                        *
+                        * A visible effect is that spurious tool tips can show up and
+                        * disappear in a split second.  This is a mostly harmless
+                        * feature that can also be observed in the Windows Explorer.
+                        * See bug 491627 for more details.
+                        */
+                       if (display.getActiveShell () == null) return LRESULT.ONE;
+
+                       display.lockActiveWindow = true;
+                       int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOSIZE;
+                       long hwndInsertAfter = hdr.code == OS.TTN_SHOW ? OS.HWND_TOPMOST : OS.HWND_NOTOPMOST;
+                       OS.SetWindowPos (hdr.hwndFrom, hwndInsertAfter, 0, 0, 0, 0, flags);
+                       display.lockActiveWindow = false;
+                       break;
+               }
+               case OS.TTN_GETDISPINFO: {
+                       NMTTDISPINFO lpnmtdi = new NMTTDISPINFO ();
+                       OS.MoveMemory (lpnmtdi, lParam, NMTTDISPINFO.sizeof);
+                       String string = toolTipText (lpnmtdi);
+                       if (string != null) {
+                               Shell shell = getShell ();
+                               string = Display.withCrLf (string);
+                               /*
+                               * Bug in Windows.  On Windows 7, tool tips hang when displaying large
+                               * strings. The fix is to limit the tool tip string to 4Kb.
+                               */
+                               if (string.length() > TOOLTIP_LIMIT) {
+                                       string = string.substring(0, TOOLTIP_LIMIT);
+                               }
+                               /*
+                                * Bug 475858: In Japanese like languages where mnemonics are not taken from the
+                                * source label text but appended in parentheses like "(&M)" at end. In order to
+                                * allow the reuse of such label text as a tool-tip text as well, "(&M)" like
+                                * character sequence has to be removed from the end of CJK-style mnemonics.
+                                */
+                               char [] chars = fixMnemonic (string, false, true);
+
+                               /*
+                               * Ensure that the orientation of the tool tip matches
+                               * the orientation of the control.
+                               */
+                               Widget widget = null;
+                               long hwnd = hdr.idFrom;
+                               if ((lpnmtdi.uFlags & OS.TTF_IDISHWND) != 0) {
+                                       widget = display.getControl (hwnd);
+                               } else {
+                                       if (hdr.hwndFrom == shell.toolTipHandle || hdr.hwndFrom == shell.balloonTipHandle) {
+                                               widget = shell.findToolTip ((int)hdr.idFrom);
+                                       }
+                               }
+                               if (widget != null) {
+                                       int style = widget.getStyle();
+                                       int flags = SWT.RIGHT_TO_LEFT | SWT.FLIP_TEXT_DIRECTION;
+                                       if ((style & flags) != 0 && (style & flags) != flags) {
+                                               lpnmtdi.uFlags |= OS.TTF_RTLREADING;
+                                       } else {
+                                               lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
+                                       }
+                               }
+                               shell.setToolTipText (lpnmtdi, chars);
+                               OS.MoveMemory (lParam, lpnmtdi, NMTTDISPINFO.sizeof);
+                               return LRESULT.ZERO;
+                       }
+                       break;
+               }
+       }
+       return super.wmNotify (hdr, wParam, lParam);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Control.java
new file mode 100644 (file)
index 0000000..d48ae75
--- /dev/null
@@ -0,0 +1,5821 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Stefan Xenos (Google) - bug 468854 - Add a requestLayout method to Control
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.gdip.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Control is the abstract superclass of all windowed user interface classes.
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>BORDER</dd>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT, FLIP_TEXT_DIRECTION</dd>
+ * <dt><b>Events:</b>
+ * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
+ *     MouseExit, MouseHover, MouseUp, MouseMove, MouseWheel, MouseHorizontalWheel, MouseVerticalWheel, Move,
+ *     Paint, Resize, Traverse</dd>
+ * </dl>
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class Control extends Widget implements Drawable {
+
+       /**
+        * 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+       Composite parent;
+       Cursor cursor;
+       Menu menu, activeMenu;
+       String toolTipText;
+       Object layoutData;
+       Accessible accessible;
+       Image backgroundImage;
+       Region region;
+       Font font;
+       int drawCount, foreground, background, backgroundAlpha = 255;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Control () {
+}
+
+/**
+ * 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#LEFT_TO_RIGHT
+ * @see SWT#RIGHT_TO_LEFT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Control (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 == 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 == 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 == 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 gesture events are generated for the control,
+ * by sending it one of the messages defined in the
+ * <code>GestureListener</code> interface.
+ * <p>
+ * NOTE: If <code>setTouchEnabled(true)</code> has previously been
+ * invoked on the receiver then <code>setTouchEnabled(false)</code>
+ * must be invoked on it to specify that gesture events should be
+ * sent instead of touch events.
+ * </p>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
+ * SWT doesn't send Gesture or Touch events on GTK.
+ * </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 GestureListener
+ * @see #removeGestureListener
+ * @see #setTouchEnabled
+ *
+ * @since 3.7
+ */
+public void addGestureListener (GestureListener listener) {
+       checkWidget();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Gesture, 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 == 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 == 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 == 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 == 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 == 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 == 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 == 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 == 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 touch events occur, by sending it
+ * one of the messages defined in the <code>TouchListener</code>
+ * interface.
+ * <p>
+ * NOTE: You must also call <code>setTouchEnabled(true)</code> to
+ * specify that touch events should be sent, which will cause gesture
+ * events to not be sent.
+ * </p>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
+ * SWT doesn't send Gesture or Touch events on GTK.
+ * </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 TouchListener
+ * @see #removeTouchListener
+ * @see #setTouchEnabled
+ *
+ * @since 3.7
+ */
+public void addTouchListener (TouchListener listener) {
+       checkWidget();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Touch,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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Traverse,typedListener);
+}
+
+int binarySearch (int [] indices, int start, int end, int index) {
+       int low = start, high = end - 1;
+       while (low <= high) {
+               int mid = (low + high) >>> 1;
+               if (indices [mid] == index) return mid;
+               if (indices [mid] < index) {
+                       low = mid + 1;
+               } else {
+                       high = mid - 1;
+               }
+       }
+       return -low - 1;
+}
+
+long borderHandle () {
+       return handle;
+}
+
+void checkBackground () {
+       Shell shell = getShell ();
+       if (this == shell) return;
+       state &= ~PARENT_BACKGROUND;
+       Composite composite = parent;
+       do {
+               int mode = composite.backgroundMode;
+               if (mode != 0 || backgroundAlpha == 0) {
+                       if (mode == SWT.INHERIT_DEFAULT || backgroundAlpha == 0) {
+                               Control control = this;
+                               do {
+                                       if ((control.state & THEME_BACKGROUND) == 0) {
+                                               return;
+                                       }
+                                       control = control.parent;
+                               } while (control != composite);
+                       }
+                       state |= PARENT_BACKGROUND;
+                       return;
+               }
+               if (composite == shell) break;
+               composite = composite.parent;
+       } while (true);
+}
+
+void checkBorder () {
+       if (getBorderWidthInPixels () == 0) style &= ~SWT.BORDER;
+}
+
+void checkBuffered () {
+       style &= ~SWT.DOUBLE_BUFFERED;
+}
+
+void checkComposited () {
+       /* Do nothing */
+}
+
+boolean checkHandle (long hwnd) {
+       return hwnd == handle;
+}
+
+void checkMirrored () {
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+               if ((bits & OS.WS_EX_LAYOUTRTL) != 0) style |= SWT.MIRRORED;
+       }
+}
+
+/**
+ * Returns the preferred size (in points) 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(boolean)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint) {
+       return computeSize(wHint, hHint, true);
+}
+
+/**
+ * Returns the preferred size (in points) 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(boolean)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint, boolean changed){
+       checkWidget ();
+       wHint = (wHint != SWT.DEFAULT ? DPIUtil.autoScaleUp(wHint) : wHint);
+       hHint = (hHint != SWT.DEFAULT ? DPIUtil.autoScaleUp(hHint) : hHint);
+       return DPIUtil.autoScaleDown(computeSizeInPixels(wHint, hHint, changed));
+}
+
+Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       int width = DEFAULT_WIDTH;
+       int height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int border = getBorderWidthInPixels ();
+       width += border * 2;
+       height += border * 2;
+       return new Point (width, height);
+}
+
+Widget computeTabGroup () {
+       if (isTabGroup ()) return this;
+       return parent.computeTabGroup ();
+}
+
+Control computeTabRoot () {
+       Control [] tabList = parent._getTabList ();
+       if (tabList != null) {
+               int index = 0;
+               while (index < tabList.length) {
+                       if (tabList [index] == this) break;
+                       index++;
+               }
+               if (index == tabList.length) {
+                       if (isTabGroup ()) return this;
+               }
+       }
+       return parent.computeTabRoot ();
+}
+
+Widget [] computeTabList () {
+       if (isTabGroup ()) {
+               if (getVisible () && getEnabled ()) {
+                       return new Widget [] {this};
+               }
+       }
+       return new Widget [0];
+}
+
+void createHandle () {
+       long hwndParent = widgetParent ();
+       handle = OS.CreateWindowEx (
+               widgetExtStyle (),
+               windowClass (),
+               null,
+               widgetStyle (),
+               OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+               hwndParent,
+               0,
+               OS.GetModuleHandle (null),
+               widgetCreateStruct ());
+       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.WS_CHILD) != 0) {
+               OS.SetWindowLongPtr (handle, OS.GWLP_ID, handle);
+       }
+       if (OS.IsDBLocale && hwndParent != 0) {
+               long hIMC = OS.ImmGetContext (hwndParent);
+               OS.ImmAssociateContext (handle, hIMC);
+               OS.ImmReleaseContext (hwndParent, hIMC);
+       }
+
+}
+
+void checkGesture () {
+       if (OS.WIN32_VERSION >= OS.VERSION (6, 1)) {
+               int value = OS.GetSystemMetrics (OS.SM_DIGITIZER);
+               if ((value & (OS.NID_READY | OS.NID_MULTI_INPUT)) != 0) {
+                       /*
+                        * Feature in Windows 7: All gestures are enabled by default except GID_ROTATE.
+                        * Enable it explicitly by calling SetGestureConfig.
+                        */
+                       long hHeap = OS.GetProcessHeap ();
+                       long pConfigs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY,  GESTURECONFIG.sizeof);
+                       if (pConfigs != 0) {
+                               GESTURECONFIG config = new GESTURECONFIG();
+                               config.dwID = OS.GID_ROTATE;
+                               config.dwWant = 1;
+                               config.dwBlock = 0;
+                               OS.MoveMemory (pConfigs, config, GESTURECONFIG.sizeof);
+                               OS.SetGestureConfig (handle, 0, 1, pConfigs, GESTURECONFIG.sizeof);
+                               OS.HeapFree (hHeap, 0, pConfigs);
+                       }
+               }
+       }
+}
+
+void createWidget () {
+       state |= DRAG_DETECT;
+       foreground = background = -1;
+       checkOrientation (parent);
+       createHandle ();
+       checkBackground ();
+       checkBuffered ();
+       checkComposited ();
+       register ();
+       subclass ();
+       setDefaultFont ();
+       checkMirrored ();
+       checkBorder ();
+       checkGesture ();
+       if ((state & PARENT_BACKGROUND) != 0) {
+               setBackground ();
+       }
+}
+
+int defaultBackground () {
+       return OS.GetSysColor (OS.COLOR_BTNFACE);
+}
+
+long defaultFont () {
+       return display.getSystemFont ().handle;
+}
+
+int defaultForeground () {
+       return OS.GetSysColor (OS.COLOR_WINDOWTEXT);
+}
+
+void deregister () {
+       display.removeControl (handle);
+}
+
+@Override
+void destroyWidget () {
+       long hwnd = topHandle ();
+       releaseHandle ();
+       if (hwnd != 0) {
+               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 if 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 boolean dragDetect (Event event) {
+       checkWidget ();
+       if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+       Point loc = event.getLocationInPixels();
+       return dragDetect (event.button, event.count, event.stateMask, loc.x, loc.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 if 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 boolean dragDetect (MouseEvent event) {
+       checkWidget ();
+       if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+       return dragDetect (event.button, event.count, event.stateMask, DPIUtil.autoScaleUp(event.x), DPIUtil.autoScaleUp(event.y)); // To Pixels
+}
+
+boolean dragDetect (int button, int count, int stateMask, int x, int y) {
+       if (button != 1 || count != 1) return false;
+       boolean dragging = dragDetect (handle, x, y, false, null, null);
+       if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+               if (OS.GetCapture () != 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 == 1 && OS.GetKeyState (OS.VK_ESCAPE) >= 0) {
+                       int wParam = 0;
+                       if ((stateMask & SWT.CTRL) != 0) wParam |= OS.MK_CONTROL;
+                       if ((stateMask & SWT.SHIFT) != 0) wParam |= OS.MK_SHIFT;
+                       if ((stateMask & SWT.ALT) != 0) wParam |= OS.MK_ALT;
+                       if ((stateMask & SWT.BUTTON1) != 0) wParam |= OS.MK_LBUTTON;
+                       if ((stateMask & SWT.BUTTON2) != 0) wParam |= OS.MK_MBUTTON;
+                       if ((stateMask & SWT.BUTTON3) != 0) wParam |= OS.MK_RBUTTON;
+                       if ((stateMask & SWT.BUTTON4) != 0) wParam |= OS.MK_XBUTTON1;
+                       if ((stateMask & SWT.BUTTON5) != 0) wParam |= OS.MK_XBUTTON2;
+                       long lParam = OS.MAKELPARAM (x, y);
+                       OS.SendMessage (handle, OS.WM_LBUTTONUP, wParam, lParam);
+               }
+               return false;
+       }
+       return sendDragEvent (button, stateMask, x, y);
+}
+
+void drawBackground (long hDC) {
+       RECT rect = new RECT ();
+       OS.GetClientRect (handle, rect);
+       drawBackground (hDC, rect);
+}
+
+void drawBackground (long hDC, RECT rect) {
+       drawBackground (hDC, rect, -1, 0, 0);
+}
+
+void drawBackground (long hDC, RECT rect, int pixel, int tx, int ty) {
+       Control control = findBackgroundControl ();
+       if (control != null) {
+               if (control.backgroundImage != null) {
+                       fillImageBackground (hDC, control, rect, tx, ty);
+                       return;
+               }
+               pixel = control.getBackgroundPixel ();
+       }
+       if (pixel == -1) {
+               if ((state & THEME_BACKGROUND) != 0) {
+                       if (OS.IsAppThemed ()) {
+                               control = findThemeControl ();
+                               if (control != null) {
+                                       fillThemeBackground (hDC, control, rect);
+                                       return;
+                               }
+                       }
+               }
+       }
+       if (pixel == -1) pixel = getBackgroundPixel ();
+       fillBackground (hDC, pixel, rect);
+}
+
+void drawImageBackground (long hDC, long hwnd, long hBitmap, RECT rect, int tx, int ty) {
+       RECT rect2 = new RECT ();
+       OS.GetClientRect (hwnd, rect2);
+       OS.MapWindowPoints (hwnd, handle, rect2, 2);
+       long hBrush = findBrush (hBitmap, OS.BS_PATTERN);
+       POINT lpPoint = new POINT ();
+       OS.GetWindowOrgEx (hDC, lpPoint);
+       OS.SetBrushOrgEx (hDC, -rect2.left - lpPoint.x - tx, -rect2.top - lpPoint.y - ty, lpPoint);
+       long 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 (long hDC, long hwnd, RECT rect) {
+       /* Do nothing */
+}
+
+void enableDrag (boolean enabled) {
+       /* Do nothing */
+}
+
+void enableWidget (boolean enabled) {
+       OS.EnableWindow (handle, enabled);
+}
+
+void fillBackground (long hDC, int pixel, RECT rect) {
+       if (rect.left > rect.right || rect.top > rect.bottom) return;
+       OS.FillRect (hDC, rect, findBrush (pixel, OS.BS_SOLID));
+}
+
+void fillImageBackground (long hDC, Control control, RECT rect, int tx, int ty) {
+       if (rect.left > rect.right || rect.top > rect.bottom) return;
+       if (control != null) {
+               Image image = control.backgroundImage;
+               if (image != null) {
+                       control.drawImageBackground (hDC, handle, image.handle, rect, tx, ty);
+               }
+       }
+}
+
+void fillThemeBackground (long hDC, Control control, RECT rect) {
+       if (rect.left > rect.right || rect.top > rect.bottom) return;
+       if (control != null) {
+               control.drawThemeBackground (hDC, handle, rect);
+       }
+}
+
+Control findBackgroundControl () {
+       if ((background != -1 || backgroundImage != null) && backgroundAlpha > 0) return this;
+       return (parent != null && (state & PARENT_BACKGROUND) != 0) ? parent.findBackgroundControl () : null;
+}
+
+long findBrush (long value, int lbStyle) {
+       return parent.findBrush (value, lbStyle);
+}
+
+Cursor findCursor () {
+       if (cursor != null) return cursor;
+       return parent.findCursor ();
+}
+
+Control findImageControl () {
+       Control control = findBackgroundControl ();
+       return control != null && control.backgroundImage != null ? control : null;
+}
+
+Control findThemeControl () {
+       return background == -1 && backgroundImage == null ? parent.findThemeControl () : null;
+}
+
+Menu [] findMenus (Control control) {
+       if (menu != null && this != control) return new Menu [] {menu};
+       return new Menu [0];
+}
+
+char findMnemonic (String string) {
+       int index = 0;
+       int length = string.length ();
+       do {
+               while (index < length && string.charAt (index) != '&') index++;
+               if (++index >= length) return '\0';
+               if (string.charAt (index) != '&') 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;
+       Display display = this.display;
+       boolean oldFixFocus = display.fixFocus;
+       display.fixFocus = true;
+       try {
+               while (control != shell && (control = control.parent) != null) {
+                               if (control.setFocus ()) return;
+               }
+       } finally {
+               display.fixFocus = oldFixFocus;
+       }
+       shell.setSavedFocus (focusControl);
+       OS.SetFocus (0);
+}
+
+/**
+ * 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 boolean forceFocus () {
+       checkWidget ();
+       if (display.focusEvent == 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 () != OS.SetFocus (handle)) return false;
+       OS.SetFocus (handle);
+       if (isDisposed ()) return false;
+       shell.setSavedFocus (this);
+       return isFocusControl ();
+}
+
+void forceResize () {
+       if (parent == null) return;
+       WINDOWPOS [] lpwp = parent.lpwp;
+       if (lpwp == null) return;
+       for (int i=0; i<lpwp.length; i++) {
+               WINDOWPOS wp = lpwp [i];
+               if (wp != null && wp.hwnd == 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) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//                     }
+                       OS.SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                       lpwp [i] = null;
+                       return;
+               }
+       }
+}
+
+/**
+ * Returns the accessible object for the receiver.
+ * <p>
+ * If this is the first time this object is requested,
+ * then the object is created and returned. The object
+ * returned by getAccessible() does not need to be disposed.
+ * </p>
+ *
+ * @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 == null) accessible = new_Accessible (this);
+       return accessible;
+}
+
+/**
+ * Returns the receiver's background color.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * For example, on some versions of Windows the background of a TabFolder,
+ * is a gradient rather than a solid color.
+ * </p>
+ * @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 ();
+       if (backgroundAlpha == 0) {
+               Color color =  Color.win32_new (display, background, 0);
+               return color;
+       }
+       else {
+               Control control = findBackgroundControl ();
+               if (control == null) control = this;
+               return Color.win32_new (display, control.getBackgroundPixel (), backgroundAlpha);
+       }
+}
+
+/**
+ * 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 == null) control = this;
+       return control.backgroundImage;
+}
+
+int getBackgroundPixel () {
+       return background != -1 ? background :  defaultBackground ();
+}
+
+/**
+ * Returns the receiver's border width in points.
+ *
+ * @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 ();
+       return DPIUtil.autoScaleDown(getBorderWidthInPixels ());
+}
+
+int getBorderWidthInPixels () {
+       long borderHandle = borderHandle ();
+       int bits1 = OS.GetWindowLong (borderHandle, OS.GWL_EXSTYLE);
+       if ((bits1 & OS.WS_EX_CLIENTEDGE) != 0) return OS.GetSystemMetrics (OS.SM_CXEDGE);
+       if ((bits1 & OS.WS_EX_STATICEDGE) != 0) return OS.GetSystemMetrics (OS.SM_CXBORDER);
+       int bits2 = OS.GetWindowLong (borderHandle, OS.GWL_STYLE);
+       if ((bits2 & OS.WS_BORDER) != 0) return OS.GetSystemMetrics (OS.SM_CXBORDER);
+       return 0;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location in points
+ * 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 ();
+       return DPIUtil.autoScaleDown(getBoundsInPixels ());
+}
+
+Rectangle getBoundsInPixels () {
+       forceResize ();
+       RECT rect = new RECT ();
+       OS.GetWindowRect (topHandle (), rect);
+       long hwndParent = parent == null ? 0 : parent.handle;
+       OS.MapWindowPoints (0, hwndParent, 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 () {
+       return OS.CP_ACP;
+}
+
+String getClipboardText () {
+       String string = "";
+       if (OS.OpenClipboard (0)) {
+               long hMem = OS.GetClipboardData (OS.CF_UNICODETEXT);
+               if (hMem != 0) {
+                       /* Ensure byteCount is a multiple of 2 bytes on UNICODE platforms */
+                       int byteCount = OS.GlobalSize (hMem) / TCHAR.sizeof * TCHAR.sizeof;
+                       long ptr = OS.GlobalLock (hMem);
+                       if (ptr != 0) {
+                               /* Use the character encoding for the default locale */
+                               TCHAR buffer = new TCHAR (0, byteCount / TCHAR.sizeof);
+                               OS.MoveMemory (buffer, ptr, byteCount);
+                               string = buffer.toString (0, buffer.strlen ());
+                               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 boolean getDragDetect () {
+       checkWidget ();
+       return (state & DRAG_DETECT) != 0;
+}
+
+boolean getDrawing () {
+       return drawCount <= 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 boolean getEnabled () {
+       checkWidget ();
+       return 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 != null) return font;
+       long hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (hFont == 0) 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 != -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 in points (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 ();
+       return DPIUtil.autoScaleDown(getLocationInPixels());
+}
+
+Point getLocationInPixels () {
+       forceResize ();
+       RECT rect = new RECT ();
+       OS.GetWindowRect (topHandle (), rect);
+       long hwndParent = parent == null ? 0 : parent.handle;
+       OS.MapWindowPoints (0, hwndParent, 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
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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 Monitor getMonitor () {
+       checkWidget ();
+       long hmonitor = OS.MonitorFromWindow (handle, OS.MONITOR_DEFAULTTONEAREST);
+       return display.getMonitor (hmonitor);
+}
+
+/**
+ * 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 3.7
+ */
+public int getOrientation () {
+       checkWidget ();
+       return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * 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 != shell) {
+               count++;
+               control = control.parent;
+       }
+       control = this;
+       Control [] result = new Control [count];
+       while (control != 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 in points. 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 ();
+       return DPIUtil.autoScaleDown(getSizeInPixels ());
+}
+
+Point getSizeInPixels () {
+       forceResize ();
+       RECT rect = new RECT ();
+       OS.GetWindowRect (topHandle (), rect);
+       int width = rect.right - rect.left;
+       int height = rect.bottom - rect.top;
+       return new Point (width, height);
+}
+
+/**
+ * Calculates a slightly different color, e.g. for the hot state of a button.
+ * @param pixel the color to start with
+ */
+int getSlightlyDifferentColor(int pixel) {
+       return getDifferentColor(pixel, 0.1);
+}
+
+/**
+ * Calculates a different color, e.g. for the checked state of a toggle button
+ * or to highlight a selected button.
+ * @param pixel the color to start with
+ */
+int getDifferentColor(int pixel) {
+       return getDifferentColor(pixel, 0.2);
+}
+
+/**
+ * @param factor must be between [0..1]. The bounds are not checked
+ */
+int getDifferentColor(int pixel, double factor) {
+       int red = pixel & 0xFF;
+       int green = (pixel & 0xFF00) >> 8;
+       int blue = (pixel & 0xFF0000) >> 16;
+       red += calcDiff(red, factor);
+       green += calcDiff(green, factor);
+       blue += calcDiff(blue, factor);
+       return (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
+}
+
+long /* int */ calcDiff(int component, double factor) {
+       if (component > 127) {
+               return Math.round(component * -1 * factor);
+       } else {
+               return Math.round((255 - component) * factor);
+       }
+}
+
+/**
+ * Calculates a slightly different background color, e.g. for highlighting the sort column
+ * in a table or tree. This method produces less contrast that {@link #getSlightlyDifferentColor(int)}.
+ * @param pixel the color to start with
+ */
+int getSlightlyDifferentBackgroundColor(int pixel) {
+       int offset = 8;
+       int red = pixel & 0xFF;
+       int green = (pixel & 0xFF00) >> 8;
+       int blue = (pixel & 0xFF0000) >> 16;
+       red = red > 127 ? red-offset : red+offset;
+       green = green > 127 ? green-offset : green+offset;
+       blue = blue > 127 ? blue-offset : blue+offset;
+       return (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
+}
+
+/**
+ * Returns the text direction 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 text direction 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.102
+ */
+public int getTextDirection() {
+       checkWidget ();
+       int flags = OS.WS_EX_LAYOUTRTL | OS.WS_EX_RTLREADING;
+       int bits  = OS.GetWindowLong (handle, OS.GWL_EXSTYLE) & flags;
+       return bits == 0 || bits == flags ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
+}
+
+/**
+ * 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 this control is set to send touch events, or
+ * <code>false</code> if it is set to send gesture events instead.  This method
+ * also returns <code>false</code> if a touch-based input device is not detected
+ * (this can be determined with <code>Display#getTouchEnabled()</code>).  Use
+ * {@link #setTouchEnabled(boolean)} to switch the events that a control sends
+ * between touch events and gesture events.
+ *
+ * @return <code>true</code> if the control is set to send touch events, or <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 #setTouchEnabled
+ * @see Display#getTouchEnabled
+ *
+ * @since 3.7
+ */
+public boolean getTouchEnabled () {
+       checkWidget ();
+       return OS.IsTouchWindow (handle, null);
+}
+
+/**
+ * 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 boolean getVisible () {
+       checkWidget ();
+       if (!getDrawing()) return (state & HIDDEN) == 0;
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       return (bits & OS.WS_VISIBLE) != 0;
+}
+
+boolean hasCursor () {
+       RECT rect = new RECT ();
+       if (!OS.GetClientRect (handle, rect)) return false;
+       OS.MapWindowPoints (handle, 0, rect, 2);
+       POINT pt = new POINT ();
+       return OS.GetCursorPos (pt) && OS.PtInRect (rect, pt);
+}
+
+boolean hasCustomBackground() {
+       return background != -1;
+}
+
+boolean hasCustomForeground() {
+       return foreground != -1;
+}
+
+boolean 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.
+       */
+       long hwndFocus = OS.GetFocus ();
+       while (hwndFocus != 0) {
+               if (hwndFocus == handle) return true;
+               if (display.getControl (hwndFocus) != 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public long internal_new_GC (GCData data) {
+       checkWidget();
+       long hwnd = handle;
+       if (data != null && data.hwnd != 0) hwnd = data.hwnd;
+       if (data != null) data.hwnd = hwnd;
+       long hDC = 0;
+       if (data == null || data.ps == null) {
+               hDC = OS.GetDC (hwnd);
+       } else {
+               hDC = OS.BeginPaint (hwnd, data.ps);
+       }
+       if (hDC == 0) error(SWT.ERROR_NO_HANDLES);
+       if (data != null) {
+               int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+               if ((data.style & mask) != 0) {
+                       data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0;
+               } else {
+                       int flags = OS.GetLayout (hDC);
+                       if ((flags & OS.LAYOUT_RTL) != 0) {
+                               data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+                       } else {
+                               data.style |= SWT.LEFT_TO_RIGHT;
+                       }
+               }
+               data.device = display;
+               int foreground = getForegroundPixel ();
+               if (foreground != OS.GetTextColor (hDC)) data.foreground = foreground;
+               Control control = findBackgroundControl ();
+               if (control == null) control = this;
+               int background = control.getBackgroundPixel ();
+               if (background != OS.GetBkColor (hDC)) data.background = background;
+               data.font = font != null ? font : Font.win32_new (display, OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0));
+               data.uiState = (int)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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void internal_dispose_GC (long hDC, GCData data) {
+       checkWidget ();
+       long hwnd = handle;
+       if (data != null && data.hwnd != 0) {
+               hwnd = data.hwnd;
+       }
+       if (data == null || data.ps == null) {
+               OS.ReleaseDC (hwnd, hDC);
+       } else {
+               OS.EndPaint (hwnd, data.ps);
+       }
+}
+
+boolean isActive () {
+       Dialog dialog = display.getModalDialog ();
+       if (dialog != null) {
+               Shell dialogShell = dialog.parent;
+               if (dialogShell != null && !dialogShell.isDisposed ()) {
+                       if (dialogShell != getShell ()) return false;
+               }
+       }
+       Shell shell = null;
+       Shell [] modalShells = display.modalShells;
+       if (modalShells != null) {
+               int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+               int index = modalShells.length;
+               while (--index >= 0) {
+                       Shell modal = modalShells [index];
+                       if (modal != null) {
+                               if ((modal.style & bits) != 0) {
+                                       Control control = this;
+                                       while (control != null) {
+                                               if (control == modal) break;
+                                               control = control.parent;
+                                       }
+                                       if (control != modal) return false;
+                                       break;
+                               }
+                               if ((modal.style & SWT.PRIMARY_MODAL) != 0) {
+                                       if (shell == null) shell = getShell ();
+                                       if (modal.parent == shell) return false;
+                               }
+                       }
+               }
+       }
+       if (shell == 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 boolean 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 boolean isFocusControl () {
+       checkWidget ();
+       Control focusControl = display.focusControl;
+       if (focusControl != null && !focusControl.isDisposed ()) {
+               return this == focusControl;
+       }
+       return hasFocus ();
+}
+
+boolean isFocusAncestor (Control control) {
+       while (control != null && control != this && !(control instanceof Shell)) {
+               control = control.parent;
+       }
+       return control == 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 boolean isReparentable () {
+       checkWidget ();
+       return true;
+}
+
+boolean 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 != null) {
+               Point size = control.getSizeInPixels ();
+               if (size.x == 0 || size.y == 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;
+//     long hDC = OS.GetDCEx (handle, 0, flags);
+//     int result = OS.GetClipBox (hDC, new RECT ());
+//     OS.ReleaseDC (handle, hDC);
+//     return result != OS.NULLREGION;
+}
+
+boolean isTabGroup () {
+       Control [] tabList = parent._getTabList ();
+       if (tabList != null) {
+               for (int i=0; i<tabList.length; i++) {
+                       if (tabList [i] == this) return true;
+               }
+       }
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       return (bits & OS.WS_TABSTOP) != 0;
+}
+
+boolean isTabItem () {
+       Control [] tabList = parent._getTabList ();
+       if (tabList != null) {
+               for (int i=0; i<tabList.length; i++) {
+                       if (tabList [i] == this) return false;
+               }
+       }
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.WS_TABSTOP) != 0) return false;
+       long code = OS.SendMessage (handle, OS.WM_GETDLGCODE, 0, 0);
+       if ((code & OS.DLGC_STATIC) != 0) return false;
+       if ((code & OS.DLGC_WANTALLKEYS) != 0) return false;
+       if ((code & OS.DLGC_WANTARROWS) != 0) return false;
+       if ((code & OS.DLGC_WANTTAB) != 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 boolean isVisible () {
+       checkWidget ();
+       if (OS.IsWindowVisible (handle)) return true;
+       return getVisible () && parent.isVisible ();
+}
+
+@Override
+void mapEvent (long hwnd, Event event) {
+       if (hwnd != handle) {
+               POINT point = new POINT ();
+               Point loc = event.getLocationInPixels();
+               point.x = loc.x;
+               point.y = loc.y;
+               OS.MapWindowPoints (hwnd, handle, point, 1);
+               event.setLocationInPixels(point.x, point.y);
+       }
+}
+
+void markLayout (boolean changed, boolean all) {
+       /* Do nothing */
+}
+
+Decorations menuShell () {
+       return parent.menuShell ();
+}
+
+boolean mnemonicHit (char key) {
+       return false;
+}
+
+boolean mnemonicMatch (char 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 ();
+       long topHandle = topHandle (), hwndAbove = OS.HWND_TOP;
+       if (control != null) {
+               if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if (parent != control.parent) return;
+               long hwnd = control.topHandle ();
+               if (hwnd == 0 || hwnd == 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 == 0 || hwndAbove == hwnd) {
+                       hwndAbove = OS.HWND_TOP;
+               }
+       }
+       int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+       OS.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 ();
+       long topHandle = topHandle (), hwndAbove = OS.HWND_BOTTOM;
+       if (control != null) {
+               if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if (parent != 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 == shell && parent != 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.
+                       */
+                       long hwndParent = parent.handle, hwnd = hwndParent;
+                       hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
+                       while (hwndAbove != 0 && hwndAbove != hwnd) {
+                               if (OS.GetWindow (hwndAbove, OS.GW_OWNER) == hwndParent) break;
+                               hwndAbove = OS.GetWindow (hwnd = hwndAbove, OS.GW_HWNDPREV);
+                       }
+                       if (hwndAbove == hwnd) return;
+               }
+       }
+       if (hwndAbove == 0 || hwndAbove == topHandle) return;
+       int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+       OS.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, boolean)
+ */
+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, boolean)
+ */
+public void pack (boolean changed) {
+       checkWidget ();
+       /*
+        * Since computeSize is overridden by Custom classes like CCombo
+        * etc... hence we cannot call computeSizeInPixels directly.
+        */
+       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 boolean print (GC gc) {
+       checkWidget ();
+       if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       long topHandle = topHandle ();
+       long hdc = gc.handle;
+       int state = 0;
+       long gdipGraphics = gc.getGCData().gdipGraphics;
+       if (gdipGraphics != 0) {
+               long clipRgn = 0;
+               Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+               long rgn = Gdip.Region_new();
+               if (rgn == 0) 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[] lpXform = null;
+               long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+               if (matrix == 0) error(SWT.ERROR_NO_HANDLES);
+               Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+               if (!Gdip.Matrix_IsIdentity(matrix)) {
+                       lpXform = new float[6];
+                       Gdip.Matrix_GetElements(matrix, lpXform);
+               }
+               Gdip.Matrix_delete(matrix);
+               hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+               state = OS.SaveDC(hdc);
+               if (lpXform != null) {
+                       OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
+                       OS.SetWorldTransform(hdc, lpXform);
+               }
+               if (clipRgn != 0) {
+                       OS.SelectClipRgn(hdc, clipRgn);
+                       OS.DeleteObject(clipRgn);
+               }
+       }
+       int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (topHandle, null, 0, flags);
+       printWidget (topHandle, hdc, gc);
+       if (gdipGraphics != 0) {
+               OS.RestoreDC(hdc, state);
+               Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
+       }
+       return true;
+}
+
+void printWidget (long hwnd, long hdc, GC gc) {
+       /*
+       * Bug in Windows.  For some reason, PrintWindow()
+       * returns success but does nothing when it is called
+       * on a printer.  The fix is to just go directly to
+       * WM_PRINT in this case.
+       */
+       boolean success = false;
+       if (!(OS.GetDeviceCaps(gc.handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER)) {
+               /*
+               * Bug in Windows.  When PrintWindow() will only draw that
+               * portion of a control that is not obscured by the shell.
+               * The fix is temporarily reparent the window to the desktop,
+               * call PrintWindow() then reparent the window back.
+               */
+               long hwndParent = OS.GetParent (hwnd);
+               long hwndShell = hwndParent;
+               while (OS.GetParent (hwndShell) != 0) {
+                       if (OS.GetWindow (hwndShell, OS.GW_OWNER) != 0) break;
+                       hwndShell = OS.GetParent (hwndShell);
+               }
+               RECT rect1 = new RECT ();
+               OS.GetWindowRect (hwnd, rect1);
+               boolean fixPrintWindow = !OS.IsWindowVisible(hwnd);
+               if (!fixPrintWindow) {
+                       RECT rect2 = new RECT ();
+                       OS.GetWindowRect (hwndShell, rect2);
+                       OS.IntersectRect (rect2, rect1, rect2);
+                       fixPrintWindow = !OS.EqualRect (rect2, rect1);
+               }
+               /*
+               * Bug in Windows. PrintWindow() does not print portions
+               * of the receiver that are clipped out using SetWindowRgn()
+               * in a parent.  The fix is temporarily reparent the window
+               * to the desktop, call PrintWindow() then reparent the window
+               * back.
+               */
+               if (!fixPrintWindow) {
+                       long rgn = OS.CreateRectRgn(0, 0, 0, 0);
+                       long parent = OS.GetParent(hwnd);
+                       while (parent != hwndShell && !fixPrintWindow) {
+                               if (OS.GetWindowRgn(parent, rgn) != 0) {
+                                       fixPrintWindow = true;
+                               }
+                               parent = OS.GetParent(parent);
+                       }
+                       OS.DeleteObject(rgn);
+               }
+               int bits1 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+               int bits2 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+               long hwndInsertAfter = 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 (hwndInsertAfter == 0 || hwndInsertAfter == hwnd) {
+                       hwndInsertAfter = OS.HWND_TOP;
+               }
+               if (fixPrintWindow) {
+                       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);
+                       int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE | OS.SWP_DRAWFRAME;
+                       if ((bits1 & OS.WS_VISIBLE) != 0) {
+                               OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
+                       }
+                       OS.SetWindowPos (hwnd, 0, x + width, y + height, 0, 0, flags);
+                       OS.SetWindowLong (hwnd, OS.GWL_STYLE, (bits1 & ~OS.WS_CHILD) | OS.WS_POPUP);
+                       OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_TOOLWINDOW);
+                       Shell shell = getShell ();
+                       Control savedFocus = shell.savedFocus;
+                       OS.SetParent (hwnd, 0);
+                       shell.setSavedFocus (savedFocus);
+                       if ((bits1 & OS.WS_VISIBLE) != 0) {
+                               OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
+                       }
+               }
+               if ((bits1 & OS.WS_VISIBLE) == 0) {
+                       OS.ShowWindow (hwnd, OS.SW_SHOW);
+               }
+               success = OS.PrintWindow (hwnd, hdc, 0);
+               if ((bits1 & OS.WS_VISIBLE) == 0) {
+                       OS.ShowWindow (hwnd, OS.SW_HIDE);
+               }
+               if (fixPrintWindow) {
+                       if ((bits1 & OS.WS_VISIBLE) != 0) {
+                               OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
+                       }
+                       OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits1);
+                       OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits2);
+                       OS.SetParent (hwnd, hwndParent);
+                       OS.MapWindowPoints (0, hwndParent, rect1, 2);
+                       int flags = OS.SWP_NOSIZE | OS.SWP_NOACTIVATE | OS.SWP_DRAWFRAME;
+                       OS.SetWindowPos (hwnd, hwndInsertAfter, rect1.left, rect1.top, rect1.right - rect1.left, rect1.bottom - rect1.top, flags);
+                       if ((bits1 & OS.WS_VISIBLE) != 0) {
+                               OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
+                       }
+               }
+       }
+
+       /*
+       * Bug in Windows.  For some reason, PrintWindow() fails
+       * when it is called on a push button.  The fix is to
+       * detect the failure and use WM_PRINT instead.  Note
+       * that WM_PRINT cannot be used all the time because it
+       * fails for browser controls when the browser has focus.
+       */
+       if (!success) {
+               int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN;
+               OS.SendMessage (hwnd, OS.WM_PRINT, hdc, flags);
+       }
+}
+
+/**
+ * Requests that this control and all of its ancestors be repositioned by
+ * their layouts at the earliest opportunity. This should be invoked after
+ * modifying the control in order to inform any dependent layouts of
+ * the change.
+ * <p>
+ * The control will not be repositioned synchronously. This method is
+ * fast-running and only marks the control for future participation in
+ * a deferred layout.
+ * <p>
+ * Invoking this method multiple times before the layout occurs is an
+ * inexpensive no-op.
+ *
+ * @since 3.105
+ */
+public void requestLayout () {
+       getShell ().layout (new Control[] {this}, SWT.DEFER);
+}
+
+/**
+ * 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.
+ * <p>
+ * Schedules a paint request if the invalidated area is visible
+ * or becomes visible later. It is not necessary for the caller
+ * to explicitly call {@link #update()} after calling this method,
+ * but depending on the platform, the automatic repaints may be
+ * delayed considerably.
+ * </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 #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 (boolean all) {
+//     checkWidget ();
+       if (!OS.IsWindowVisible (handle)) return;
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+       if (all) flags |= OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (handle, null, 0, 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.
+ * <p>
+ * Schedules a paint request if the invalidated area is visible
+ * or becomes visible later. It is not necessary for the caller
+ * to explicitly call {@link #update()} after calling this method,
+ * but depending on the platform, the automatic repaints may be
+ * delayed considerably.
+ * </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 #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, boolean all) {
+       checkWidget ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       redrawInPixels(x, y, width, height, all);
+}
+
+void redrawInPixels (int x, int y, int width, int height, boolean all) {
+       if (width <= 0 || height <= 0) return;
+       if (!OS.IsWindowVisible (handle)) return;
+       RECT rect = new RECT ();
+       OS.SetRect (rect, x, y, x + width, y + height);
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+       if (all) flags |= OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (handle, rect, 0, flags);
+}
+
+boolean redrawChildren () {
+       if (!OS.IsWindowVisible (handle)) return false;
+       Control control = findBackgroundControl ();
+       if (control == null) {
+               if ((state & THEME_BACKGROUND) != 0) {
+                       if (OS.IsAppThemed ()) {
+                               OS.InvalidateRect (handle, null, true);
+                               return true;
+                       }
+               }
+       } else {
+               if (control.backgroundImage != null) {
+                       OS.InvalidateRect (handle, null, true);
+                       return true;
+               }
+       }
+       return false;
+}
+
+void register () {
+       display.addControl (handle, this);
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       handle = 0;
+       parent = null;
+}
+
+@Override
+void releaseParent () {
+       parent.removeControl (this);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (OS.IsDBLocale) {
+               OS.ImmAssociateContext (handle, 0);
+       }
+       if (toolTipText != null) {
+               setToolTipText (getShell (), null);
+       }
+       toolTipText = null;
+       if (menu != null && !menu.isDisposed ()) {
+               menu.dispose ();
+       }
+       backgroundImage = null;
+       menu = null;
+       cursor = null;
+       unsubclass ();
+       deregister ();
+       layoutData = null;
+       if (accessible != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 gesture 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 GestureListener
+ * @see #addGestureListener
+ *
+ * @since 3.7
+ */
+public void removeGestureListener (GestureListener listener) {
+       checkWidget();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Gesture, 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook(SWT.Paint, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when touch 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 TouchListener
+ * @see #addTouchListener
+ *
+ * @since 3.7
+ */
+public void removeTouchListener(TouchListener listener) {
+       checkWidget();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Touch, 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Traverse, listener);
+}
+
+int resolveTextDirection() {
+       /*
+        * For generic Controls do nothing here. Text-enabled Controls will resolve
+        * AUTO text direction according to their text content.
+        */
+       return SWT.NONE;
+}
+
+void showWidget (boolean visible) {
+       long topHandle = topHandle ();
+       OS.ShowWindow (topHandle, visible ? OS.SW_SHOW : OS.SW_HIDE);
+       if (handle != topHandle) OS.ShowWindow (handle, visible ? OS.SW_SHOW : OS.SW_HIDE);
+}
+
+@Override
+boolean 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 != display.getActiveShell ()) {
+                                       shell.setActiveControl (null);
+                               }
+                               break;
+               }
+       }
+       return true;
+}
+
+boolean sendGestureEvent (GESTUREINFO gi) {
+       /**
+        * Feature in Windows 7.  GID_BEGIN and GID_END events bubble up through the window
+        * hierarchy for legacy support.  Ignore events not targeted for this control.
+        */
+       if (gi.hwndTarget != handle) return true;
+       Event event = new Event ();
+       int type = 0;
+       Point globalPt = new Point(gi.x, gi.y);
+       Point point = toControlInPixels(globalPt.x, globalPt.y);
+       event.setLocationInPixels(point.x, point.y);
+       switch (gi.dwID) {
+               case OS.GID_ZOOM:
+                       type = SWT.Gesture;
+                       event.detail = SWT.GESTURE_MAGNIFY;
+                       int fingerDistance = OS.LODWORD (gi.ullArguments);
+                       if ((gi.dwFlags & OS.GF_BEGIN) != 0) {
+                               event.detail = SWT.GESTURE_BEGIN;
+                               display.magStartDistance = display.lastDistance = fingerDistance;
+                       } else if ((gi.dwFlags & OS.GF_END) != 0) {
+                               event.detail = SWT.GESTURE_END;
+                       }
+
+                       /*
+                       * The gi.ullArguments is the distance between the fingers.
+                       * Scale factor is relative to that original value.
+                       */
+                       if (fingerDistance == display.lastDistance && event.detail == SWT.GESTURE_MAGNIFY) return true;
+                       if (fingerDistance != 0) event.magnification = fingerDistance / display.magStartDistance;
+                       display.lastDistance = fingerDistance;
+                       break;
+               case OS.GID_PAN:
+                       type = SWT.Gesture;
+                       event.detail = SWT.GESTURE_PAN;
+                       if ((gi.dwFlags & OS.GF_BEGIN) != 0) {
+                               event.detail = SWT.GESTURE_BEGIN;
+                               display.lastX = point.x;
+                               display.lastY = point.y;
+                       } else if ((gi.dwFlags & OS.GF_END) != 0) {
+                               event.detail = SWT.GESTURE_END;
+                       }
+                       if (display.lastX == point.x && display.lastY == point.y && event.detail == SWT.GESTURE_PAN) return true;
+                       event.xDirection = point.x - display.lastX;
+                       event.yDirection = point.y - display.lastY;
+                       display.lastX = point.x;
+                       display.lastY = point.y;
+                       break;
+               case OS.GID_ROTATE:
+                       type = SWT.Gesture;
+                       event.detail = SWT.GESTURE_ROTATE;
+                       double rotationInRadians = OS.GID_ROTATE_ANGLE_FROM_ARGUMENT (OS.LODWORD (gi.ullArguments));
+                       if ((gi.dwFlags & OS.GF_BEGIN) != 0) {
+                               event.detail = SWT.GESTURE_BEGIN;
+                               display.rotationAngle = rotationInRadians;
+                       } else if ((gi.dwFlags & OS.GF_END) != 0) {
+                               event.detail = SWT.GESTURE_END;
+                       }
+
+                       /*
+                       * Feature in Win32. Rotation events are sent even when the fingers are at rest.
+                       * If the current rotation is the same as the last one received don't send the event.
+                       */
+                       if (display.rotationAngle == rotationInRadians && event.detail == SWT.GESTURE_ROTATE) return true;
+                       event.rotation = rotationInRadians * 180.0 / Math.PI;
+                       display.rotationAngle = rotationInRadians;
+                       break;
+               default:
+                       // Unknown gesture -- ignore.
+                       break;
+       }
+
+       if (type == 0) return true;
+       setInputState (event, type);
+       sendEvent (type, event);
+       return event.doit;
+}
+
+void sendMove () {
+       sendEvent (SWT.Move);
+}
+
+void sendResize () {
+       sendEvent (SWT.Resize);
+}
+
+void sendTouchEvent (TOUCHINPUT touchInput []) {
+       Event event = new Event ();
+       POINT pt = new POINT ();
+       OS.GetCursorPos (pt);
+       OS.ScreenToClient (handle, pt);
+       event.setLocationInPixels(pt.x, pt.y);
+       Touch [] touches = new Touch [touchInput.length];
+       Monitor monitor = getMonitor ();
+       for (int i = 0; i < touchInput.length; i++) {
+               TOUCHINPUT ti = touchInput [i];
+               TouchSource inputSource = display.findTouchSource (ti.hSource, monitor);
+               int state = 0;
+               if ((ti.dwFlags & OS.TOUCHEVENTF_DOWN) != 0) state = SWT.TOUCHSTATE_DOWN;
+               if ((ti.dwFlags & OS.TOUCHEVENTF_UP) != 0) state = SWT.TOUCHSTATE_UP;
+               if ((ti.dwFlags & OS.TOUCHEVENTF_MOVE) != 0) state = SWT.TOUCHSTATE_MOVE;
+               boolean primary = (ti.dwFlags & OS.TOUCHEVENTF_PRIMARY) != 0;
+               int x = (int)OS.TOUCH_COORD_TO_PIXEL (ti.x);
+               int y = (int)OS.TOUCH_COORD_TO_PIXEL (ti.y);
+               touches [i] = new Touch (ti.dwID, inputSource, state, primary, x, y);
+       }
+       event.touches = touches;
+       setInputState (event, SWT.Touch);
+       postEvent (SWT.Touch, event);
+}
+
+void setBackground () {
+       Control control = findBackgroundControl ();
+       if (control == null) control = this;
+       if (control.backgroundImage != null) {
+               Shell shell = getShell ();
+               shell.releaseBrushes ();
+               setBackgroundImage (control.backgroundImage.handle);
+       } else {
+               setBackgroundPixel (control.background == -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.
+ * </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 ();
+       _setBackground (color);
+       if (color != null) {
+               this.updateBackgroundMode ();
+       }
+}
+
+private void _setBackground (Color color) {
+       int pixel = -1;
+       int alpha = 255;
+       if (color != null) {
+               if (color.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+               alpha = color.getAlpha();
+       }
+       if (pixel == background && alpha == backgroundAlpha) return;
+       background = pixel;
+       backgroundAlpha = alpha;
+       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 != null) {
+               if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (image.type != SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (backgroundImage == image && backgroundAlpha > 0) return;
+       backgroundAlpha = 255;
+       backgroundImage = image;
+       Shell shell = getShell ();
+       shell.releaseBrushes ();
+       updateBackgroundImage ();
+}
+
+void setBackgroundImage (long hBitmap) {
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+void setBackgroundPixel (int pixel) {
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+/**
+ * Sets the receiver's size and location in points 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>
+ * <p>
+ * Note: On GTK, attempting to set the width or height of the
+ * receiver to a number higher or equal 2^14 will cause them to be
+ * set to (2^14)-1 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 ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       setBoundsInPixels(x, y, width, height);
+}
+
+void setBoundsInPixels (int x, int y, int width, int height) {
+       int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+       setBoundsInPixels (x, y, Math.max (0, width), Math.max (0, height), flags);
+}
+
+void setBoundsInPixels (int x, int y, int width, int height, int flags) {
+       setBoundsInPixels (x, y, width, height, flags, true);
+}
+
+void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
+       if (findImageControl () != null) {
+               if (backgroundImage == null) flags |= OS.SWP_NOCOPYBITS;
+       } else {
+               if (OS.GetWindow (handle, OS.GW_CHILD) == 0) {
+                       if (OS.IsAppThemed ()) {
+                               if (findThemeControl () != null) flags |= OS.SWP_NOCOPYBITS;
+                       }
+               }
+       }
+       long topHandle = topHandle ();
+       if (defer && parent != null) {
+               forceResize ();
+               if (parent.lpwp != null) {
+                       int index = 0;
+                       WINDOWPOS [] lpwp = parent.lpwp;
+                       while (index < lpwp.length) {
+                               if (lpwp [index] == null) break;
+                               index ++;
+                       }
+                       if (index == lpwp.length) {
+                               WINDOWPOS [] newLpwp = new WINDOWPOS [lpwp.length + 4];
+                               System.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;
+               }
+       }
+       OS.SetWindowPos (topHandle, 0, x, y, width, height, flags);
+}
+
+/**
+ * Sets the receiver's size and location in points 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>
+ * <p>
+ * Note: On GTK, attempting to set the width or height of the
+ * receiver to a number higher or equal 2^14 will cause them to be
+ * set to (2^14)-1 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       setBoundsInPixels(DPIUtil.autoScaleUp(rect));
+}
+
+void setBoundsInPixels (Rectangle rect) {
+       setBoundsInPixels (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 (boolean capture) {
+       checkWidget ();
+       if (capture) {
+               OS.SetCapture (handle);
+       } else {
+               if (OS.GetCapture () == handle) {
+                       OS.ReleaseCapture ();
+               }
+       }
+}
+
+void setCursor () {
+       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 != null && cursor.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       this.cursor = cursor;
+       long hwndCursor = OS.GetCapture ();
+       if (hwndCursor == 0) {
+               POINT pt = new POINT ();
+               if (!OS.GetCursorPos (pt)) return;
+               long hwnd = hwndCursor = OS.WindowFromPoint (pt);
+               while (hwnd != 0 && hwnd != handle) {
+                       hwnd = OS.GetParent (hwnd);
+               }
+               if (hwnd == 0) return;
+       }
+       Control control = display.getControl (hwndCursor);
+       if (control == null) control = this;
+       control.setCursor ();
+}
+
+void setDefaultFont () {
+       long 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 (boolean 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 (boolean 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;
+       boolean fixFocus = false;
+       if (!enabled) {
+               if (display.focusEvent != SWT.FocusOut) {
+                       control = display.getFocusControl ();
+                       fixFocus = isFocusAncestor (control);
+               }
+       }
+       enableWidget (enabled);
+       if (fixFocus) fixFocus (control);
+}
+
+/**
+ * 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 boolean setFocus () {
+       checkWidget ();
+       if ((style & SWT.NO_FOCUS) != 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 ();
+       long hFont = 0;
+       if (font != null) {
+               if (font.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               hFont = font.handle;
+       }
+       this.font = font;
+       if (hFont == 0) 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 != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == 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 ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       setLocationInPixels(x, y);
+}
+
+void setLocationInPixels (int x, int y) {
+       int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE | OS.SWP_DRAWFRAME;
+       setBoundsInPixels (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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       location = DPIUtil.autoScaleUp(location);
+       setLocationInPixels(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 != null) {
+               if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if ((menu.style & SWT.POP_UP) == 0) {
+                       error (SWT.ERROR_MENU_NOT_POP_UP);
+               }
+               if (menu.parent != menuShell ()) {
+                       error (SWT.ERROR_INVALID_PARENT);
+               }
+       }
+       this.menu = menu;
+}
+
+/**
+ * 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 3.7
+ */
+public void setOrientation (int orientation) {
+       checkWidget ();
+       int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+       if ((orientation & flags) == 0 || (orientation & flags) == flags) return;
+       style &= ~SWT.MIRRORED;
+       style &= ~flags;
+       style |= orientation & flags;
+       style &= ~SWT.FLIP_TEXT_DIRECTION;
+       updateOrientation ();
+       checkMirrored ();
+}
+
+boolean setRadioFocus (boolean tabbing) {
+       return false;
+}
+
+boolean setRadioSelection (boolean 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, boolean)
+ * @see #update()
+ */
+public void setRedraw (boolean 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 == 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.WS_VISIBLE) == 0) state |= HIDDEN;
+       }
+       if (redraw) {
+               if (--drawCount == 0) {
+                       long topHandle = topHandle ();
+                       OS.SendMessage (topHandle, OS.WM_SETREDRAW, 1, 0);
+                       if (handle != topHandle) OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+                       if ((state & HIDDEN) != 0) {
+                               state &= ~HIDDEN;
+                               OS.ShowWindow (topHandle, OS.SW_HIDE);
+                               if (handle != topHandle) OS.ShowWindow (handle, OS.SW_HIDE);
+                       } else {
+                               int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                               OS.RedrawWindow (topHandle, null, 0, flags);
+                       }
+               }
+       } else {
+               if (drawCount++ == 0) {
+                       long topHandle = topHandle ();
+                       OS.SendMessage (topHandle, OS.WM_SETREDRAW, 0, 0);
+                       if (handle != 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 != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+       long hRegion = 0;
+       if (region != 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;
+}
+
+/**
+ * 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>
+ * <p>
+ * Note: On GTK, attempting to set the width or height of the
+ * receiver to a number higher or equal 2^14 will cause them to be
+ * set to (2^14)-1 instead.
+ * </p>
+ *
+ * @param width the new width in points for the receiver
+ * @param height the new height in points 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 ();
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       setSizeInPixels(width, height);
+}
+
+void setSizeInPixels (int width, int height) {
+       int flags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+       setBoundsInPixels (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>
+ * <p>
+ * Note: On GTK, attempting to set the width or height of the
+ * receiver to a number higher or equal 2^14 will cause them to be
+ * set to (2^14)-1 instead.
+ * </p>
+ *
+ * @param size the new size in points 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       size = DPIUtil.autoScaleUp(size);
+       setSizeInPixels(size.x, size.y);
+}
+
+@Override
+boolean setTabItemFocus () {
+       if (!isShowing ()) return false;
+       return forceFocus ();
+}
+
+/**
+ * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
+ * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code>,
+ * <code>SWT.RIGHT_TO_LEFT</code>, or <code>SWT.AUTO_TEXT_DIRECTION</code>.
+ * <p>
+ * <code>setOrientation</code> would override this value with the text direction
+ * that is consistent with the new orientation.
+ * </p>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows.
+ * It doesn't set the base text direction on GTK and Cocoa.
+ * </p>
+ *
+ * @param textDirection the base text direction 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>
+ *
+ * @see SWT#LEFT_TO_RIGHT
+ * @see SWT#RIGHT_TO_LEFT
+ * @see SWT#AUTO_TEXT_DIRECTION
+ * @see SWT#FLIP_TEXT_DIRECTION
+ *
+ * @since 3.102
+ */
+public void setTextDirection(int textDirection) {
+       checkWidget ();
+       textDirection &= (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
+       updateTextDirection (textDirection);
+       if (textDirection == AUTO_TEXT_DIRECTION) {
+               state |= HAS_AUTO_DIRECTION;
+       } else {
+               state &= ~HAS_AUTO_DIRECTION;
+       }
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ *
+ * @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);
+}
+
+/**
+ * Sets whether this control should send touch events (by default controls do not).
+ * Setting this to <code>false</code> causes the receiver to send gesture events
+ * instead.  No exception is thrown if a touch-based input device is not
+ * detected (this can be determined with <code>Display#getTouchEnabled()</code>).
+ *
+ * @param enabled the new touch-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 Display#getTouchEnabled
+ *
+ * @since 3.7
+ */
+public void setTouchEnabled(boolean enabled) {
+       checkWidget();
+       if (enabled) {
+               OS.RegisterTouchWindow(handle, 0);
+       } else {
+               OS.UnregisterTouchWindow(handle);
+       }
+}
+
+/**
+ * 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 (boolean visible) {
+       checkWidget ();
+       if (!getDrawing()) {
+               if (((state & HIDDEN) == 0) == visible) return;
+       } else {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if (((bits & OS.WS_VISIBLE) != 0) == 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;
+       boolean fixFocus = false;
+       if (!visible) {
+               if (display.focusEvent != SWT.FocusOut) {
+                       control = display.getFocusControl ();
+                       fixFocus = isFocusAncestor (control);
+               }
+       }
+       if (!getDrawing()) {
+               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 () {
+       long oldProc = windowProc ();
+       long newProc = display.windowProc;
+       if (oldProc == 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>
+ * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
+ * {@link Display#map(Control, Control, Rectangle)}.
+ * </p>
+ *
+ * @param x the x coordinate in points to be translated
+ * @param y the y coordinate in points 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 ();
+       return DPIUtil.autoScaleDown(toControlInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y)));
+}
+
+Point toControlInPixels (int x, int y) {
+       POINT pt = new POINT ();
+       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>
+ * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
+ * {@link Display#map(Control, Control, Rectangle)}.
+ * </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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       point = DPIUtil.autoScaleUp(point);
+       return DPIUtil.autoScaleDown(toControlInPixels(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>
+ * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
+ * {@link Display#map(Control, Control, Rectangle)}.
+ * </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 ();
+       return DPIUtil.autoScaleDown(toDisplayInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y)));
+}
+
+Point toDisplayInPixels (int x, int y) {
+       POINT pt = new POINT ();
+       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>
+ * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
+ * {@link Display#map(Control, Control, Rectangle)}.
+ * </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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       point = DPIUtil.autoScaleUp(point);
+       return DPIUtil.autoScaleDown(toDisplayInPixels(point.x, point.y));
+}
+
+long topHandle () {
+       return handle;
+}
+
+boolean translateAccelerator (MSG msg) {
+       return menuShell ().translateAccelerator (msg);
+}
+
+boolean translateMnemonic (Event event, Control control) {
+       if (control == this) return false;
+       if (!isVisible () || !isEnabled ()) return false;
+       event.doit = mnemonicMatch (event.character);
+       return traverse (event);
+}
+
+boolean translateMnemonic (MSG msg) {
+       if (msg.wParam < 0x20) return false;
+       long hwnd = msg.hwnd;
+       if (OS.GetKeyState (OS.VK_MENU) >= 0) {
+               long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+               if ((code & OS.DLGC_WANTALLKEYS) != 0) return false;
+               if ((code & OS.DLGC_BUTTON) == 0) return false;
+       }
+       Decorations shell = menuShell ();
+       if (shell.isVisible () && shell.isEnabled ()) {
+               display.lastAscii = (int)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;
+}
+
+boolean translateTraversal (MSG msg) {
+       long hwnd = msg.hwnd;
+       int key = (int)msg.wParam;
+       if (key == OS.VK_MENU) {
+               if ((msg.lParam & 0x40000000) == 0) {
+                       OS.SendMessage (hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+               }
+               return false;
+       }
+       int detail = SWT.TRAVERSE_NONE;
+       boolean doit = true, all = false;
+       boolean lastVirtual = false;
+       int lastKey = key, lastAscii = 0;
+       switch (key) {
+               case OS.VK_ESCAPE: {
+                       all = true;
+                       lastAscii = 27;
+                       long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+                       if ((code & OS.DLGC_WANTALLKEYS) != 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) == 0) doit = false;
+                       }
+                       detail = SWT.TRAVERSE_ESCAPE;
+                       break;
+               }
+               case OS.VK_RETURN: {
+                       all = true;
+                       lastAscii = '\r';
+                       long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+                       if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false;
+                       detail = SWT.TRAVERSE_RETURN;
+                       break;
+               }
+               case OS.VK_TAB: {
+                       lastAscii = '\t';
+                       boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
+                       long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+                       if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) != 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) != 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: {
+                       lastVirtual = true;
+                       long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+                       if ((code & (OS.DLGC_WANTARROWS /*| OS.DLGC_WANTALLKEYS*/)) != 0) doit = false;
+                       boolean next = key == OS.VK_DOWN || key == OS.VK_RIGHT;
+                       if (parent != null && (parent.style & SWT.MIRRORED) != 0) {
+                               if (key == OS.VK_LEFT || key == 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;
+                       long code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+                       if ((code & OS.DLGC_WANTALLKEYS) != 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) == 0) doit = false;
+                       }
+                       detail = key == 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 == shell) return false;
+               control = control.parent;
+       } while (all && control != null);
+       return false;
+}
+
+boolean 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);
+       }
+       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>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
+ * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_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 boolean traverse (int traversal) {
+       checkWidget ();
+       Event event = new Event ();
+       event.doit = true;
+       event.detail = traversal;
+       return traverse (event);
+}
+
+/**
+ * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
+ *
+ * <p>Valid traversal values are
+ * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
+ * <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>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
+ * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
+ * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
+ * event is created with standard values based on the KeyDown event.  If
+ * <code>traversal</code> is one of the other traversal constants then the Traverse
+ * event is created with this detail, and its <code>doit</code> is taken from the
+ * KeyDown event.
+ * </p>
+ *
+ * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
+ * this from <code>event</code>
+ * @param event the KeyDown event
+ *
+ * @return <code>true</code> if the traversal succeeded
+ *
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_NULL_ARGUMENT if 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>
+ *
+ * @since 3.6
+ */
+public boolean traverse (int traversal, Event event) {
+       checkWidget ();
+       if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+       return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
+}
+
+/**
+ * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
+ *
+ * <p>Valid traversal values are
+ * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
+ * <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>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
+ * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
+ * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
+ * event is created with standard values based on the KeyDown event.  If
+ * <code>traversal</code> is one of the other traversal constants then the Traverse
+ * event is created with this detail, and its <code>doit</code> is taken from the
+ * KeyDown event.
+ * </p>
+ *
+ * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
+ * this from <code>event</code>
+ * @param event the KeyDown event
+ *
+ * @return <code>true</code> if the traversal succeeded
+ *
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_NULL_ARGUMENT if 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>
+ *
+ * @since 3.6
+ */
+public boolean traverse (int traversal, KeyEvent event) {
+       checkWidget ();
+       if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+       return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
+}
+
+boolean traverse (int traversal, char character, int keyCode, int keyLocation, int stateMask, boolean doit) {
+       if (traversal == SWT.TRAVERSE_NONE) {
+               switch (keyCode) {
+                       case SWT.ESC: {
+                               traversal = SWT.TRAVERSE_ESCAPE;
+                               doit = true;
+                               break;
+                       }
+                       case SWT.CR: {
+                               traversal = SWT.TRAVERSE_RETURN;
+                               doit = true;
+                               break;
+                       }
+                       case SWT.ARROW_DOWN:
+                       case SWT.ARROW_RIGHT: {
+                               traversal = SWT.TRAVERSE_ARROW_NEXT;
+                               doit = false;
+                               break;
+                       }
+                       case SWT.ARROW_UP:
+                       case SWT.ARROW_LEFT: {
+                               traversal = SWT.TRAVERSE_ARROW_PREVIOUS;
+                               doit = false;
+                               break;
+                       }
+                       case SWT.TAB: {
+                               traversal = (stateMask & SWT.SHIFT) != 0 ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT;
+                               doit = true;
+                               break;
+                       }
+                       case SWT.PAGE_DOWN: {
+                               if ((stateMask & SWT.CTRL) != 0) {
+                                       traversal = SWT.TRAVERSE_PAGE_NEXT;
+                                       doit = true;
+                               }
+                               break;
+                       }
+                       case SWT.PAGE_UP: {
+                               if ((stateMask & SWT.CTRL) != 0) {
+                                       traversal = SWT.TRAVERSE_PAGE_PREVIOUS;
+                                       doit = true;
+                               }
+                               break;
+                       }
+                       default: {
+                               if (character != 0 && (stateMask & (SWT.ALT | SWT.CTRL)) == SWT.ALT) {
+                                       traversal = SWT.TRAVERSE_MNEMONIC;
+                                       doit = true;
+                               }
+                               break;
+                       }
+               }
+       }
+
+       Event event = new Event ();
+       event.character = character;
+       event.detail = traversal;
+       event.doit = doit;
+       event.keyCode = keyCode;
+       event.keyLocation = keyLocation;
+       event.stateMask = stateMask;
+
+       Shell shell = getShell ();
+       boolean all = false;
+       switch (traversal) {
+               case SWT.TRAVERSE_ESCAPE:
+               case SWT.TRAVERSE_RETURN:
+               case SWT.TRAVERSE_PAGE_NEXT:
+               case SWT.TRAVERSE_PAGE_PREVIOUS: {
+                       all = true;
+                       // FALL THROUGH
+               }
+               case SWT.TRAVERSE_ARROW_NEXT:
+               case SWT.TRAVERSE_ARROW_PREVIOUS:
+               case SWT.TRAVERSE_TAB_NEXT:
+               case SWT.TRAVERSE_TAB_PREVIOUS: {
+                       /* traversal is a valid traversal action */
+                       break;
+               }
+               case SWT.TRAVERSE_MNEMONIC: {
+                       return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
+               }
+               default: {
+                       /* traversal is not a valid traversal action */
+                       return false;
+               }
+       }
+
+       Control control = this;
+       do {
+               if (control.traverse (event)) {
+                       OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+                       return true;
+               }
+               if (!event.doit && control.hooks (SWT.Traverse)) return false;
+               if (control == shell) return false;
+               control = control.parent;
+       } while (all && control != null);
+       return false;
+}
+
+boolean traverseEscape () {
+       return false;
+}
+
+boolean traverseGroup (boolean next) {
+       Control root = computeTabRoot ();
+       Widget group = computeTabGroup ();
+       Widget [] list = root.computeTabList ();
+       int length = list.length;
+       int index = 0;
+       while (index < length) {
+               if (list [index] == 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 == length) return false;
+       int start = index, offset = (next) ? 1 : -1;
+       while ((index = ((index + offset + length) % length)) != start) {
+               Widget widget = list [index];
+               if (!widget.isDisposed () && widget.setTabGroupFocus ()) {
+                       return true;
+               }
+       }
+       if (group.isDisposed ()) return false;
+       return group.setTabGroupFocus ();
+}
+
+boolean traverseItem (boolean next) {
+       Control [] children = parent._getChildren ();
+       int length = children.length;
+       int index = 0;
+       while (index < length) {
+               if (children [index] == 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 == length) return false;
+       int start = index, offset = (next) ? 1 : -1;
+       while ((index = (index + offset + length) % length) != start) {
+               Control child = children [index];
+               if (!child.isDisposed () && child.isTabItem ()) {
+                       if (child.setTabItemFocus ()) return true;
+               }
+       }
+       return false;
+}
+
+boolean traverseMnemonic (char key) {
+       if (mnemonicHit (key)) {
+               OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+               return true;
+       }
+       return false;
+}
+
+boolean traversePage (boolean next) {
+       return false;
+}
+
+boolean traverseReturn () {
+       return false;
+}
+
+void unsubclass () {
+       long newProc = windowProc ();
+       long oldProc = display.windowProc;
+       if (oldProc == 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, boolean)
+ * @see PaintListener
+ * @see SWT#Paint
+ */
+public void update () {
+       checkWidget ();
+       update (false);
+}
+
+void update (boolean all) {
+//     checkWidget ();
+       int flags = OS.RDW_UPDATENOW;
+       if (all) flags |= OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+void updateBackgroundColor () {
+       Control control = findBackgroundControl ();
+       if (control == null) control = this;
+       setBackgroundPixel (control.background);
+}
+
+void updateBackgroundImage () {
+       Control control = findBackgroundControl ();
+       Image image = control != null ? control.backgroundImage : backgroundImage;
+       setBackgroundImage (image != null ? image.handle : 0);
+}
+
+void updateBackgroundMode () {
+       int oldState = state & PARENT_BACKGROUND;
+       checkBackground ();
+       if (oldState != (state & PARENT_BACKGROUND)) {
+               setBackground ();
+       }
+}
+
+void updateFont (Font oldFont, Font newFont) {
+       if (getFont ().equals (oldFont)) setFont (newFont);
+}
+
+void updateLayout (boolean resize, boolean all) {
+       /* Do nothing */
+}
+
+void updateOrientation () {
+       int bits  = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               bits |= OS.WS_EX_LAYOUTRTL;
+       } else {
+               bits &= ~OS.WS_EX_LAYOUTRTL;
+       }
+       bits &= ~OS.WS_EX_RTLREADING;
+       OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+       OS.InvalidateRect (handle, null, true);
+}
+
+boolean updateTextDirection (int textDirection) {
+       if (textDirection == AUTO_TEXT_DIRECTION) {
+               textDirection = resolveTextDirection();
+               state |= HAS_AUTO_DIRECTION;
+       } else {
+               state &= ~HAS_AUTO_DIRECTION;
+       }
+       if (textDirection == 0) return false;
+       int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+       /*
+       * OS.WS_EX_RTLREADING means that the text direction is opposite to the
+       * natural one for the current layout. So text direction would be RTL when
+       * one and only one of the flags OS.WS_EX_LAYOUTRTL | OS.WS_EX_RTLREADING is
+       * on.
+       */
+       int flags = OS.WS_EX_LAYOUTRTL | OS.WS_EX_RTLREADING;
+       boolean oldRtl = ((bits & flags) != 0 && (bits & flags) != flags);
+       boolean newRtl = textDirection == SWT.RIGHT_TO_LEFT;
+       if (newRtl == oldRtl) return false;
+       oldRtl = (bits & OS.WS_EX_LAYOUTRTL) != 0;
+       if (newRtl != oldRtl) {
+               bits |= OS.WS_EX_RTLREADING;
+               style |= SWT.FLIP_TEXT_DIRECTION;
+       } else {
+               bits &= ~OS.WS_EX_RTLREADING;
+               style &= ~SWT.FLIP_TEXT_DIRECTION;
+       }
+       OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+       OS.InvalidateRect (handle, null, true);
+       return true;
+}
+
+CREATESTRUCT widgetCreateStruct () {
+       return null;
+}
+
+int widgetExtStyle () {
+       int bits = 0;
+       if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_CLIENTEDGE;
+//     if ((style & SWT.BORDER) != 0) {
+//             if ((style & SWT.FLAT) == 0) bits |= OS.WS_EX_CLIENTEDGE;
+//     }
+       bits |= OS.WS_EX_NOINHERITLAYOUT;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL;
+       if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) bits |= OS.WS_EX_RTLREADING;
+       return bits;
+}
+
+long 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) != 0) {
+//             if ((style & SWT.FLAT) != 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) != 0) bits |= OS.WS_CLIPSIBLINGS;
+//     if ((style & SWT.CLIP_CHILDREN) != 0) bits |= OS.WS_CLIPCHILDREN;
+//     return bits;
+}
+
+/**
+ * Changes the parent of the widget to be the one provided.
+ * 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 boolean setParent (Composite parent) {
+       checkWidget ();
+       if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (parent.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       if (this.parent == parent) return true;
+       if (!isReparentable ()) return false;
+       releaseParent ();
+       Shell newShell = parent.getShell (), oldShell = getShell ();
+       Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
+       if (oldShell != newShell || oldDecorations != newDecorations) {
+               Menu [] menus = oldShell.findMenus (this);
+               fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+       }
+       long topHandle = topHandle ();
+       if (OS.SetParent (topHandle, parent.handle) == 0) return false;
+       this.parent = parent;
+       int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+       OS.SetWindowPos (topHandle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
+       reskin (SWT.ALL);
+       return true;
+}
+
+abstract TCHAR windowClass ();
+
+abstract long windowProc ();
+
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       Display display = this.display;
+       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_GESTURE:                             result = WM_GESTURE (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_MOUSEHWHEEL:                 result = WM_MOUSEHWHEEL (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_ENTERMENULOOP:               result = WM_ENTERMENULOOP (wParam, lParam); break;
+               case OS.WM_EXITMENULOOP:                result = WM_EXITMENULOOP (wParam, lParam); break;
+               case OS.WM_ENTERSIZEMOVE:               result = WM_ENTERSIZEMOVE (wParam, lParam); break;
+               case OS.WM_EXITSIZEMOVE:                result = WM_EXITSIZEMOVE (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_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_TABLET_FLICK:                result = WM_TABLET_FLICK (wParam, lParam); break;
+               case OS.WM_TIMER:                               result = WM_TIMER (wParam, lParam); break;
+               case OS.WM_TOUCH:                               result = WM_TOUCH (wParam, lParam); break;
+               case OS.WM_UNDO:                                result = WM_UNDO (wParam, lParam); break;
+               case OS.WM_UNINITMENUPOPUP:             result = WM_UNINITMENUPOPUP (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;
+               case OS.WM_DPICHANGED:                  result = WM_DPICHANGED (wParam, lParam); break;
+       }
+       if (result != null) return result.value;
+       // widget could be disposed at this point
+       display.sendPreExternalEventDispatchEvent ();
+       try {
+               return callWindowProc (hwnd, msg, wParam, lParam);
+       } finally {
+               // widget could be disposed at this point
+               display.sendPostExternalEventDispatchEvent ();
+       }
+}
+
+LRESULT WM_ACTIVATE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_CAPTURECHANGED (long wParam, long lParam) {
+       return wmCaptureChanged (handle, wParam, lParam);
+}
+
+LRESULT WM_CHANGEUISTATE (long wParam, long lParam) {
+       if ((state & IGNORE_WM_CHANGEUISTATE) != 0) return LRESULT.ZERO;
+       return null;
+}
+
+LRESULT WM_CHAR (long wParam, long lParam) {
+       return wmChar (handle, wParam, lParam);
+}
+
+LRESULT WM_CLEAR (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_CLOSE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_COMMAND (long wParam, long lParam) {
+       /*
+       * When the WM_COMMAND message is sent from a
+       * menu, the HWND parameter in LPARAM is zero.
+       */
+       if (lParam == 0) {
+               Decorations shell = menuShell ();
+               if (shell.isEnabled ()) {
+                       int id = OS.LOWORD (wParam);
+                       MenuItem item = display.getMenuItem (id);
+                       if (item != null && item.isEnabled ()) {
+                               return item.wmCommandChild (wParam, lParam);
+                       }
+               }
+               return null;
+       }
+       Control control = display.getControl (lParam);
+       if (control == null) return null;
+       return control.wmCommandChild (wParam, lParam);
+}
+
+LRESULT WM_CONTEXTMENU (long wParam, long lParam) {
+       return wmContextMenu (handle, wParam, lParam);
+}
+
+LRESULT WM_CTLCOLOR (long wParam, long lParam) {
+       Control control = display.getControl (lParam);
+       if (control == null) return null;
+       return control.wmColorChild (wParam, lParam);
+}
+
+LRESULT WM_CUT (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_DESTROY (long wParam, long lParam) {
+       OS.KillTimer (this.handle, Menu.ID_TOOLTIP_TIMER);
+       return null;
+}
+
+LRESULT WM_DPICHANGED (long wParam, long lParam) {
+       // Map DPI to Zoom and compare
+       int nativeZoom = DPIUtil.mapDPIToZoom (OS.HIWORD (wParam));
+       int newSWTZoom = DPIUtil.getZoomForAutoscaleProperty (nativeZoom);
+       int oldSWTZoom = DPIUtil.getDeviceZoom();
+
+       // Throw the DPI change event if zoom value changes
+       if (newSWTZoom != oldSWTZoom) {
+               Event event = new Event();
+               event.type = SWT.ZoomChanged;
+               event.widget = this;
+               event.detail = newSWTZoom;
+               event.doit = true;
+               notifyListeners(SWT.ZoomChanged, event);
+               return LRESULT.ZERO;
+       }
+       return LRESULT.ONE;
+}
+
+LRESULT WM_DRAWITEM (long wParam, long lParam) {
+       DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+       if (struct.CtlType == OS.ODT_MENU) {
+               MenuItem item = display.getMenuItem (struct.itemID);
+               if (item == null) return null;
+               return item.wmDrawChild (wParam, lParam);
+       }
+       Control control = display.getControl (struct.hwndItem);
+       if (control == null) return null;
+       return control.wmDrawChild (wParam, lParam);
+}
+
+LRESULT WM_ENDSESSION (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_ENTERIDLE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_ENTERMENULOOP (long wParam, long lParam) {
+       display.externalEventLoop = true;
+       return null;
+}
+
+LRESULT WM_ENTERSIZEMOVE (long wParam, long lParam) {
+       display.externalEventLoop = true;
+       return null;
+}
+
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       if ((state & DRAW_BACKGROUND) != 0) {
+               if (findImageControl () != null) return LRESULT.ONE;
+       }
+       if ((state & THEME_BACKGROUND) != 0) {
+               if (OS.IsAppThemed ()) {
+                       if (findThemeControl () != null) return LRESULT.ONE;
+               }
+       }
+       return null;
+}
+
+LRESULT WM_EXITMENULOOP (long wParam, long lParam) {
+       display.externalEventLoop = false;
+       return null;
+}
+
+LRESULT WM_EXITSIZEMOVE (long wParam, long lParam) {
+       display.externalEventLoop = false;
+       return null;
+}
+
+LRESULT WM_GESTURE (long wParam, long lParam) {
+       if (hooks (SWT.Gesture) || filters (SWT.Gesture)) {
+               GESTUREINFO gi = new GESTUREINFO ();
+               gi.cbSize = GESTUREINFO.sizeof;
+               if (OS.GetGestureInfo (lParam, gi)) {
+                       if (!sendGestureEvent (gi)) {
+                               OS.CloseGestureInfoHandle (lParam);
+                               return LRESULT.ZERO;
+                       }
+               }
+       }
+       return null;
+}
+
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_GETFONT (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_GETOBJECT (long wParam, long lParam) {
+       if (accessible != null) {
+               long result = accessible.internal_WM_GETOBJECT (wParam, lParam);
+               if (result != 0) return new LRESULT (result);
+       }
+       return null;
+}
+
+LRESULT WM_GETMINMAXINFO (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_HOTKEY (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_HELP (long wParam, long lParam) {
+       HELPINFO lphi = new HELPINFO ();
+       OS.MoveMemory (lphi, lParam, HELPINFO.sizeof);
+       Decorations shell = menuShell ();
+       if (!shell.isEnabled ()) return null;
+       if (lphi.iContextType == OS.HELPINFO_MENUITEM) {
+               MenuItem item = display.getMenuItem (lphi.iCtrlId);
+               if (item != 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 != null) {
+                               long 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 (long wParam, long lParam) {
+       Control control = display.getControl (lParam);
+       if (control == null) return null;
+       return control.wmScrollChild (wParam, lParam);
+}
+
+LRESULT WM_IME_CHAR (long wParam, long lParam) {
+       return wmIMEChar (handle, wParam, lParam);
+}
+
+LRESULT WM_IME_COMPOSITION (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_IME_COMPOSITION_START (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_IME_ENDCOMPOSITION (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_UNINITMENUPOPUP (long wParam, long lParam) {
+       Menu hiddenMenu = menuShell ().findMenu (wParam);
+       if (hiddenMenu != null) {
+               Shell shell = getShell ();
+               hiddenMenu.sendEvent (SWT.Hide);
+               if (hiddenMenu == shell.activeMenu) shell.activeMenu = null;
+       }
+       return null;
+}
+
+LRESULT WM_INITMENUPOPUP (long wParam, 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) == 0) {
+               newMenu = menuShell ().findMenu (wParam);
+               if (newMenu != null) newMenu.update ();
+       }
+       Menu menu = newMenu;
+       while (menu != null && menu != oldMenu) {
+               menu = menu.getParentMenu ();
+       }
+       if (menu == null) {
+               menu = shell.activeMenu;
+               while (menu != 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 != null && ancestor != menu) {
+                               ancestor = ancestor.getParentMenu ();
+                       }
+                       if (ancestor != 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 != null && newMenu.isDisposed ()) newMenu = null;
+       shell.activeMenu = newMenu;
+
+       /* Send the show event */
+       if (newMenu != null && newMenu != oldMenu) {
+               newMenu.sendEvent (SWT.Show);
+               // widget could be disposed at this point
+       }
+       return null;
+}
+
+LRESULT WM_INPUTLANGCHANGE (long wParam, long lParam) {
+       menuShell().destroyAccelerators();
+       return null;
+}
+
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       return wmKeyDown (handle, wParam, lParam);
+}
+
+LRESULT WM_KEYUP (long wParam, long lParam) {
+       return wmKeyUp (handle, wParam, lParam);
+}
+
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       return wmKillFocus (handle, wParam, lParam);
+}
+
+LRESULT WM_LBUTTONDBLCLK (long wParam, long lParam) {
+       return wmLButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       return wmLButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_LBUTTONUP (long wParam, long lParam) {
+       return wmLButtonUp (handle, wParam, lParam);
+}
+
+LRESULT WM_MBUTTONDBLCLK (long wParam, long lParam) {
+       return wmMButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_MBUTTONDOWN (long wParam, long lParam) {
+       return wmMButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_MBUTTONUP (long wParam, long lParam) {
+       return wmMButtonUp (handle, wParam, lParam);
+}
+
+LRESULT WM_MEASUREITEM (long wParam, long lParam) {
+       MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof);
+       if (struct.CtlType == OS.ODT_MENU) {
+               MenuItem item = display.getMenuItem (struct.itemID);
+               if (item == null) return null;
+               return item.wmMeasureChild (wParam, lParam);
+       }
+       long hwnd = OS.GetDlgItem (handle, struct.CtlID);
+       Control control = display.getControl (hwnd);
+       if (control == null) return null;
+       return control.wmMeasureChild (wParam, lParam);
+}
+
+LRESULT WM_MENUCHAR (long wParam, 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 == 0 || type == OS.MF_SYSMENU) {
+               display.mnemonicKeyHit = false;
+               return new LRESULT (OS.MAKELRESULT (0, OS.MNC_CLOSE));
+       }
+       return null;
+}
+
+LRESULT WM_MENUSELECT (long wParam, long lParam) {
+       int code = OS.HIWORD (wParam);
+       Shell shell = getShell ();
+       OS.KillTimer (this.handle, Menu.ID_TOOLTIP_TIMER);
+       if (activeMenu != null)
+               activeMenu.hideCurrentToolTip ();
+       if (code == 0xFFFF && lParam == 0) {
+               Menu menu = shell.activeMenu;
+               while (menu != 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) != 0) return null;
+       if ((code & OS.MF_HILITE) != 0) {
+               MenuItem item = null;
+               Decorations menuShell = menuShell ();
+               if ((code & OS.MF_POPUP) != 0) {
+                       int index = OS.LOWORD (wParam);
+                       MENUITEMINFO info = new MENUITEMINFO ();
+                       info.cbSize = MENUITEMINFO.sizeof;
+                       info.fMask = OS.MIIM_SUBMENU;
+                       if (OS.GetMenuItemInfo (lParam, index, true, info)) {
+                               Menu newMenu = menuShell.findMenu (info.hSubMenu);
+                               if (newMenu != null) {
+                                       item = newMenu.cascade;
+                                       activeMenu = newMenu;
+                                       activeMenu.selectedMenuItem = newMenu.cascade;
+                                       OS.SetTimer (this.handle, Menu.ID_TOOLTIP_TIMER, OS.TTM_GETDELAYTIME, 0);
+                               }
+                       }
+               } else {
+                       Menu newMenu = menuShell.findMenu (lParam);
+                       if (newMenu != null) {
+                               int id = OS.LOWORD (wParam);
+                               item = display.getMenuItem (id);
+                       }
+                       activeMenu = (newMenu == null) ? menu : newMenu;
+                       if (item != null && activeMenu != null) {
+                               activeMenu.selectedMenuItem = item;
+                               OS.SetTimer (this.handle, Menu.ID_TOOLTIP_TIMER, OS.TTM_GETDELAYTIME, 0);
+                       }
+               }
+               if (item != null) item.sendEvent (SWT.Arm);
+       }
+       return null;
+}
+
+LRESULT WM_MOUSEACTIVATE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_MOUSEHOVER (long wParam, long lParam) {
+       return wmMouseHover (handle, wParam, lParam);
+}
+
+LRESULT WM_MOUSELEAVE (long wParam, long lParam) {
+       getShell ().fixToolTip ();
+       return wmMouseLeave (handle, wParam, lParam);
+}
+
+LRESULT WM_MOUSEMOVE (long wParam, long lParam) {
+       return wmMouseMove (handle, wParam, lParam);
+}
+
+LRESULT WM_MOUSEWHEEL (long wParam, long lParam) {
+       return wmMouseWheel (handle, wParam, lParam);
+}
+
+LRESULT WM_MOUSEHWHEEL (long wParam, long lParam) {
+       return wmMouseHWheel (handle, wParam, lParam);
+}
+
+LRESULT WM_MOVE (long wParam, long lParam) {
+       state |= MOVE_OCCURRED;
+       if (findImageControl () != null) {
+               if (this != getShell ()) redrawChildren ();
+       } else {
+               if ((state & THEME_BACKGROUND) != 0) {
+                       if (OS.IsAppThemed ()) {
+                               if (OS.IsWindowVisible (handle)) {
+                                       if (findThemeControl () != null) redrawChildren ();
+                               }
+                       }
+               }
+       }
+       if ((state & MOVE_DEFERRED) == 0) sendEvent (SWT.Move);
+       // widget could be disposed at this point
+       return null;
+}
+
+LRESULT WM_NCACTIVATE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_NCCALCSIZE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       if (!OS.IsWindowEnabled (handle)) return null;
+       if (!isActive ()) return new LRESULT (OS.HTTRANSPARENT);
+       return null;
+}
+
+LRESULT WM_NCLBUTTONDOWN (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_NCPAINT (long wParam, long lParam) {
+       return wmNCPaint (handle, wParam, lParam);
+}
+
+LRESULT WM_NOTIFY (long wParam, long lParam) {
+       NMHDR hdr = new NMHDR ();
+       OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+       return wmNotify (hdr, wParam, lParam);
+}
+
+LRESULT WM_PAINT (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+       return wmPaint (handle, wParam, lParam);
+}
+
+LRESULT WM_PARENTNOTIFY (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_PASTE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_PRINT (long wParam, long lParam) {
+       return wmPrint (handle, wParam, lParam);
+}
+
+LRESULT WM_PRINTCLIENT (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_QUERYENDSESSION (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_QUERYOPEN (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_RBUTTONDBLCLK (long wParam, long lParam) {
+       return wmRButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_RBUTTONDOWN (long wParam, long lParam) {
+       return wmRButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_RBUTTONUP (long wParam, long lParam) {
+       return wmRButtonUp (handle, wParam, lParam);
+}
+
+LRESULT WM_SETCURSOR (long wParam, long lParam) {
+       int hitTest = (short) OS.LOWORD (lParam);
+       if (hitTest == OS.HTCLIENT) {
+               Control control = display.getControl (wParam);
+               if (control == null) return null;
+               Cursor cursor = control.findCursor ();
+               if (cursor != null) {
+                       OS.SetCursor (cursor.handle);
+                       return LRESULT.ONE;
+               }
+       }
+       return null;
+}
+
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       return wmSetFocus (handle, wParam, lParam);
+}
+
+LRESULT WM_SETTINGCHANGE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_SETFONT (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_SETREDRAW (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_SHOWWINDOW (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_SIZE (long wParam, long lParam) {
+       state |= RESIZE_OCCURRED;
+       if ((state & RESIZE_DEFERRED) == 0) sendEvent (SWT.Resize);
+       // widget could be disposed at this point
+       return null;
+}
+
+LRESULT WM_SYSCHAR (long wParam, long lParam) {
+       return wmSysChar (handle, wParam, lParam);
+}
+
+LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_SYSCOMMAND (long wParam, 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) == 0) {
+               Decorations shell = menuShell ();
+               if (shell.isEnabled ()) {
+                       MenuItem item = display.getMenuItem (OS.LOWORD (wParam));
+                       if (item != null) item.wmCommandChild (wParam, lParam);
+               }
+               return LRESULT.ZERO;
+       }
+
+       /* Process the System Command */
+       int cmd = (int)wParam & 0xFFF0;
+       switch (cmd) {
+               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 == 0) {
+                               Decorations shell = menuShell ();
+                               Menu menu = shell.getMenuBar ();
+                               if (menu == null) {
+                                       Control control = display._getFocusControl ();
+                                       if (control != 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 != ' ') {
+                                               Decorations shell = menuShell ();
+                                               Menu menu = shell.getMenuBar ();
+                                               if (menu != null) {
+                                                       char key = (char) lParam;
+                                                       if (key != 0) {
+                                                               key = Character.toUpperCase (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 == 0) {
+                                                                               char ch = text.charAt (0);
+                                                                               if (Character.toUpperCase (ch) == 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;
+       }
+       return null;
+}
+
+LRESULT WM_SYSKEYDOWN (long wParam, long lParam) {
+       return wmSysKeyDown (handle, wParam, lParam);
+}
+
+LRESULT WM_SYSKEYUP (long wParam, long lParam) {
+       return wmSysKeyUp (handle, wParam, lParam);
+}
+
+LRESULT WM_TABLET_FLICK (long wParam, long lParam) {
+       if (!hooks (SWT.Gesture) && !filters (SWT.Gesture)) return null;
+       Event event = new Event ();
+       FLICK_DATA fData = new FLICK_DATA ();
+       long [] source = new long [1];
+       source[0] = wParam;
+       OS.MoveMemory (fData, source, OS.FLICK_DATA_sizeof ());
+       FLICK_POINT fPoint = new FLICK_POINT ();
+       source [0] = lParam;
+       OS.MoveMemory (fPoint, source, OS.FLICK_POINT_sizeof ());
+
+       switch (fData.iFlickDirection) {
+               case OS.FLICKDIRECTION_RIGHT:
+                       event.xDirection = 1;
+                       event.yDirection = 0;
+                       break;
+               case OS.FLICKDIRECTION_UPRIGHT:
+                       event.xDirection = 1;
+                       event.yDirection = -1;
+                       break;
+               case OS.FLICKDIRECTION_UP:
+                       event.xDirection = 0;
+                       event.yDirection = -1;
+                       break;
+               case OS.FLICKDIRECTION_UPLEFT:
+                       event.xDirection = -1;
+                       event.yDirection = -1;
+                       break;
+               case OS.FLICKDIRECTION_LEFT:
+                       event.xDirection = -1;
+                       event.yDirection = 0;
+                       break;
+               case OS.FLICKDIRECTION_DOWNLEFT:
+                       event.xDirection = -1;
+                       event.yDirection = 1;
+                       break;
+               case OS.FLICKDIRECTION_DOWN:
+                       event.xDirection = 0;
+                       event.yDirection = 1;
+                       break;
+               case OS.FLICKDIRECTION_DOWNRIGHT:
+                       event.xDirection = 1;
+                       event.yDirection = 1;
+                       break;
+       }
+       event.setLocationInPixels(fPoint.x, fPoint.y);
+       event.type = SWT.Gesture;
+       event.detail = SWT.GESTURE_SWIPE;
+       setInputState (event, SWT.Gesture);
+       sendEvent (SWT.Gesture, event);
+       return event.doit ? null : LRESULT.ONE;
+}
+
+LRESULT WM_TOUCH (long wParam, long lParam) {
+       LRESULT result = null;
+       if (hooks (SWT.Touch) || filters (SWT.Touch)) {
+               int cInputs = OS.LOWORD (wParam);
+               long hHeap = OS.GetProcessHeap ();
+               long pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY,  cInputs * TOUCHINPUT.sizeof);
+               if (pInputs != 0) {
+                       if (OS.GetTouchInputInfo (lParam, cInputs, pInputs, TOUCHINPUT.sizeof)) {
+                               TOUCHINPUT ti [] = new TOUCHINPUT [cInputs];
+                               for (int i = 0; i < cInputs; i++){
+                                       ti [i] = new TOUCHINPUT ();
+                                       OS.MoveMemory (ti [i], pInputs + i * TOUCHINPUT.sizeof, TOUCHINPUT.sizeof);
+                               }
+                               sendTouchEvent (ti);
+                               OS.CloseTouchInputHandle (lParam);
+                               result = LRESULT.ZERO;
+                       }
+                       OS.HeapFree (hHeap, 0, pInputs);
+               }
+       }
+       return result;
+}
+
+LRESULT WM_TIMER (long wParam, long lParam) {
+       if (wParam == Menu.ID_TOOLTIP_TIMER && activeMenu != null) {
+               OS.KillTimer (this.handle, Menu.ID_TOOLTIP_TIMER);
+               activeMenu.wmTimer (wParam, lParam);
+       }
+       return null;
+}
+
+LRESULT WM_UNDO (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT WM_VSCROLL (long wParam, long lParam) {
+       Control control = display.getControl (lParam);
+       if (control == null) return null;
+       return control.wmScrollChild (wParam, lParam);
+}
+
+LRESULT WM_WINDOWPOSCHANGED (long wParam, long lParam) {
+       try {
+               display.resizeCount++;
+               long code = callWindowProc (handle, OS.WM_WINDOWPOSCHANGED, wParam, lParam);
+               return code == 0 ? LRESULT.ZERO : new LRESULT (code);
+       } finally {
+               --display.resizeCount;
+       }
+}
+
+LRESULT WM_WINDOWPOSCHANGING (long wParam, 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 (!getDrawing()) {
+               Shell shell = getShell ();
+               if (shell != this) {
+                       WINDOWPOS lpwp = new WINDOWPOS ();
+                       OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+                       if ((lpwp.flags & OS.SWP_NOMOVE) == 0 || (lpwp.flags & OS.SWP_NOSIZE) == 0) {
+                               RECT rect = new RECT ();
+                               OS.GetWindowRect (topHandle (), rect);
+                               int width = rect.right - rect.left;
+                               int height = rect.bottom - rect.top;
+                               if (width != 0 && height != 0) {
+                                       long hwndParent = parent == null ? 0 : parent.handle;
+                                       OS.MapWindowPoints (0, hwndParent, rect, 2);
+                                       long rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+                                       long 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 (long wParam, long lParam) {
+       return wmXButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_XBUTTONDOWN (long wParam, long lParam) {
+       return wmXButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_XBUTTONUP (long wParam, long lParam) {
+       return wmXButtonUp (handle, wParam, lParam);
+}
+
+LRESULT wmColorChild (long wParam, long lParam) {
+       Control control = findBackgroundControl ();
+       if (control == null) {
+               if ((state & THEME_BACKGROUND) != 0) {
+                       if (OS.IsAppThemed ()) {
+                               control = findThemeControl ();
+                               if (control != null) {
+                                       RECT rect = new RECT ();
+                                       OS.GetClientRect (handle, rect);
+                                       OS.SetTextColor (wParam, getForegroundPixel ());
+                                       OS.SetBkColor (wParam, getBackgroundPixel ());
+                                       fillThemeBackground (wParam, control, rect);
+                                       OS.SetBkMode (wParam, OS.TRANSPARENT);
+                                       return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
+                               }
+                       }
+               }
+               if (foreground == -1) return null;
+       }
+       if (control == null) control = this;
+       int forePixel = getForegroundPixel ();
+       int backPixel = control.getBackgroundPixel ();
+       OS.SetTextColor (wParam, forePixel);
+       OS.SetBkColor (wParam, backPixel);
+       if (control.backgroundImage != null) {
+               RECT rect = new RECT ();
+               OS.GetClientRect (handle, rect);
+               long hwnd = control.handle;
+               long hBitmap = control.backgroundImage.handle;
+               OS.MapWindowPoints (handle, hwnd, rect, 2);
+               POINT lpPoint = new POINT ();
+               OS.GetWindowOrgEx (wParam, lpPoint);
+               OS.SetBrushOrgEx (wParam, -rect.left - lpPoint.x, -rect.top - lpPoint.y, lpPoint);
+               long hBrush = findBrush (hBitmap, OS.BS_PATTERN);
+               if ((state & DRAW_BACKGROUND) != 0) {
+                       long hOldBrush = OS.SelectObject (wParam, hBrush);
+                       OS.MapWindowPoints (hwnd, handle, rect, 2);
+                       OS.PatBlt (wParam, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+                       OS.SelectObject (wParam, hOldBrush);
+               }
+               OS.SetBkMode (wParam, OS.TRANSPARENT);
+               return new LRESULT (hBrush);
+       }
+       long hBrush = findBrush (backPixel, OS.BS_SOLID);
+       if ((state & DRAW_BACKGROUND) != 0) {
+               RECT rect = new RECT ();
+               OS.GetClientRect (handle, rect);
+               long hOldBrush = OS.SelectObject (wParam, hBrush);
+               OS.PatBlt (wParam, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+               OS.SelectObject (wParam, hOldBrush);
+       }
+       return new LRESULT (hBrush);
+}
+
+LRESULT wmCommandChild (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT wmDrawChild (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT wmMeasureChild (long wParam, long lParam) {
+       return null;
+}
+
+LRESULT wmNotify (NMHDR hdr, long wParam, long lParam) {
+       Control control = display.getControl (hdr.hwndFrom);
+       if (control == null) return null;
+       return control.wmNotifyChild (hdr, wParam, lParam);
+}
+
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       return null;
+}
+
+LRESULT wmScrollChild (long wParam, long lParam) {
+       return null;
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/CoolBar.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/CoolBar.java
new file mode 100644 (file)
index 0000000..5afbbde
--- /dev/null
@@ -0,0 +1,1210 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>FLAT, HORIZONTAL, VERTICAL</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/#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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class CoolBar extends Composite {
+       CoolItem [] items;
+       CoolItem [] originalItems;
+       boolean locked;
+       boolean ignoreResize;
+       static final long ReBarProc;
+       static final TCHAR ReBarClass = new TCHAR (0, OS.REBARCLASSNAME, true);
+       static {
+               INITCOMMONCONTROLSEX icex = new INITCOMMONCONTROLSEX ();
+               icex.dwSize = INITCOMMONCONTROLSEX.sizeof;
+               icex.dwICC = OS.ICC_COOL_CLASSES;
+               OS.InitCommonControlsEx (icex);
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ReBarClass, lpWndClass);
+               ReBarProc = lpWndClass.lpfnWndProc;
+       }
+       static final int SEPARATOR_WIDTH = 2;
+       static final int MAX_WIDTH = 0x7FFF;
+       static final int DEFAULT_COOLBAR_WIDTH = 0;
+       static final 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 SWT#FLAT
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolBar (Composite parent, int style) {
+       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) != 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
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       int width = 0, height = 0;
+       int border = getBorderWidthInPixels ();
+       int newWidth = wHint == SWT.DEFAULT ? 0x3FFF : wHint + (border * 2);
+       int newHeight = hHint == SWT.DEFAULT ? 0x3FFF : hHint + (border * 2);
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (count != 0) {
+               ignoreResize = true;
+               boolean redraw = false;
+               if (OS.IsWindowVisible (handle)) {
+                       redraw = true;
+                       OS.UpdateWindow (handle);
+                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+               }
+               RECT oldRect = new RECT ();
+               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;
+               OS.SetWindowPos (handle, 0, 0, 0, newWidth, newHeight, flags);
+               RECT rect = new RECT ();
+               OS.SendMessage (handle, OS.RB_GETRECT, count - 1, rect);
+               height = Math.max (height, rect.bottom);
+               OS.SetWindowPos (handle, 0, 0, 0, oldWidth, oldHeight, flags);
+               REBARBANDINFO rbBand = new REBARBANDINFO ();
+               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) != 0) {
+                               width = Math.max(width, rowWidth);
+                               rowWidth = 0;
+                       }
+                       rowWidth += rbBand.cxIdeal + getMargin (i);
+               }
+               width = Math.max(width, rowWidth);
+               if (redraw) {
+                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+               }
+               ignoreResize = false;
+       }
+       if (width == 0) width = DEFAULT_COOLBAR_WIDTH;
+       if (height == 0) height = DEFAULT_COOLBAR_HEIGHT;
+       if ((style & SWT.VERTICAL) != 0) {
+               int tmp = width;
+               width = height;
+               height = tmp;
+       }
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != 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.
+       */
+       long hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+       OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+}
+
+void createItem (CoolItem item, int index) {
+       int count = (int)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] != null) id++;
+       if (id == items.length) {
+               CoolItem [] newItems = new CoolItem [items.length + 4];
+               System.arraycopy (items, 0, newItems, 0, items.length);
+               items = newItems;
+       }
+       long hHeap = OS.GetProcessHeap ();
+       long lpText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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) != 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);
+       boolean fixLast = index == 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 == 0 && count > 0) {
+               getItem (0).setWrap (false);
+       }
+
+       /* Insert the item */
+       if (OS.SendMessage (handle, OS.RB_INSERTBAND, index, rbBand) == 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 = (int)OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (count != 0) {
+               int lastIndex = getLastIndexOfRow (index);
+               if (index == 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;
+       boolean wasVisible = control != 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) == 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] == 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 (long hDC, long hwnd, RECT rect) {
+       if (OS.IsAppThemed ()) {
+               if (background == -1 && (style & SWT.FLAT) != 0) {
+                       Control control = findBackgroundControl ();
+                       if (control != null && control.backgroundImage != null) {
+                               fillBackground (hDC, control.getBackgroundPixel (), rect);
+                               return;
+                       }
+               }
+       }
+       RECT rect2 = new RECT ();
+       OS.GetClientRect (handle, rect2);
+       OS.MapWindowPoints (handle, hwnd, rect2, 2);
+       POINT lpPoint = new POINT ();
+       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) != 0) return this;
+       return background == -1 && backgroundImage == null ? this : super.findThemeControl ();
+}
+
+int getMargin (int index) {
+       int margin = 0;
+       MARGINS margins = new MARGINS ();
+       OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, margins);
+       margin += margins.cxLeftWidth + margins.cxRightWidth;
+       RECT rect = new RECT ();
+       OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, rect);
+       if ((style & SWT.FLAT) != 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) != 0) {
+                       margin += rect.top + 4;
+               } else {
+                       margin += rect.left + 4;
+               }
+       } else {
+               if ((style & SWT.VERTICAL) != 0) {
+                       margin += rect.top + rect.bottom;
+               } else {
+                       margin += rect.left + rect.right;
+               }
+       }
+       if ((style & SWT.FLAT) == 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 = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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 (int)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 = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       int [] indices = new int [count];
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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] == item) break;
+                       index++;
+               }
+               if (index == 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 = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       CoolItem [] result = new CoolItem [count];
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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 ();
+       Point [] sizes = getItemSizesInPixels();
+       if (sizes != null) {
+               for (int i = 0; i < sizes.length; i++) {
+                       sizes[i] = DPIUtil.autoScaleDown(sizes[i]);
+               }
+       }
+       return sizes;
+}
+
+Point [] getItemSizesInPixels () {
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       Point [] sizes = new Point [count];
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       rbBand.cbSize = REBARBANDINFO.sizeof;
+       rbBand.fMask = OS.RBBIM_CHILDSIZE;
+       int separator = (style & SWT.FLAT) == 0 ? SEPARATOR_WIDTH : 0;
+       MARGINS margins = new MARGINS ();
+       for (int i=0; i<count; i++) {
+               RECT rect = new RECT ();
+               OS.SendMessage (handle, OS.RB_GETRECT, i, rect);
+               OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
+               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) != 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 = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (count == 0) return -1;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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) != 0) {
+                       return i - 1;
+               }
+       }
+       return count - 1;
+}
+
+boolean isLastItemOfRow (int index) {
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (index + 1 == count) return true;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       rbBand.cbSize = REBARBANDINFO.sizeof;
+       rbBand.fMask = OS.RBBIM_STYLE;
+       OS.SendMessage (handle, OS.RB_GETBANDINFO, index + 1, rbBand);
+       return (rbBand.fStyle & OS.RBBS_BREAK) != 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 boolean 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+       return (int)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 = (int)OS.SendMessage(handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (0 <= index && index < count) {
+               REBARBANDINFO rbBand = new REBARBANDINFO();
+               rbBand.cbSize = REBARBANDINFO.sizeof;
+               rbBand.fMask = OS.RBBIM_IDEALSIZE;
+               OS.SendMessage (handle, OS.RB_GETBANDINFO, index, rbBand);
+               RECT rect = new RECT ();
+               OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, rect);
+               rbBand.cx = rbBand.cxIdeal + rect.left;
+               if ((style & SWT.FLAT) == 0) rbBand.cx += rect.right;
+               rbBand.fMask = OS.RBBIM_SIZE;
+               OS.SendMessage (handle, OS.RB_SETBANDINFO, index, rbBand);
+       }
+}
+
+void resizeToMaximumWidth (int index) {
+       REBARBANDINFO rbBand = new REBARBANDINFO();
+       rbBand.cbSize = REBARBANDINFO.sizeof;
+       rbBand.fMask = OS.RBBIM_SIZE;
+       rbBand.cx = MAX_WIDTH;
+       OS.SendMessage (handle, OS.RB_SETBANDINFO, index, rbBand);
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       CoolItem item = items [i];
+                       if (item != 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 != null && item.control == control) {
+                       item.setControl (null);
+               }
+       }
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       CoolItem item = items [i];
+                       if (item != null) item.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+@Override
+void setBackgroundPixel (int pixel) {
+       if (pixel == -1) pixel = defaultBackground ();
+       OS.SendMessage (handle, OS.RB_SETBKCOLOR, 0, pixel);
+       setItemColors ((int)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;
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+@Override
+void setForegroundPixel (int pixel) {
+       if (pixel == -1) pixel = defaultForeground ();
+       OS.SendMessage (handle, OS.RB_SETTEXTCOLOR, 0, pixel);
+       setItemColors (pixel, (int)OS.SendMessage (handle, OS.RB_GETBKCOLOR, 0, 0));
+}
+
+void setItemColors (int foreColor, int backColor) {
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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_NULL_ARGUMENT - if item order or sizes is null</li>
+ *    <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 ();
+       if (sizes == null) error (SWT.ERROR_NULL_ARGUMENT);
+       Point [] sizesInPoints = new Point [sizes.length];
+       for (int i = 0; i < sizes.length; i++) {
+               sizesInPoints[i] = DPIUtil.autoScaleUp(sizes[i]);
+       }
+       setItemLayoutInPixels (itemOrder, wrapIndices, sizesInPoints);
+}
+
+void setItemLayoutInPixels (int [] itemOrder, int [] wrapIndices, Point [] sizes) {
+       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_NULL_ARGUMENT - if the item order is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ */
+void setItemOrder (int [] itemOrder) {
+       if (itemOrder == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int itemCount = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (itemOrder.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
+
+       /* Ensure that itemOrder does not contain any duplicates. */
+       boolean [] set = new boolean [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 = new REBARBANDINFO ();
+       rbBand.cbSize = REBARBANDINFO.sizeof;
+       for (int i=0; i<itemOrder.length; i++) {
+               int id = originalItems [itemOrder [i]].id;
+               int index = (int)OS.SendMessage (handle, OS.RB_IDTOINDEX, id, 0);
+               if (index != i) {
+                       int lastItemSrcRow = getLastIndexOfRow (index);
+                       int lastItemDstRow = getLastIndexOfRow (i);
+                       if (index == lastItemSrcRow) {
+                               resizeToPreferredWidth (index);
+                       }
+                       if (i == lastItemDstRow) {
+                               resizeToPreferredWidth (i);
+                       }
+
+                       /* Move the item */
+                       OS.SendMessage (handle, OS.RB_MOVEBAND, index, i);
+
+                       if (index == lastItemSrcRow && index - 1 >= 0) {
+                               resizeToMaximumWidth (index - 1);
+                       }
+                       if (i == 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) {
+       if (sizes == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       if (sizes.length != count) error (SWT.ERROR_INVALID_ARGUMENT);
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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].setSizeInPixels (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 (boolean locked) {
+       checkWidget ();
+       this.locked = locked;
+       int count = (int)OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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 == 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) == 0) bits |= OS.RBS_BANDBORDERS;
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return ReBarClass;
+}
+
+@Override
+long windowProc () {
+       return ReBarProc;
+}
+
+@Override
+LRESULT WM_COMMAND (long wParam, long 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 != null) return result;
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long 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.IsAppThemed ()) {
+               drawBackground (wParam);
+               return null;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_NOTIFY (long wParam, long 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 != null) return result;
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_SETREDRAW (long wParam, long lParam) {
+       LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+       if (result != 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.
+       */
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       if (ignoreResize) {
+               long code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+               if (code == 0) return LRESULT.ZERO;
+               return new LRESULT (code);
+       }
+       //TEMPORARY CODE
+//     if (OS.IsAppThemed ()) {
+//             if (background == -1 && (style & SWT.FLAT) == 0) {
+//                     OS.InvalidateRect (handle, null, true);
+//             }
+//     }
+       return super.WM_SIZE (wParam, lParam);
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.RBN_BEGINDRAG: {
+                       int pos = OS.GetMessagePos ();
+                       POINT pt = new POINT ();
+                       OS.POINTSTOPOINT (pt, pos);
+                       OS.ScreenToClient (handle, pt);
+                       int button = display.lastButton != 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  = new NMREBARCHILDSIZE ();
+                       OS.MoveMemory (lprbcs, lParam, NMREBARCHILDSIZE.sizeof);
+                       if (lprbcs.uBand != -1) {
+                               CoolItem item = items [lprbcs.wID];
+                               Control control = item.control;
+                               if (control != null) {
+                                       int width = lprbcs.rcChild_right - lprbcs.rcChild_left;
+                                       int height = lprbcs.rcChild_bottom - lprbcs.rcChild_top;
+                                       control.setBoundsInPixels (lprbcs.rcChild_left, lprbcs.rcChild_top, width, height);
+                               }
+                       }
+                       break;
+               }
+               case OS.RBN_HEIGHTCHANGE: {
+                       if (!ignoreResize) {
+                               Point size = getSizeInPixels ();
+                               int border = getBorderWidthInPixels ();
+                               int barHeight = (int)OS.SendMessage (handle, OS.RB_GETBARHEIGHT, 0, 0);
+                               if ((style & SWT.VERTICAL) != 0) {
+                                       setSizeInPixels (barHeight + 2 * border, size.y);
+                               } else {
+                                       setSizeInPixels (size.x, barHeight + 2 * border);
+                               }
+                       }
+                       break;
+               }
+               case OS.RBN_CHEVRONPUSHED: {
+                       NMREBARCHEVRON lpnm = new NMREBARCHEVRON ();
+                       OS.MoveMemory (lpnm, lParam, NMREBARCHEVRON.sizeof);
+                       CoolItem item = items [lpnm.wID];
+                       if (item != null) {
+                               Event event = new Event();
+                               event.detail = SWT.ARROW;
+                               if ((style & SWT.VERTICAL) != 0) {
+                                       event.setLocationInPixels(lpnm.right, lpnm.top);
+                               } else {
+                                       event.setLocationInPixels(lpnm.left, lpnm.bottom);
+                               }
+                               item.sendSelectionEvent(SWT.Selection, event, false);
+                       }
+                       break;
+               }
+               case OS.NM_CUSTOMDRAW: {
+                       if (findBackgroundControl () != null || (style & SWT.FLAT) != 0) {
+                               NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
+                               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;
+                               }
+                       }
+                       break;
+               }
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/CoolItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/CoolItem.java
new file mode 100644 (file)
index 0000000..961b177
--- /dev/null
@@ -0,0 +1,754 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class CoolItem extends Item {
+       CoolBar parent;
+       Control control;
+       int id;
+       boolean 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 CoolItem (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 CoolItem (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 == 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 ();
+       wHint = (wHint != SWT.DEFAULT ? DPIUtil.autoScaleUp(wHint) : wHint);
+       hHint = (hHint != SWT.DEFAULT ? DPIUtil.autoScaleUp(hHint) : hHint);
+       return DPIUtil.autoScaleDown(computeSizeInPixels(wHint, hHint));
+}
+Point computeSizeInPixels (int wHint, int hHint) {
+       int index = parent.indexOf (this);
+       if (index == -1) return new Point (0, 0);
+       int width = wHint, height = hHint;
+       if (wHint == SWT.DEFAULT) width = 32;
+       if (hHint == SWT.DEFAULT) height = 32;
+       if ((parent.style & SWT.VERTICAL) != 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 ();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels () {
+       int index = parent.indexOf (this);
+       if (index == -1) return new Rectangle (0, 0, 0, 0);
+       long hwnd = parent.handle;
+       RECT rect = new RECT ();
+       OS.SendMessage (hwnd, OS.RB_GETRECT, index, rect);
+       MARGINS margins = new 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) == 0 ? CoolBar.SEPARATOR_WIDTH : 0;
+       }
+       int width = rect.right - rect.left;
+       int height = rect.bottom - rect.top;
+       if ((parent.style & SWT.VERTICAL) != 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 == -1) return new Rectangle (0, 0, 0, 0);
+       long hwnd = parent.handle;
+       RECT insetRect = new RECT ();
+       OS.SendMessage (hwnd, OS.RB_GETBANDBORDERS, index, insetRect);
+       RECT rect = new 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) == 0) {
+               y += insetRect.top;
+               width -= insetRect.right;
+               height -= insetRect.top + insetRect.bottom;
+       }
+       if (index == 0) {
+               REBARBANDINFO rbBand = new REBARBANDINFO ();
+               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 != null) {
+               if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+       }
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       if (this.control != null && this.control.isDisposed ()) {
+               this.control = null;
+       }
+       Control oldControl = this.control, newControl = control;
+       long hwnd = parent.handle;
+       long hwndChild = newControl != null ? control.topHandle () : 0;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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.
+       */
+       long hwndAbove = 0;
+       if (newControl != null) {
+               hwndAbove = OS.GetWindow (hwndChild, OS.GW_HWNDPREV);
+       }
+       boolean hideNew = newControl != null && !newControl.getVisible ();
+       boolean showOld = oldControl != null && oldControl.getVisible ();
+       OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, rbBand);
+       if (hideNew) newControl.setVisible (false);
+       if (showOld) oldControl.setVisible (true);
+       if (hwndAbove != 0 && hwndAbove != hwndChild) {
+               int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+               OS.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 ();
+       return DPIUtil.autoScaleDown(getPreferredSizeInPixels());
+}
+
+Point getPreferredSizeInPixels () {
+       int index = parent.indexOf (this);
+       if (index == -1) return new Point (0, 0);
+       long hwnd = parent.handle;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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) != 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 ();
+       setPreferredSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void setPreferredSizeInPixels (int width, int height) {
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       width = Math.max (0, width);
+       height = Math.max (0, height);
+       ideal = true;
+       long hwnd = parent.handle;
+       int cxIdeal, cyMaxChild;
+       if ((parent.style & SWT.VERTICAL) != 0) {
+               cxIdeal = Math.max (0, height - parent.getMargin (index));
+               cyMaxChild = width;
+       } else {
+               cxIdeal = Math.max (0, width - parent.getMargin (index));
+               cyMaxChild = height;
+       }
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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 == null) error(SWT.ERROR_NULL_ARGUMENT);
+       size = DPIUtil.autoScaleUp(size);
+       setPreferredSizeInPixels(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 ();
+       return DPIUtil.autoScaleDown(getSizeInPixels());
+}
+
+Point getSizeInPixels() {
+       int index = parent.indexOf (this);
+       if (index == -1) new Point (0, 0);
+       long hwnd = parent.handle;
+       RECT rect = new RECT ();
+       OS.SendMessage (hwnd, OS.RB_GETRECT, index, rect);
+       MARGINS margins = new 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) == 0 ? CoolBar.SEPARATOR_WIDTH : 0;
+       }
+       int width = rect.right - rect.left;
+       int height = rect.bottom - rect.top;
+       if ((parent.style & SWT.VERTICAL) != 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 ();
+       setSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void setSizeInPixels (int width, int height) {
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       width = Math.max (0, width);
+       height = Math.max (0, height);
+       long hwnd = parent.handle;
+       int cx, cyChild, cxIdeal;
+       if ((parent.style & SWT.VERTICAL) != 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 = new REBARBANDINFO ();
+       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)) {
+               MARGINS margins = new MARGINS ();
+               OS.SendMessage (hwnd, OS.RB_GETBANDMARGINS, 0, margins);
+               cx -= margins.cxLeftWidth + margins.cxRightWidth;
+               int separator = (parent.style & SWT.FLAT) == 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) {
+       checkWidget ();
+       if (size == null) error(SWT.ERROR_NULL_ARGUMENT);
+       size = DPIUtil.autoScaleUp(size);
+       setSizeInPixels(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 SWT logical points
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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 ();
+       return DPIUtil.autoScaleDown(getMinimumSizeInPixels());
+}
+
+Point getMinimumSizeInPixels () {
+       int index = parent.indexOf (this);
+       if (index == -1) return new Point (0, 0);
+       long hwnd = parent.handle;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       rbBand.cbSize = REBARBANDINFO.sizeof;
+       rbBand.fMask = OS.RBBIM_CHILDSIZE;
+       OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand);
+       if ((parent.style & SWT.VERTICAL) != 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 SWT logical points
+ * @param height the minimum height of the cool item, in SWT logical points
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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 ();
+       setMinimumSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void setMinimumSizeInPixels (int width, int height) {
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       width = Math.max (0, width);
+       height = Math.max (0, height);
+       minimum = true;
+       long hwnd = parent.handle;
+       int cxMinChild, cyMinChild;
+       if ((parent.style & SWT.VERTICAL) != 0) {
+               cxMinChild = height;
+               cyMinChild = width;
+       } else {
+               cxMinChild = width;
+               cyMinChild = height;
+       }
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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 SWT logical points
+ *
+ * @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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       size = DPIUtil.autoScaleUp(size);
+       setMinimumSizeInPixels(size.x, size.y);
+}
+
+boolean getWrap() {
+       int index = parent.indexOf (this);
+       long hwnd = parent.handle;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       rbBand.cbSize = REBARBANDINFO.sizeof;
+       rbBand.fMask = OS.RBBIM_STYLE;
+       OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand);
+       return (rbBand.fStyle & OS.RBBS_BREAK) != 0;
+}
+
+void setWrap(boolean wrap) {
+       int index = parent.indexOf (this);
+       long hwnd = parent.handle;
+       REBARBANDINFO rbBand = new REBARBANDINFO ();
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/DateTime.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/DateTime.java
new file mode 100644 (file)
index 0000000..512ab51
--- /dev/null
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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, DROP_DOWN, CALENDAR_WEEKNUMBERS</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, 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.
+ * The DROP_DOWN style is only valid with the DATE style.
+ * </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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class DateTime extends Composite {
+       static final int MIN_YEAR = 1752; // Gregorian switchover in North America: September 19, 1752
+       static final int MAX_YEAR = 9999;
+       boolean doubleClick, ignoreSelection;
+       SYSTEMTIME lastSystemTime;
+       SYSTEMTIME time = new SYSTEMTIME (); // only used in calendar mode
+       static final long DateTimeProc;
+       static final TCHAR DateTimeClass = new TCHAR (0, OS.DATETIMEPICK_CLASS, true);
+       static final long CalendarProc;
+       static final TCHAR CalendarClass = new TCHAR (0, OS.MONTHCAL_CLASS, true);
+       static {
+               INITCOMMONCONTROLSEX icex = new INITCOMMONCONTROLSEX ();
+               icex.dwSize = INITCOMMONCONTROLSEX.sizeof;
+               icex.dwICC = OS.ICC_DATE_CLASSES;
+               OS.InitCommonControlsEx (icex);
+       }
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, DateTimeClass, 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.
+               */
+               lpWndClass.hInstance = OS.GetModuleHandle (null);
+               lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+               lpWndClass.style |= OS.CS_DBLCLKS;
+               OS.RegisterClass (DateTimeClass, lpWndClass);
+       }
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, CalendarClass, 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.
+               */
+               lpWndClass.hInstance = OS.GetModuleHandle (null);;
+               lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+               lpWndClass.style |= OS.CS_DBLCLKS;
+               OS.RegisterClass (CalendarClass, lpWndClass);
+       }
+       static final char SINGLE_QUOTE = '\''; //$NON-NLS-1$ short date format may include quoted text
+       static final char DAY_FORMAT_CONSTANT = 'd'; //$NON-NLS-1$ 1-4 lowercase 'd's represent day
+       static final char MONTH_FORMAT_CONSTANT = 'M'; //$NON-NLS-1$ 1-4 uppercase 'M's represent month
+       static final char YEAR_FORMAT_CONSTANT = 'y'; //$NON-NLS-1$ 1-5 lowercase 'y's represent year
+       static final char HOURS_FORMAT_CONSTANT = 'h'; //$NON-NLS-1$ 1-2 upper or lowercase 'h's represent hours
+       static final char MINUTES_FORMAT_CONSTANT = 'm'; //$NON-NLS-1$ 1-2 lowercase 'm's represent minutes
+       static final char SECONDS_FORMAT_CONSTANT = 's'; //$NON-NLS-1$ 1-2 lowercase 's's represent seconds
+       static final char AMPM_FORMAT_CONSTANT = 't'; //$NON-NLS-1$ 1-2 lowercase 't's represent am/pm
+
+
+/**
+ * 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 SWT#CALENDAR_WEEKNUMBERS
+ * @see SWT#SHORT
+ * @see SWT#MEDIUM
+ * @see SWT#LONG
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public DateTime (Composite parent, int style) {
+       super (parent, checkStyle (style));
+       if ((this.style & SWT.SHORT) != 0) {
+               String buffer = ((this.style & SWT.DATE) != 0) ? getCustomShortDateFormat() : getCustomShortTimeFormat();
+               TCHAR lpszFormat = new TCHAR (0, buffer, true);
+               OS.SendMessage (handle, OS.DTM_SETFORMAT, 0, lpszFormat);
+       }
+}
+
+/**
+ * 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 typically called when ENTER is pressed.
+ * </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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection, typedListener);
+       addListener (SWT.DefaultSelection, typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       return OS.CallWindowProc (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);
+       style = checkBits (style, SWT.MEDIUM, SWT.SHORT, SWT.LONG, 0, 0, 0);
+       if ((style & SWT.DATE) == 0) style &=~ SWT.DROP_DOWN;
+       return style;
+}
+
+@Override
+protected void checkSubclass () {
+       if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width = 0, height = 0;
+       if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+               if ((style & SWT.CALENDAR) != 0) {
+                       RECT rect = new RECT ();
+                       OS.SendMessage(handle, OS.MCM_GETMINREQRECT, 0, rect);
+                       width = rect.right;
+                       height = rect.bottom;
+               } else {
+                       // customize the style of the drop-down calendar, to get the correct size
+                       if ((style & SWT.CALENDAR_WEEKNUMBERS) != 0) {
+                               // get current style and add week numbers to the calendar drop-down
+                               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                               OS.SendMessage(handle, OS.DTM_SETMCSTYLE, 0, bits | OS.MCS_WEEKNUMBERS);
+                       }
+                       SIZE size = new SIZE ();
+                       OS.SendMessage(handle, OS.DTM_GETIDEALSIZE, 0, size);
+                       width = size.cx;
+                       height = size.cy;
+                       // TODO: Can maybe use DTM_GETDATETIMEPICKERINFO for this
+                       int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL) + 7;
+                       height = Math.max (height, upDownHeight);
+               }
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int border = getBorderWidthInPixels ();
+       width += border * 2;
+       height += border * 2;
+       return new Point (width, height);
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       state &= ~(CANVAS | THEME_BACKGROUND);
+
+       if ((style & SWT.BORDER) == 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 getCustomShortDateFormat () {
+       TCHAR tchar = new TCHAR (getCodePage (), 80);
+       int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SYEARMONTH, tchar, 80);
+       return size != 0 ? tchar.toString (0, size - 1) : "M/yyyy"; //$NON-NLS-1$
+}
+
+String getCustomShortTimeFormat () {
+       StringBuilder buffer = new StringBuilder (getTimeFormat ());
+       int length = buffer.length ();
+       boolean inQuotes = false;
+       int start = 0, end = 0;
+       while (start < length) {
+               char ch = buffer.charAt (start);
+               if (ch == SINGLE_QUOTE) inQuotes = !inQuotes;
+               else if (ch == SECONDS_FORMAT_CONSTANT && !inQuotes) {
+                       end = start + 1;
+                       while (end < length && buffer.charAt (end) == SECONDS_FORMAT_CONSTANT) end++;
+                       // skip the preceding separator
+                       while (start > 0 && buffer.charAt (start) != MINUTES_FORMAT_CONSTANT) start--;
+                       start++;
+                       break;
+               }
+               start++;
+       }
+       if (start < end) buffer.delete (start, end);
+       return buffer.toString ();
+}
+
+String getTimeFormat () {
+       TCHAR tchar = new TCHAR (getCodePage (), 80);
+       int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_STIMEFORMAT, tchar, 80);
+       return size > 0 ? tchar.toString (0, size - 1) : "h:mm:ss tt"; //$NON-NLS-1$
+}
+
+/**
+ * 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 = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 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) != 0) return time.wHour;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 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) != 0) return time.wMinute;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 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 = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       return systime.wMonth - 1;
+}
+
+@Override
+String getNameText() {
+       return (style & SWT.TIME) != 0 ? getHours() + ":" + getMinutes() + ":" + getSeconds()
+                       : (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) != 0) return time.wSecond;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 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 = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       return systime.wYear;
+}
+
+@Override
+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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 ();
+       if (year < MIN_YEAR || year > MAX_YEAR) return;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wYear = (short)year;
+       systime.wMonth = (short)(month + 1);
+       systime.wDay = (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.
+ * If the specified day is not valid for the receiver's month and year, then it is ignored.
+ * </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>
+ *
+ * @see #setDate
+ */
+public void setDay (int day) {
+       checkWidget ();
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wDay = (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 ();
+       if (hours < 0 || hours > 23) return;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wHour = (short)hours;
+       OS.SendMessage (handle, msg, 0, systime);
+       if ((style & SWT.CALENDAR) != 0 && hours >= 0 && hours <= 23) time.wHour = (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 ();
+       if (minutes < 0 || minutes > 59) return;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wMinute = (short)minutes;
+       OS.SendMessage (handle, msg, 0, systime);
+       if ((style & SWT.CALENDAR) != 0 && minutes >= 0 && minutes <= 59) time.wMinute = (short)minutes;
+}
+
+/**
+ * Sets the receiver's month.
+ * <p>
+ * The first month of the year is 0, and the last month is 11.
+ * If the specified month is not valid for the receiver's day and year, then it is ignored.
+ * </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>
+ *
+ * @see #setDate
+ */
+public void setMonth (int month) {
+       checkWidget ();
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wMonth = (short)(month + 1);
+       OS.SendMessage (handle, msg, 0, systime);
+       lastSystemTime = null;
+}
+
+@Override
+public void setOrientation (int orientation) {
+       /* Currently supported only for CALENDAR style. */
+       if ((style & SWT.CALENDAR) != 0) super.setOrientation (orientation);
+}
+/**
+ * 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 ();
+       if (seconds < 0 || seconds > 59) return;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wSecond = (short)seconds;
+       OS.SendMessage (handle, msg, 0, systime);
+       if ((style & SWT.CALENDAR) != 0 && seconds >= 0 && seconds <= 59) time.wSecond = (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 ();
+       if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59) return;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wHour = (short)hours;
+       systime.wMinute = (short)minutes;
+       systime.wSecond = (short)seconds;
+       OS.SendMessage (handle, msg, 0, systime);
+       if ((style & SWT.CALENDAR) != 0
+                       && hours >= 0 && hours <= 23
+                       && minutes >= 0 && minutes <= 59
+                       && seconds >= 0 && seconds <= 59) {
+               time.wHour = (short)hours;
+               time.wMinute = (short)minutes;
+               time.wSecond = (short)seconds;
+       }
+}
+
+/**
+ * Sets the receiver's year.
+ * <p>
+ * The first year is 1752 and the last year is 9999.
+ * If the specified year is not valid for the receiver's day and month, then it is ignored.
+ * </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>
+ *
+ * @see #setDate
+ */
+public void setYear (int year) {
+       checkWidget ();
+       if (year < MIN_YEAR || year > MAX_YEAR) return;
+       SYSTEMTIME systime = new SYSTEMTIME ();
+       int msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+       OS.SendMessage (handle, msg, 0, systime);
+       msg = (style & SWT.CALENDAR) != 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+       systime.wYear = (short)year;
+       OS.SendMessage (handle, msg, 0, systime);
+       lastSystemTime = null;
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.WS_TABSTOP;
+       if ((style & SWT.CALENDAR_WEEKNUMBERS) != 0) {
+               bits |= OS.MCS_WEEKNUMBERS;
+       }
+       if ((style & SWT.CALENDAR) != 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) != 0) bits |= OS.DTS_TIMEFORMAT;
+       if ((style & SWT.DATE) != 0) {
+               bits |= ((style & SWT.MEDIUM) != 0 ? OS.DTS_SHORTDATECENTURYFORMAT : OS.DTS_LONGDATEFORMAT);
+               if ((style & SWT.DROP_DOWN) == 0) bits |= OS.DTS_UPDOWN;
+       }
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return (style & SWT.CALENDAR) != 0 ? CalendarClass : DateTimeClass;
+}
+
+@Override
+long windowProc () {
+       return (style & SWT.CALENDAR) != 0 ? CalendarProc : DateTimeProc;
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.DTN_CLOSEUP: {
+                       /*
+                       * Feature in Windows.  When the user selects the drop-down button,
+                       * the DateTimePicker runs a modal loop and consumes WM_LBUTTONUP.
+                       * This is done without adding a mouse capture.  Since WM_LBUTTONUP
+                       * is not delivered, the normal mechanism where a mouse capture is
+                       * added on mouse down and removed when the mouse is released
+                       * is broken, leaving an unwanted capture.  The fix is to avoid
+                       * setting capture on mouse down right after WM_LBUTTONUP is consumed.
+                       */
+                       display.captureChanged = true;
+                       break;
+               }
+               case OS.MCN_SELCHANGE: {
+                       if (ignoreSelection) break;
+                       SYSTEMTIME systime = new SYSTEMTIME ();
+                       OS.SendMessage (handle, OS.MCM_GETCURSEL, 0, systime);
+                       sendSelectionEvent (SWT.Selection);
+                       break;
+               }
+               case OS.DTN_DATETIMECHANGE: {
+                       SYSTEMTIME systime = new SYSTEMTIME ();
+                       OS.SendMessage (handle, OS.DTM_GETSYSTEMTIME, 0, systime);
+                       if (lastSystemTime == null || systime.wDay != lastSystemTime.wDay || systime.wMonth != lastSystemTime.wMonth || systime.wYear != lastSystemTime.wYear) {
+                               sendSelectionEvent (SWT.Selection);
+                               if ((style & SWT.TIME) == 0) lastSystemTime = systime;
+                       }
+                       break;
+               }
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != null) return result;
+       /*
+       * Feature in Windows.  For some reason, 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 ((int)wParam) {
+               case SWT.CR:
+                       sendSelectionEvent (SWT.DefaultSelection);
+                       // FALL THROUGH
+               case SWT.TAB:
+               case SWT.ESC: return LRESULT.ZERO;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDBLCLK (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
+       if (isDisposed ()) return LRESULT.ZERO;
+       if ((style & SWT.CALENDAR) != 0) {
+               MCHITTESTINFO pMCHitTest = new MCHITTESTINFO ();
+               pMCHitTest.cbSize = MCHITTESTINFO.sizeof;
+               POINT pt = new POINT ();
+               pt.x = OS.GET_X_LPARAM (lParam);
+               pt.y = OS.GET_Y_LPARAM (lParam);
+               pMCHitTest.pt = pt;
+               long code = OS.SendMessage (handle, OS.MCM_HITTEST, 0, pMCHitTest);
+               if ((code & OS.MCHT_CALENDARDATE) == OS.MCHT_CALENDARDATE) doubleClick = true;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+       doubleClick = false;
+       /*
+       * Feature in Windows. For some reason, the calendar control
+       * does not take focus on WM_LBUTTONDOWN.  The fix is to
+       * explicitly set focus.
+       */
+       if ((style & SWT.CALENDAR) != 0) {
+               if ((style & SWT.NO_FOCUS) == 0) OS.SetFocus (handle);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONUP (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
+       if (isDisposed ()) return LRESULT.ZERO;
+       if (doubleClick) sendSelectionEvent (SWT.DefaultSelection);
+       doubleClick = false;
+       return result;
+}
+
+@Override
+LRESULT WM_TIMER (long wParam, long lParam) {
+       LRESULT result = super.WM_TIMER (wParam, lParam);
+       if (result != 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;
+       long code = callWindowProc(handle, OS.WM_TIMER, wParam, lParam);
+       ignoreSelection = false;
+       return code == 0 ? LRESULT.ZERO : new LRESULT(code);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Decorations.java
new file mode 100644 (file)
index 0000000..9c584ce
--- /dev/null
@@ -0,0 +1,1710 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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:
+ * </p>
+ * <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>
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Decorations extends Canvas {
+       Image image, smallImage, largeImage;
+       Image [] images;
+       Menu menuBar;
+       Menu [] menus;
+       Control savedFocus;
+       Button defaultButton, saveDefault;
+       int swFlags, nAccel;
+       long hAccel;
+       boolean moved, resized, opened;
+       int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT;
+       int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT;
+       RECT maxRect = new RECT();
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Decorations () {
+}
+
+/**
+ * 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#NO_MOVE
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#TOOL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Decorations (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+void _setMaximized (boolean maximized) {
+       swFlags = maximized ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
+       if (!OS.IsWindowVisible (handle)) return;
+       if (maximized == OS.IsZoomed (handle)) return;
+       OS.ShowWindow (handle, swFlags);
+       OS.UpdateWindow (handle);
+}
+
+void _setMinimized (boolean minimized) {
+       swFlags = minimized ? OS.SW_SHOWMINNOACTIVE : OS.SW_RESTORE;
+       if (!OS.IsWindowVisible (handle)) return;
+       if (minimized == OS.IsIconic (handle)) return;
+       int flags = swFlags;
+       if (flags == OS.SW_SHOWMINNOACTIVE && handle == OS.GetActiveWindow ()) {
+               flags = OS.SW_MINIMIZE;
+       }
+       OS.ShowWindow (handle, flags);
+       OS.UpdateWindow (handle);
+}
+
+void addMenu (Menu menu) {
+       if (menus == null) menus = new Menu [4];
+       for (int i=0; i<menus.length; i++) {
+               if (menus [i] == 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) != 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) != 0) {
+               style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER);
+       } else if ((style & SWT.NO_MOVE) != 0) {
+               style |= SWT.TITLE;
+       }
+       if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) != 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)) != 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) != 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) != 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
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 == value2) {
+               int transparent1 = data1.getTransparencyType ();
+               int transparent2 = data2.getTransparencyType ();
+               if (transparent1 == transparent2) {
+                       if (data1.depth == data2.depth) return 0;
+                       return data1.depth > data2.depth && data1.depth <= depth ? -1 : 1;
+               }
+               if (transparent1 == SWT.TRANSPARENCY_ALPHA) return -1;
+               if (transparent2 == SWT.TRANSPARENCY_ALPHA) return 1;
+               if (transparent1 == SWT.TRANSPARENCY_MASK) return -1;
+               if (transparent2 == SWT.TRANSPARENCY_MASK) return 1;
+               if (transparent1 == SWT.TRANSPARENCY_PIXEL) return -1;
+               if (transparent2 == SWT.TRANSPARENCY_PIXEL) return 1;
+               return 0;
+       }
+       return value1 < value2 ? -1 : 1;
+}
+
+@Override
+Widget computeTabGroup () {
+       return this;
+}
+
+@Override
+Control computeTabRoot () {
+       return this;
+}
+
+@Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       checkWidget ();
+
+       /* Get the size of the trimmings */
+       RECT rect = new 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);
+       boolean hasMenu = OS.GetMenu (handle) != 0;
+       OS.AdjustWindowRectEx (rect, bits1, hasMenu, bits2);
+
+       /* Get the size of the scroll bars */
+       if (horizontalBar != null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+       if (verticalBar != null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+
+       /* Compute the height of the menu bar */
+       if (hasMenu) {
+               RECT testRect = new RECT ();
+               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 == 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 = nAccel = 0;
+       MenuItem [] items = display.items;
+       if (menuBar == null || items == null) {
+               return;
+       }
+       ACCEL accel = new ACCEL ();
+       byte [] buffer1 = new byte [ACCEL.sizeof];
+       byte [] buffer2 = new byte [items.length * ACCEL.sizeof];
+       for (int i=0; i<items.length; i++) {
+               MenuItem item = items [i];
+               if (item != null && item.accelerator != 0) {
+                       Menu menu = item.parent;
+                       if (menu.parent == this) {
+                               while (menu != null && menu != menuBar) {
+                                       menu = menu.getParentMenu ();
+                               }
+                               if (menu == menuBar && item.fillAccel (accel)) {
+                                       OS.MoveMemory (buffer1, accel, ACCEL.sizeof);
+                                       System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof);
+                                       nAccel++;
+                               }
+                       }
+               }
+       }
+       if (nAccel != 0) hAccel = OS.CreateAcceleratorTable (buffer2, nAccel);
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       if (parent != null || ((style & SWT.TOOL) != 0)) {
+               setParent ();
+               setSystemMenu ();
+       }
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       swFlags = OS.SW_SHOWNOACTIVATE;
+       hAccel = -1;
+}
+
+void destroyAccelerators () {
+       if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
+       hAccel = -1;
+}
+
+@Override
+public void dispose () {
+       if (isDisposed()) return;
+       if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+       if (!(this instanceof Shell)) {
+               if (!traverseDecorations (true)) {
+                       Shell shell = getShell ();
+                       shell.setFocus ();
+               }
+               setVisible (false);
+       }
+       super.dispose ();
+}
+
+Menu findMenu (long hMenu) {
+       if (menus == null) return null;
+       for (int i=0; i<menus.length; i++) {
+               Menu menu = menus [i];
+               if (menu != null && hMenu == menu.handle) return menu;
+       }
+       return null;
+}
+
+void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) {
+       if (this == newDecorations) return;
+       if (control == savedFocus) savedFocus = null;
+       if (control == defaultButton) defaultButton = null;
+       if (control == saveDefault) saveDefault = null;
+       if (menus == null) return;
+       Menu menu = control.menu;
+       if (menu != null) {
+               int index = 0;
+               while (index <menus.length) {
+                       if (menus [index] == menu) {
+                               control.setMenu (null);
+                               return;
+                       }
+                       index++;
+               }
+               menu.fixMenus (newDecorations);
+               destroyAccelerators ();
+               newDecorations.destroyAccelerators ();
+       }
+}
+
+@Override Rectangle getBoundsInPixels () {
+       checkWidget ();
+       if (OS.IsIconic (handle)) {
+               WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+               lpwndpl.length = WINDOWPLACEMENT.sizeof;
+               OS.GetWindowPlacement (handle, lpwndpl);
+               if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
+                       int width = maxRect.right - maxRect.left;
+                       int height = maxRect.bottom - maxRect.top;
+                       return new Rectangle (maxRect.left, maxRect.top, width, height);
+               }
+               int width = lpwndpl.right - lpwndpl.left;
+               int height = lpwndpl.bottom - lpwndpl.top;
+               return new Rectangle (lpwndpl.left, lpwndpl.top, width, height);
+       }
+       return super.getBoundsInPixels ();
+}
+
+@Override Rectangle getClientAreaInPixels () {
+       checkWidget ();
+       if (OS.IsIconic (handle)) {
+               WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+               lpwndpl.length = WINDOWPLACEMENT.sizeof;
+               OS.GetWindowPlacement (handle, lpwndpl);
+               if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
+                       return new Rectangle (0, 0, oldWidth, oldHeight);
+               }
+               int width = lpwndpl.right - lpwndpl.left;
+               int height = lpwndpl.bottom - lpwndpl.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 != null) width -= OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+               if (verticalBar != null) height -= OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+               RECT rect = new RECT ();
+               int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+               boolean hasMenu = OS.GetMenu (handle) != 0;
+               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.getClientAreaInPixels ();
+}
+
+/**
+ * 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 ();
+       if (defaultButton != null && defaultButton.isDisposed ()) return null;
+       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 == null) return new Image [0];
+       Image [] result = new Image [images.length];
+       System.arraycopy (images, 0, result, 0, images.length);
+       return result;
+}
+
+@Override Point getLocationInPixels () {
+       checkWidget ();
+       if (OS.IsIconic (handle)) {
+               WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+               lpwndpl.length = WINDOWPLACEMENT.sizeof;
+               OS.GetWindowPlacement (handle, lpwndpl);
+               if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
+                       return new Point (maxRect.left, maxRect.top);
+               }
+               return new Point (lpwndpl.left, lpwndpl.top);
+       }
+       return super.getLocationInPixels ();
+}
+
+/**
+ * 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 boolean getMaximized () {
+       checkWidget ();
+       if (OS.IsWindowVisible (handle)) return OS.IsZoomed (handle);
+       return swFlags == 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 boolean getMinimized () {
+       checkWidget ();
+       if (OS.IsWindowVisible (handle)) return OS.IsIconic (handle);
+       return swFlags == OS.SW_SHOWMINNOACTIVE;
+}
+
+@Override
+String getNameText () {
+       return getText ();
+}
+
+@Override Point getSizeInPixels () {
+       checkWidget ();
+       if (OS.IsIconic (handle)) {
+               WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+               lpwndpl.length = WINDOWPLACEMENT.sizeof;
+               OS.GetWindowPlacement (handle, lpwndpl);
+               if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
+                       int width = maxRect.right - maxRect.left;
+                       int height = maxRect.bottom - maxRect.top;
+                       return new Point (width, height);
+               }
+               int width = lpwndpl.right - lpwndpl.left;
+               int height = lpwndpl.bottom - lpwndpl.top;
+               return new Point (width, height);
+       }
+       return super.getSizeInPixels ();
+}
+
+/**
+ * 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 == 0) return "";
+       char [] buffer = new char [length + 1];
+       OS.GetWindowText (handle, buffer, length + 1);
+       return new String (buffer, 0, length);
+}
+
+@Override
+public boolean 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
+boolean isTabGroup () {
+       /*
+       * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+       */
+       return true;
+}
+
+@Override
+boolean 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 (boolean destroy) {
+       if (menuBar != null) {
+               menuBar.release (false);
+               menuBar = null;
+       }
+       super.releaseChildren (destroy);
+       if (menus != null) {
+               for (int i=0; i<menus.length; i++) {
+                       Menu menu = menus [i];
+                       if (menu != null && !menu.isDisposed ()) {
+                               menu.dispose ();
+                       }
+               }
+               menus = null;
+       }
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (smallImage != null) smallImage.dispose ();
+       if (largeImage != null) largeImage.dispose ();
+       smallImage = largeImage = image = null;
+       images = null;
+       savedFocus = null;
+       defaultButton = saveDefault = null;
+       if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
+       hAccel = -1;
+}
+
+void removeMenu (Menu menu) {
+       if (menus == null) return;
+       for (int i=0; i<menus.length; i++) {
+               if (menus [i] == menu) {
+                       menus [i] = null;
+                       return;
+               }
+       }
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (menuBar != null) menuBar.reskin (flags);
+       if (menus != null) {
+               for (int i=0; i<menus.length; i++) {
+                       Menu menu = menus [i];
+                       if (menu != null) menu.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+boolean restoreFocus () {
+       if (display.ignoreRestoreFocus) return true;
+       if (savedFocus != null && savedFocus.isDisposed ()) savedFocus = null;
+       if (savedFocus != null && savedFocus.setFocus ()) return true;
+       return false;
+}
+
+void saveFocus () {
+       Control control = display._getFocusControl ();
+       if (control != null && control != this && this == control.menuShell ()) {
+               setSavedFocus (control);
+       }
+}
+
+@Override
+void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
+       swFlags = OS.SW_SHOWNOACTIVATE;
+       if (OS.IsIconic (handle)) {
+               setPlacement (x, y, width, height, flags);
+               return;
+       }
+       forceResize ();
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       boolean sameOrigin = true;
+       if ((OS.SWP_NOMOVE & flags) == 0) {
+               sameOrigin = rect.left == x && rect.top == y;
+               if (!sameOrigin) moved = true;
+       }
+       boolean sameExtent = true;
+       if ((OS.SWP_NOSIZE & flags) == 0) {
+               sameExtent = rect.right - rect.left == width && rect.bottom - rect.top == height;
+               if (!sameExtent) resized = true;
+       }
+       if (OS.IsZoomed (handle)) {
+               if (sameOrigin && sameExtent) return;
+               setPlacement (x, y, width, height, flags);
+               _setMaximized (false);
+               return;
+       }
+       super.setBoundsInPixels (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 != null) {
+               if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (button.menuShell () != this) error(SWT.ERROR_INVALID_PARENT);
+       }
+       setDefaultButton (button, true);
+}
+
+void setDefaultButton (Button button, boolean save) {
+       if (button == null) {
+               if (defaultButton == saveDefault) {
+                       if (save) saveDefault = null;
+                       return;
+               }
+       } else {
+               if ((button.style & SWT.PUSH) == 0) return;
+               if (button == defaultButton) {
+                       if (save) saveDefault = defaultButton;
+                       return;
+               }
+       }
+       if (defaultButton != null) {
+               if (!defaultButton.isDisposed ()) defaultButton.setDefault (false);
+       }
+       if ((defaultButton = button) == null) defaultButton = saveDefault;
+       if (defaultButton != null) {
+               if (!defaultButton.isDisposed ()) defaultButton.setDefault (true);
+       }
+       if (save) saveDefault = defaultButton;
+       if (saveDefault != 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 != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       this.image = image;
+       setImages (image, null);
+}
+
+void setImages (Image image, Image [] images) {
+       if (smallImage != null) smallImage.dispose ();
+       if (largeImage != null) largeImage.dispose ();
+       smallImage = largeImage = null;
+       long hSmallIcon = 0, hLargeIcon = 0;
+       Image smallIcon = null, largeIcon = null;
+       if (image != null) {
+               smallIcon = largeIcon = image;
+       } else {
+               if (images != 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 (DPIUtil.getDeviceZoom ());
+                               }
+                               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 != null) {
+               switch (smallIcon.type) {
+                       case SWT.BITMAP:
+                               smallImage = Display.createIcon (smallIcon);
+                               hSmallIcon = smallImage.handle;
+                               break;
+                       case SWT.ICON:
+                               hSmallIcon = smallIcon.handle;
+                               break;
+               }
+       }
+       OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_SMALL, hSmallIcon);
+       if (largeIcon != null) {
+               switch (largeIcon.type) {
+                       case SWT.BITMAP:
+                               largeImage = Display.createIcon (largeIcon);
+                               hLargeIcon = largeImage.handle;
+                               break;
+                       case SWT.ICON:
+                               hLargeIcon = largeIcon.handle;
+                               break;
+               }
+       }
+       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.
+       */
+       if (hSmallIcon == 0 && hLargeIcon == 0 && (style & SWT.BORDER) != 0) {
+               int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
+               OS.RedrawWindow (handle, null, 0, 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_NULL_ARGUMENT - if the array of images is null</li>
+ *    <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 ();
+       if (images == null) error (SWT.ERROR_INVALID_ARGUMENT);
+       for (int i = 0; i < images.length; i++) {
+               if (images [i] == 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 (boolean 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 == menu) return;
+       if (menu != null) {
+               if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR);
+               if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT);
+       }
+       if (menu != null) display.removeBar (menu);
+       menuBar = menu;
+       long hMenu = menuBar != null ? menuBar.handle: 0;
+       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 (boolean minimized) {
+       checkWidget ();
+       Display.lpStartupInfo = null;
+       _setMinimized (minimized);
+}
+
+@Override
+public void setOrientation (int orientation) {
+       super.setOrientation (orientation);
+       if (menus != null) {
+               for (int i=0; i<menus.length; i++) {
+                       Menu menu = menus [i];
+                       if (menu != null && !menu.isDisposed () && (menu.getStyle () & SWT.POP_UP) != 0) {
+                               menu._setOrientation (menu.getOrientation ());
+                       }
+               }
+       }
+}
+
+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.
+       */
+       long 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;
+       OS.SetWindowPos (handle, 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 = new WINDOWPLACEMENT ();
+       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;
+               }
+       }
+       boolean sameOrigin = true;
+       if ((flags & OS.SWP_NOMOVE) == 0) {
+               sameOrigin = lpwndpl.left != x || lpwndpl.top != y;
+               lpwndpl.right = x + (lpwndpl.right - lpwndpl.left);
+               lpwndpl.bottom = y + (lpwndpl.bottom - lpwndpl.top);
+               lpwndpl.left = x;
+               lpwndpl.top = y;
+       }
+       boolean sameExtent = true;
+       if ((flags & OS.SWP_NOSIZE) == 0) {
+               sameExtent = lpwndpl.right - lpwndpl.left != width || lpwndpl.bottom - lpwndpl.top != height;
+               lpwndpl.right = lpwndpl.left + width;
+               lpwndpl.bottom = lpwndpl.top + height;
+       }
+       OS.SetWindowPlacement (handle, lpwndpl);
+       if (OS.IsIconic (handle)) {
+               if (sameOrigin) {
+                       moved = true;
+                       Point location = getLocationInPixels ();
+                       oldX = location.x;
+                       oldY = location.y;
+                       sendEvent (SWT.Move);
+                       if (isDisposed ()) return;
+               }
+               if (sameExtent) {
+                       resized = true;
+                       Rectangle rect = getClientAreaInPixels ();
+                       oldWidth = rect.width;
+                       oldHeight = rect.height;
+                       sendEvent (SWT.Resize);
+                       if (isDisposed ()) return;
+                       if (layout != null) {
+                               markLayout (false, false);
+                               updateLayout (true, false);
+                       }
+               }
+       }
+}
+
+void setSavedFocus (Control control) {
+       savedFocus = control;
+}
+
+void setSystemMenu () {
+       long hMenu = OS.GetSystemMenu (handle, false);
+       if (hMenu == 0) return;
+       int oldCount = OS.GetMenuItemCount (hMenu);
+       if ((style & SWT.RESIZE) == 0) {
+               OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND);
+       }
+       if ((style & SWT.MIN) == 0) {
+               OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND);
+       }
+       if ((style & SWT.MAX) == 0) {
+               OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND);
+       }
+       if ((style & (SWT.MIN | SWT.MAX)) == 0) {
+               OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND);
+       }
+       int newCount = OS.GetMenuItemCount (hMenu);
+       if ((style & SWT.CLOSE) == 0 || newCount != oldCount) {
+               OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND);
+               MENUITEMINFO info = new MENUITEMINFO ();
+               info.cbSize = MENUITEMINFO.sizeof;
+               info.fMask = OS.MIIM_ID;
+               int index = 0;
+               while (index < newCount) {
+                       if (OS.GetMenuItemInfo (hMenu, index, true, info)) {
+                               if (info.wID == OS.SC_CLOSE) break;
+                       }
+                       index++;
+               }
+               if (index != newCount) {
+                       OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION);
+                       if ((style & SWT.CLOSE) == 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.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       /* Use the character encoding for the default locale */
+       TCHAR buffer = new TCHAR (0, string, true);
+       /* Ensure that the title appears in the task bar.*/
+       if ((state & FOREIGN_HANDLE) != 0) {
+               long hHeap = OS.GetProcessHeap ();
+               int byteCount = buffer.length () * TCHAR.sizeof;
+               long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory (pszText, buffer, byteCount);
+               OS.DefWindowProc (handle, OS.WM_SETTEXT, 0, pszText);
+               if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+       } else {
+               OS.SetWindowText (handle, buffer);
+       }
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+}
+
+@Override
+public void setVisible (boolean visible) {
+       checkWidget ();
+       if (!getDrawing()) {
+               if (((state & HIDDEN) == 0) == visible) return;
+       } else {
+               if (visible == 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;
+               if (!getDrawing()) {
+                       state &= ~HIDDEN;
+               } else {
+                       if (menuBar != null) {
+                               display.removeBar (menuBar);
+                               OS.DrawMenuBar (handle);
+                       }
+                       STARTUPINFO lpStartUpInfo = Display.lpStartupInfo;
+                       if (lpStartUpInfo != null && (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) != 0) {
+                               OS.ShowWindow (handle, lpStartUpInfo.wShowWindow);
+                       } else {
+                               OS.ShowWindow (handle, swFlags);
+                       }
+                       if (isDisposed ()) return;
+                       opened = true;
+                       if (!moved) {
+                               moved = true;
+                               Point location = getLocationInPixels ();
+                               oldX = location.x;
+                               oldY = location.y;
+                       }
+                       if (!resized) {
+                               resized = true;
+                               Rectangle rect = getClientAreaInPixels ();
+                               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.
+                       */
+                       if (OS.IsAppThemed () || !OS.IsHungAppWindow (handle)) {
+                               OS.UpdateWindow (handle);
+                       }
+               }
+       } else {
+               if (OS.IsIconic (handle)) {
+                       swFlags = OS.SW_SHOWMINNOACTIVE;
+               } else {
+                       if (OS.IsZoomed (handle)) {
+                               swFlags = OS.SW_SHOWMAXIMIZED;
+                       } else {
+                               swFlags = OS.SW_SHOWNOACTIVATE;
+                       }
+               }
+               if (!getDrawing()) {
+                       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
+boolean translateAccelerator (MSG msg) {
+       if (!isEnabled () || !isActive ()) return false;
+       if (menuBar != null && !menuBar.isEnabled ()) return false;
+       if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true;
+       Decorations decorations = parent.menuShell ();
+       return decorations.translateAccelerator (msg);
+}
+
+boolean translateMenuAccelerator (MSG msg) {
+       if (hAccel == -1) createAccelerators ();
+       return hAccel != 0 && OS.TranslateAccelerator (handle, hAccel, msg) != 0;
+}
+
+boolean translateMDIAccelerator (MSG msg) {
+       if (!(this instanceof Shell)) {
+               Shell shell = getShell ();
+               long hwndMDIClient = shell.hwndMDIClient;
+               if (hwndMDIClient != 0 && OS.TranslateMDISysAccel (hwndMDIClient, msg)) {
+                       return true;
+               }
+               if (msg.message == OS.WM_KEYDOWN) {
+                       if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
+                       switch ((int)(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;
+                       }
+                       return false;
+               }
+               if (msg.message == OS.WM_SYSKEYDOWN) {
+                       switch ((int)(msg.wParam)) {
+                               case OS.VK_F4:
+                                       OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0);
+                                       return true;
+                       }
+                       return false;
+               }
+       }
+       return false;
+}
+
+boolean traverseDecorations (boolean next) {
+       Control [] children = parent._getChildren ();
+       int length = children.length;
+       int index = 0;
+       while (index < length) {
+               if (children [index] == 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) != start) {
+               Control child = children [index];
+               if (!child.isDisposed () && child instanceof Decorations) {
+                       if (child.setFocus ()) return true;
+               }
+       }
+       return false;
+}
+
+@Override
+boolean traverseItem (boolean next) {
+       return false;
+}
+
+@Override
+boolean traverseReturn () {
+       if (defaultButton == 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) != 0) return bits;
+       if ((style & SWT.RESIZE) != 0) return bits;
+       if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_DLGMODALFRAME;
+       return bits;
+}
+
+@Override
+long 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) != 0) {
+               if (parent == null) {
+                       bits |= OS.WS_SYSMENU | OS.WS_MINIMIZEBOX;
+               }
+               return bits;
+       }
+       if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
+
+       /* Set the min and max button bits */
+       if ((style & SWT.MIN) != 0) bits |= OS.WS_MINIMIZEBOX;
+       if ((style & SWT.MAX) != 0) bits |= OS.WS_MAXIMIZEBOX;
+
+       /* Set the resize, dialog border or border bits */
+       if ((style & SWT.RESIZE) != 0) {
+               bits |= OS.WS_THICKFRAME;
+       } else if ((style & SWT.BORDER) == 0) {
+               bits |= OS.WS_BORDER;
+       }
+
+       /* Set the system menu and close box bits */
+       if ((style & SWT.CLOSE) != 0) bits |= OS.WS_SYSMENU;
+
+       return bits;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       switch (msg) {
+               case Display.SWT_GETACCEL:
+               case Display.SWT_GETACCELCOUNT:
+                       if (hAccel == -1) createAccelerators ();
+                       return msg == Display.SWT_GETACCELCOUNT ? nAccel : hAccel;
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT WM_ACTIVATE (long wParam, long lParam) {
+       LRESULT result = super.WM_ACTIVATE (wParam, lParam);
+       if (result != 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 (lParam) == handle) {
+               char [] buffer = new char [128];
+               int length = OS.GetClassName (lParam, buffer, buffer.length);
+               String className = new String (buffer, 0, length);
+               if (className.equals (Display.AWT_WINDOW_CLASS)) {
+                       return LRESULT.ZERO;
+               }
+       }
+       int loWord = OS.LOWORD (wParam);
+       if (loWord != 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) != 0) return result;
+               Control control = display.findControl (lParam);
+               if (control == null || control instanceof Shell) {
+                       if (this instanceof Shell) {
+                               Event event = new Event ();
+                               event.detail = loWord == OS.WA_CLICKACTIVE ? SWT.MouseDown : SWT.None;
+                               sendEvent (SWT.Activate, event);
+                               if (isDisposed ()) return LRESULT.ZERO;
+                       }
+               }
+               if (restoreFocus ()) return LRESULT.ZERO;
+       } else {
+               Display display = this.display;
+               boolean lockWindow = display.isXMouseActive ();
+               if (lockWindow) display.lockActiveWindow = true;
+               Control control = display.findControl (lParam);
+               if (control == null || control instanceof Shell) {
+                       if (this instanceof Shell) {
+                               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 (long wParam, long lParam) {
+       LRESULT result = super.WM_CLOSE (wParam, lParam);
+       if (result != null) return result;
+       if (isEnabled () && isActive ()) closeWidget ();
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+       saveFocus ();
+       return result;
+}
+
+@Override
+LRESULT WM_MOVE (long wParam, long lParam) {
+       if (moved) {
+               Point location = getLocationInPixels ();
+               if (location.x == oldX && location.y == oldY) {
+                       return null;
+               }
+               oldX = location.x;
+               oldY = location.y;
+       }
+       return super.WM_MOVE (wParam, lParam);
+}
+
+@Override
+LRESULT WM_NCACTIVATE (long wParam, long lParam) {
+       LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
+       if (result != null) return result;
+       if (wParam == 0) {
+               if (display.lockActiveWindow) return LRESULT.ZERO;
+               Control control = display.findControl (lParam);
+               if (control != null) {
+                       Shell shell = getShell ();
+                       Decorations decorations = control.menuShell ();
+                       if (decorations.getShell () == shell) {
+                               if (this instanceof Shell) return LRESULT.ONE;
+                               if (display.ignoreRestoreFocus) {
+                                       if (display.lastHittest != OS.HTCLIENT) {
+                                               result = LRESULT.ONE;
+                                       }
+                               }
+                       }
+               }
+       }
+       if (!(this instanceof Shell)) {
+               long hwndShell = getShell().handle;
+               OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_QUERYOPEN (long wParam, long lParam) {
+       LRESULT result = super.WM_QUERYOPEN (wParam, lParam);
+       if (result != null) return result;
+       sendEvent (SWT.Deiconify);
+       // widget could be disposed at this point
+       return result;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+       if (isDisposed ()) return result;
+       if (savedFocus != this) restoreFocus ();
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result = null;
+       boolean changed = true;
+       if (resized) {
+               int newWidth = 0, newHeight = 0;
+               switch ((int)wParam) {
+                       case OS.SIZE_MAXIMIZED:
+                               OS.GetWindowRect (handle, maxRect);
+                       case OS.SIZE_RESTORED:
+                               newWidth = OS.LOWORD (lParam);
+                               newHeight = OS.HIWORD (lParam);
+                               break;
+                       case OS.SIZE_MINIMIZED:
+                               Rectangle rect = getClientAreaInPixels ();
+                               newWidth = rect.width;
+                               newHeight = rect.height;
+                               break;
+               }
+               changed = newWidth != oldWidth || newHeight != oldHeight;
+               if (changed) {
+                       oldWidth = newWidth;
+                       oldHeight = newHeight;
+               }
+       }
+       if (changed) {
+               result = super.WM_SIZE (wParam, lParam);
+               if (isDisposed ()) return result;
+       }
+       if (wParam == OS.SIZE_MINIMIZED) {
+               sendEvent (SWT.Iconify);
+               // widget could be disposed at this point
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SYSCOMMAND (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+       if (result != null) return result;
+       if (!(this instanceof Shell)) {
+               int cmd = (int)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;
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
+       LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+       if (result != null) return result;
+       if (display.lockActiveWindow) {
+               WINDOWPOS lpwp = new WINDOWPOS ();
+               OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+               lpwp.flags |= OS.SWP_NOZORDER;
+               OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
+       }
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Dialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Dialog.java
new file mode 100644 (file)
index 0000000..06be165
--- /dev/null
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+
+/**
+ * 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:</p>
+ * <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;
+ *     }
+ * }
+ * </code></pre>
+ * <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.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>APPLICATION_MODAL, PRIMARY_MODAL, SYSTEM_MODAL, SHEET</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 Dialog (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 Dialog (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 () {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       parent.checkWidget ();
+}
+
+static int checkStyle (Shell parent, int style) {
+       int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+       if ((style & SWT.SHEET) != 0) {
+               style &= ~SWT.SHEET;
+               if ((style & mask) == 0) {
+                       style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
+               }
+       }
+       if ((style & mask) == 0) {
+               style |= SWT.APPLICATION_MODAL;
+       }
+       style &= ~SWT.MIRRORED;
+       if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
+               if (parent != null) {
+                       if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT;
+                       if ((parent.style & SWT.RIGHT_TO_LEFT) != 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       title = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/DirectoryDialog.java
new file mode 100644 (file)
index 0000000..60bda29
--- /dev/null
@@ -0,0 +1,375 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Martin Karpisek <martin.karpisek@gmail.com> - Bug 443250
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class DirectoryDialog extends Dialog {
+       String message = "", filterPath = "";  //$NON-NLS-1$//$NON-NLS-2$
+       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 DirectoryDialog (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 DirectoryDialog (Shell parent, int style) {
+       super (parent, checkStyle (parent, style));
+       checkSubclass ();
+}
+
+long BrowseCallbackProc (long hwnd, long uMsg, long lParam, long lpData) {
+       switch ((int)uMsg) {
+               case OS.BFFM_INITIALIZED:
+                       if (filterPath != null && filterPath.length () != 0) {
+                               /* Use the character encoding for the default locale */
+                               TCHAR buffer = new TCHAR (0, filterPath.replace ('/', '\\'), true);
+                               OS.SendMessage (hwnd, OS.BFFM_SETSELECTION, 1, buffer);
+                       }
+                       if (title != null && title.length () != 0) {
+                               /* Use the character encoding for the default locale */
+                               TCHAR buffer = new TCHAR (0, title, true);
+                               OS.SetWindowText (hwnd, buffer);
+                       }
+                       break;
+               case OS.BFFM_VALIDATEFAILED:
+                       /* Use the character encoding for the default locale */
+                       int length = OS.wcslen (lParam);
+                       TCHAR buffer = new TCHAR (0, length);
+                       int byteCount = buffer.length () * TCHAR.sizeof;
+                       OS.MoveMemory (buffer, lParam, byteCount);
+                       directoryPath = buffer.toString (0, length);
+                       break;
+       }
+       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.WIN32_VERSION >= OS.VERSION (6, 0)) {
+               return openCommonItemDialog();
+       }
+       return openCommonFileDialog();
+}
+
+private String openCommonFileDialog () {
+       long hHeap = OS.GetProcessHeap ();
+
+       /* Get the owner HWND for the dialog */
+       long hwndOwner = 0;
+       if (parent != null) hwndOwner = parent.handle;
+
+       /* Copy the message to OS memory */
+       long lpszTitle = 0;
+       if (message.length () != 0) {
+               String string = message;
+               if (string.indexOf ('&') != -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 == '&') buffer [index++] = '&';
+                               buffer [index++] = ch;
+                       }
+                       string = new String (buffer, 0, index);
+               }
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR (0, string, true);
+               int byteCount = buffer.length () * TCHAR.sizeof;
+               lpszTitle = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory (lpszTitle, buffer, byteCount);
+       }
+
+       /* Create the BrowseCallbackProc */
+       Callback callback = new Callback (this, "BrowseCallbackProc", 4); //$NON-NLS-1$
+       long lpfn = callback.getAddress ();
+       if (lpfn == 0) 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)) != 0) {
+               oldModal = display.getModalDialog ();
+               display.setModalDialog (this);
+       }
+
+       directoryPath = null;
+       BROWSEINFO lpbi = new BROWSEINFO ();
+       lpbi.hwndOwner = hwndOwner;
+       lpbi.lpszTitle = lpszTitle;
+       lpbi.ulFlags = OS.BIF_NEWDIALOGSTYLE | OS.BIF_RETURNONLYFSDIRS | OS.BIF_EDITBOX | OS.BIF_VALIDATE;
+       lpbi.lpfn = lpfn;
+       /*
+       * 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);
+
+       display.sendPreExternalEventDispatchEvent ();
+       display.externalEventLoop = true;
+       long lpItemIdList = OS.SHBrowseForFolder (lpbi);
+       display.externalEventLoop = false;
+       display.sendPostExternalEventDispatchEvent ();
+       OS.SetErrorMode (oldErrorMode);
+
+       /* Clear the temporary dialog modal parent */
+       if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+               display.setModalDialog (oldModal);
+       }
+
+       boolean success = lpItemIdList != 0;
+       if (success) {
+               /* Use the character encoding for the default locale */
+               TCHAR buffer = new TCHAR (0, OS.MAX_PATH);
+               if (OS.SHGetPathFromIDList (lpItemIdList, buffer)) {
+                       directoryPath = buffer.toString (0, buffer.strlen ());
+                       filterPath = directoryPath;
+               }
+       }
+
+       /* Free the BrowseCallbackProc */
+       callback.dispose ();
+
+       /* Free the OS memory */
+       if (lpszTitle != 0) OS.HeapFree (hHeap, 0, lpszTitle);
+
+       /* Free the pointer to the ITEMIDLIST */
+       long [] ppMalloc = new long [1];
+       if (OS.SHGetMalloc (ppMalloc) == OS.S_OK) {
+               /* void Free (struct IMalloc *this, void *pv); */
+               COM.VtblCall (5, ppMalloc [0], 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 != 0) OS.UpdateWindow (hwndOwner);
+
+       /* Return the directory path */
+       if (!success) return null;
+       return directoryPath;
+}
+
+private String openCommonItemDialog() {
+       this.directoryPath = null;
+
+       long [] ppv = new long [1];
+       if (COM.CoCreateInstance(COM.CLSID_FileOpenDialog, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IFileOpenDialog, ppv) == OS.S_OK) {
+               IFileDialog fileDialog = new IFileDialog(ppv[0]);
+
+               int[] options = new int[1];
+               if (fileDialog.GetOptions(options) == OS.S_OK) {
+                       options[0] |= OS.FOS_PICKFOLDERS | OS.FOS_FORCEFILESYSTEM | OS.FOS_NOCHANGEDIR;
+                       fileDialog.SetOptions(options[0]);
+               }
+
+               if (title == null) title = "";
+               if (title.length() > 0) {
+                       char[] buffer = new char[title.length() + 1];
+                       title.getChars(0, title.length(), buffer, 0);
+                       fileDialog.SetTitle(buffer);
+               }
+
+               if (filterPath != null && filterPath.length() > 0) {
+                       String path = filterPath.replace('/', '\\');
+                       char[] buffer = new char[path.length() + 1];
+                       path.getChars(0, path.length(), buffer, 0);
+                       if (COM.SHCreateItemFromParsingName(buffer, 0, COM.IID_IShellItem, ppv) == OS.S_OK) {
+                               IShellItem psi = new IShellItem(ppv[0]);
+                               /*
+                                * SetDefaultDirectory does not work if the dialog has
+                                * persisted recently used folder. The fix is to clear the
+                                * persisted data.
+                                */
+                               fileDialog.ClearClientData();
+                               fileDialog.SetDefaultFolder(psi);
+                               psi.Release();
+                       }
+               }
+
+               Display display = parent.getDisplay();
+               long hwndOwner = parent.handle;
+               display.externalEventLoop = true;
+               if (fileDialog.Show(hwndOwner) == OS.S_OK) {
+                       if (fileDialog.GetResult(ppv) == OS.S_OK) {
+                               IShellItem psi = new IShellItem(ppv[0]);
+                               if (psi.GetDisplayName(OS.SIGDN_FILESYSPATH, ppv) == OS.S_OK) {
+                                       long wstr = ppv[0];
+                                       int length = OS.wcslen(wstr);
+                                       char[] buffer = new char[length];
+                                       OS.MoveMemory(buffer, wstr, length * 2);
+                                       OS.CoTaskMemFree(wstr);
+
+                                       directoryPath = new String(buffer);
+                               }
+                               psi.Release();
+                       }
+               }
+               display.externalEventLoop = false;
+
+               fileDialog.Release();
+       }
+
+       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.
+ * <p>
+ * NOTE: This operation is a hint and is not supported on some platforms. For
+ * example, on Windows (Vista and later), the <code>DirectoryDialog</code>
+ * doesn't have any provision to set a message.
+ * </p>
+ *
+ * @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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       message = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Display.java
new file mode 100644 (file)
index 0000000..8323179
--- /dev/null
@@ -0,0 +1,4985 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import java.net.*;
+import java.util.*;
+import java.util.function.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * <p>
+ * 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, OpenDocument, Settings, Skin</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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Display extends 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public MSG msg = new MSG ();
+
+       static String APP_NAME = "SWT"; //$NON-NLS-1$
+       static String APP_VERSION = ""; //$NON-NLS-1$
+
+       /* Windows and Events */
+       Event [] eventQueue;
+       Callback windowCallback;
+       long windowProc;
+       int threadId;
+       TCHAR windowClass, windowShadowClass, windowOwnDCClass;
+       static int WindowClassCount;
+       static final String WindowName = "SWT_Window"; //$NON-NLS-1$
+       static final String WindowShadowName = "SWT_WindowShadow"; //$NON-NLS-1$
+       static final String WindowOwnDCName = "SWT_WindowOwnDC"; //$NON-NLS-1$
+       EventTable eventTable, filterTable;
+       boolean useOwnDC;
+       boolean externalEventLoop; // events are dispatched outside SWT, e.g. TrackPopupMenu or DoDragDrop
+
+       /* Widget Table */
+       int freeSlot;
+       int [] indexTable;
+       Control lastControl, lastGetControl;
+       long lastHwnd, lastGetHwnd;
+       Control [] controlTable;
+       static final int GROW_SIZE = 1024;
+       static final int SWT_OBJECT_INDEX = OS.GlobalAddAtom (new TCHAR (0, "SWT_OBJECT_INDEX", true)); //$NON-NLS-1$
+
+       /* Startup info */
+       static STARTUPINFO lpStartupInfo;
+       static {
+               lpStartupInfo = new STARTUPINFO ();
+               lpStartupInfo.cb = STARTUPINFO.sizeof;
+               OS.GetStartupInfo (lpStartupInfo);
+       }
+
+       /* XP Themes */
+       long hButtonTheme, hEditTheme, hExplorerBarTheme, hScrollBarTheme, hTabTheme;
+       static final char [] BUTTON = new char [] {'B', 'U', 'T', 'T', 'O', 'N', 0};
+       static final char [] EDIT = new char [] {'E', 'D', 'I', 'T', 0};
+       static final char [] EXPLORER = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 0};
+       static final char [] EXPLORERBAR = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 'B', 'A', 'R', 0};
+       static final char [] SCROLLBAR = new char [] {'S', 'C', 'R', 'O', 'L', 'L', 'B', 'A', 'R', 0};
+       static final char [] LISTVIEW = new char [] {'L', 'I', 'S', 'T', 'V', 'I', 'E', 'W', 0};
+       static final char [] TAB = new char [] {'T', 'A', 'B', 0};
+       static final char [] TREEVIEW = new char [] {'T', 'R', 'E', 'E', 'V', 'I', 'E', 'W', 0};
+
+       /* Custom icons */
+       long hIconSearch;
+       long hIconCancel;
+
+       /* Focus */
+       int focusEvent;
+       Control focusControl;
+       boolean fixFocus;
+
+       /* 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 final int ID_START = 108;
+
+       /* Filter Hook */
+       Callback msgFilterCallback;
+       long msgFilterProc, filterHook;
+       MSG hookMsg = new MSG ();
+       boolean runDragDrop = true, dragCancelled = false;
+
+       /* Idle Hook */
+       Callback foregroundIdleCallback;
+       long foregroundIdleProc, idleHook;
+
+       /* Message Hook and Embedding */
+       boolean ignoreNextKey;
+       Callback getMsgCallback, embeddedCallback;
+       long getMsgProc, msgHook, embeddedHwnd, embeddedProc;
+       static final String AWT_WINDOW_CLASS = "SunAwtWindow"; //$NON-NLS-1$
+       static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
+
+       /* Sync/Async Widget Communication */
+       Synchronizer synchronizer = new Synchronizer (this);
+       Consumer<RuntimeException> runtimeExceptionHandler = DefaultExceptionHandler.RUNTIME_EXCEPTION_HANDLER;
+       Consumer<Error> errorHandler = DefaultExceptionHandler.RUNTIME_ERROR_HANDLER;
+       boolean runMessagesInIdle = false, runMessagesInMessageProc = true;
+       static final 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$
+       static final String USE_OWNDC_KEY = "org.eclipse.swt.internal.win32.useOwnDC"; //$NON-NLS-1$
+       static final String ACCEL_KEY_HIT = "org.eclipse.swt.internal.win32.accelKeyHit"; //$NON-NLS-1$
+       static final String EXTERNAL_EVENT_LOOP_KEY = "org.eclipse.swt.internal.win32.externalEventLoop"; //$NON-NLS-1$
+       Thread thread;
+
+       /* Display Shutdown */
+       Runnable [] disposeList;
+
+       /* Deferred Layout list */
+       Composite[] layoutDeferred;
+       int layoutDeferredCount;
+
+       /* System Tray */
+       Tray tray;
+       int nextTrayId;
+
+       /* TaskBar */
+       TaskBar taskBar;
+       static final String TASKBAR_EVENT = "/SWTINTERNAL_ID"; //$NON-NLS-1$
+       static final String LAUNCHER_PREFIX = "--launcher.openFile "; //$NON-NLS-1$
+
+       /* Timers */
+       long [] timerIds;
+       Runnable [] timerList;
+       long nextTimerId = SETTINGS_ID + 1;
+
+       /* Settings */
+       static final long SETTINGS_ID = 100;
+       static final int SETTINGS_DELAY = 2000;
+
+       /* Keyboard and Mouse */
+       RECT clickRect;
+       int clickCount, lastTime, lastButton;
+       long lastClickHwnd;
+       int scrollRemainder, scrollHRemainder;
+       int lastKey, lastMouse, lastAscii;
+       boolean lastVirtual, lastNull, lastDead;
+       byte [] keyboard = new byte [256];
+       boolean accelKeyHit, mnemonicKeyHit;
+       boolean lockActiveWindow, captureChanged, xMouse;
+
+       /* Gesture state */
+       double magStartDistance, lastDistance;
+       double rotationAngle;
+       int lastX, lastY;
+
+       /* Touch state */
+       TouchSource [] touchSources;
+
+       /* Tool Tips */
+       int nextToolTipId;
+
+       /* MDI */
+       boolean ignoreRestoreFocus;
+       Control lastHittestControl;
+       int lastHittest;
+
+       /* Message Only Window */
+       Callback messageCallback;
+       long hwndMessage, messageProc;
+
+       /* System Resources */
+       LOGFONT lfSystemFont;
+       Font systemFont;
+       Image errorImage, infoImage, questionImage, warningIcon;
+       Cursor [] cursors = new Cursor [SWT.CURSOR_HAND + 1];
+       Resource [] resources;
+       static final int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1;
+
+       /* ImageList Cache */
+       ImageList[] imageList, toolImageList, toolHotImageList, toolDisabledImageList;
+
+       /* Custom Colors for ChooseColor */
+       long lpCustColors;
+
+       /* Table */
+       char [] tableBuffer;
+
+       /* Resize and move recursion */
+       int resizeCount;
+       static final int RESIZE_LIMIT = 4;
+
+       /* Display Data */
+       Object data;
+       String [] keys;
+       Object [] values;
+
+       /* Key Mappings */
+       static final 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},
+               {OS.VK_F16,     SWT.F16},
+               {OS.VK_F17,     SWT.F17},
+               {OS.VK_F18,     SWT.F18},
+               {OS.VK_F19,     SWT.F19},
+               {OS.VK_F20,     SWT.F20},
+
+               /* 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 = new Display [4];
+
+       /* Multiple Monitors */
+       Monitor[] monitors = null;
+       int monitorCount = 0;
+
+       /* Modality */
+       Shell [] modalShells;
+       Dialog modalDialog;
+       static boolean TrimEnabled = false;
+
+       /* Private SWT Window Messages */
+       static final int SWT_GETACCELCOUNT      = OS.WM_APP;
+       static final int SWT_GETACCEL           = OS.WM_APP + 1;
+       static final int SWT_KEYMSG                     = OS.WM_APP + 2;
+       static final int SWT_DESTROY            = OS.WM_APP + 3;
+       static final int SWT_TRAYICONMSG        = OS.WM_APP + 4;
+       static final int SWT_NULL                       = OS.WM_APP + 5;
+       static final int SWT_RUNASYNC           = OS.WM_APP + 6;
+       static int TASKBARCREATED;
+       static int TASKBARBUTTONCREATED;
+       static int SWT_RESTORECARET;
+       static int DI_GETDRAGIMAGE;
+       static int SWT_OPENDOC;
+
+       /* Skinning support */
+       Widget [] skinList = new Widget [GROW_SIZE];
+       int skinCount;
+
+       /* Package Name */
+       static final 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.
+       */
+       static {
+               DeviceFinder = () -> {
+                       Device device = getCurrent ();
+                       if (device == null) {
+                               device = getDefault ();
+                       }
+                       setDevice (device);
+               };
+       }
+
+/*
+* TEMPORARY CODE.
+*/
+static void setDevice (Device device) {
+       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 Display () {
+       this (null);
+}
+
+/**
+ * Constructs a new instance of this class using the parameter.
+ *
+ * @param data the device data
+ */
+public Display (DeviceData data) {
+       super (data);
+}
+
+Control _getFocusControl () {
+       return findControl (OS.GetFocus ());
+}
+
+void addBar (Menu menu) {
+       if (bars == null) bars = new Menu [4];
+       int length = bars.length;
+       for (int i=0; i<length; i++) {
+               if (bars [i] == menu) return;
+       }
+       int index = 0;
+       while (index < length) {
+               if (bars [index] == null) break;
+               index++;
+       }
+       if (index == length) {
+               Menu [] newBars = new Menu [length + 4];
+               System.arraycopy (bars, 0, newBars, 0, length);
+               bars = newBars;
+       }
+       bars [index] = menu;
+}
+
+void addControl (long handle, Control control) {
+       if (handle == 0) return;
+       if (freeSlot == -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;
+       }
+       OS.SetProp (handle, SWT_OBJECT_INDEX, freeSlot + 1);
+       int oldSlot = freeSlot;
+       freeSlot = indexTable [oldSlot];
+       indexTable [oldSlot] = -2;
+       controlTable [oldSlot] = control;
+}
+
+void addSkinnableWidget (Widget widget) {
+       if (skinCount >= skinList.length) {
+               Widget[] newSkinWidgets = new Widget [skinList.length + GROW_SIZE];
+               System.arraycopy (skinList, 0, newSkinWidgets, 0, skinList.length);
+               skinList = newSkinWidgets;
+       }
+       skinList [skinCount++] = widget;
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (filterTable == null) filterTable = new EventTable ();
+       filterTable.hook (eventType, listener);
+}
+
+void addLayoutDeferred (Composite comp) {
+       if (layoutDeferred == null) layoutDeferred = new Composite [64];
+       if (layoutDeferredCount == layoutDeferred.length) {
+               Composite [] temp = new Composite [layoutDeferred.length + 64];
+               System.arraycopy (layoutDeferred, 0, temp, 0, layoutDeferred.length);
+               layoutDeferred = temp;
+       }
+       layoutDeferred[layoutDeferredCount++] = comp;
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) eventTable = new EventTable ();
+       eventTable.hook (eventType, listener);
+}
+
+void addMenuItem (MenuItem item) {
+       if (items == null) items = new MenuItem [64];
+       for (int i=0; i<items.length; i++) {
+               if (items [i] == 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 == null) popups = new Menu [4];
+       int length = popups.length;
+       for (int i=0; i<length; i++) {
+               if (popups [i] == menu) return;
+       }
+       int index = 0;
+       while (index < length) {
+               if (popups [index] == null) break;
+               index++;
+       }
+       if (index == length) {
+               Menu [] newPopups = new Menu [length + 4];
+               System.arraycopy (popups, 0, newPopups, 0, length);
+               popups = newPopups;
+       }
+       popups [index] = menu;
+}
+
+int asciiKey (int key) {
+       /* Get the current keyboard. */
+       for (int i=0; i<keyboard.length; i++) keyboard [i] = 0;
+       if (!OS.GetKeyboardState (keyboard)) return 0;
+
+       /* Translate the key to ASCII or UNICODE using the virtual keyboard */
+       char [] result = new char [1];
+       if (OS.ToUnicode (key, key, keyboard, result, 1, 0) == 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.class) {
+               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 == null) error (SWT.ERROR_WIDGET_DISPOSED);
+       if (thread != Thread.currentThread ()) {
+               /*
+               * 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 != OS.GetCurrentThreadId ()) {
+                       error (SWT.ERROR_THREAD_INVALID_ACCESS);
+               }
+       }
+       if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+}
+
+static void checkDisplay (Thread thread, boolean multiple) {
+       synchronized (Device.class) {
+               for (int i=0; i<Displays.length; i++) {
+                       if (Displays [i] != null) {
+                               if (!multiple) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$
+                               if (Displays [i].thread == thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+                       }
+               }
+       }
+}
+
+void clearModal (Shell shell) {
+       if (modalShells == null) return;
+       int index = 0, length = modalShells.length;
+       while (index < length) {
+               if (modalShells [index] == shell) break;
+               if (modalShells [index] == null) return;
+               index++;
+       }
+       if (index == length) return;
+       System.arraycopy (modalShells, index + 1, modalShells, index, --length - index);
+       modalShells [length] = null;
+       if (index == 0 && modalShells [0] == null) modalShells = null;
+       Shell [] shells = getShells ();
+       for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+}
+
+int controlKey (int key) {
+       int upper = (int)OS.CharUpper ((short) 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.currentThread (), true);
+       createDisplay (data);
+       register (this);
+       if (Default == null) Default = this;
+}
+
+void createDisplay (DeviceData data) {
+}
+
+static long create32bitDIB (Image image) {
+       int transparentPixel = -1, alpha = -1;
+       long hMask = 0, hBitmap = 0;
+       byte[] alphaData = null;
+       switch (image.type) {
+               case SWT.ICON:
+                       ICONINFO info = new ICONINFO ();
+                       OS.GetIconInfo (image.handle, info);
+                       hBitmap = info.hbmColor;
+                       hMask = info.hbmMask;
+                       break;
+               case SWT.BITMAP:
+                       ImageData data = image.getImageData (DPIUtil.getDeviceZoom ());
+                       hBitmap = image.handle;
+                       alpha = data.alpha;
+                       alphaData = data.alphaData;
+                       transparentPixel = data.transparentPixel;
+                       break;
+       }
+       BITMAP bm = new BITMAP ();
+       OS.GetObject (hBitmap, BITMAP.sizeof, bm);
+       int imgWidth = bm.bmWidth;
+       int imgHeight = bm.bmHeight;
+       long hDC = OS.GetDC (0);
+       long srcHdc = OS.CreateCompatibleDC (hDC);
+       long oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
+       long memHdc = OS.CreateCompatibleDC (hDC);
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+       bmiHeader.biWidth = imgWidth;
+       bmiHeader.biHeight = -imgHeight;
+       bmiHeader.biPlanes = 1;
+       bmiHeader.biBitCount = (short)32;
+       bmiHeader.biCompression = OS.BI_RGB;
+       byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
+       OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+       long [] pBits = new long [1];
+       long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+       if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+       long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+       BITMAP dibBM = new BITMAP ();
+       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 != -1) {
+               if (bm.bmBitsPixel <= 8) {
+                       byte [] color = new byte [4];
+                       OS.GetDIBColorTable (srcHdc, transparentPixel, 1, color);
+                       blue = color [0];
+                       green = color [1];
+                       red = color [2];
+               } else {
+                       switch (bm.bmBitsPixel) {
+                               case 16:
+                                       blue = (byte)((transparentPixel & 0x1F) << 3);
+                                       green = (byte)((transparentPixel & 0x3E0) >> 2);
+                                       red = (byte)((transparentPixel & 0x7C00) >> 7);
+                                       break;
+                               case 24:
+                                       blue = (byte)((transparentPixel & 0xFF0000) >> 16);
+                                       green = (byte)((transparentPixel & 0xFF00) >> 8);
+                                       red = (byte)(transparentPixel & 0xFF);
+                                       break;
+                               case 32:
+                                       blue = (byte)((transparentPixel & 0xFF000000) >>> 24);
+                                       green = (byte)((transparentPixel & 0xFF0000) >> 16);
+                                       red = (byte)((transparentPixel & 0xFF00) >> 8);
+                                       break;
+                       }
+               }
+       }
+       byte [] srcData = new byte [sizeInBytes];
+       OS.MoveMemory (srcData, pBits [0], sizeInBytes);
+       if (hMask != 0) {
+               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) != 0) {
+                                       srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData[dp + 3] = (byte)0;
+                               } else {
+                                       srcData[dp + 3] = (byte)0xFF;
+                               }
+                               dp += 4;
+                       }
+               }
+       } else if (alpha != -1) {
+               for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                       for (int x = 0; x < imgWidth; ++x) {
+                               int r = ((srcData[dp + 0] & 0xFF) * alpha) + 128;
+                               r = (r + (r >> 8)) >> 8;
+                               int g = ((srcData[dp + 1] & 0xFF) * alpha) + 128;
+                               g = (g + (g >> 8)) >> 8;
+                               int b = ((srcData[dp + 2] & 0xFF) * alpha) + 128;
+                               b = (b + (b >> 8)) >> 8;
+                               srcData[dp+0] = (byte)r;
+                               srcData[dp+1] = (byte)g;
+                               srcData[dp+2] = (byte)b;
+                               srcData[dp+3] = (byte)alpha;
+                               dp += 4;
+                       }
+               }
+       } else if (alphaData != null) {
+               for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
+                       for (int x = 0; x < imgWidth; ++x) {
+                               int a = alphaData[ap++] & 0xFF;
+                               int r = ((srcData[dp + 0] & 0xFF) * a) + 128;
+                               r = (r + (r >> 8)) >> 8;
+                               int g = ((srcData[dp + 1] & 0xFF) * a) + 128;
+                               g = (g + (g >> 8)) >> 8;
+                               int b = ((srcData[dp + 2] & 0xFF) * a) + 128;
+                               b = (b + (b >> 8)) >> 8;
+                               srcData[dp+0] = (byte)r;
+                               srcData[dp+1] = (byte)g;
+                               srcData[dp+2] = (byte)b;
+                               srcData[dp+3] = (byte)a;
+                               dp += 4;
+                       }
+               }
+       } else if (transparentPixel != -1) {
+               for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                       for (int x = 0; x < imgWidth; ++x) {
+                               if (srcData [dp] == blue && srcData [dp + 1] == green && srcData [dp + 2] == red) {
+                                       srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData [dp + 3] = (byte)0;
+                               } else {
+                                       srcData [dp + 3] = (byte)0xFF;
+                               }
+                               dp += 4;
+                       }
+               }
+       } else {
+               for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                       for (int x = 0; x < imgWidth; ++x) {
+                               srcData [dp + 3] = (byte)0xFF;
+                               dp += 4;
+                       }
+               }
+       }
+       OS.MoveMemory (pBits [0], srcData, sizeInBytes);
+       OS.SelectObject (srcHdc, oldSrcBitmap);
+       OS.SelectObject (memHdc, oldMemBitmap);
+       OS.DeleteObject (srcHdc);
+       OS.DeleteObject (memHdc);
+       OS.ReleaseDC (0, hDC);
+       if (hBitmap != image.handle && hBitmap != 0) OS.DeleteObject (hBitmap);
+       if (hMask != 0) OS.DeleteObject (hMask);
+       return memDib;
+}
+static long create32bitDIB (long hBitmap, int alpha, byte [] alphaData, int transparentPixel) {
+       BITMAP bm = new BITMAP ();
+       OS.GetObject (hBitmap, BITMAP.sizeof, bm);
+       int imgWidth = bm.bmWidth;
+       int imgHeight = bm.bmHeight;
+       long hDC = OS.GetDC (0);
+       long srcHdc = OS.CreateCompatibleDC (hDC);
+       long oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
+       long memHdc = OS.CreateCompatibleDC (hDC);
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+       bmiHeader.biWidth = imgWidth;
+       bmiHeader.biHeight = -imgHeight;
+       bmiHeader.biPlanes = 1;
+       bmiHeader.biBitCount = (short)32;
+       bmiHeader.biCompression = OS.BI_RGB;
+       byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
+       OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+       long [] pBits = new long [1];
+       long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+       if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+       long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+       BITMAP dibBM = new BITMAP ();
+       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 != -1) {
+               if (bm.bmBitsPixel <= 8) {
+                       byte [] color = new byte [4];
+                       OS.GetDIBColorTable (srcHdc, transparentPixel, 1, color);
+                       blue = color [0];
+                       green = color [1];
+                       red = color [2];
+               } else {
+                       switch (bm.bmBitsPixel) {
+                               case 16:
+                                       blue = (byte)((transparentPixel & 0x1F) << 3);
+                                       green = (byte)((transparentPixel & 0x3E0) >> 2);
+                                       red = (byte)((transparentPixel & 0x7C00) >> 7);
+                                       break;
+                               case 24:
+                                       blue = (byte)((transparentPixel & 0xFF0000) >> 16);
+                                       green = (byte)((transparentPixel & 0xFF00) >> 8);
+                                       red = (byte)(transparentPixel & 0xFF);
+                                       break;
+                               case 32:
+                                       blue = (byte)((transparentPixel & 0xFF000000) >>> 24);
+                                       green = (byte)((transparentPixel & 0xFF0000) >> 16);
+                                       red = (byte)((transparentPixel & 0xFF00) >> 8);
+                                       break;
+                       }
+               }
+       }
+       OS.SelectObject (srcHdc, oldSrcBitmap);
+       OS.SelectObject (memHdc, oldMemBitmap);
+       OS.DeleteObject (srcHdc);
+       OS.DeleteObject (memHdc);
+       OS.ReleaseDC (0, hDC);
+       byte [] srcData = new byte [sizeInBytes];
+       OS.MoveMemory (srcData, pBits [0], sizeInBytes);
+       if (alpha != -1) {
+               for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                       for (int x = 0; x < imgWidth; ++x) {
+                               srcData [dp + 3] = (byte)alpha;
+                               dp += 4;
+                       }
+               }
+       } else if (alphaData != 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 != -1) {
+               for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                       for (int x = 0; x < imgWidth; ++x) {
+                               if (srcData [dp] == blue && srcData [dp + 1] == green && srcData [dp + 2] == red) {
+                                       srcData [dp + 3] = (byte)0;
+                               } else {
+                                       srcData [dp + 3] = (byte)0xFF;
+                               }
+                               dp += 4;
+                       }
+               }
+       }
+       OS.MoveMemory (pBits [0], srcData, sizeInBytes);
+       return memDib;
+}
+
+static Image createIcon (Image image) {
+       Device device = image.getDevice ();
+       ImageData data = image.getImageData (DPIUtil.getDeviceZoom ());
+       if (data.alpha == -1 && data.alphaData == null) {
+               ImageData mask = data.getTransparencyMask ();
+               return new Image (device, data, mask);
+       }
+       int width = data.width, height = data.height;
+       long hMask, hBitmap;
+       long hDC = device.internal_new_GC (null);
+       long dstHdc = OS.CreateCompatibleDC (hDC), oldDstBitmap;
+       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);
+       OS.SelectObject (dstHdc, oldDstBitmap);
+       OS.DeleteDC (dstHdc);
+       device.internal_dispose_GC (hDC, null);
+       ICONINFO info = new ICONINFO ();
+       info.fIcon = true;
+       info.hbmColor = hBitmap;
+       info.hbmMask = hMask;
+       long hIcon = OS.CreateIconIndirect (info);
+       if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+       OS.DeleteObject (hBitmap);
+       OS.DeleteObject (hMask);
+       return Image.win32_new (device, SWT.ICON, hIcon);
+}
+
+static void deregister (Display display) {
+       synchronized (Device.class) {
+               for (int i=0; i<Displays.length; i++) {
+                       if (display == 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 == 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 == null) disposeList = new Runnable [4];
+       for (int i=0; i<disposeList.length; i++) {
+               if (disposeList [i] == null) {
+                       disposeList [i] = runnable;
+                       return;
+               }
+       }
+       Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
+       System.arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
+       newDisposeList [disposeList.length] = runnable;
+       disposeList = newDisposeList;
+}
+
+void drawMenuBars () {
+       if (bars == null) return;
+       for (int i=0; i<bars.length; i++) {
+               Menu menu = bars [i];
+               if (menu != null && !menu.isDisposed ()) menu.update ();
+       }
+       bars = null;
+}
+
+long embeddedProc (long hwnd, long msg, long wParam, long lParam) {
+       switch ((int)msg) {
+               case SWT_KEYMSG: {
+                       MSG keyMsg = new MSG ();
+                       OS.MoveMemory (keyMsg, lParam, MSG.sizeof);
+                       OS.TranslateMessage (keyMsg);
+                       OS.DispatchMessage (keyMsg);
+                       long hHeap = OS.GetProcessHeap ();
+                       OS.HeapFree (hHeap, 0, lParam);
+                       break;
+               }
+               case SWT_DESTROY: {
+                       OS.DestroyWindow (hwnd);
+                       if (embeddedCallback != null) embeddedCallback.dispose ();
+                       if (getMsgCallback != null) getMsgCallback.dispose ();
+                       embeddedCallback = getMsgCallback = null;
+                       embeddedProc = getMsgProc = 0;
+                       break;
+               }
+       }
+       return OS.DefWindowProc (hwnd, (int)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);
+}
+
+boolean filterEvent (Event event) {
+       if (filterTable != null) {
+               int type = event.type;
+               sendPreEvent (type);
+               try {
+                       filterTable.sendEvent (event);
+               } finally {
+                       sendPostEvent (type);
+               }
+       }
+       return false;
+}
+
+boolean filters (int eventType) {
+       if (filterTable == null) return false;
+       return filterTable.hooks (eventType);
+}
+
+boolean filterMessage (MSG msg) {
+       int message = msg.message;
+       if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
+               Control control = findControl (msg.hwnd);
+               if (control != null) {
+                       if (translateAccelerator (msg, control) || translateMnemonic (msg, control) || translateTraversal (msg, control)) {
+                               lastAscii = lastKey = 0;
+                               lastVirtual = lastNull = lastDead = false;
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+Control findControl (long handle) {
+       if (handle == 0) return null;
+       long hwndOwner = 0;
+       do {
+               Control control = getControl (handle);
+               if (control != null) return control;
+               hwndOwner = OS.GetWindow (handle, OS.GW_OWNER);
+               handle = OS.GetParent (handle);
+       } while (handle != 0 && handle != 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public Widget findWidget (long 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.1
+ */
+public Widget findWidget (long handle, long id) {
+       checkDevice ();
+       Control control = getControl (handle);
+       return control != null ? control.findItem (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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.3
+ */
+public Widget findWidget (Widget widget, long id) {
+       checkDevice ();
+       if (widget instanceof Control) {
+               return findWidget (((Control) widget).handle, id);
+       }
+       return null;
+}
+
+long foregroundIdleProc (long code, long wParam, long lParam) {
+       if (code >= 0) {
+               if (getMessageCount () != 0) {
+                       sendPostExternalEventDispatchEvent ();
+                       if (runMessagesInIdle) {
+                               if (runMessagesInMessageProc) {
+                                       OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
+                               } else {
+                                       runAsyncMessages (false);
+                               }
+                       }
+                       /*
+                       * Bug in Windows.  For some reason, input events can be lost
+                       * when a message is posted to the queue from a foreground idle
+                       * hook.  The fix is to detect that there are outstanding input
+                       * events and avoid posting the wake event.
+                       *
+                       * Note that PeekMessage() changes the state of events on the
+                       * queue to no longer be considered new. If we peek for input
+                       * events and posted messages (PM_QS_INPUT | PM_QS_POSTMESSAGE),
+                       * it is possible to cause WaitMessage() to sleep until a new
+                       * input event is generated causing sync runnables not to be
+                       * executed.
+                       */
+                       MSG msg = new MSG();
+                       int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT;
+                       if (!OS.PeekMessage (msg, 0, 0, 0, flags)) wakeThread ();
+                       sendPreExternalEventDispatchEvent ();
+               }
+       }
+       return OS.CallNextHookEx (idleHook, (int)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) {
+       synchronized (Device.class) {
+               for (int i=0; i<Displays.length; i++) {
+                       Display display = Displays [i];
+                       if (display != null && display.thread == thread) {
+                               return display;
+                       }
+               }
+               return null;
+       }
+}
+
+TouchSource findTouchSource (long touchDevice, Monitor monitor) {
+       if (touchSources == null) touchSources = new TouchSource [4];
+       int length = touchSources.length;
+       for (int i=0; i<length; i++) {
+               if (touchSources [i] != null && touchSources [i].handle == touchDevice) {
+                       return touchSources [i];
+               }
+       }
+       int index = 0;
+       while (index < length) {
+               if (touchSources [index] == null) break;
+               index++;
+       }
+       if (index == length) {
+               TouchSource [] newTouchSources = new TouchSource [length + 4];
+               System.arraycopy (touchSources, 0, newTouchSources, 0, length);
+               touchSources = newTouchSources;
+       }
+       return touchSources [index] = new TouchSource (touchDevice, true, monitor.getBounds ());
+}
+
+/**
+ * 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 != null ? control.getShell () : null;
+}
+
+/**
+ * Returns the single instance of the application menu bar, or
+ * <code>null</code> if there is no application menu bar for the platform.
+ *
+ * @return the application menu bar, or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.7
+ */
+public Menu getMenuBar () {
+       checkDevice ();
+       return 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 ();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels () {
+       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 () {
+       return findDisplay (Thread.currentThread ());
+}
+
+int getClickCount (int type, int button, long hwnd, long lParam) {
+       switch (type) {
+               case SWT.MouseDown:
+                       int doubleClick = OS.GetDoubleClickTime ();
+                       if (clickRect == null) clickRect = new RECT ();
+                       int deltaTime = Math.abs (lastTime - getLastEventTime ());
+                       POINT pt = new POINT ();
+                       OS.POINTSTOPOINT (pt, lParam);
+                       if (lastClickHwnd == hwnd && lastButton == 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;
+       }
+       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 ();
+       return DPIUtil.autoScaleDown(getClientAreaInPixels());
+}
+
+Rectangle getClientAreaInPixels () {
+       checkDevice ();
+       if (OS.GetSystemMetrics (OS.SM_CMONITORS) < 2) {
+               RECT rect = new 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 (long handle) {
+       if (handle == 0) return null;
+       if (lastControl != null && lastHwnd == handle) {
+               return lastControl;
+       }
+       if (lastGetControl != null && lastGetHwnd == handle) {
+               return lastGetControl;
+       }
+       int index = (int)OS.GetProp (handle, SWT_OBJECT_INDEX) - 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 != 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 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>
+ */
+public Control getCursorControl () {
+       checkDevice ();
+       POINT pt = new POINT ();
+       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 ();
+       return DPIUtil.autoScaleDown(getCursorLocationInPixels());
+}
+
+Point getCursorLocationInPixels () {
+       POINT pt = new POINT ();
+       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 [] {
+               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 () {
+       synchronized (Device.class) {
+               if (Default == null) Default = new Display ();
+               return Default;
+       }
+}
+
+/**
+ * @since 3.108
+ */
+@Override
+protected int getDeviceZoom() {
+       /*
+        * Win8.1 and above we should pick zoom for the primary monitor which always
+        * reflects the latest OS zoom value, for more details refer bug 537273.
+        */
+       if (OS.WIN32_VERSION >= OS.VERSION (6, 3)) {
+               return getPrimaryMonitor().getZoom();
+       }
+       /* Otherwise return Windows zoom level, as set during session login. */
+       return super.getDeviceZoom();
+}
+
+static boolean 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the key 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 #setData(String, Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData (String key) {
+       checkDevice ();
+       if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) {
+               return runMessagesInIdle;
+       }
+       if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
+               return runMessagesInMessageProc;
+       }
+       if (key.equals (USE_OWNDC_KEY)) {
+               return useOwnDC;
+       }
+       if (key.equals (ACCEL_KEY_HIT)) {
+               return accelKeyHit;
+       }
+       if (keys == null) return null;
+       for (int i=0; i<keys.length; i++) {
+               if (keys [i].equals (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 focus control 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>
+ */
+public Control getFocusControl () {
+       checkDevice ();
+       if (focusControl != null && !focusControl.isDisposed ()) {
+               return focusControl;
+       }
+       return _getFocusControl ();
+}
+
+String getFontName (LOGFONT logFont) {
+       char[] chars = logFont.lfFaceName;
+       int index = 0;
+       while (index < chars.length) {
+               if (chars [index] == 0) break;
+               index++;
+       }
+       return new String (chars, 0, index);
+}
+
+/**
+ * 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 boolean getHighContrast () {
+       checkDevice ();
+       HIGHCONTRAST pvParam = new HIGHCONTRAST ();
+       pvParam.cbSize = HIGHCONTRAST.sizeof;
+       OS.SystemParametersInfo (OS.SPI_GETHIGHCONTRAST, 0, pvParam, 0);
+       return (pvParam.dwFlags & OS.HCF_HIGHCONTRASTON) != 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 (getDepth () >= 24) return 32;
+
+       /* Use the character encoding for the default locale */
+       TCHAR buffer1 = new TCHAR (0, "Control Panel\\Desktop\\WindowMetrics", true); //$NON-NLS-1$
+
+       long [] phkResult = new long [1];
+       int result = OS.RegOpenKeyEx (OS.HKEY_CURRENT_USER, buffer1, 0, OS.KEY_READ, phkResult);
+       if (result != 0) return 4;
+       int depth = 4;
+       int [] lpcbData = new int [1];
+
+       /* Use the character encoding for the default locale */
+       TCHAR buffer2 = new TCHAR (0, "Shell Icon BPP", true); //$NON-NLS-1$
+       result = OS.RegQueryValueEx (phkResult [0], buffer2, 0, null, (TCHAR) null, lpcbData);
+       if (result == 0) {
+               TCHAR lpData = new TCHAR (0, lpcbData [0] / TCHAR.sizeof);
+               result = OS.RegQueryValueEx (phkResult [0], buffer2, 0, null, lpData, lpcbData);
+               if (result == 0) {
+                       try {
+                               depth = Integer.parseInt (lpData.toString (0, lpData.strlen ()));
+                       } catch (NumberFormatException e) {}
+               }
+       }
+       OS.RegCloseKey (phkResult [0]);
+       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 [] {
+               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 == null) imageList = new ImageList [4];
+
+       int i = 0;
+       int length = imageList.length;
+       while (i < length) {
+               ImageList list = imageList [i];
+               if (list == null) break;
+               Point size = list.getImageSize();
+               if (size.x == width && size.y == height) {
+                       if (list.getStyle () == style) {
+                               list.addRef();
+                               return list;
+                       }
+               }
+               i++;
+       }
+
+       if (i == length) {
+               ImageList [] newList = new ImageList [length + 4];
+               System.arraycopy (imageList, 0, newList, 0, length);
+               imageList = newList;
+       }
+
+       ImageList list = new ImageList (style, width, height);
+       imageList [i] = list;
+       list.addRef();
+       return list;
+}
+
+ImageList getImageListToolBar (int style, int width, int height) {
+       if (toolImageList == null) toolImageList = new ImageList [4];
+
+       int i = 0;
+       int length = toolImageList.length;
+       while (i < length) {
+               ImageList list = toolImageList [i];
+               if (list == null) break;
+               Point size = list.getImageSize();
+               if (size.x == width && size.y == height) {
+                       if (list.getStyle () == style) {
+                               list.addRef();
+                               return list;
+                       }
+               }
+               i++;
+       }
+
+       if (i == length) {
+               ImageList [] newList = new ImageList [length + 4];
+               System.arraycopy (toolImageList, 0, newList, 0, length);
+               toolImageList = newList;
+       }
+
+       ImageList list = new ImageList (style, width, height);
+       toolImageList [i] = list;
+       list.addRef();
+       return list;
+}
+
+ImageList getImageListToolBarDisabled (int style, int width, int height) {
+       if (toolDisabledImageList == null) toolDisabledImageList = new ImageList [4];
+
+       int i = 0;
+       int length = toolDisabledImageList.length;
+       while (i < length) {
+               ImageList list = toolDisabledImageList [i];
+               if (list == null) break;
+               Point size = list.getImageSize();
+               if (size.x == width && size.y == height) {
+                       if (list.getStyle () == style) {
+                               list.addRef();
+                               return list;
+                       }
+               }
+               i++;
+       }
+
+       if (i == length) {
+               ImageList [] newList = new ImageList [length + 4];
+               System.arraycopy (toolDisabledImageList, 0, newList, 0, length);
+               toolDisabledImageList = newList;
+       }
+
+       ImageList list = new ImageList (style, width, height);
+       toolDisabledImageList [i] = list;
+       list.addRef();
+       return list;
+}
+
+ImageList getImageListToolBarHot (int style, int width, int height) {
+       if (toolHotImageList == null) toolHotImageList = new ImageList [4];
+
+       int i = 0;
+       int length = toolHotImageList.length;
+       while (i < length) {
+               ImageList list = toolHotImageList [i];
+               if (list == null) break;
+               Point size = list.getImageSize();
+               if (size.x == width && size.y == height) {
+                       if (list.getStyle () == style) {
+                               list.addRef();
+                               return list;
+                       }
+               }
+               i++;
+       }
+
+       if (i == length) {
+               ImageList [] newList = new ImageList [length + 4];
+               System.arraycopy (toolHotImageList, 0, newList, 0, length);
+               toolHotImageList = newList;
+       }
+
+       ImageList list = new ImageList (style, width, height);
+       toolHotImageList [i] = list;
+       list.addRef();
+       return list;
+}
+
+/**
+ * Returns <code>true</code> if the current OS theme has a dark appearance, else
+ * returns <code>false</code>.
+ * <p>
+ * Note: This operation is a hint and is not supported on platforms that do not
+ * have this concept.
+ * </p>
+ * <p>
+ * Note: Windows 10 onwards users can separately configure the theme for OS and
+ * Application level and this can be read from the Windows registry. Since the
+ * application needs to honor the application level theme, this API reads the
+ * Application level theme setting.
+ * </p>
+ *
+ * @return <code>true</code> if the current OS theme has a dark appearance, else
+ *         returns <code>false</code>.
+ *
+ * @since 3.112
+ */
+public static boolean isSystemDarkTheme () {
+       boolean isDarkTheme = false;
+       /*
+        * Win10 onwards we can read the Dark Theme from the OS registry.
+        */
+       if (OS.WIN32_VERSION >= OS.VERSION (10, 0)) {
+               try {
+                       int result = OS.readRegistryDword(OS.HKEY_CURRENT_USER,
+                                       "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme");
+                       isDarkTheme = (result == 0);
+               } catch (Exception e) {
+                       // Registry entry not found
+               }
+       }
+       return isDarkTheme;
+}
+
+int getLastEventTime () {
+       return OS.GetMessageTime ();
+}
+
+MenuItem getMenuItem (int id) {
+       if (items == null) return null;
+       id = id - ID_START;
+       if (0 <= id && id < items.length) return items [id];
+       return null;
+}
+
+int getMessageCount () {
+       /*
+        * On Windows10 (update 18272), an NPE is seen in below code which leads to a
+        * possible crash, adding a null check for synchronizer instance. For more
+        * details refer bug 540762
+        */
+       if (synchronizer != null) return synchronizer.getMessageCount ();
+       return 0;
+}
+
+
+Shell getModalShell () {
+       if (modalShells == null) return null;
+       int index = modalShells.length;
+       while (--index >= 0) {
+               Shell shell = modalShells [index];
+               if (shell != null) return shell;
+       }
+       return null;
+}
+
+Dialog getModalDialog () {
+       return modalDialog;
+}
+
+Monitor getMonitor (long hmonitor) {
+       MONITORINFO lpmi = new MONITORINFO ();
+       lpmi.cbSize = MONITORINFO.sizeof;
+       OS.GetMonitorInfo (hmonitor, lpmi);
+       Monitor monitor = new Monitor ();
+       monitor.handle = hmonitor;
+       Rectangle boundsInPixels = new Rectangle (lpmi.rcMonitor_left, lpmi.rcMonitor_top, lpmi.rcMonitor_right - lpmi.rcMonitor_left,lpmi.rcMonitor_bottom - lpmi.rcMonitor_top);
+       monitor.setBounds (DPIUtil.autoScaleDown (boundsInPixels));
+       Rectangle clientAreaInPixels = new Rectangle (lpmi.rcWork_left, lpmi.rcWork_top, lpmi.rcWork_right - lpmi.rcWork_left, lpmi.rcWork_bottom - lpmi.rcWork_top);
+       monitor.setClientArea (DPIUtil.autoScaleDown (clientAreaInPixels));
+       if (OS.WIN32_VERSION >= OS.VERSION (6, 3)) {
+               int [] dpiX = new int[1];
+               int [] dpiY = new int[1];
+               int result = OS.GetDpiForMonitor (monitor.handle, OS.MDT_EFFECTIVE_DPI, dpiX, dpiY);
+               result = (result == OS.S_OK) ? DPIUtil.mapDPIToZoom (dpiX[0]) : 100;
+               /*
+                * Always return true monitor zoom value as fetched from native, else will lead
+                * to scaling issue on OS Win8.1 and above, for more details refer bug 537614.
+                */
+               monitor.zoom = result;
+       } else {
+               monitor.zoom = getDeviceZoom ();
+       }
+       return monitor;
+}
+
+/**
+ * Returns an array of monitors attached to the device.
+ *
+ * @return the array of monitors
+ *
+ * @since 3.0
+ */
+public Monitor [] getMonitors () {
+       checkDevice ();
+       monitors = new Monitor [4];
+       Callback callback = new Callback (this, "monitorEnumProc", 4); //$NON-NLS-1$
+       long lpfnEnum = callback.getAddress ();
+       if (lpfnEnum == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+       OS.EnumDisplayMonitors (0, null, lpfnEnum, 0);
+       callback.dispose ();
+       Monitor [] result = new Monitor [monitorCount];
+       System.arraycopy (monitors, 0, result, 0, monitorCount);
+       monitors = null;
+       monitorCount = 0;
+       return result;
+}
+
+long getMsgProc (long code, long wParam, long lParam) {
+       if (embeddedHwnd == 0) {
+               long hInstance = OS.GetModuleHandle (null);
+               embeddedHwnd = OS.CreateWindowEx (0,
+                       windowClass,
+                       null,
+                       OS.WS_OVERLAPPED,
+                       0, 0, 0, 0,
+                       0,
+                       0,
+                       hInstance,
+                       null);
+               embeddedCallback = new Callback (this, "embeddedProc", 4); //$NON-NLS-1$
+               embeddedProc = embeddedCallback.getAddress ();
+               if (embeddedProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+               OS.SetWindowLongPtr (embeddedHwnd, OS.GWLP_WNDPROC, embeddedProc);
+       }
+       if (code >= 0 && (wParam & OS.PM_REMOVE) != 0) {
+               MSG msg = new MSG ();
+               OS.MoveMemory (msg, lParam, MSG.sizeof);
+               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 != null) {
+                                       long hHeap = OS.GetProcessHeap ();
+                                       long keyMsg = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, MSG.sizeof);
+                                       OS.MoveMemory (keyMsg, msg, MSG.sizeof);
+                                       OS.PostMessage (hwndMessage, SWT_KEYMSG, wParam, keyMsg);
+                                       switch ((int)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);
+                                       }
+                               }
+                       }
+               }
+       }
+       return OS.CallNextHookEx (msgHook, (int)code, wParam, lParam);
+}
+
+/**
+ * Returns the primary monitor for that device.
+ *
+ * @return the primary monitor
+ *
+ * @since 3.0
+ */
+public Monitor getPrimaryMonitor () {
+       checkDevice ();
+       long hmonitor = OS.MonitorFromWindow (0, OS.MONITOR_DEFAULTTOPRIMARY);
+       return getMonitor (hmonitor);
+}
+
+/**
+ * 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 != null && control instanceof Shell) {
+                       int j = 0;
+                       while (j < index) {
+                               if (result [j] == control) break;
+                               j++;
+                       }
+                       if (j == index) {
+                               if (index == result.length) {
+                                       Shell [] newResult = new Shell [index + 16];
+                                       System.arraycopy (result, 0, newResult, 0, index);
+                                       result = newResult;
+                               }
+                               result [index++] = (Shell) control;
+                       }
+               }
+       }
+       if (index == result.length) return result;
+       Shell [] newResult = new Shell [index];
+       System.arraycopy (result, 0, newResult, 0, index);
+       return newResult;
+}
+
+/**
+ * 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.class) {
+               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_DISABLED_FOREGROUND: pixel = OS.GetSysColor(OS.COLOR_GRAYTEXT); 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_TEXT_DISABLED_BACKGROUND:
+               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_LINK_FOREGROUND:         pixel = OS.GetSysColor (OS.COLOR_HOTLIGHT);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 == 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 == 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] == 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 != null) return systemFont;
+       long hFont = 0;
+       NONCLIENTMETRICS info = new NONCLIENTMETRICS ();
+       info.cbSize = NONCLIENTMETRICS.sizeof;
+       if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, info, 0)) {
+               LOGFONT logFont = info.lfMessageFont;
+               hFont = OS.CreateFontIndirect (logFont);
+               lfSystemFont = hFont != 0 ? logFont : null;
+       }
+       if (hFont == 0) hFont = OS.GetStockObject (OS.DEFAULT_GUI_FONT);
+       if (hFont == 0) 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 != null) return errorImage;
+                       long hIcon = OS.LoadImage (0, 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 != null) return infoImage;
+                       long hIcon = OS.LoadImage (0, 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 != null) return questionImage;
+                       long hIcon = OS.LoadImage (0, 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 != null) return warningIcon;
+                       long hIcon = OS.LoadImage (0, OS.OIC_BANG, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
+                       return warningIcon = Image.win32_new (this, SWT.ICON, hIcon);
+               }
+       }
+       return null;
+}
+
+/**
+ * Returns the single instance of the system-provided menu for the application, or
+ * <code>null</code> on platforms where no menu is provided for the application.
+ *
+ * @return the system menu, 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>
+ *
+ * @since 3.7
+ */
+public Menu getSystemMenu () {
+       checkDevice();
+       return null;
+}
+
+/**
+ * Returns the single instance of the system taskBar or null
+ * when there is no system taskBar available for the platform.
+ *
+ * @return the system taskBar or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.6
+ */
+public TaskBar getSystemTaskBar () {
+       checkDevice ();
+       if (taskBar != null) return taskBar;
+       if (OS.WIN32_VERSION >= OS.VERSION (6, 1)) {
+               taskBar = new TaskBar (this, SWT.NONE);
+       }
+       return taskBar;
+}
+
+/**
+ * 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 == null) 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.class) {
+               if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+               return thread;
+       }
+}
+
+/**
+ * Returns a boolean indicating whether a touch-aware input device is
+ * attached to the system and is ready for use.
+ *
+ * @return <code>true</code> if a touch-aware input device is detected, or <code>false</code> otherwise
+ *
+ * @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.7
+ */
+public boolean getTouchEnabled () {
+       checkDevice();
+       int value = OS.GetSystemMetrics (OS.SM_DIGITIZER);
+       return (value & (OS.NID_READY | OS.NID_MULTI_INPUT)) == (OS.NID_READY | OS.NID_MULTI_INPUT);
+}
+
+long hButtonTheme () {
+       if (hButtonTheme != 0) return hButtonTheme;
+       return hButtonTheme = OS.OpenThemeData (hwndMessage, BUTTON);
+}
+
+long hEditTheme () {
+       if (hEditTheme != 0) return hEditTheme;
+       return hEditTheme = OS.OpenThemeData (hwndMessage, EDIT);
+}
+
+long hExplorerBarTheme () {
+       if (hExplorerBarTheme != 0) return hExplorerBarTheme;
+       return hExplorerBarTheme = OS.OpenThemeData (hwndMessage, EXPLORERBAR);
+}
+
+long hScrollBarTheme () {
+       if (hScrollBarTheme != 0) return hScrollBarTheme;
+       return hScrollBarTheme = OS.OpenThemeData (hwndMessage, SCROLLBAR);
+}
+
+long hTabTheme () {
+       if (hTabTheme != 0) return hTabTheme;
+       return hTabTheme = OS.OpenThemeData (hwndMessage, TAB);
+}
+
+/**
+ * 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>
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public long internal_new_GC (GCData data) {
+       if (isDisposed()) error(SWT.ERROR_DEVICE_DISPOSED);
+       long hDC = OS.GetDC (0);
+       if (hDC == 0) error (SWT.ERROR_NO_HANDLES);
+       if (data != null) {
+               int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+               if ((data.style & mask) != 0) {
+                       data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 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 ();
+       DPIUtil.setDeviceZoom (getDeviceZoom ());
+
+       /* Set the application user model ID, if APP_NAME is non Default */
+       char [] appName = null;
+       if (APP_NAME != null && !"SWT".equalsIgnoreCase (APP_NAME)) {
+               if (OS.WIN32_VERSION >= OS.VERSION (6, 1)) {
+                       int length = APP_NAME.length ();
+                       appName = new char [length + 1];
+                       APP_NAME.getChars (0, length, appName, 0);
+                       long [] appID = new long [1];
+                       if (OS.GetCurrentProcessExplicitAppUserModelID(appID) != 0) {
+                               OS.SetCurrentProcessExplicitAppUserModelID (appName);
+                       }
+                       if (appID[0] != 0) OS.CoTaskMemFree(appID[0]);
+               }
+       }
+
+       /* Create the callbacks */
+       windowCallback = new Callback (this, "windowProc", 4); //$NON-NLS-1$
+       windowProc = windowCallback.getAddress ();
+       if (windowProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+       /* Remember the current thread id */
+       threadId = OS.GetCurrentThreadId ();
+
+       /* Use the character encoding for the default locale */
+       windowClass = new TCHAR (0, WindowName + WindowClassCount, true);
+       windowShadowClass = new TCHAR (0, WindowShadowName + WindowClassCount, true);
+       windowOwnDCClass = new TCHAR (0, WindowOwnDCName + WindowClassCount, true);
+       WindowClassCount++;
+
+       /* Register the SWT window class */
+       long hInstance = OS.GetModuleHandle (null);
+       WNDCLASS lpWndClass = new WNDCLASS ();
+       lpWndClass.hInstance = hInstance;
+       lpWndClass.lpfnWndProc = windowProc;
+       lpWndClass.style = OS.CS_DBLCLKS;
+       lpWndClass.hCursor = OS.LoadCursor (0, OS.IDC_ARROW);
+       lpWndClass.hIcon = OS.LoadIcon (0, OS.IDI_APPLICATION);
+       OS.RegisterClass (windowClass, lpWndClass);
+
+       /* Register the SWT drop shadow window class */
+       lpWndClass.style |= OS.CS_DROPSHADOW;
+       OS.RegisterClass (windowShadowClass, lpWndClass);
+
+       /* Register the CS_OWNDC window class */
+       lpWndClass.style |= OS.CS_OWNDC;
+       OS.RegisterClass (windowOwnDCClass, lpWndClass);
+
+       /* Create the message only HWND */
+       hwndMessage = OS.CreateWindowEx (0,
+               windowClass,
+               null,
+               OS.WS_OVERLAPPED,
+               0, 0, 0, 0,
+               0,
+               0,
+               hInstance,
+               null);
+       String title = "SWT_Window_"+APP_NAME;
+       OS.SetWindowText(hwndMessage, new TCHAR(0, title, true));
+       messageCallback = new Callback (this, "messageProc", 4); //$NON-NLS-1$
+       messageProc = messageCallback.getAddress ();
+       if (messageProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+       OS.SetWindowLongPtr (hwndMessage, OS.GWLP_WNDPROC, messageProc);
+
+       /* Create the filter hook */
+       msgFilterCallback = new Callback (this, "msgFilterProc", 3); //$NON-NLS-1$
+       msgFilterProc = msgFilterCallback.getAddress ();
+       if (msgFilterProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+       filterHook = OS.SetWindowsHookEx (OS.WH_MSGFILTER, msgFilterProc, 0, threadId);
+
+       /* Create the idle hook */
+       foregroundIdleCallback = new Callback (this, "foregroundIdleProc", 3); //$NON-NLS-1$
+       foregroundIdleProc = foregroundIdleCallback.getAddress ();
+       if (foregroundIdleProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+       idleHook = OS.SetWindowsHookEx (OS.WH_FOREGROUNDIDLE, foregroundIdleProc, 0, threadId);
+
+       /* Register window messages */
+       TASKBARCREATED = OS.RegisterWindowMessage (new TCHAR (0, "TaskbarCreated", true)); //$NON-NLS-1$
+       TASKBARBUTTONCREATED = OS.RegisterWindowMessage (new TCHAR (0, "TaskbarButtonCreated", true)); //$NON-NLS-1$
+       SWT_RESTORECARET = OS.RegisterWindowMessage (new TCHAR (0, "SWT_RESTORECARET", true)); //$NON-NLS-1$
+       DI_GETDRAGIMAGE = OS.RegisterWindowMessage (new TCHAR (0, "ShellGetDragImage", true)); //$NON-NLS-1$
+       SWT_OPENDOC = OS.RegisterWindowMessage(new TCHAR (0, "SWT_OPENDOC", true)); //$NON-NLS-1$
+
+       /* Initialize OLE */
+       OS.OleInitialize (0);
+
+       if (appName != null) {
+               /* Delete any old jump list set for the ID */
+               long [] ppv = new long [1];
+               int hr = COM.CoCreateInstance (COM.CLSID_DestinationList, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ICustomDestinationList, ppv);
+               if (hr == OS.S_OK) {
+                       ICustomDestinationList pList = new ICustomDestinationList (ppv [0]);
+                       pList.DeleteList (appName);
+                       pList.Release ();
+               }
+       }
+
+       /* Initialize buffered painting */
+       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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void internal_dispose_GC (long hDC, GCData data) {
+       OS.ReleaseDC (0, hDC);
+}
+
+boolean isXMouseActive () {
+       /*
+       * NOTE: X-Mouse is active when bit 1 of the UserPreferencesMask is set.
+       */
+       boolean xMouseActive = false;
+       try {
+               int result = OS.readRegistryDword(OS.HKEY_CURRENT_USER, "Control Panel\\Desktop", "UserPreferencesMask");
+               xMouseActive = (result & 0x01) != 0;
+       } catch (Exception e) {
+               // Registry entry not found
+       }
+       return xMouseActive;
+}
+
+boolean isValidThread () {
+       return thread == Thread.currentThread ();
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       point = DPIUtil.autoScaleUp(point);
+       return DPIUtil.autoScaleDown(mapInPixels(from, to, point));
+}
+
+Point mapInPixels (Control from, Control to, Point point) {
+       return mapInPixels (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 ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       return DPIUtil.autoScaleDown(mapInPixels(from, to, x, y));
+}
+
+Point mapInPixels (Control from, Control to, int x, int y) {
+       if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (from == to) return new Point (x, y);
+       long hwndFrom = from != null ? from.handle : 0;
+       long hwndTo = to != null ? to.handle : 0;
+       POINT point = new 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       rectangle = DPIUtil.autoScaleUp(rectangle);
+       return DPIUtil.autoScaleDown(mapInPixels(from, to, rectangle));
+}
+
+Rectangle mapInPixels (Control from, Control to, Rectangle rectangle) {
+       return mapInPixels (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 ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       return DPIUtil.autoScaleDown(mapInPixels(from, to, x, y, width, height));
+}
+
+Rectangle mapInPixels (Control from, Control to, int x, int y, int width, int height) {
+       if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (from == to) return new Rectangle (x, y, width, height);
+       long hwndFrom = from != null ? from.handle : 0;
+       long hwndTo = to != null ? to.handle : 0;
+       RECT rect = new RECT ();
+       rect.left = x;
+       rect.top  = y;
+       rect.right = x + width;
+       rect.bottom = y + height;
+       OS.MapWindowPoints (hwndFrom, hwndTo, rect, 2);
+       return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+long messageProc (long hwnd, long msg, long wParam, long lParam) {
+       switch ((int)msg) {
+               case SWT_RUNASYNC: {
+                       if (runMessagesInIdle) runAsyncMessages (false);
+                       break;
+               }
+               case SWT_KEYMSG: {
+                       boolean consumed = false;
+                       MSG keyMsg = new MSG ();
+                       OS.MoveMemory (keyMsg, lParam, MSG.sizeof);
+                       Control control = findControl (keyMsg.hwnd);
+                       if (control != 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().
+                               */
+                               boolean accentKey = false;
+                               switch (keyMsg.message) {
+                                       case OS.WM_KEYDOWN:
+                                       case OS.WM_SYSKEYDOWN: {
+                                               switch ((int)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: {
+                                                               int mapKey = OS.MapVirtualKey ((int)keyMsg.wParam, 2);
+                                                               if (mapKey != 0) {
+                                                                       accentKey = (mapKey & 0x80000000) != 0;
+                                                                       if (!accentKey) {
+                                                                               for (int i=0; i<ACCENTS.length; i++) {
+                                                                                       int value = OS.VkKeyScan (ACCENTS [i]);
+                                                                                       if (value != -1 && (value & 0xFF) == keyMsg.wParam) {
+                                                                                               int state = value >> 8;
+                                                                                               if ((OS.GetKeyState (OS.VK_SHIFT) < 0) == ((state & 0x1) != 0) &&
+                                                                                                       (OS.GetKeyState (OS.VK_CONTROL) < 0) == ((state & 0x2) != 0) &&
+                                                                                                       (OS.GetKeyState (OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
+                                                                                                               if ((state & 0x7) != 0) accentKey = true;
+                                                                                                               break;
+                                                                                               }
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                               break;
+                                       }
+                               }
+                               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) == 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 ((int)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;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       switch ((int)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;
+                       }
+                       if (consumed) {
+                               long hHeap = OS.GetProcessHeap ();
+                               OS.HeapFree (hHeap, 0, lParam);
+                       } else {
+                               OS.PostMessage (embeddedHwnd, SWT_KEYMSG, wParam, lParam);
+                       }
+                       return 0;
+               }
+               case SWT_TRAYICONMSG: {
+                       if (tray != null) {
+                               TrayItem [] items = tray.items;
+                               for (int i=0; i<items.length; i++) {
+                                       TrayItem item = items [i];
+                                       if (item != null && item.id == wParam) {
+                                               return item.messageProc (hwnd, (int)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 != 0) {
+                               if (!isXMouseActive ()) {
+                                       long hwndActive = OS.GetActiveWindow ();
+                                       if (hwndActive != 0 && OS.IsWindowEnabled (hwndActive)) break;
+                                       Shell modal = modalDialog != null ? modalDialog.parent : getModalShell ();
+                                       if (modal != null && !modal.isDisposed ()) {
+                                               long hwndModal = modal.handle;
+                                               if (OS.IsWindowEnabled (hwndModal)) {
+                                                       modal.bringToTop ();
+                                                       if (modal.isDisposed ()) break;
+                                               }
+                                               long hwndPopup = OS.GetLastActivePopup (hwndModal);
+                                               if (hwndPopup != 0 && hwndPopup != modal.handle) {
+                                                       if (getControl (hwndPopup) == null) {
+                                                               if (OS.IsWindowEnabled (hwndPopup)) {
+                                                                       OS.SetActiveWindow (hwndPopup);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+               }
+               case OS.WM_ENDSESSION: {
+                       if (wParam != 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:
+               case OS.WM_SETTINGCHANGE: {
+                       /* Set the initial timer or push the time out period forward */
+                       OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, 0);
+                       break;
+               }
+               case OS.WM_THEMECHANGED: {
+                       if (hButtonTheme != 0) OS.CloseThemeData (hButtonTheme);
+                       if (hEditTheme != 0) OS.CloseThemeData (hEditTheme);
+                       if (hExplorerBarTheme != 0) OS.CloseThemeData (hExplorerBarTheme);
+                       if (hScrollBarTheme != 0) OS.CloseThemeData (hScrollBarTheme);
+                       if (hTabTheme != 0) OS.CloseThemeData (hTabTheme);
+                       hButtonTheme = hEditTheme = hExplorerBarTheme = hScrollBarTheme = hTabTheme = 0;
+                       break;
+               }
+               case OS.WM_TIMER: {
+                       if (wParam == SETTINGS_ID) {
+                               OS.KillTimer (hwndMessage, SETTINGS_ID);
+                               runSettings ();
+                       } else {
+                               runTimer (wParam);
+                       }
+                       break;
+               }
+               default: {
+                       if ((int)msg == TASKBARCREATED) {
+                               if (tray != null) {
+                                       TrayItem [] items = tray.items;
+                                       for (int i=0; i<items.length; i++) {
+                                               TrayItem item = items [i];
+                                               if (item != null) item.recreate ();
+                                       }
+                               }
+                       }
+                       if ((int)msg == SWT_OPENDOC) {
+                               String filename = getSharedData((int)wParam, (int)lParam);
+                               if (filename != null) {
+                                       if (filename.startsWith (TASKBAR_EVENT)) {
+                                               String text = filename.substring (TASKBAR_EVENT.length ());
+                                               int id = Integer.parseInt (text);
+                                               MenuItem item = getMenuItem (id);
+                                               if (item != null) {
+                                                       item.sendSelectionEvent (SWT.Selection);
+                                               }
+                                       } else {
+                                               Event event = new Event ();
+                                               event.text = filename;
+                                               try {
+                                                       new URI (filename);
+                                                       sendEvent (SWT.OpenUrl, event);
+                                               } catch (URISyntaxException e) {
+                                                       sendEvent (SWT.OpenDocument, event);
+                                               }
+                                       }
+                                       wakeThread ();
+                               }
+                       }
+               }
+       }
+       return OS.DefWindowProc (hwnd, (int)msg, wParam, lParam);
+}
+
+String getSharedData(int pid, int  handle) {
+       long [] mapHandle = new long [1];
+       if (pid == OS.GetCurrentProcessId()) {
+               mapHandle[0] = handle;
+       } else {
+               long processHandle = OS.OpenProcess(OS.PROCESS_VM_READ|OS.PROCESS_DUP_HANDLE, false, pid);
+               if (processHandle == 0) return null;
+               OS.DuplicateHandle(processHandle, handle, OS.GetCurrentProcess(), mapHandle, OS.DUPLICATE_SAME_ACCESS, false, OS.DUPLICATE_SAME_ACCESS);
+               OS.CloseHandle(processHandle);
+       }
+
+       long sharedData = OS.MapViewOfFile(mapHandle[0], OS.FILE_MAP_READ, 0, 0, 0);
+       if (sharedData == 0) return null;
+       int length = OS.wcslen (sharedData);
+       TCHAR buffer = new TCHAR (0, length);
+       int byteCount = buffer.length () * TCHAR.sizeof;
+       OS.MoveMemory (buffer, sharedData, byteCount);
+       String result = buffer.toString (0, length);
+       OS.UnmapViewOfFile(sharedData);
+       if (handle != mapHandle[0]) {
+               OS.CloseHandle(mapHandle[0]);
+       }
+       return result;
+}
+
+long monitorEnumProc (long hmonitor, long hdc, long lprcMonitor, long dwData) {
+       if (monitorCount >= monitors.length) {
+               Monitor[] newMonitors = new Monitor [monitors.length + 4];
+               System.arraycopy (monitors, 0, newMonitors, 0, monitors.length);
+               monitors = newMonitors;
+       }
+       monitors [monitorCount++] = getMonitor (hmonitor);
+       return 1;
+}
+
+long msgFilterProc (long code, long wParam, long lParam) {
+       switch ((int)code) {
+               case OS.MSGF_COMMCTRL_BEGINDRAG: {
+                       if (!runDragDrop && !dragCancelled) {
+                               OS.MoveMemory (hookMsg, lParam, MSG.sizeof);
+                               if (hookMsg.message == 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: {
+                       OS.MoveMemory (hookMsg, lParam, MSG.sizeof);
+                       if (hookMsg.message == OS.WM_NULL) {
+                               MSG msg = new MSG ();
+                               int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+                               if (!OS.PeekMessage (msg, 0, 0, 0, flags)) {
+                                       if (runAsyncMessages (false)) wakeThread ();
+                               }
+                       }
+                       break;
+               }
+       }
+       return OS.CallNextHookEx (filterHook, (int)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 '/';
+       }
+       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></ul>
+ * <p> Either one of:</p>
+ * <ul><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> Optional (on some platforms): </p>
+ * <ul><li>(in) stateMask the state of the keyboard modifier,
+ *                     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>
+ * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates</li>
+ * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates</li>
+ * </ul>
+ * <p>MouseWheel</p>
+ * <p>The following fields in the <code>Event</code> apply:</p>
+ * <ul>
+ * <li>(in) type MouseWheel</li>
+ * <li>(in) detail either SWT.SCROLL_LINE or SWT.SCROLL_PAGE</li>
+ * <li>(in) count the number of lines or pages to scroll</li>
+ * </ul>
+ *
+ * @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 boolean post (Event event) {
+       synchronized (Device.class) {
+               if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+               if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+               int type = event.type;
+               switch (type){
+                       case SWT.KeyDown:
+                       case SWT.KeyUp: {
+                               KEYBDINPUT inputs = new KEYBDINPUT ();
+                               inputs.wVk = (short) untranslateKey (event.keyCode);
+                               if (inputs.wVk == 0) {
+                                       char key = event.character;
+                                       switch (key) {
+                                               case SWT.BS: inputs.wVk = (short) OS.VK_BACK; break;
+                                               case SWT.CR: inputs.wVk = (short) OS.VK_RETURN; break;
+                                               case SWT.DEL: inputs.wVk = (short) OS.VK_DELETE; break;
+                                               case SWT.ESC: inputs.wVk = (short) OS.VK_ESCAPE; break;
+                                               case SWT.TAB: inputs.wVk = (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 = (short) OS.VK_RETURN; break;
+                                               case SWT.LF: return false;
+                                               default: {
+                                                       inputs.wVk = OS.VkKeyScan ((short) key);
+                                                       if (inputs.wVk == -1) return false;
+                                                       inputs.wVk &= 0xFF;
+                                               }
+                                       }
+                               }
+                               inputs.dwFlags = type == SWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
+                               switch (inputs.wVk) {
+                                       case OS.VK_INSERT:
+                                       case OS.VK_DELETE:
+                                       case OS.VK_HOME:
+                                       case OS.VK_END:
+                                       case OS.VK_PRIOR:
+                                       case OS.VK_NEXT:
+                                       case OS.VK_UP:
+                                       case OS.VK_DOWN:
+                                       case OS.VK_LEFT:
+                                       case OS.VK_RIGHT:
+                                       case OS.VK_NUMLOCK:
+                                       case OS.VK_SNAPSHOT:
+                                       case OS.VK_CANCEL:
+                                       case OS.VK_DIVIDE:
+                                               inputs.dwFlags |= OS.KEYEVENTF_EXTENDEDKEY;
+                               }
+                               long hHeap = OS.GetProcessHeap ();
+                               long pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
+                               OS.MoveMemory(pInputs, new int[] {OS.INPUT_KEYBOARD}, 4);
+                               //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
+                               OS.MoveMemory (pInputs + C.PTR_SIZEOF, inputs, KEYBDINPUT.sizeof);
+                               boolean result = OS.SendInput (1, pInputs, INPUT.sizeof) != 0;
+                               OS.HeapFree (hHeap, 0, pInputs);
+                               return result;
+                       }
+                       case SWT.MouseDown:
+                       case SWT.MouseMove:
+                       case SWT.MouseUp:
+                       case SWT.MouseWheel: {
+                               MOUSEINPUT inputs = new MOUSEINPUT ();
+                               if (type == SWT.MouseMove){
+                                       inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE | OS.MOUSEEVENTF_VIRTUALDESK;
+                                       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);
+                                       Point loc = event.getLocationInPixels();
+                                       inputs.dx = ((loc.x - x) * 65535 + width - 2) / (width - 1);
+                                       inputs.dy = ((loc.y - y) * 65535 + height - 2) / (height - 1);
+                               } else {
+                                       if (type == SWT.MouseWheel) {
+                                               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 = new int [1];
+                                                               OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, value, 0);
+                                                               inputs.mouseData = event.count * OS.WHEEL_DELTA / value [0];
+                                                               break;
+                                                       default: return false;
+                                               }
+                                       } else {
+                                               switch (event.button) {
+                                                       case 1: inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
+                                                       case 2: inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
+                                                       case 3: inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
+                                                       case 4: {
+                                                               inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                                               inputs.mouseData = OS.XBUTTON1;
+                                                               break;
+                                                       }
+                                                       case 5: {
+                                                               inputs.dwFlags = type == SWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                                               inputs.mouseData = OS.XBUTTON2;
+                                                               break;
+                                                       }
+                                                       default: return false;
+                                               }
+                                       }
+                               }
+                               long hHeap = OS.GetProcessHeap ();
+                               long pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
+                               OS.MoveMemory(pInputs, new int[] {OS.INPUT_MOUSE}, 4);
+                               //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
+                               OS.MoveMemory (pInputs + C.PTR_SIZEOF, inputs, MOUSEINPUT.sizeof);
+                               boolean result = OS.SendInput (1, pInputs, INPUT.sizeof) != 0;
+                               OS.HeapFree (hHeap, 0, pInputs);
+                               return result;
+                       }
+               }
+               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 == null) eventQueue = new Event [4];
+       int index = 0;
+       int length = eventQueue.length;
+       while (index < length) {
+               if (eventQueue [index] == null) break;
+               index++;
+       }
+       if (index == 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 boolean readAndDispatch () {
+       checkDevice ();
+       lpStartupInfo = null;
+       drawMenuBars ();
+       runSkin ();
+       runDeferredLayouts ();
+       runPopups ();
+       if (OS.PeekMessage (msg, 0, 0, 0, OS.PM_REMOVE)) {
+               if (!filterMessage (msg)) {
+                       OS.TranslateMessage (msg);
+                       OS.DispatchMessage (msg);
+               }
+               runDeferredEvents ();
+               return true;
+       }
+       return isDisposed () || runAsyncMessages (false);
+}
+
+static void register (Display display) {
+       synchronized (Device.class) {
+               for (int i=0; i<Displays.length; i++) {
+                       if (Displays [i] == 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 != null) tray.dispose ();
+       tray = null;
+       if (taskBar != null) taskBar.dispose ();
+       taskBar = null;
+       while (readAndDispatch ()) {}
+       if (disposeList != null) {
+               for (int i=0; i<disposeList.length; i++) {
+                       Runnable next = disposeList [i];
+                       if (next != null) {
+                               try {
+                                       next.run ();
+                               } catch (RuntimeException exception) {
+                                       runtimeExceptionHandler.accept (exception);
+                               } catch (Error error) {
+                                       errorHandler.accept (error);
+                               }
+                       }
+               }
+       }
+       disposeList = null;
+       synchronizer.releaseSynchronizer ();
+       synchronizer = null;
+       releaseDisplay ();
+       super.release ();
+}
+
+void releaseDisplay () {
+       if (embeddedHwnd != 0) {
+               OS.PostMessage (embeddedHwnd, SWT_DESTROY, 0, 0);
+       }
+
+       /* Free custom icons */
+       if (hIconSearch != 0) OS.DestroyIcon (hIconSearch);
+       if (hIconCancel != 0) OS.DestroyIcon (hIconCancel);
+
+       /* Release XP Themes */
+       if (hButtonTheme != 0) OS.CloseThemeData (hButtonTheme);
+       if (hEditTheme != 0) OS.CloseThemeData (hEditTheme);
+       if (hExplorerBarTheme != 0) OS.CloseThemeData (hExplorerBarTheme);
+       if (hScrollBarTheme != 0) OS.CloseThemeData (hScrollBarTheme);
+       if (hTabTheme != 0) OS.CloseThemeData (hTabTheme);
+       hButtonTheme = hEditTheme = hExplorerBarTheme = hScrollBarTheme = hTabTheme = 0;
+
+       /* Unhook the message hook */
+       if (msgHook != 0) OS.UnhookWindowsHookEx (msgHook);
+       msgHook = 0;
+
+       /* Unhook the filter hook */
+       if (filterHook != 0) OS.UnhookWindowsHookEx (filterHook);
+       filterHook = 0;
+       msgFilterCallback.dispose ();
+       msgFilterCallback = null;
+       msgFilterProc = 0;
+
+       /* Unhook the idle hook */
+       if (idleHook != 0) OS.UnhookWindowsHookEx (idleHook);
+       idleHook = 0;
+       foregroundIdleCallback.dispose ();
+       foregroundIdleCallback = null;
+       foregroundIdleProc = 0;
+
+       /* Stop the settings timer */
+       OS.KillTimer (hwndMessage, SETTINGS_ID);
+
+       /* Destroy the message only HWND */
+       if (hwndMessage != 0) OS.DestroyWindow (hwndMessage);
+       hwndMessage = 0;
+       messageCallback.dispose ();
+       messageCallback = null;
+       messageProc = 0;
+
+       /* Unregister the SWT window class */
+       long hHeap = OS.GetProcessHeap ();
+       long hInstance = OS.GetModuleHandle (null);
+       OS.UnregisterClass (windowClass, hInstance);
+
+       /* Unregister the SWT drop shadow and CS_OWNDC window class */
+       OS.UnregisterClass (windowShadowClass, hInstance);
+       OS.UnregisterClass (windowOwnDCClass, hInstance);
+       windowClass = windowShadowClass = windowOwnDCClass = null;
+       windowCallback.dispose ();
+       windowCallback = null;
+       windowProc = 0;
+
+       /* Release the System fonts */
+       if (systemFont != null) systemFont.dispose ();
+       systemFont = null;
+       lfSystemFont = null;
+
+       /* Release the System Images */
+       if (errorImage != null) errorImage.dispose ();
+       if (infoImage != null) infoImage.dispose ();
+       if (questionImage != null) questionImage.dispose ();
+       if (warningIcon != null) warningIcon.dispose ();
+       errorImage = infoImage = questionImage = warningIcon = null;
+
+       /* Release the System Cursors */
+       for (int i = 0; i < cursors.length; i++) {
+               if (cursors [i] != null) cursors [i].dispose ();
+       }
+       cursors = null;
+
+       /* Release Acquired Resources */
+       if (resources != null) {
+               for (int i=0; i<resources.length; i++) {
+                       if (resources [i] != null) resources [i].dispose ();
+               }
+               resources = null;
+       }
+
+       /* Release Custom Colors for ChooseColor */
+       if (lpCustColors != 0) OS.HeapFree (hHeap, 0, lpCustColors);
+       lpCustColors = 0;
+
+       /* Uninitialize OLE */
+       OS.OleUninitialize ();
+
+       /* Uninitialize buffered painting */
+       OS.BufferedPaintUnInit ();
+
+       /* Release references */
+       thread = null;
+       msg = 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;
+       eventTable = filterTable = null;
+       items = null;
+       clickRect = null;
+       monitors = null;
+       touchSources = null;
+
+       /* Release handles */
+       threadId = 0;
+}
+
+void releaseImageList (ImageList list) {
+       int i = 0;
+       int length = imageList.length;
+       while (i < length) {
+               if (imageList [i] == 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] != null) return;
+                       }
+                       imageList = null;
+                       return;
+               }
+               i++;
+       }
+}
+
+void releaseToolImageList (ImageList list) {
+       int i = 0;
+       int length = toolImageList.length;
+       while (i < length) {
+               if (toolImageList [i] == 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] != null) return;
+                       }
+                       toolImageList = null;
+                       return;
+               }
+               i++;
+       }
+}
+
+void releaseToolHotImageList (ImageList list) {
+       int i = 0;
+       int length = toolHotImageList.length;
+       while (i < length) {
+               if (toolHotImageList [i] == 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] != null) return;
+                       }
+                       toolHotImageList = null;
+                       return;
+               }
+               i++;
+       }
+}
+
+void releaseToolDisabledImageList (ImageList list) {
+       int i = 0;
+       int length = toolDisabledImageList.length;
+       while (i < length) {
+               if (toolDisabledImageList [i] == 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] != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (filterTable == null) return;
+       filterTable.unhook (eventType, listener);
+       if (filterTable.size () == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (eventType, listener);
+}
+
+void removeBar (Menu menu) {
+       if (bars == null) return;
+       for (int i=0; i<bars.length; i++) {
+               if (bars [i] == menu) {
+                       bars [i] = null;
+                       return;
+               }
+       }
+}
+
+Control removeControl (long handle) {
+       if (handle == 0) return null;
+       lastControl = lastGetControl = null;
+       Control control = null;
+       int index = (int)OS.RemoveProp (handle, SWT_OBJECT_INDEX) - 1;
+       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 == null) return;
+       items [item.id - ID_START] = null;
+}
+
+void removePopup (Menu menu) {
+       if (popups == null) return;
+       for (int i=0; i<popups.length; i++) {
+               if (popups [i] == menu) {
+                       popups [i] = null;
+                       return;
+               }
+       }
+}
+
+boolean runAsyncMessages (boolean all) {
+       return synchronizer.runAsyncMessages (all);
+}
+
+boolean runDeferredEvents () {
+       boolean run = false;
+       /*
+       * 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 != null) {
+
+               /* Take an event off the queue */
+               Event event = eventQueue [0];
+               if (event == 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 != null && !widget.isDisposed ()) {
+                       Widget item = event.item;
+                       if (item == null || !item.isDisposed ()) {
+                               run = true;
+                               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 run;
+}
+
+boolean runDeferredLayouts () {
+       if (layoutDeferredCount != 0) {
+               Composite[] temp = layoutDeferred;
+               int count = layoutDeferredCount;
+               layoutDeferred = null;
+               layoutDeferredCount = 0;
+               for (int i = 0; i < count; i++) {
+                       Composite comp = temp[i];
+                       if (!comp.isDisposed()) comp.setLayoutDeferred (false);
+               }
+               return true;
+       }
+       return false;
+}
+
+boolean runPopups () {
+       if (popups == null) return false;
+       boolean result = false;
+       while (popups != null) {
+               Menu menu = popups [0];
+               if (menu == 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 ();
+       sendEvent (SWT.Settings, null);
+       Font newFont = getSystemFont ();
+       boolean sameFont = oldFont.equals (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);
+               }
+       }
+}
+
+boolean runSkin () {
+       if (skinCount > 0) {
+               Widget [] oldSkinWidgets = skinList;
+               int count = skinCount;
+               skinList = new Widget[GROW_SIZE];
+               skinCount = 0;
+               if (eventTable != null && eventTable.hooks(SWT.Skin)) {
+                       for (int i = 0; i < count; i++) {
+                               Widget widget = oldSkinWidgets[i];
+                               if (widget != null && !widget.isDisposed()) {
+                                       widget.state &= ~Widget.SKIN_NEEDED;
+                                       oldSkinWidgets[i] = null;
+                                       Event event = new Event ();
+                                       event.widget = widget;
+                                       sendEvent (SWT.Skin, event);
+                               }
+                       }
+               }
+               return true;
+       }
+       return false;
+}
+
+boolean runTimer (long id) {
+       if (timerList != null && timerIds != null) {
+               int index = 0;
+               while (index <timerIds.length) {
+                       if (timerIds [index] == id) {
+                               OS.KillTimer (hwndMessage, timerIds [index]);
+                               timerIds [index] = 0;
+                               Runnable runnable = timerList [index];
+                               timerList [index] = null;
+                               if (runnable != null) {
+                                       try {
+                                               runnable.run ();
+                                       } catch (RuntimeException exception) {
+                                               runtimeExceptionHandler.accept (exception);
+                                       } catch (Error exception) {
+                                               errorHandler.accept (exception);
+                                       }
+                               }
+                               return true;
+                       }
+                       index++;
+               }
+       }
+       return false;
+}
+
+void saveResources () {
+       int resourceCount = 0;
+       if (resources == 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 != null) {
+               NONCLIENTMETRICS info = new NONCLIENTMETRICS ();
+               info.cbSize = NONCLIENTMETRICS.sizeof;
+               if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, info, 0)) {
+                       LOGFONT logFont = info.lfMessageFont;
+                       if (lfSystemFont == null ||
+                               logFont.lfCharSet != lfSystemFont.lfCharSet ||
+                               logFont.lfHeight != lfSystemFont.lfHeight ||
+                               logFont.lfWidth != lfSystemFont.lfWidth ||
+                               logFont.lfEscapement != lfSystemFont.lfEscapement ||
+                               logFont.lfOrientation != lfSystemFont.lfOrientation ||
+                               logFont.lfWeight != lfSystemFont.lfWeight ||
+                               logFont.lfItalic != lfSystemFont.lfItalic ||
+                               logFont.lfUnderline != lfSystemFont.lfUnderline ||
+                               logFont.lfStrikeOut != lfSystemFont.lfStrikeOut ||
+                               logFont.lfCharSet != lfSystemFont.lfCharSet ||
+                               logFont.lfOutPrecision != lfSystemFont.lfOutPrecision ||
+                               logFont.lfClipPrecision != lfSystemFont.lfClipPrecision ||
+                               logFont.lfQuality != lfSystemFont.lfQuality ||
+                               logFont.lfPitchAndFamily != lfSystemFont.lfPitchAndFamily ||
+                               !getFontName (logFont).equals (getFontName (lfSystemFont))) {
+                                       resources [resourceCount++] = systemFont;
+                                       lfSystemFont = logFont;
+                                       systemFont = null;
+                       }
+               }
+       }
+       if (errorImage != null) resources [resourceCount++] = errorImage;
+       if (infoImage != null) resources [resourceCount++] = infoImage;
+       if (questionImage != null) resources [resourceCount++] = questionImage;
+       if (warningIcon != null) resources [resourceCount++] = warningIcon;
+       errorImage = infoImage = questionImage = warningIcon = null;
+       for (int i=0; i<cursors.length; i++) {
+               if (cursors [i] != 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 == null && filterTable == null) {
+               return;
+       }
+       if (event == null) event = new Event ();
+       event.display = this;
+       event.type = eventType;
+       if (event.time == 0) event.time = getLastEventTime ();
+       if (!filterEvent (event)) {
+               if (eventTable != null) sendEvent (eventTable, event);
+       }
+}
+
+void sendEvent (EventTable eventTable, Event event) {
+       int type = event.type;
+       sendPreEvent (type);
+       try {
+               eventTable.sendEvent (event);
+       } finally {
+               sendPostEvent (type);
+       }
+}
+
+void sendPreEvent (int eventType) {
+       if (eventType != SWT.PreEvent && eventType != SWT.PostEvent
+                       && eventType != SWT.PreExternalEventDispatch
+                       && eventType != SWT.PostExternalEventDispatch) {
+               if (eventTable != null && eventTable.hooks (SWT.PreEvent)) {
+                       Event event = new Event ();
+                       event.detail = eventType;
+                       sendEvent (SWT.PreEvent, event);
+               }
+       }
+}
+
+void sendPostEvent (int eventType) {
+       if (eventType != SWT.PreEvent && eventType != SWT.PostEvent
+                       && eventType != SWT.PreExternalEventDispatch
+                       && eventType != SWT.PostExternalEventDispatch) {
+               if (eventTable != null && eventTable.hooks (SWT.PostEvent)) {
+                       Event event = new Event ();
+                       event.detail = eventType;
+                       sendEvent (SWT.PostEvent, event);
+               }
+       }
+}
+
+/**
+ * Sends a SWT.PreExternalEventDispatch event.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public void sendPreExternalEventDispatchEvent () {
+       if (eventTable != null && eventTable.hooks (SWT.PreExternalEventDispatch)) {
+               sendEvent (SWT.PreExternalEventDispatch, null);
+       }
+}
+
+/**
+ * Sends a SWT.PostExternalEventDispatch event.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public void sendPostExternalEventDispatchEvent () {
+       if (eventTable != null && eventTable.hooks (SWT.PostExternalEventDispatch)) {
+               sendEvent (SWT.PostExternalEventDispatch, null);
+       }
+}
+
+/**
+ * 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 ();
+       setCursorLocationInPixels (DPIUtil.autoScaleUp (x), DPIUtil.autoScaleUp (y));
+}
+
+void setCursorLocationInPixels (int x, int y) {
+       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 == 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the key 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 #getData(String)
+ * @see #disposeExec(Runnable)
+ */
+public void setData (String key, Object value) {
+       checkDevice ();
+       if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+
+       if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) {
+               Boolean data = (Boolean) value;
+               runMessagesInIdle = data != null && data.booleanValue ();
+               return;
+       }
+       if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
+               Boolean data = (Boolean) value;
+               runMessagesInMessageProc = data != null && data.booleanValue ();
+               return;
+       }
+       if (key.equals (USE_OWNDC_KEY)) {
+               Boolean data = (Boolean) value;
+               useOwnDC = data != null && data.booleanValue ();
+               return;
+       }
+       if (key.equals (ACCEL_KEY_HIT)) {
+               Boolean data = (Boolean) value;
+               accelKeyHit = data != null && data.booleanValue ();
+               return;
+       }
+       if (key.equals (EXTERNAL_EVENT_LOOP_KEY)) {
+               Boolean data = (Boolean) value;
+               externalEventLoop = data != null && data.booleanValue ();
+               return;
+       }
+       /* Remove the key/value pair */
+       if (value == null) {
+               if (keys == null) return;
+               int index = 0;
+               while (index < keys.length && !keys [index].equals (key)) index++;
+               if (index == keys.length) return;
+               if (keys.length == 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 == null) {
+               keys = new String [] {key};
+               values = new Object [] {value};
+               return;
+       }
+       for (int i=0; i<keys.length; i++) {
+               if (keys [i].equals (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;
+}
+
+/**
+ * Returns the application name.
+ *
+ * @return the application name
+ *
+ * @see #setAppName(String)
+ *
+ * @since 3.6
+ */
+public static String getAppName () {
+       return APP_NAME;
+}
+
+/**
+ * Returns the application version.
+ *
+ * @return the application version
+ *
+ * @see #setAppVersion(String)
+ *
+ * @since 3.6
+ */
+public static String getAppVersion () {
+       return APP_VERSION;
+}
+
+/**
+ * Sets the application name to the argument.
+ * <p>
+ * The application name can be used in several ways,
+ * depending on the platform and tools being used.
+ * Accessibility tools could ask for the application
+ * name. On Windows, if the application name is set
+ * to any value other than "SWT" (case insensitive),
+ * it is used to set the application user model ID
+ * which is used by the OS for taskbar grouping.
+ * @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd378459%28v=vs.85%29.aspx#HOW">AppUserModelID (Windows)</a>
+ * </p><p>
+ * Specifying <code>null</code> for the name clears it.
+ * </p>
+ *
+ * @param name the new app name or <code>null</code>
+ */
+public static void setAppName (String name) {
+       APP_NAME = name;
+}
+
+/**
+ * Sets the application version to the argument.
+ *
+ * @param version the new app version
+ *
+ * @since 3.6
+ */
+public static void setAppVersion (String version) {
+       APP_VERSION = version;
+}
+
+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 == null) modalShells = new Shell [4];
+       int index = 0, length = modalShells.length;
+       while (index < length) {
+               if (modalShells [index] == shell) return;
+               if (modalShells [index] == null) break;
+               index++;
+       }
+       if (index == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (synchronizer == this.synchronizer) return;
+       Synchronizer oldSynchronizer;
+       synchronized (Device.class) {
+               oldSynchronizer = this.synchronizer;
+               this.synchronizer = synchronizer;
+       }
+       if (oldSynchronizer != null) {
+               oldSynchronizer.moveAllEventsTo(synchronizer);
+       }
+}
+
+/**
+ * Sets a callback that will be invoked whenever an exception is thrown by a listener or external
+ * callback function. The application may use this to set a global exception handling policy:
+ * the most common policies are either to log and discard the exception or to re-throw the
+ * exception.
+ * <p>
+ * The default SWT error handling policy is to rethrow exceptions.
+ *
+ * @param runtimeExceptionHandler new exception handler to be registered.
+ * @since 3.106
+ */
+public final void setRuntimeExceptionHandler (Consumer<RuntimeException> runtimeExceptionHandler) {
+       checkDevice();
+       this.runtimeExceptionHandler = Objects.requireNonNull (runtimeExceptionHandler);
+}
+
+/**
+ * Returns the current exception handler. It will receive all exceptions thrown by listeners
+ * and external callbacks in this display. If code wishes to temporarily replace the exception
+ * handler (for example, during a unit test), it is common practice to invoke this method prior
+ * to replacing the exception handler so that the old handler may be restored afterward.
+ *
+ * @return the current exception handler. Never <code>null</code>.
+ * @since 3.106
+ */
+public final Consumer<RuntimeException> getRuntimeExceptionHandler () {
+       return runtimeExceptionHandler;
+}
+
+/**
+ * Sets a callback that will be invoked whenever an error is thrown by a listener or external
+ * callback function. The application may use this to set a global exception handling policy:
+ * the most common policies are either to log and discard the exception or to re-throw the
+ * exception.
+ * <p>
+ * The default SWT error handling policy is to rethrow exceptions.
+ *
+ * @param errorHandler new error handler to be registered.
+ * @since 3.106
+ */
+public final void setErrorHandler (Consumer<Error> errorHandler) {
+       checkDevice();
+       this.errorHandler = Objects.requireNonNull (errorHandler);
+}
+
+/**
+ * Returns the current exception handler. It will receive all errors thrown by listeners
+ * and external callbacks in this display. If code wishes to temporarily replace the error
+ * handler (for example, during a unit test), it is common practice to invoke this method prior
+ * to replacing the error handler so that the old handler may be restored afterward.
+ *
+ * @return the current error handler. Never <code>null</code>.
+ * @since 3.106
+ */
+public final Consumer<Error> getErrorHandler () {
+       return errorHandler;
+}
+
+int shiftedKey (int key) {
+       /* 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 */
+       char [] result = new char [1];
+       if (OS.ToUnicode (key, key, keyboard, result, 1, 0) == 1) return result [0];
+       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 boolean sleep () {
+       checkDevice ();
+       if (getMessageCount () != 0) return true;
+       sendPreExternalEventDispatchEvent ();
+       boolean result = OS.WaitMessage ();
+       sendPostExternalEventDispatchEvent ();
+       return result;
+}
+
+/**
+ * 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.class) {
+               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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (timerList == null) timerList = new Runnable [4];
+       if (timerIds == null) timerIds = new long [4];
+       int index = 0;
+       while (index < timerList.length) {
+               if (timerList [index] == runnable) break;
+               index++;
+       }
+       long timerId = 0;
+       if (index != 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] == null) break;
+                       index++;
+               }
+               timerId = nextTimerId++;
+               if (index == timerList.length) {
+                       Runnable [] newTimerList = new Runnable [timerList.length + 4];
+                       System.arraycopy (timerList, 0, newTimerList, 0, timerList.length);
+                       timerList = newTimerList;
+                       long [] newTimerIds = new long [timerIds.length + 4];
+                       System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
+                       timerIds = newTimerIds;
+               }
+       }
+       long newTimerID = OS.SetTimer (hwndMessage, timerId, milliseconds, 0);
+       if (newTimerID != 0) {
+               timerList [index] = runnable;
+               timerIds [index] = newTimerID;
+       }
+}
+
+boolean translateAccelerator (MSG msg, Control control) {
+       accelKeyHit = true;
+       boolean 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] == key) return KeyTable [i] [1];
+       }
+       return 0;
+}
+
+boolean translateMnemonic (MSG msg, Control control) {
+       switch (msg.message) {
+               case OS.WM_CHAR:
+               case OS.WM_SYSCHAR:
+                       return control.translateMnemonic (msg);
+       }
+       return false;
+}
+
+boolean translateTraversal (MSG msg, Control control) {
+       switch (msg.message) {
+               case OS.WM_KEYDOWN:
+                       switch ((int)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);
+                       }
+                       break;
+               case OS.WM_SYSKEYDOWN:
+                       switch ((int)msg.wParam) {
+                               case OS.VK_MENU:
+                                       return control.translateTraversal (msg);
+                       }
+                       break;
+       }
+       return false;
+}
+
+static int untranslateKey (int key) {
+       for (int i=0; i<KeyTable.length; i++) {
+               if (KeyTable [i] [1] == 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.IsHungAppWindow (hwndMessage)) {
+               MSG msg = new 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);
+       }
+}
+
+/**
+ * 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.class) {
+               if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+               if (thread == Thread.currentThread ()) return;
+               wakeThread ();
+       }
+}
+
+void wakeThread () {
+       OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
+}
+
+long windowProc (long hwnd, long msg, long wParam, long lParam) {
+       if (lastControl != null && lastHwnd == hwnd) {
+               return lastControl.windowProc (hwnd, (int)msg, wParam, lParam);
+       }
+       int index = (int)OS.GetProp (hwnd, SWT_OBJECT_INDEX) - 1;
+       if (0 <= index && index < controlTable.length) {
+               Control control = controlTable [index];
+               if (control != null) {
+                       lastHwnd = hwnd;
+                       lastControl = control;
+                       return control.windowProc (hwnd, (int)msg, wParam, lParam);
+               }
+       }
+       return OS.DefWindowProc (hwnd, (int)msg, wParam, lParam);
+}
+
+int textWidth (String text, long handle) {
+       long oldFont = 0;
+       RECT rect = new RECT ();
+       long hDC = OS.GetDC (handle);
+       long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+       char [] buffer = text.toCharArray ();
+       OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       return (rect.right - rect.left);
+}
+
+String wrapText (String text, long handle, int width) {
+       String Lf = "\r\n"; //$NON-NLS-1$
+       text = withCrLf (text);
+       int length = text.length ();
+       if (width <= 0 || length == 0 || length == 1) return text;
+       StringBuilder result = new StringBuilder ();
+       int lineStart = 0, lineEnd = 0;
+       while (lineStart < length) {
+               lineEnd = text.indexOf (Lf, lineStart);
+               boolean noLf = lineEnd == -1;
+               if (noLf) lineEnd = length;
+               int nextStart = lineEnd + Lf.length ();
+               while (lineEnd > lineStart + 1 && Character.isWhitespace (text.charAt (lineEnd - 1))) {
+                       lineEnd--;
+               }
+               int wordStart = lineStart, wordEnd = lineStart;
+               int i = lineStart;
+               while (i < lineEnd) {
+                       int lastStart = wordStart, lastEnd = wordEnd;
+                       wordStart = i;
+                       while (i < lineEnd && !Character.isWhitespace (text.charAt (i))) {
+                               i++;
+                       }
+                       wordEnd = i - 1;
+                       String line = text.substring (lineStart, wordEnd + 1);
+                       int lineWidth = textWidth (line, handle);
+                       while (i < lineEnd && Character.isWhitespace (text.charAt (i))) {
+                               i++;
+                       }
+                       if (lineWidth > width) {
+                               if (lastStart == wordStart) {
+                                       while (wordStart < wordEnd) {
+                                               line = text.substring (lineStart, wordStart + 1);
+                                               lineWidth = textWidth (line, handle);
+                                               if (lineWidth >= width) break;
+                                               wordStart++;
+                                       }
+                                       if (wordStart == lastStart) wordStart++;
+                                       lastEnd = wordStart - 1;
+                               }
+                               line = text.substring (lineStart, lastEnd + 1);
+                               result.append (line); result.append (Lf);
+                               i = wordStart; lineStart = wordStart; wordEnd = wordStart;
+                       }
+               }
+               if (lineStart < lineEnd) {
+                       result.append (text.substring (lineStart, lineEnd));
+               }
+               if (!noLf) {
+                       result.append (Lf);
+               }
+               lineStart = nextStart;
+       }
+       return result.toString ();
+}
+
+static String withCrLf (String string) {
+
+       /* If the string is empty, return the string. */
+       int length = string.length ();
+       if (length == 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 == -1) return string;
+       if (i > 0 && string.charAt (i - 1) == '\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)) == -1) break;
+               count++; i++;
+       }
+       count += length;
+
+       /* Create a new string with the CR/LF line terminator. */
+       i = 0;
+       StringBuilder result = new StringBuilder (count);
+       while (i < length) {
+               int j = string.indexOf ('\n', i);
+               if (j == -1) j = length;
+               result.append (string.substring (i, j));
+               if ((i = j) < length) {
+                       result.append ("\r\n"); //$NON-NLS-1$
+                       i++;
+               }
+       }
+       return result.toString ();
+}
+
+static char [] withCrLf (char [] string) {
+       /* If the string is empty, return the string. */
+       int length = string.length;
+       if (length == 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.
+       * Also, compute the number of lines.
+       */
+       int count = 0;
+       for (int i = 0; i < string.length; i++) {
+               if (string [i] == '\n') {
+                       count++;
+                       if (count == 1 && i > 0 && string [i - 1] == '\r') return string;
+               }
+       }
+       if (count == 0) return string;
+
+       /*
+       * The string is formatted with LF.
+       */
+       count += length;
+
+       /* Create a new string with the CR/LF line terminator. */
+       char [] result = new char [count];
+       for (int i = 0, j = 0; i < length && j < count; i++) {
+               if (string [i] == '\n') {
+                       result [j++] = '\r';
+               }
+               result [j++] = string [i];
+       }
+
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Event.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Event.java
new file mode 100644 (file)
index 0000000..a6181d6
--- /dev/null
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 that are pending which may always be zero
+        * on some platforms, or the number of lines or pages to
+        * scroll using the mouse wheel, or the number of times the
+        * mouse has been clicked
+        */
+       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 char character;
+
+       /**
+        * 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 location of key specified by the
+        * keyCode or character. The possible values for this field are
+        * <code>SWT.LEFT</code>, <code>SWT.RIGHT</code>, <code>SWT.KEYPAD</code>,
+        * or <code>SWT.NONE</code> representing the main keyboard area.
+        * <p>
+        * The location field can be used to differentiate key events that have
+        * the same key code and character but are generated by different keys
+        * in the keyboard. For example, a key down event with the key code equals
+        * to SWT.SHIFT can be generated by the left and the right shift keys in the
+        * keyboard. The location field can only be used to determine the location
+        * of the key code or character in the current event. It does not
+        * include information about the location of modifiers in state
+        * mask.
+        * </p>
+        *
+        * @see org.eclipse.swt.SWT#LEFT
+        * @see org.eclipse.swt.SWT#RIGHT
+        * @see org.eclipse.swt.SWT#KEYPAD
+        *
+        * @since 3.6
+        */
+       public int keyLocation;
+
+       /**
+        * 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#MODIFIER_MASK
+        * @see org.eclipse.swt.SWT#BUTTON_MASK
+        */
+       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;
+
+       /**
+        * Bidi segment offsets
+        * @since 3.8
+        */
+       public int[] segments;
+
+       /**
+        * Characters to be applied on the segment boundaries
+        * @since 3.8
+        */
+       public char[] segmentsChars;
+
+       /**
+        * depending on the event, a flag indicating whether the operation
+        * should be allowed.  Setting this field to false will cancel the
+        * operation.
+        */
+       public boolean doit = true;
+
+       /**
+        * a field for application use
+        */
+       public Object data;
+
+       /**
+        * An array of the touch states for the current touch event.
+        *
+        * @since 3.7
+        */
+       public Touch[] touches;
+
+       /**
+        * If nonzero, a positive value indicates a swipe to the right,
+        * and a negative value indicates a swipe to the left.
+        *
+        * @since 3.7
+        */
+       public int xDirection;
+
+       /**
+        * If nonzero, a positive value indicates a swipe in the up direction,
+        * and a negative value indicates a swipe in the down direction.
+        *
+        * @since 3.7
+        */
+       public int yDirection;
+
+       /**
+        * The change in magnification. This value should be added to the current
+        * scaling of an item to get the new scale factor.
+        *
+        * @since 3.7
+        */
+       public double magnification;
+
+       /**
+        * The number of degrees rotated on the track pad.
+        *
+        * @since 3.7
+        */
+       public double rotation;
+
+/**
+ * Gets the bounds.
+ *
+ * @return a rectangle that is the bounds.
+ */
+public Rectangle getBounds () {
+       return new Rectangle (x, y, width, height);
+}
+Rectangle getBoundsInPixels () {
+       return DPIUtil.autoScaleUp(getBounds());
+}
+
+Point getLocation () {
+       return new Point (x, y);
+}
+
+Point getLocationInPixels () {
+       return DPIUtil.autoScaleUp(new Point(x, y));
+}
+
+/**
+ * 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;
+}
+
+void setBoundsInPixels (Rectangle rect) {
+       setBounds(DPIUtil.autoScaleDown(rect));
+}
+
+void setLocationInPixels (int x, int y) {
+       this.x = DPIUtil.autoScaleDown(x);
+       this.y = DPIUtil.autoScaleDown(y);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString () {
+       return "Event {type=" + type + " " + widget + " time=" + time + " data=" + data + " x=" + x + " y=" + y + " width=" + width + " height=" + height + " detail=" + detail + "}";  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/EventTable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/EventTable.java
new file mode 100644 (file)
index 0000000..0053461
--- /dev/null
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 == null) return new Listener [0];
+       int count = 0;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == eventType) count++;
+       }
+       if (count == 0) return new Listener [0];
+       Listener [] result = new Listener [count];
+       count = 0;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == eventType) {
+                       result [count++] = listeners [i];
+               }
+       }
+       return result;
+}
+
+public void hook (int eventType, Listener listener) {
+       if (types == null) types = new int [GROW_SIZE];
+       if (listeners == null) listeners = new Listener [GROW_SIZE];
+       int length = types.length, index = length - 1;
+       while (index >= 0) {
+               if (types [index] != 0) break;
+               --index;
+       }
+       index++;
+       if (index == length) {
+               int [] newTypes = new int [length + GROW_SIZE];
+               System.arraycopy (types, 0, newTypes, 0, length);
+               types = newTypes;
+               Listener [] newListeners = new Listener [length + GROW_SIZE];
+               System.arraycopy (listeners, 0, newListeners, 0, length);
+               listeners = newListeners;
+       }
+       types [index] = eventType;
+       listeners [index] = listener;
+}
+
+public boolean hooks (int eventType) {
+       if (types == null) return false;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == eventType) return true;
+       }
+       return false;
+}
+
+public void sendEvent (Event event) {
+       if (types == null) return;
+       level += level >= 0 ? 1 : -1;
+       try {
+               for (int i=0; i<types.length; i++) {
+                       if (event.type == SWT.None) return;
+                       if (types [i] == event.type) {
+                               Listener listener = listeners [i];
+                               if (listener != null) {
+                                       try {
+                                               listener.handleEvent (event);
+                                       } catch (RuntimeException runtimeException) {
+                                               Display display = Display.getCurrent ();
+
+                                               if (display == null) {
+                                                       throw runtimeException;
+                                               }
+
+                                               display.getRuntimeExceptionHandler ().accept (runtimeException);
+                                       } catch (Error error) {
+                                               Display display = Display.getCurrent ();
+
+                                               if (display == null) {
+                                                       throw error;
+                                               }
+
+                                               display.getErrorHandler ().accept (error);
+                                       }
+                               }
+                       }
+               }
+       } finally {
+               boolean compact = level < 0;
+               level -= level >= 0 ? 1 : -1;
+               if (compact && level == 0) {
+                       int index = 0;
+                       for (int i=0; i<types.length; i++) {
+                               if (types [i] != 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 == null) return 0;
+       int count = 0;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] != 0) count++;
+       }
+       return count;
+}
+
+void remove (int index) {
+       if (level == 0) {
+               int end = types.length - 1;
+               System.arraycopy (types, index + 1, types, index, end - index);
+               System.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 == null) return;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == eventType && listeners [i] == listener) {
+                       remove (i);
+                       return;
+               }
+       }
+}
+
+public void unhook (int eventType, SWTEventListener listener) {
+       if (types == null) return;
+       for (int i=0; i<types.length; i++) {
+               if (types [i] == eventType) {
+                       if (listeners [i] instanceof TypedListener) {
+                               TypedListener typedListener = (TypedListener) listeners [i];
+                               if (typedListener.getEventListener () == listener) {
+                                       remove (i);
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ExpandBar.java
new file mode 100644 (file)
index 0000000..b1e01e6
--- /dev/null
@@ -0,0 +1,876 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>V_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Expand, Collapse</dd>
+ * </dl>
+ * <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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ExpandBar extends Composite {
+       ExpandItem[] items;
+       int itemCount;
+       ExpandItem focusItem;
+       int spacing = 4;
+       int yCurrentScroll;
+       long 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 SWT#V_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandBar (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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Expand, typedListener);
+       addListener (SWT.Collapse, typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       int height = 0, width = 0;
+       if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+               if (itemCount > 0) {
+                       long hDC = OS.GetDC (handle);
+                       long hTheme = 0;
+                       if (isAppThemed ()) {
+                               hTheme = display.hExplorerBarTheme ();
+                       }
+                       long hCurrentFont = 0, oldFont = 0;
+                       if (hTheme == 0) {
+                               if (hFont != 0) {
+                                       hCurrentFont = hFont;
+                               } else {
+                                       NONCLIENTMETRICS info = new NONCLIENTMETRICS ();
+                                       info.cbSize = NONCLIENTMETRICS.sizeof;
+                                       if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, info, 0)) {
+                                               LOGFONT logFont = info.lfCaptionFont;
+                                               hCurrentFont = OS.CreateFontIndirect (logFont);
+                                       }
+                               }
+                               if (hCurrentFont != 0) {
+                                       oldFont = OS.SelectObject (hDC, hCurrentFont);
+                               }
+                       }
+                       height += spacing;
+                       for (int i = 0; i < itemCount; i++) {
+                               ExpandItem item = items [i];
+                               height += item.getHeaderHeightInPixels ();
+                               if (item.expanded) height += item.height;
+                               height += spacing;
+                               width = Math.max (width, item.getPreferredWidth (hTheme, hDC));
+                       }
+                       if (hCurrentFont != 0) {
+                               OS.SelectObject (hDC, oldFont);
+                               if (hCurrentFont != hFont) OS.DeleteObject (hCurrentFont);
+                       }
+                       OS.ReleaseDC (handle, hDC);
+               }
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       Rectangle trim = computeTrimInPixels (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 == 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 == null) focusItem = item;
+
+       RECT rect = new 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] == item) break;
+               index++;
+       }
+       if (index == itemCount) return;
+       if (item == 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 (long hDC, long hwnd, RECT rect) {
+       RECT rect2 = new RECT ();
+       OS.GetClientRect (handle, rect2);
+       OS.MapWindowPoints (handle, hwnd, rect2, 2);
+       OS.DrawThemeBackground (display.hExplorerBarTheme (), hDC, OS.EBP_NORMALGROUPBACKGROUND, 0, rect2, null);
+}
+
+void drawWidget (GC gc, RECT clipRect) {
+       long hTheme = 0;
+       if (isAppThemed ()) {
+               hTheme = display.hExplorerBarTheme ();
+       }
+       if (hTheme != 0) {
+               RECT rect = new RECT ();
+               OS.GetClientRect (handle, rect);
+               OS.DrawThemeBackground (hTheme, gc.handle, OS.EBP_HEADERBACKGROUND, 0, rect, clipRect);
+       } else {
+               drawBackground (gc.handle);
+       }
+       boolean drawFocus = false;
+       if (handle == OS.GetFocus ()) {
+               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+               drawFocus = (uiState & OS.UISF_HIDEFOCUS) == 0;
+       }
+       long hCurrentFont = 0, oldFont = 0;
+       if (hTheme == 0) {
+               if (hFont != 0) {
+                       hCurrentFont = hFont;
+               } else {
+                       NONCLIENTMETRICS info = new NONCLIENTMETRICS ();
+                       info.cbSize = NONCLIENTMETRICS.sizeof;
+                       if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, info, 0)) {
+                               LOGFONT logFont = info.lfCaptionFont;
+                               hCurrentFont = OS.CreateFontIndirect (logFont);
+                       }
+               }
+               if (hCurrentFont != 0) {
+                       oldFont = OS.SelectObject (gc.handle, hCurrentFont);
+               }
+               if (foreground != -1) {
+                       OS.SetTextColor (gc.handle, foreground);
+               }
+       }
+       for (int i = 0; i < itemCount; i++) {
+               ExpandItem item = items[i];
+               item.drawItem (gc, hTheme, clipRect, item == focusItem && drawFocus);
+       }
+       if (hCurrentFont != 0) {
+               OS.SelectObject (gc.handle, oldFont);
+               if (hCurrentFont != hFont) OS.DeleteObject (hCurrentFont);
+       }
+}
+
+@Override
+Control findBackgroundControl () {
+       Control control = super.findBackgroundControl ();
+       if (!isAppThemed ()) {
+               if (control == null) control = this;
+       }
+       return control;
+}
+
+@Override
+Control findThemeControl () {
+       return isAppThemed () ? this : super.findThemeControl ();
+}
+
+int getBandHeight () {
+       long hDC = OS.GetDC (handle);
+       long oldHFont = OS.SelectObject (hDC, hFont == 0 ? defaultFont () : hFont);
+       TEXTMETRIC lptm = new TEXTMETRIC ();
+       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 DPIUtil.autoScaleDown(getSpacingInPixels ());
+}
+
+int getSpacingInPixels () {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i = 0; i < itemCount; i++) {
+               if (items [i] == item) return i;
+       }
+       return -1;
+}
+
+boolean isAppThemed () {
+       if (background != -1) return false;
+       if (foreground != -1) return false;
+       if (hFont != 0) return false;
+       return OS.IsAppThemed ();
+}
+
+void layoutItems (int index, boolean 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.getHeaderHeightInPixels () + spacing;
+               }
+               for (int i = index; i < itemCount; i++) {
+                       ExpandItem item = items [i];
+                       item.setBoundsInPixels (spacing, y, 0, 0, true, false);
+                       if (item.expanded) y += item.height;
+                       y += item.getHeaderHeightInPixels () + spacing;
+               }
+       }
+       if (setScrollbar) setScrollbar ();
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       ExpandItem item = items [i];
+                       if (item != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Expand, listener);
+       eventTable.unhook (SWT.Collapse, listener);
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       ExpandItem item = items [i];
+                       if (item != null ) item.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+@Override
+void setBackgroundPixel (int pixel) {
+       super.setBackgroundPixel (pixel);
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+@Override
+public void setFont (Font font) {
+       super.setFont (font);
+       hFont = font != null ? font.handle : 0;
+       layoutItems (0, true);
+}
+
+@Override
+void setForegroundPixel (int pixel) {
+       super.setForegroundPixel (pixel);
+       int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+void setScrollbar () {
+       if (itemCount == 0) return;
+       if ((style & SWT.V_SCROLL) == 0) return;
+       RECT rect = new 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 = new SCROLLINFO ();
+       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 != 0) info.nPage++;
+       OS.SetScrollInfo (handle, OS.SB_VERT, info, true);
+}
+
+/**
+ * Sets the receiver's spacing. Spacing specifies the number of points 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 ();
+       setSpacingInPixels(DPIUtil.autoScaleUp(spacing));
+}
+
+void setSpacingInPixels (int spacing) {
+       if (spacing < 0) return;
+       if (spacing == this.spacing) return;
+       this.spacing = spacing;
+       RECT rect = new 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 != width) item.setBoundsInPixels (0, 0, width, item.height, false, true);
+       }
+       layoutItems (0, true);
+       OS.InvalidateRect (handle, null, true);
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               for (int i = 0, n = items.length; i < n; i++) {
+                       if (items[i] != null) {
+                               items[i].updateTextDirection(textDirection == AUTO_TEXT_DIRECTION ? AUTO_TEXT_DIRECTION : style & SWT.FLIP_TEXT_DIRECTION);
+                       }
+               }
+               return true;
+       }
+       return false;
+}
+
+void showItem (ExpandItem item) {
+       Control control = item.control;
+       if (control != null && !control.isDisposed ()) {
+               control.setVisible (item.expanded);
+       }
+       item.redraw (true);
+       int index = indexOf (item);
+       layoutItems (index + 1, true);
+}
+
+void showFocus (boolean up) {
+       RECT rect = new 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 != 0) {
+               yCurrentScroll = Math.max (0, yCurrentScroll - updateY);
+               if ((style & SWT.V_SCROLL) != 0) {
+                       SCROLLINFO info = new SCROLLINFO ();
+                       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, 0, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE);
+               for (int i = 0; i < itemCount; i++) {
+                       items [i].y += updateY;
+               }
+       }
+}
+
+@Override
+TCHAR windowClass () {
+       return display.windowClass;
+}
+
+@Override
+long windowProc () {
+       return display.windowProc;
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       if (focusItem == null) return result;
+       switch ((int)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;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+       if (focusItem != null) focusItem.redraw (true);
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+       if (result == 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];
+               boolean hover = item.isHover (x, y);
+               if (hover && focusItem != item) {
+                       focusItem.redraw (true);
+                       focusItem = item;
+                       focusItem.redraw (true);
+                       forceFocus ();
+                       break;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONUP (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+       if (focusItem == null) return result;
+       int x = OS.GET_X_LPARAM (lParam);
+       int y = OS.GET_Y_LPARAM (lParam);
+       boolean 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSELEAVE (wParam, lParam);
+       if (result != 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+       if (result == 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];
+               boolean hover = item.isHover (x, y);
+               if (item.hover != hover) {
+                       item.hover = hover;
+                       item.redraw (false);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEWHEEL (long wParam, long lParam) {
+       return wmScrollWheel (true, wParam, lParam);
+}
+
+@Override
+LRESULT WM_PAINT (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+
+       PAINTSTRUCT ps = new PAINTSTRUCT ();
+       GCData data = new GCData ();
+       data.ps = ps;
+       data.hwnd = handle;
+       GC gc = new_GC (data);
+       if (gc != null) {
+               int width = ps.right - ps.left;
+               int height = ps.bottom - ps.top;
+               if (width != 0 && height != 0) {
+                       RECT rect = new RECT ();
+                       OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                       drawWidget (gc, rect);
+                       if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+                               Event event = new Event ();
+                               event.gc = gc;
+                               event.setBoundsInPixels(new Rectangle(rect.left, rect.top, width, height));
+                               sendEvent (SWT.Paint, event);
+                               event.gc = null;
+                       }
+               }
+               gc.dispose ();
+       }
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_PRINTCLIENT (long wParam, long lParam) {
+       LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+       RECT rect = new RECT ();
+       OS.GetClientRect (handle, rect);
+       GCData data = new GCData ();
+       data.device = display;
+       data.foreground = getForegroundPixel ();
+       GC gc = GC.win32_new (wParam, data);
+       drawWidget (gc, rect);
+       gc.dispose ();
+       return result;
+}
+
+@Override
+LRESULT WM_SETCURSOR (long wParam, long lParam) {
+       LRESULT result = super.WM_SETCURSOR (wParam, lParam);
+       if (result != null) return result;
+       int hitTest = (short) OS.LOWORD (lParam);
+       if (hitTest == OS.HTCLIENT) {
+               for (int i = 0; i < itemCount; i++) {
+                       ExpandItem item = items [i];
+                       if (item.hover) {
+                               long hCursor = OS.LoadCursor (0, OS.IDC_HAND);
+                               OS.SetCursor (hCursor);
+                               return LRESULT.ONE;
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+       if (focusItem != null) focusItem.redraw (true);
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       RECT rect = new 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 != width) item.setBoundsInPixels (0, 0, width, item.height, false, true);
+       }
+       setScrollbar ();
+       OS.InvalidateRect (handle, null, true);
+       return result;
+}
+
+@Override
+LRESULT wmScroll (ScrollBar bar, boolean update, long hwnd, int msg, long wParam, long lParam) {
+       LRESULT result = super.wmScroll (bar, true, hwnd, msg, wParam, lParam);
+       SCROLLINFO info = new SCROLLINFO ();
+       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, 0, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE);
+       yCurrentScroll = info.nPos;
+       if (updateY != 0) {
+               for (int i = 0; i < itemCount; i++) {
+                       items [i].y += updateY;
+               }
+       }
+       return result;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ExpandItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ExpandItem.java
new file mode 100644 (file)
index 0000000..a092e41
--- /dev/null
@@ -0,0 +1,523 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a expandable item in a expand bar.
+ * <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 ExpandBar
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ExpandItem extends Item {
+       ExpandBar parent;
+       Control control;
+       boolean expanded, hover;
+       int x, y, width, height;
+       int imageHeight, imageWidth;
+       static final int TEXT_INSET = 6;
+       static final int BORDER = 1;
+       static final 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 ExpandItem (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 ExpandItem (ExpandBar parent, int style, int index) {
+       super (parent, style);
+       this.parent = parent;
+       parent.createItem (this, style, index);
+}
+
+static ExpandBar checkNull (ExpandBar control) {
+       if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return control;
+}
+
+private void drawChevron (long hDC, RECT rect) {
+       long 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;
+       long hPen = OS.CreatePen (OS.PS_SOLID, 1, parent.getForegroundPixel ());
+       long oldPen = OS.SelectObject (hDC, hPen);
+       int [] polyline1, polyline2;
+       if (expanded) {
+               int px = rect.left + 5;
+               int py = rect.top + 7;
+               polyline1 = new int [] {
+                               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 = new int [] {
+                               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 = new int[] {
+                               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 = new int [] {
+                               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, polyline1, polyline1.length / 2);
+       OS.Polyline (hDC, polyline2, polyline2.length / 2);
+       if (hover) {
+               long whitePen = OS.CreatePen (OS.PS_SOLID, 1, OS.GetSysColor (OS.COLOR_3DHILIGHT));
+               long 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, points1, points1.length / 2);
+               OS.SelectObject (hDC, darkGrayPen);
+               int [] points2 = {
+                               rect.right, rect.top,
+                               rect.right, rect.bottom,
+                               rect.left, rect.bottom};
+               OS.Polyline (hDC, points2, 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, long hTheme, RECT clipRect, boolean drawFocus) {
+       long hDC = gc.handle;
+       int headerHeight = parent.getBandHeight ();
+       RECT rect = new RECT ();
+       OS.SetRect (rect, x, y, x + width, y + headerHeight);
+       if (hTheme != 0) {
+               OS.DrawThemeBackground (hTheme, hDC, OS.EBP_NORMALGROUPHEAD, 0, rect, clipRect);
+       } else {
+               long 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 != null) {
+               rect.left += ExpandItem.TEXT_INSET;
+               if (imageHeight > headerHeight) {
+                       gc.drawImage (image, DPIUtil.autoScaleDown(rect.left), DPIUtil.autoScaleDown(rect.top + headerHeight - imageHeight));
+               } else {
+                       gc.drawImage (image, DPIUtil.autoScaleDown(rect.left), DPIUtil.autoScaleDown(rect.top + (headerHeight - imageHeight) / 2));
+               }
+               rect.left += imageWidth;
+       }
+       if (text.length () > 0) {
+               rect.left += ExpandItem.TEXT_INSET;
+               char [] buffer;
+               if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) {
+                       int bits  = OS.GetWindowLong (parent.handle, OS.GWL_EXSTYLE);
+                       if ((bits & OS.WS_EX_LAYOUTRTL) != 0) {
+                               buffer = (LRE + text).toCharArray ();
+                       } else {
+                               buffer = (RLE + text).toCharArray ();
+                       }
+               }
+               else {
+                       buffer = text.toCharArray ();
+               }
+               if (hTheme != 0) {
+                       OS.DrawThemeText (hTheme, hDC, OS.EBP_NORMALGROUPHEAD, 0, buffer, buffer.length, OS.DT_VCENTER | OS.DT_SINGLELINE, 0, rect);
+               } else {
+                       int oldBkMode = OS.SetBkMode (hDC, OS.TRANSPARENT);
+                       OS.DrawText (hDC, buffer, 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 != 0) {
+               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 ()) {
+                       long pen = OS.CreatePen (OS.PS_SOLID, 1, OS.GetSysColor (OS.COLOR_BTNFACE));
+                       long 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, points, 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 boolean 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 DPIUtil.autoScaleDown(getHeaderHeightInPixels());
+}
+
+int getHeaderHeightInPixels () {
+       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 DPIUtil.autoScaleDown(getHeightInPixels());
+}
+
+int getHeightInPixels () {
+       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 (long hTheme, long hDC) {
+       int width = ExpandItem.TEXT_INSET * 2 + ExpandItem.CHEVRON_SIZE;
+       if (image != null) {
+               width += ExpandItem.TEXT_INSET + imageWidth;
+       }
+       if (text.length() > 0) {
+               RECT rect = new RECT ();
+               char [] buffer = text.toCharArray ();
+               if (hTheme != 0) {
+                       OS.GetThemeTextExtent (hTheme, hDC, OS.EBP_NORMALGROUPHEAD, 0, buffer, buffer.length, OS.DT_SINGLELINE, null, rect);
+               } else {
+                       OS.DrawText (hDC, buffer, buffer.length, rect, OS.DT_CALCRECT);
+               }
+               width += (rect.right - rect.left);
+       }
+       return width;
+}
+
+boolean 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 (boolean all) {
+       long parentHandle = parent.handle;
+       int headerHeight = parent.getBandHeight ();
+       RECT rect = new 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 setBoundsInPixels (int x, int y, int width, int height, boolean move, boolean 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 != 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.setBoundsInPixels (x, y + headerHeight, width, height);
+               if (move && !size) control.setLocationInPixels (x, y + headerHeight);
+               if (!move && size) control.setSizeInPixels (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 != null) {
+               if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+       }
+       this.control = control;
+       if (control != 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.setBoundsInPixels (x + BORDER, y + headerHeight, width, height);
+               } else {
+                       control.setBoundsInPixels (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 (boolean 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 ();
+       setHeightInPixels(DPIUtil.autoScaleUp(height));
+}
+
+void setHeightInPixels (int height) {
+       if (height < 0) return;
+       setBoundsInPixels (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 != null) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               imageHeight = bounds.height;
+               imageWidth = bounds.width;
+       } else {
+               imageHeight = imageWidth = 0;
+       }
+       if (oldImageHeight != imageHeight) {
+               parent.layoutItems (parent.indexOf (this), true);
+       } else {
+               redraw (true);
+       }
+}
+
+@Override
+public void setText (String string) {
+       super.setText (string);
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+       redraw (true);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/FileDialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/FileDialog.java
new file mode 100644 (file)
index 0000000..7bac8a0
--- /dev/null
@@ -0,0 +1,598 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class FileDialog extends Dialog {
+       String [] filterNames = new String [0];
+       String [] filterExtensions = new String [0];
+       String [] fileNames = new String [0];
+       String filterPath = "", fileName = "";
+       int filterIndex = 0;
+       boolean overwrite = false;
+       static final String FILTER = "*.*";
+       static int BUFFER_SIZE = 1024 * 32;
+       static boolean USE_HOOK = true;
+       static {
+               /*
+               *  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.
+               */
+               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 FileDialog (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>
+ *
+ * @see SWT#SAVE
+ * @see SWT#OPEN
+ * @see SWT#MULTI
+ */
+public FileDialog (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 boolean getOverwrite () {
+       return overwrite;
+}
+
+long OFNHookProc (long hdlg, long uiMsg, long wParam, long lParam) {
+       switch ((int)uiMsg) {
+               case OS.WM_NOTIFY:
+                       OFNOTIFY ofn = new OFNOTIFY ();
+                       OS.MoveMemory (ofn, lParam, OFNOTIFY.sizeof);
+                       if (ofn.code == OS.CDN_SELCHANGE) {
+                               int lResult = (int)OS.SendMessage (ofn.hwndFrom, OS.CDM_GETSPEC, 0, 0);
+                               if (lResult > 0) {
+                                       lResult += OS.MAX_PATH;
+                                       OPENFILENAME lpofn = new OPENFILENAME ();
+                                       OS.MoveMemory (lpofn, ofn.lpOFN, OPENFILENAME.sizeof);
+                                       if (lpofn.nMaxFile < lResult) {
+                                               long hHeap = OS.GetProcessHeap ();
+                                               long lpstrFile = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, lResult * TCHAR.sizeof);
+                                               if (lpstrFile != 0) {
+                                                       if (lpofn.lpstrFile != 0) OS.HeapFree (hHeap, 0, lpofn.lpstrFile);
+                                                       lpofn.lpstrFile = lpstrFile;
+                                                       lpofn.nMaxFile = lResult;
+                                                       OS.MoveMemory (ofn.lpOFN, lpofn, OPENFILENAME.sizeof);
+                                               }
+                                       }
+                               }
+                       }
+               break;
+       }
+       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 () {
+       long hHeap = OS.GetProcessHeap ();
+
+       /* Get the owner HWND for the dialog */
+       long hwndOwner = parent.handle;
+       long 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.
+       */
+       boolean enabled = false;
+       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 != parentOrientation) {
+               int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+               if (dialogOrientation == SWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+               hwndOwner = OS.CreateWindowEx (
+                       exStyle,
+                       Shell.DialogClass,
+                       null,
+                       0,
+                       OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                       hwndParent,
+                       0,
+                       OS.GetModuleHandle (null),
+                       null);
+               enabled = OS.IsWindowEnabled (hwndParent);
+               if (enabled) OS.EnableWindow (hwndParent, false);
+       }
+
+       /* Convert the title and copy it into lpstrTitle */
+       if (title == null) title = "";
+       /* Use the character encoding for the default locale */
+       TCHAR buffer3 = new TCHAR (0, title, true);
+       int byteCount3 = buffer3.length () * TCHAR.sizeof;
+       long lpstrTitle = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount3);
+       OS.MoveMemory (lpstrTitle, buffer3, byteCount3);
+
+       /* Compute filters and copy into lpstrFilter */
+       String strFilter = "";
+       if (filterNames == null) filterNames = new String [0];
+       if (filterExtensions == null) filterExtensions = new String [0];
+       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 == 0) {
+               strFilter = strFilter + FILTER + '\0' + FILTER + '\0';
+       }
+       /* Use the character encoding for the default locale */
+       TCHAR buffer4 = new TCHAR (0, strFilter, true);
+       int byteCount4 = buffer4.length () * TCHAR.sizeof;
+       long lpstrFilter = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount4);
+       OS.MoveMemory (lpstrFilter, buffer4, byteCount4);
+
+       /* Convert the fileName and filterName to C strings */
+       if (fileName == null) fileName = "";
+       /* Use the character encoding for the default locale */
+       TCHAR name = new TCHAR (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) != 0) nMaxFile = Math.max (nMaxFile, BUFFER_SIZE);
+       int byteCount = nMaxFile * TCHAR.sizeof;
+       long lpstrFile = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       int byteCountFile = Math.min (name.length () * TCHAR.sizeof, byteCount - TCHAR.sizeof);
+       OS.MoveMemory (lpstrFile, name, byteCountFile);
+
+       /*
+       * Copy the path into lpstrInitialDir and ensure that
+       * the last byte is NULL and the buffer does not overrun.
+       */
+       if (filterPath == null) filterPath = "";
+       /* Use the character encoding for the default locale */
+       TCHAR path = new TCHAR (0, filterPath.replace ('/', '\\'), true);
+       int byteCount5 = OS.MAX_PATH * TCHAR.sizeof;
+       long lpstrInitialDir = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount5);
+       int byteCountDir = Math.min (path.length () * TCHAR.sizeof, byteCount5 - TCHAR.sizeof);
+       OS.MoveMemory (lpstrInitialDir, path, byteCountDir);
+
+       /* Create the file dialog struct */
+       OPENFILENAME struct = new OPENFILENAME ();
+       struct.lStructSize = OPENFILENAME.sizeof;
+       struct.Flags = OS.OFN_HIDEREADONLY | OS.OFN_NOCHANGEDIR;
+       boolean save = (style & SWT.SAVE) != 0;
+       if (save && overwrite) struct.Flags |= OS.OFN_OVERWRITEPROMPT;
+       Callback callback = null;
+       if ((style & SWT.MULTI) != 0) {
+               struct.Flags |= OS.OFN_ALLOWMULTISELECT | OS.OFN_EXPLORER | OS.OFN_ENABLESIZING;
+               if (USE_HOOK) {
+                       callback = new Callback (this, "OFNHookProc", 4); //$NON-NLS-1$
+                       long lpfnHook = callback.getAddress ();
+                       if (lpfnHook == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+                       struct.lpfnHook = lpfnHook;
+                       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 == 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.
+       */
+       long lpstrDefExt = 0;
+       if (save) {
+               lpstrDefExt = 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)) != 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.
+       */
+       boolean oldRunMessagesInIdle = display.runMessagesInIdle;
+       display.runMessagesInIdle = true;
+       display.externalEventLoop = true;
+       display.sendPreExternalEventDispatchEvent ();
+       /*
+       * Open the dialog.  If the open fails due to an invalid
+       * file name, use an empty file name and open it again.
+       */
+       boolean success = (save) ? OS.GetSaveFileName (struct) : OS.GetOpenFileName (struct);
+       display.externalEventLoop = false;
+       display.sendPostExternalEventDispatchEvent ();
+       switch (OS.CommDlgExtendedError ()) {
+               case OS.FNERR_INVALIDFILENAME:
+                       OS.MoveMemory (lpstrFile, new char [1], TCHAR.sizeof);
+                       display.externalEventLoop = true;
+                       display.sendPreExternalEventDispatchEvent ();
+                       success = (save) ? OS.GetSaveFileName (struct) : OS.GetOpenFileName (struct);
+                       display.externalEventLoop = false;
+                       display.sendPostExternalEventDispatchEvent ();
+                       break;
+               case OS.FNERR_BUFFERTOOSMALL:
+                       USE_HOOK = true;
+                       break;
+       }
+       display.runMessagesInIdle = oldRunMessagesInIdle;
+
+       /* Clear the temporary dialog modal parent */
+       if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+               display.setModalDialog (oldModal);
+       }
+
+       /* Dispose the callback and reassign the buffer */
+       if (callback != null) callback.dispose ();
+       lpstrFile = struct.lpstrFile;
+
+       /* Set the new path, file name and filter */
+       fileNames = new String [0];
+       String fullPath = null;
+       if (success) {
+               char [] buffer = new char [struct.nMaxFile];
+               OS.MoveMemory (buffer, lpstrFile, buffer.length * TCHAR.sizeof);
+               int nFileOffset = struct.nFileOffset;
+               if (nFileOffset > 0) {
+                       filterPath = new String (buffer, 0, nFileOffset - 1);
+
+                       /*
+                       * 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) != 0 ? 4 : 1];
+                       int start = nFileOffset;
+                       do {
+                               int end = start;
+                               while (end < buffer.length && buffer [end] != 0) end++;
+                               String string = new String (buffer, start, end - start);
+                               start = end + 1;
+                               if (count == 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) == 0) break;
+                       } while (start < buffer.length && buffer[start] != 0);
+
+                       if (fileNames.length > 0) fileName = fileNames  [0];
+                       String separator = "";
+                       int length = filterPath.length ();
+                       if (length > 0 && filterPath.charAt (length - 1) != '\\') {
+                               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 != 0) OS.HeapFree (hHeap, 0, lpstrDefExt);
+
+       /* Destroy the BIDI orientation window */
+       if (hwndParent != 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 != 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>
+ * <p>
+ * Note: On Mac, setting the file extension filter affects how
+ * app bundles are treated by the dialog. When a filter extension
+ * having the app extension (.app) is selected, bundles are treated
+ * as files. For all other extension filters, bundles are treated
+ * as directories. When no filter extension is set, bundles are
+ * treated as files.
+ * </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 (boolean overwrite) {
+       this.overwrite = overwrite;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/FontDialog.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/FontDialog.java
new file mode 100644 (file)
index 0000000..7567914
--- /dev/null
@@ -0,0 +1,368 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class FontDialog extends Dialog {
+       FontData fontData;
+       RGB rgb;
+       boolean effectsVisible = true;
+
+/**
+ * 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 FontDialog (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 FontDialog (Shell parent, int style) {
+       super (parent, checkStyle (parent, style));
+       checkSubclass ();
+}
+
+/**
+ * Returns <code>true</code> if the dialog's effects selection controls
+ * are visible, and <code>false</code> otherwise.
+ * <p>
+ * If the platform's font dialog does not have any effects selection controls,
+ * then this method always returns false.
+ * </p>
+ *
+ * @return <code>true</code> if the dialog's effects selection controls
+ * are visible and <code>false</code> otherwise
+ *
+ * @since 3.8
+ */
+public boolean getEffectsVisible () {
+       return effectsVisible;
+}
+
+/**
+ * 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 ()
+ */
+@Deprecated
+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 == 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 () {
+       /* Get the owner HWND for the dialog */
+       long hwndOwner = parent.handle;
+       long 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.
+       */
+       boolean enabled = false;
+       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 != parentOrientation) {
+               int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+               if (dialogOrientation == SWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+               hwndOwner = OS.CreateWindowEx (
+                       exStyle,
+                       Shell.DialogClass,
+                       null,
+                       0,
+                       OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                       hwndParent,
+                       0,
+                       OS.GetModuleHandle (null),
+                       null);
+               enabled = OS.IsWindowEnabled (hwndParent);
+               if (enabled) OS.EnableWindow (hwndParent, false);
+       }
+
+       /* Open the dialog */
+       long hHeap = OS.GetProcessHeap ();
+       CHOOSEFONT lpcf = new CHOOSEFONT ();
+       lpcf.lStructSize = CHOOSEFONT.sizeof;
+       lpcf.hwndOwner = hwndOwner;
+       lpcf.Flags = OS.CF_SCREENFONTS;
+       if (effectsVisible) {
+               lpcf.Flags |= OS.CF_EFFECTS;
+       }
+
+       long lpLogFont = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, LOGFONT.sizeof);
+       if (fontData != null && fontData.data != null) {
+               LOGFONT logFont = fontData.data;
+               int lfHeight = logFont.lfHeight;
+               long hDC = OS.GetDC (0);
+               int pixels = -(int)(0.5f + (fontData.height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY) / 72));
+               OS.ReleaseDC (0, hDC);
+               logFont.lfHeight = pixels;
+               lpcf.Flags |= OS.CF_INITTOLOGFONTSTRUCT;
+               OS.MoveMemory (lpLogFont, logFont, LOGFONT.sizeof);
+               logFont.lfHeight = lfHeight;
+       }
+       lpcf.lpLogFont = lpLogFont;
+       if (rgb != 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 = parent.getDisplay ();
+       if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+               oldModal = display.getModalDialog ();
+               display.setModalDialog (this);
+       }
+
+       display.externalEventLoop = true;
+       display.sendPreExternalEventDispatchEvent ();
+       /* Open the dialog */
+       boolean success = OS.ChooseFont (lpcf);
+       display.externalEventLoop = false;
+       display.sendPostExternalEventDispatchEvent ();
+
+       /* Clear the temporary dialog modal parent */
+       if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+               display.setModalDialog (oldModal);
+       }
+
+       /* Compute the result */
+       if (success) {
+               LOGFONT logFont = new LOGFONT ();
+               OS.MoveMemory (logFont, lpLogFont, LOGFONT.sizeof);
+
+               /*
+                * This will not work on multiple screens or
+                * for printing. Should use DC for the proper device.
+                */
+               long hDC = OS.GetDC(0);
+               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.
+                        */
+                       long hFont = OS.CreateFontIndirect(logFont);
+                       long oldFont = OS.SelectObject(hDC, hFont);
+                       TEXTMETRIC lptm = new TEXTMETRIC ();
+                       OS.GetTextMetrics(hDC, lptm);
+                       OS.SelectObject(hDC, oldFont);
+                       OS.DeleteObject(hFont);
+                       pixels = logFont.lfHeight - lptm.tmInternalLeading;
+               } else {
+                       pixels = -logFont.lfHeight;
+               }
+               OS.ReleaseDC(0, hDC);
+
+               float points = pixels * 72f /logPixelsY;
+               fontData = FontData.win32_new (logFont, points);
+               if (effectsVisible) {
+                       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 != 0) OS.HeapFree (hHeap, 0, lpLogFont);
+
+       /* Destroy the BIDI orientation window */
+       if (hwndParent != 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 != 0) OS.UpdateWindow (hwndOwner);
+
+       if (!success) return null;
+       return fontData;
+}
+
+/**
+ * Sets the effects selection controls in the dialog visible if the
+ * argument is <code>true</code>, and invisible otherwise.
+ * <p>
+ * By default the effects selection controls are displayed if the
+ * platform font dialog supports effects selection.
+ * </p>
+ *
+ * @param visible whether or not the dialog will show the effects selection controls
+ *
+ * @since 3.8
+ */
+public void setEffectsVisible(boolean visible) {
+       effectsVisible = visible;
+}
+
+/**
+ * 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 [])
+ */
+@Deprecated
+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 != 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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Group.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Group.java
new file mode 100644 (file)
index 0000000..0277d35
--- /dev/null
@@ -0,0 +1,627 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Group extends Composite {
+       String text = "";
+       static final int CLIENT_INSET = 3;
+       static final long GroupProc;
+       static final TCHAR GroupClass = new TCHAR (0, "SWT_GROUP", true);
+       static {
+               /*
+               * 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.
+               */
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               TCHAR WC_BUTTON = new TCHAR (0, "BUTTON", true);
+               OS.GetClassInfo (0, WC_BUTTON, lpWndClass);
+               GroupProc = lpWndClass.lpfnWndProc;
+               long hInstance = OS.GetModuleHandle (null);
+               if (!OS.GetClassInfo (hInstance, GroupClass, lpWndClass)) {
+                       lpWndClass.hInstance = hInstance;
+                       lpWndClass.style &= ~(OS.CS_HREDRAW | OS.CS_VREDRAW);
+                       OS.RegisterClass (GroupClass, lpWndClass);
+               }
+       }
+
+/**
+ * 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 Group (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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);
+       }
+       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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       Point size = super.computeSizeInPixels (wHint, hHint, changed);
+       int length = text.length ();
+       if (length != 0) {
+               String string = fixText (false);
+
+               /*
+               * If the group has text, and the text is wider than the
+               * client area, pad the width so the text is not clipped.
+               */
+               char [] buffer = (string == null ? text : string).toCharArray ();
+               long newFont, oldFont = 0;
+               long hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               RECT rect = new RECT ();
+               int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+               OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+               int offsetY = OS.IsAppThemed () ? 0 : 1;
+               size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6 + offsetY);
+       }
+       return size;
+}
+
+@Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       checkWidget ();
+       Rectangle trim = super.computeTrimInPixels (x, y, width, height);
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       TEXTMETRIC tm = new TEXTMETRIC ();
+       OS.GetTextMetrics (hDC, tm);
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       int offsetY = OS.IsAppThemed () ? 0 : 1;
+       trim.x -= CLIENT_INSET;
+       trim.y -= tm.tmHeight + offsetY;
+       trim.width += CLIENT_INSET * 2;
+       trim.height += tm.tmHeight + CLIENT_INSET + offsetY;
+       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 (boolean 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.
+       */
+       String string = fixText (enabled);
+       if (string != null) {
+               TCHAR buffer = new TCHAR (getCodePage (), string, true);
+               OS.SetWindowText (handle, buffer);
+       }
+       if (enabled && hasCustomForeground()) {
+               OS.InvalidateRect (handle, null, true);
+       }
+}
+
+String fixText (boolean 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 (text.length() == 0) return null;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               String string = null;
+               if (!enabled && !OS.IsAppThemed ()) {
+                       string = " " + text + " ";
+               }
+               return (style & SWT.FLIP_TEXT_DIRECTION) == 0 ? string : string != null ? LRE + string : LRE + text;
+       } else if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) {
+               return RLE + text;
+       }
+       return null;
+}
+
+@Override Rectangle getClientAreaInPixels () {
+       checkWidget ();
+       forceResize ();
+       RECT rect = new RECT ();
+       OS.GetClientRect (handle, rect);
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       TEXTMETRIC tm = new TEXTMETRIC ();
+       OS.GetTextMetrics (hDC, tm);
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       int offsetY = 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
+boolean mnemonicHit (char key) {
+       return setFocus ();
+}
+
+@Override
+boolean mnemonicMatch (char key) {
+       char mnemonic = findMnemonic (getText ());
+       if (mnemonic == '\0') return false;
+       return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+}
+
+@Override
+void printWidget (long hwnd, long hdc, GC gc) {
+       /*
+       * Bug in Windows.  For some reason, PrintWindow()
+       * returns success but does nothing when it is called
+       * on a printer.  The fix is to just go directly to
+       * WM_PRINT in this case.
+       */
+       boolean success = false;
+       if (!(OS.GetDeviceCaps(gc.handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER)) {
+               int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+               if ((bits & OS.WS_VISIBLE) == 0) {
+                       OS.ShowWindow (hwnd, OS.SW_SHOW);
+               }
+               success = OS.PrintWindow (hwnd, hdc, 0);
+               if ((bits & OS.WS_VISIBLE) == 0) {
+                       OS.ShowWindow (hwnd, OS.SW_HIDE);
+               }
+       }
+
+       /*
+       * Bug in Windows.  For some reason, PrintWindow() fails
+       * when it is called on a push button.  The fix is to
+       * detect the failure and use WM_PRINT instead.  Note
+       * that WM_PRINT cannot be used all the time because it
+       * fails for browser controls when the browser has focus.
+       */
+       if (!success) {
+               /*
+               * 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 = getBoundsInPixels ();
+               OS.IntersectClipRect (hdc, 0, 0, rect.width, rect.height);
+               for (int i=children.length - 1; i>=0; --i) {
+                       Point location = children [i].getLocationInPixels ();
+                       int graphicsMode = OS.GetGraphicsMode(hdc);
+                       if (graphicsMode == OS.GM_ADVANCED) {
+                               float [] lpXform = {1, 0, 0, 1, location.x, location.y};
+                               OS.ModifyWorldTransform(hdc, lpXform, OS.MWT_LEFTMULTIPLY);
+                       } else {
+                               OS.SetWindowOrgEx (hdc, -location.x, -location.y, null);
+                       }
+                       long topHandle = children [i].topHandle();
+                       int bits = OS.GetWindowLong (topHandle, OS.GWL_STYLE);
+                       if ((bits & OS.WS_VISIBLE) != 0) {
+                               children [i].printWidget (topHandle, hdc, gc);
+                       }
+                       if (graphicsMode == OS.GM_ADVANCED) {
+                               float [] lpXform = {1, 0, 0, 1, -location.x, -location.y};
+                               OS.ModifyWorldTransform(hdc, lpXform, OS.MWT_LEFTMULTIPLY);
+                       }
+               }
+               OS.RestoreDC (hdc, nSavedDC);
+       }
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       text = null;
+}
+
+@Override
+int resolveTextDirection () {
+       return BidiUtil.resolveTextDirection (text);
+}
+
+@Override
+public void setFont (Font font) {
+       checkWidget ();
+       Rectangle oldRect = getClientAreaInPixels ();
+       super.setFont (font);
+       Rectangle newRect = getClientAreaInPixels ();
+       if (!oldRect.equals (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><p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       text = string;
+       if ((state & HAS_AUTO_DIRECTION) == 0 || !updateTextDirection (AUTO_TEXT_DIRECTION)) {
+               string = fixText (OS.IsWindowEnabled (handle));
+               TCHAR buffer = new TCHAR (getCodePage (), string == null ? text : string, true);
+               OS.SetWindowText (handle, buffer);
+       }
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               String string = fixText (OS.IsWindowEnabled (handle));
+               TCHAR buffer = new TCHAR (getCodePage (), string == null ? text : string, true);
+               OS.SetWindowText (handle, buffer);
+               return true;
+       }
+       return false;
+}
+
+@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
+TCHAR windowClass () {
+       return GroupClass;
+}
+
+@Override
+long windowProc () {
+       return GroupProc;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if (result != null) return result;
+       /*
+       * Feature in Windows.  Group boxes do not erase
+       * the background before drawing.  The fix is to
+       * fill the background.
+       */
+       drawBackground (wParam);
+       return LRESULT.ONE;
+}
+
+@Override
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+       if (result != 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.
+       */
+       long code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+       if (code == OS.HTTRANSPARENT) code = OS.HTCLIENT;
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_MOUSEMOVE (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+       if (result != 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_PAINT (long wParam, long lParam) {
+       LRESULT result = super.WM_PAINT(wParam, lParam);
+
+       if (hasCustomForeground() && text.length () != 0) {
+               String string = fixText (false);
+               char [] buffer = (string == null ? text : string).toCharArray ();
+
+               // We cannot use BeginPaint and EndPaint, because that removes the group border
+               long hDC = OS.GetDC(handle);
+               RECT rect = new RECT ();
+               OS.GetClientRect (handle, rect);
+               rect.left += 3*CLIENT_INSET;
+
+               long newFont, oldFont = 0;
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+
+               OS.DrawText(hDC, buffer, buffer.length, rect, OS.DT_SINGLELINE | OS.DT_LEFT | OS.DT_TOP | OS.DT_CALCRECT);
+               // The calculated rectangle is a little bit too small. Italic fonts would show some small part in the default color.
+               rect.right += CLIENT_INSET;
+               drawBackground(hDC, rect);
+               OS.SetBkMode(hDC, OS.TRANSPARENT);
+               OS.SetTextColor(hDC, getForegroundPixel());
+               OS.DrawText(hDC, buffer, buffer.length, rect, OS.DT_SINGLELINE | OS.DT_LEFT | OS.DT_TOP);
+
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC(handle, hDC);
+               // Without validating the drawn area it would be overdrawn by windows
+               OS.ValidateRect(handle, rect);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_PRINTCLIENT (long wParam, long lParam) {
+       LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+       if (result != 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.IsAppThemed ()) {
+               int nSavedDC = OS.SaveDC (wParam);
+               long code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+               OS.RestoreDC (wParam, nSavedDC);
+               return new LRESULT (code);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+       if (result != 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.
+       */
+       boolean redraw = findImageControl () != null;
+       if (!redraw) {
+               if ((state & THEME_BACKGROUND) != 0) {
+                       if (OS.IsAppThemed ()) {
+                               redraw = findThemeControl () != null;
+                       }
+               }
+               if (!redraw) redraw = findBackgroundControl () != null;
+       }
+       if (redraw) {
+               OS.InvalidateRect (handle, null, false);
+               long code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+               return new LRESULT (code);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
+       LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+       if (result != 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.
+       */
+       if (!OS.IsWindowVisible (handle)) return result;
+       WINDOWPOS lpwp = new WINDOWPOS ();
+       OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+       if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) != 0) {
+               return result;
+       }
+       RECT rect = new 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 == oldWidth && newHeight == oldHeight) {
+               return result;
+       }
+       if (newWidth != 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 != 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/IME.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/IME.java
new file mode 100644 (file)
index 0000000..8468050
--- /dev/null
@@ -0,0 +1,589 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class IME extends Widget {
+       Canvas parent;
+       int caretOffset;
+       int startOffset;
+       int commitCount;
+       String text;
+       int [] ranges;
+       TextStyle [] styles;
+
+       static final int WM_MSIME_MOUSE = OS.RegisterWindowMessage (new TCHAR (0, "MSIMEMouseOperation", true)); //$NON-NLS-1$
+
+       /* TextLayout has a copy of these constants */
+       static final int UNDERLINE_IME_DOT = 1 << 16;
+       static final int UNDERLINE_IME_DASH = 2 << 16;
+       static final int UNDERLINE_IME_THICK = 3 << 16;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+IME () {
+}
+
+/**
+ * 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 IME (Canvas parent, int style) {
+       super (parent, style);
+       this.parent = parent;
+       createWidget ();
+}
+
+void createWidget () {
+       text = ""; //$NON-NLS-1$
+       startOffset = -1;
+       if (parent.getIME () == null) {
+               parent.setIME (this);
+       }
+}
+
+/**
+ * Returns the offset of the caret from the start of the document.
+ * -1 means that there is currently no active composition.
+ * 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) {
+       long [] ppv = new long [1];
+       int hr = COM.CoCreateInstance (COM.CLSID_TF_InputProcessorProfiles, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ITfInputProcessorProfiles, ppv);
+       TF_DISPLAYATTRIBUTE pda = null;
+       if (hr == OS.S_OK) {
+               ITfInputProcessorProfiles pProfiles = new ITfInputProcessorProfiles (ppv [0]);
+               GUID pclsid = new GUID ();
+               GUID pguidProfile = new GUID ();
+               hr = pProfiles.GetDefaultLanguageProfile (langid, COM.GUID_TFCAT_TIP_KEYBOARD, pclsid, pguidProfile);
+               if (hr == OS.S_OK) {
+                       hr = COM.CoCreateInstance (pclsid, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ITfDisplayAttributeProvider, ppv);
+                       if (hr == OS.S_OK) {
+                               ITfDisplayAttributeProvider pProvider = new ITfDisplayAttributeProvider (ppv [0]);
+                               hr = pProvider.EnumDisplayAttributeInfo (ppv);
+                               if (hr == OS.S_OK) {
+                                       IEnumTfDisplayAttributeInfo pEnum = new IEnumTfDisplayAttributeInfo (ppv [0]);
+                                       TF_DISPLAYATTRIBUTE tempPda = new TF_DISPLAYATTRIBUTE ();
+                                       while ((hr = pEnum.Next (1, ppv, null)) == OS.S_OK) {
+                                               ITfDisplayAttributeInfo pDispInfo = new ITfDisplayAttributeInfo (ppv [0]);
+                                               pDispInfo.GetAttributeInfo (tempPda);
+                                               pDispInfo.Release ();
+                                               if (tempPda.bAttr == attInfo) {
+                                                       pda = tempPda;
+                                                       break;
+                                               }
+                                       }
+                                       pEnum.Release ();
+                               }
+                               pProvider.Release ();
+                       }
+               }
+               pProfiles.Release ();
+       }
+       if (pda == 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 == OS.TF_ATTR_TARGET_CONVERTED;
+                               break;
+               }
+       }
+       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 == 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 == 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 boolean getWideCaret() {
+       checkWidget ();
+       long layout = OS.GetKeyboardLayout (0);
+       short langID = (short)OS.LOWORD (layout);
+       return OS.PRIMARYLANGID (langID) == OS.LANG_KOREAN;
+}
+
+boolean isInlineEnabled () {
+       return OS.IsDBLocale && hooks (SWT.ImeComposition);
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (this == parent.getIME ()) parent.setIME (null);
+}
+
+@Override
+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.
+ *
+ * @param offset 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 != -1) {
+               startOffset = offset;
+       }
+}
+
+LRESULT WM_IME_COMPOSITION (long wParam, long lParam) {
+       if (!isInlineEnabled ()) return null;
+       ranges = null;
+       styles = null;
+       caretOffset = commitCount = 0;
+       long hwnd = parent.handle;
+       long hIMC = OS.ImmGetContext (hwnd);
+       if (hIMC != 0) {
+               char [] buffer = null;
+               if ((lParam & OS.GCS_RESULTSTR) != 0) {
+                       int length = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, (char [])null, 0);
+                       if (length > 0) {
+                               buffer = new char [length / TCHAR.sizeof];
+                               OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer, length);
+                               if (startOffset == -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 != null ? new String (buffer) : ""; //$NON-NLS-1$
+                               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++) {
+                                               char c = chars.charAt (i);
+                                               display.lastAscii = c;
+                                               event = new Event ();
+                                               event.character = c;
+                                               parent.sendEvent (SWT.KeyDown, event);
+                                       }
+                               }
+                       }
+                       if ((lParam & OS.GCS_COMPSTR) == 0) return LRESULT.ONE;
+               }
+               buffer = null;
+               if ((lParam & OS.GCS_COMPSTR) != 0) {
+                       int length = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, (char [])null, 0);
+                       if (length > 0) {
+                               buffer = new char [length / TCHAR.sizeof];
+                               OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer, length);
+                               if ((lParam & OS.GCS_CURSORPOS) != 0) {
+                                       caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, (char [])null, 0);
+                               }
+                               int [] clauses = null;
+                               if ((lParam & OS.GCS_COMPCLAUSE) != 0) {
+                                       length = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPCLAUSE, (int [])null, 0);
+                                       if (length > 0) {
+                                               clauses = new int [length / 4];
+                                               OS.ImmGetCompositionString (hIMC, OS.GCS_COMPCLAUSE, clauses, length);
+                                       }
+                               }
+                               if ((lParam & OS.GCS_COMPATTR) != 0 && clauses != null) {
+                                       length = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPATTR, (byte [])null, 0);
+                                       if (length > 0) {
+                                               byte [] attrs = new byte [length];
+                                               OS.ImmGetCompositionString (hIMC, OS.GCS_COMPATTR, attrs, length);
+                                               length = clauses.length - 1;
+                                               ranges = new int [length * 2];
+                                               styles = new TextStyle [length];
+                                               long layout = OS.GetKeyboardLayout (0);
+                                               short langID = (short)OS.LOWORD (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 ();
+                                                       /* Added length check to avoid possibility of AIOOB, bug 444926 */
+                                                       if (clauses [i] >= 0 && clauses [i] < attrs.length) {
+                                                               attr = getDisplayAttribute (langID, attrs [clauses [i]]);
+                                                               if (attr != null) {
+                                                                       switch (attr.crText.type) {
+                                                                               case OS.TF_CT_COLORREF:
+                                                                                       style.foreground = Color.win32_new (display, attr.crText.cr);
+                                                                                       break;
+                                                                               case OS.TF_CT_SYSCOLOR:
+                                                                                       int colorRef = OS.GetSysColor (attr.crText.cr);
+                                                                                       style.foreground = Color.win32_new (display, colorRef);
+                                                                                       break;
+                                                                       }
+                                                                       switch (attr.crBk.type) {
+                                                                               case OS.TF_CT_COLORREF:
+                                                                                       style.background = Color.win32_new (display, attr.crBk.cr);
+                                                                                       break;
+                                                                               case OS.TF_CT_SYSCOLOR:
+                                                                                       int colorRef = OS.GetSysColor (attr.crBk.cr);
+                                                                                       style.background = Color.win32_new (display, colorRef);
+                                                                                       break;
+                                                                       }
+                                                                       switch (attr.crLine.type) {
+                                                                               case OS.TF_CT_COLORREF:
+                                                                                       style.underlineColor = Color.win32_new (display, attr.crLine.cr);
+                                                                                       break;
+                                                                               case OS.TF_CT_SYSCOLOR:
+                                                                                       int colorRef = OS.GetSysColor (attr.crLine.cr);
+                                                                                       style.underlineColor = Color.win32_new (display, colorRef);
+                                                                                       break;
+                                                                       }
+                                                                       style.underline = attr.lsStyle != 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;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       OS.ImmReleaseContext (hwnd, hIMC);
+               }
+               int end = startOffset + text.length();
+               if (startOffset == -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 != null ? new String (buffer) : ""; //$NON-NLS-1$
+               sendEvent (SWT.ImeComposition, event);
+               if (text.length() == 0) {
+                       startOffset = -1;
+                       ranges = null;
+                       styles = null;
+               }
+       }
+       return LRESULT.ONE;
+}
+
+LRESULT WM_IME_COMPOSITION_START (long wParam, long lParam) {
+       return isInlineEnabled () ? LRESULT.ONE : null;
+}
+
+LRESULT WM_IME_ENDCOMPOSITION (long wParam, long lParam) {
+       // Reset defaults. Otherwise the next composition overwrites the previous one.
+       startOffset = -1;
+       caretOffset = 0;
+       return isInlineEnabled () ? LRESULT.ONE : null;
+}
+
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       if (wParam == OS.VK_HANJA) {
+               long hKL = OS.GetKeyboardLayout (0);
+               short langID = (short)OS.LOWORD (hKL);
+               if (OS.PRIMARYLANGID (langID) == OS.LANG_KOREAN) {
+                       Event event = new Event ();
+                       event.detail = SWT.COMPOSITION_SELECTION;
+                       sendEvent (SWT.ImeComposition, event);
+                       if (event.start == event.end) {
+                               event.text = null;
+                               event.end = event.start + 1;
+                               sendEvent (SWT.ImeComposition, event);
+                       }
+                       if (event.text != null && event.text.length() > 0) {
+                               int length = event.text.length();
+                               if (length > 1) {
+                                       event.end = event.start + 1;
+                               }
+                               long hwnd = parent.handle;
+                               long hIMC = OS.ImmGetContext (hwnd);
+                               TCHAR buffer = new TCHAR (0, event.text, true);
+                               long rc = OS.ImmEscape(hKL, hIMC, OS.IME_ESC_HANJA_MODE, buffer);
+                               if (rc != 0) {
+                                       sendEvent (SWT.ImeComposition, event);
+                               }
+                       }
+               }
+       }
+       return null;
+}
+
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       if (!isInlineEnabled ()) return null;
+       long hwnd = parent.handle;
+       long hIMC = OS.ImmGetContext (hwnd);
+       if (hIMC != 0) {
+               if (OS.ImmGetOpenStatus (hIMC)) {
+                       OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0);
+               }
+               OS.ImmReleaseContext (hwnd, hIMC);
+       }
+       return null;
+}
+
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       if (!isInlineEnabled ()) return null;
+       long hwnd = parent.handle;
+       long hIMC = OS.ImmGetContext (hwnd);
+       if (hIMC != 0) {
+               if (OS.ImmGetOpenStatus (hIMC)) {
+                       if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, (char [])null, 0) > 0) {
+                               Event event = new Event ();
+                               event.detail = SWT.COMPOSITION_OFFSET;
+                               event.setLocationInPixels(OS.GET_X_LPARAM (lParam), OS.GET_Y_LPARAM (lParam));
+                               sendEvent (SWT.ImeComposition, event);
+                               int offset = event.index;
+                               int length = text.length();
+                               if (offset != -1 && startOffset != -1 && startOffset <= offset && offset < startOffset + length) {
+                                       long imeWnd = OS.ImmGetDefaultIMEWnd (hwnd);
+                                       offset = event.index + event.count - startOffset;
+                                       int trailing = event.count > 0 ? 1 : 2;
+                                       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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Item.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Item.java
new file mode 100644 (file)
index 0000000..3044241
--- /dev/null
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+
+/**
+ * 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 extends Widget {
+       String text;
+       Image image;
+       /**
+        * Maximum number of characters Windows can reliably display in one line.
+        * Mac and Linux can display more but we are limited by windows here.
+        */
+       static final int TEXT_LIMIT = 8192;
+
+       static final String ELLIPSIS = "...";
+
+
+
+/**
+ * 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 Item (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 Item (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 != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       this.image = image;
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       text = string;
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+}
+
+boolean updateTextDirection(int textDirection) {
+       /*
+        * textDirection argument passed here is either (1) AUTO_TEXT_DIRECTION, or
+        * (2) 0 (i.e. match orientation) or FLIP_TEXT_DIRECTION (mismatch orientation).
+        */
+       if (textDirection == AUTO_TEXT_DIRECTION) {
+               state |= HAS_AUTO_DIRECTION;
+               textDirection = (style ^ BidiUtil.resolveTextDirection (text)) == 0 ? 0 : SWT.FLIP_TEXT_DIRECTION;
+       } else {
+               state &= ~HAS_AUTO_DIRECTION;
+       }
+       if (((style & SWT.FLIP_TEXT_DIRECTION) ^ textDirection) != 0) {
+               style ^= SWT.FLIP_TEXT_DIRECTION;
+               return true;
+       }
+       return textDirection == AUTO_TEXT_DIRECTION;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Label.java
new file mode 100644 (file)
index 0000000..e15b7da
--- /dev/null
@@ -0,0 +1,620 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Paul Pazderski - Bug 205199: setImage(null) on Label overrides text
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 honored
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Label extends Control {
+       String text = "";
+       Image image;
+       static final int MARGIN = 4;
+       static /*final*/ boolean IMAGE_AND_TEXT = false;
+       static final long LabelProc;
+       static final TCHAR LabelClass = new TCHAR (0, "STATIC", true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, LabelClass, lpWndClass);
+               LabelProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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 Label (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       /*
+       * Feature in Windows 7.  When the user double clicks
+       * on the label, the text of the label is copied to the
+       * clipboard.  This is unwanted. The fix is to avoid
+       * calling the label window proc.
+       */
+       if (OS.WIN32_VERSION >= OS.VERSION(6, 1)) {
+               switch (msg) {
+                       case OS.WM_LBUTTONDBLCLK: return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+               }
+       }
+       return OS.CallWindowProc (LabelProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+       style |= SWT.NO_FOCUS;
+       if ((style & SWT.SEPARATOR) != 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width = 0, height = 0, border = getBorderWidthInPixels ();
+       if ((style & SWT.SEPARATOR) != 0) {
+               int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+               if ((style & SWT.HORIZONTAL) != 0) {
+                       width = DEFAULT_WIDTH;  height = lineWidth * 2;
+               } else {
+                       width = lineWidth * 2; height = DEFAULT_HEIGHT;
+               }
+               if (wHint != SWT.DEFAULT) width = wHint;
+               if (hHint != SWT.DEFAULT) height = hHint;
+               width += border * 2; height += border * 2;
+               return new Point (width, height);
+       }
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       boolean drawText = true;
+       boolean drawImage = (bits & OS.SS_OWNERDRAW) == OS.SS_OWNERDRAW;
+       if (drawImage) {
+               if (image != null) {
+                       Rectangle rect = image.getBoundsInPixels();
+                       width += rect.width;
+                       height += rect.height;
+                       if (IMAGE_AND_TEXT) {
+                               if (text.length () != 0) width += MARGIN;
+                       } else {
+                               drawText = false;
+                       }
+               }
+       }
+       if (drawText) {
+               long hDC = OS.GetDC (handle);
+               long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               long oldFont = OS.SelectObject (hDC, newFont);
+               int length = OS.GetWindowTextLength (handle);
+               if (length == 0) {
+                       TEXTMETRIC tm = new TEXTMETRIC ();
+                       OS.GetTextMetrics (hDC, tm);
+                       height = Math.max (height, tm.tmHeight);
+               } else {
+                       RECT rect = new RECT ();
+                       int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS;
+                       if ((style & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) {
+                               flags |= OS.DT_WORDBREAK;
+                               rect.right = Math.max (0, wHint - width);
+                       }
+                       char [] buffer = new char [length + 1];
+                       OS.GetWindowText (handle, buffer, length + 1);
+                       OS.DrawText (hDC, buffer, length, rect, flags);
+                       width += rect.right - rect.left;
+                       height = Math.max (height, rect.bottom - rect.top);
+               }
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+       }
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       width += border * 2;
+       height += border * 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) != 0) return 0;
+       if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+       if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+       if ((style & SWT.RIGHT) != 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) != 0) return "";
+       return text;
+}
+
+@Override
+boolean mnemonicHit (char key) {
+       Control control = this;
+       while (control.parent != null) {
+               Control [] children = control.parent._getChildren ();
+               int index = 0;
+               while (index < children.length) {
+                       if (children [index] == control) break;
+                       index++;
+               }
+               index++;
+               if (index < children.length) {
+                       if (children [index].setFocus ()) return true;
+               }
+               control = control.parent;
+       }
+       return false;
+}
+
+@Override
+boolean mnemonicMatch (char key) {
+       char mnemonic = findMnemonic (getText ());
+       if (mnemonic == '\0') return false;
+       return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       text = null;
+       image = null;
+}
+
+@Override
+int resolveTextDirection() {
+       return (style & SWT.SEPARATOR) != 0 ? SWT.NONE : BidiUtil.resolveTextDirection (text);
+}
+
+/**
+ * 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) != 0) return;
+       if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 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) != OS.SS_OWNERDRAW) {
+               bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT);
+               if ((style & SWT.LEFT) != 0) {
+                       if ((style & SWT.WRAP) != 0) {
+                               bits |= OS.SS_LEFT;
+                       } else {
+                               bits |= OS.SS_LEFTNOWORDWRAP;
+                       }
+               }
+               if ((style & SWT.CENTER) != 0) bits |= OS.SS_CENTER;
+               if ((style & SWT.RIGHT) != 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) != 0) return;
+       if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       this.image = image;
+       updateStyleBits(image == null);
+       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>
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if ((style & SWT.SEPARATOR) != 0) return;
+       updateStyleBits(true);
+       /*
+       * 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;
+       string = Display.withCrLf (string);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       OS.SetWindowText (handle, buffer);
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+}
+
+/**
+ * Update the control's static style bits to reflect the changed image vs. text
+ * situation.
+ *
+ * @param showText if <code>true</code> set required style bits to render text
+ *                 otherwise to render the image
+ */
+void updateStyleBits(boolean showText) {
+       if (showText) {
+               int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+               newBits &= ~OS.SS_OWNERDRAW;
+               if ((style & SWT.LEFT) != 0) {
+                       if ((style & SWT.WRAP) != 0) {
+                               newBits |= OS.SS_LEFT;
+                       } else {
+                               newBits |= OS.SS_LEFTNOWORDWRAP;
+                       }
+               }
+               if ((style & SWT.CENTER) != 0) newBits |= OS.SS_CENTER;
+               if ((style & SWT.RIGHT) != 0) newBits |= OS.SS_RIGHT;
+               if (oldBits != newBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+       } else {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.SS_OWNERDRAW) != OS.SS_OWNERDRAW) {
+                       bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT);
+                       bits |= OS.SS_OWNERDRAW;
+                       OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+               }
+       }
+}
+
+@Override
+int widgetExtStyle () {
+       int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
+       if ((style & SWT.BORDER) != 0) return bits | OS.WS_EX_STATICEDGE;
+       return bits;
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.SS_NOTIFY;
+       if ((style & SWT.SEPARATOR) != 0) return bits | OS.SS_OWNERDRAW;
+       if ((style & SWT.WRAP) != 0) bits |= OS.SS_EDITCONTROL;
+       if ((style & SWT.CENTER) != 0) return bits | OS.SS_CENTER;
+       if ((style & SWT.RIGHT) != 0) return bits | OS.SS_RIGHT;
+       if ((style & SWT.WRAP) != 0) return bits | OS.SS_LEFT;
+       return bits | OS.SS_LEFTNOWORDWRAP;
+}
+
+@Override
+TCHAR windowClass () {
+       return LabelClass;
+}
+
+@Override
+long windowProc () {
+       return LabelProc;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if (result != null) return result;
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.SS_OWNERDRAW) == OS.SS_OWNERDRAW) {
+               return LRESULT.ONE;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       if (isDisposed ()) return result;
+       if ((style & SWT.SEPARATOR) != 0) {
+               OS.InvalidateRect (handle, null, true);
+               return result;
+       }
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.SS_OWNERDRAW) == 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) != OS.SS_LEFTNOWORDWRAP) {
+               OS.InvalidateRect (handle, null, true);
+               return result;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+       if (result != 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.
+       */
+       boolean redraw = findImageControl () != null;
+       if (!redraw) {
+               if ((state & THEME_BACKGROUND) != 0) {
+                       if (OS.IsAppThemed ()) {
+                               redraw = findThemeControl () != null;
+                       }
+               }
+       }
+       if (redraw) {
+               OS.InvalidateRect (handle, null, false);
+               long code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+               return new LRESULT (code);
+       }
+       return result;
+}
+
+@Override
+LRESULT wmDrawChild (long wParam, long lParam) {
+       DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+       drawBackground (struct.hDC);
+       if ((style & SWT.SEPARATOR) != 0) {
+               if ((style & SWT.SHADOW_NONE) != 0) return null;
+               RECT rect = new RECT ();
+               int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+               int flags = (style & SWT.SHADOW_IN) != 0 ? OS.EDGE_SUNKEN : OS.EDGE_ETCHED;
+               if ((style & SWT.HORIZONTAL) != 0) {
+                       int bottom = struct.top + Math.max (lineWidth * 2, (struct.bottom - struct.top) / 2);
+                       OS.SetRect (rect, struct.left, struct.top, struct.right, bottom);
+                       OS.DrawEdge (struct.hDC, rect, flags, OS.BF_BOTTOM);
+               } else {
+                       int right = struct.left + Math.max (lineWidth * 2, (struct.right - struct.left) / 2);
+                       OS.SetRect (rect, struct.left, struct.top, right, struct.bottom);
+                       OS.DrawEdge (struct.hDC, rect, flags, OS.BF_RIGHT);
+               }
+       } else {
+               int width = struct.right - struct.left;
+               int height = struct.bottom - struct.top;
+               if (width != 0 && height != 0) {
+                       boolean drawImage = image != null;
+                       boolean drawText = IMAGE_AND_TEXT && text.length () != 0;
+                       int margin = drawText && drawImage ? MARGIN : 0;
+                       int imageWidth = 0, imageHeight = 0;
+                       if (drawImage) {
+                               Rectangle rect = image.getBoundsInPixels ();
+                               imageWidth = rect.width;
+                               imageHeight = rect.height;
+                       }
+                       RECT rect = null;
+                       char [] 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) != 0) flags |= OS.DT_LEFT;
+                               if ((style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+                               if ((style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+                               if ((style & SWT.WRAP) != 0) {
+                                       flags |= OS.DT_WORDBREAK;
+                                       rect.right = Math.max (0, width - imageWidth - margin);
+                               }
+                               buffer = text.toCharArray ();
+                               OS.DrawText (struct.hDC, buffer, buffer.length, rect, flags);
+                               textWidth = rect.right - rect.left;
+                               textHeight = rect.bottom - rect.top;
+                       }
+                       int x = 0;
+                       if ((style & SWT.CENTER) != 0) {
+                               x = Math.max (0, (width - imageWidth - textWidth - margin) / 2);
+                       } else {
+                               if ((style & SWT.RIGHT) != 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, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(Math.max (0, (height - imageHeight) / 2)));
+                               if (image != 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, buffer.length, rect, flags);
+                       }
+               }
+       }
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Layout.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Layout.java
new file mode 100644 (file)
index 0000000..980c701
--- /dev/null
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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"
+ */
+protected abstract Point computeSize (Composite composite, int wHint, int hHint, boolean 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
+ */
+protected boolean 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
+ */
+protected abstract void layout (Composite composite, boolean flushCache);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Link.java
new file mode 100644 (file)
index 0000000..12af3a0
--- /dev/null
@@ -0,0 +1,741 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Conrad Groth - Bug 401015 - [CSS] Add support for styling hyperlinks in Links
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent a selectable
+ * user interface object that displays a text with
+ * links.
+ * <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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Link extends Control {
+       String text;
+       int linkForeground = -1;
+       String [] ids;
+       char [] mnemonics;
+       int nextFocusItem = -1;
+       static final long LinkProc;
+       static final TCHAR LinkClass = new TCHAR (0, OS.WC_LINK, true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, LinkClass, 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.
+               */
+               lpWndClass.hInstance = OS.GetModuleHandle (null);
+               lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+               lpWndClass.style |= OS.CS_DBLCLKS;
+               OS.RegisterClass (LinkClass, lpWndClass);
+       }
+
+/**
+ * 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 Link (Composite parent, int style) {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection, typedListener);
+       addListener (SWT.DefaultSelection, typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       /*
+       * 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 != 0) {
+                               OS.SendMessage (hwnd, OS.WM_PRINTCLIENT, wParam, 0);
+                               return 0;
+                       }
+                       break;
+       }
+       return OS.CallWindowProc (LinkProc, hwnd, msg, wParam, lParam);
+}
+
+@Override
+Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width, height;
+       /*
+        * When the text is empty, LM_GETIDEALSIZE returns zero width and height,
+        * but SWT convention is to return zero width and line height.
+        */
+       if (text.isEmpty()) {
+               long hDC = OS.GetDC (handle);
+               long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               long oldFont = OS.SelectObject (hDC, newFont);
+               TEXTMETRIC lptm = new TEXTMETRIC ();
+               OS.GetTextMetrics (hDC, lptm);
+               width = 0;
+               height = lptm.tmHeight;
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+       } else {
+               SIZE size = new SIZE ();
+               int maxWidth = (wHint == SWT.DEFAULT) ? 0x7fffffff : wHint;
+               OS.SendMessage (handle, OS.LM_GETIDEALSIZE, maxWidth, size);
+               width = size.cx;
+               height = size.cy;
+       }
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int border = getBorderWidthInPixels ();
+       width += border * 2;
+       height += border * 2;
+       return new Point (width, height);
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       state |= THEME_BACKGROUND;
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       text = "";
+       ids = new String[0];
+       mnemonics = new char[0];
+}
+
+@Override
+void enableWidget (boolean enabled) {
+       super.enableWidget (enabled);
+       /*
+        * Feature in Windows.  SysLink32 control doesn't natively
+        * provide disabled state. Emulate it with custom draw.
+        */
+       OS.InvalidateRect (handle, null, true);
+}
+
+int getFocusItem () {
+       LITEM item = new LITEM ();
+       item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
+       item.stateMask = OS.LIS_FOCUSED;
+       while (OS.SendMessage (handle, OS.LM_GETITEM, 0, item) != 0) {
+               if ((item.state & OS.LIS_FOCUSED) != 0) {
+                       return item.iLink;
+               }
+               item.iLink++;
+       }
+       return -1;
+}
+
+/**
+ * Returns the link foreground color.
+ *
+ * @return the receiver's link 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.105
+ */
+public Color getLinkForeground () {
+       checkWidget ();
+       if (linkForeground != -1) {
+               return Color.win32_new (display, linkForeground);
+       }
+       return Color.win32_new (display, OS.GetSysColor (OS.COLOR_HOTLIGHT));
+}
+
+@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
+boolean mnemonicHit (char key) {
+       char uckey = Character.toUpperCase (key);
+       for (int i = 0; i < mnemonics.length; i++) {
+               if (uckey == mnemonics[i]) {
+                       nextFocusItem = i;
+                       return setFocus () && setFocusItem (i);
+               }
+       }
+       return false;
+}
+
+@Override
+boolean mnemonicMatch (char key) {
+       char uckey = Character.toUpperCase (key);
+       for (int i = 0; i < mnemonics.length; i++) {
+               if (uckey == mnemonics[i]) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+void parse (String string) {
+       int length = string.length ();
+       // The shortest link length is 7 characters (<a></a>).
+       ids = new String [length / 7];
+       mnemonics = new char [length / 7];
+       int index = 0, state = 0, linkIndex = 0;
+       int linkStart = 0, linkEnd = 0, refStart = 0, refEnd = 0;
+       char mnemonic = 0;
+       while (index < length) {
+               char c = Character.toLowerCase (string.charAt (index));
+               switch (state) {
+                       case 0:
+                               if (c == '<') {
+                                       state++;
+                               } else if (c == '&') {
+                                       state = 16;
+                               }
+                               break;
+                       case 1:
+                               if (c == 'a') state++;
+                               break;
+                       case 2:
+                               switch (c) {
+                                       case 'h':
+                                               state = 7;
+                                               break;
+                                       case '>':
+                                               linkStart = index  + 1;
+                                               state++;
+                                               break;
+                                       default:
+                                               if (Character.isWhitespace(c)) break;
+                                               else state = 13;
+                               }
+                               break;
+                       case 3:
+                               if (c == '<') {
+                                       linkEnd = index;
+                                       state++;
+                               }
+                               break;
+                       case 4:
+                               state = c == '/' ? state + 1 : 3;
+                               break;
+                       case 5:
+                               state = c == 'a' ? state + 1 : 3;
+                               break;
+                       case 6:
+                               if (c == '>') {
+                                       if (refStart == 0) {
+                                               refStart = linkStart;
+                                               refEnd = linkEnd;
+                                       }
+                                       ids [linkIndex] = string.substring(refStart, refEnd);
+                                       if (mnemonic != 0) {
+                                               mnemonics [linkIndex] = mnemonic;
+                                       }
+                                       linkIndex++;
+                                       linkStart = linkEnd = refStart = refEnd = mnemonic = 0;
+                                       state = 0;
+                               } else {
+                                       state = 3;
+                               }
+                               break;
+                       case 7:
+                               state = c == 'r' ? state + 1 : 0;
+                               break;
+                       case 8:
+                               state = c == 'e' ? state + 1 : 0;
+                               break;
+                       case 9:
+                               state = c == 'f' ? state + 1 : 0;
+                               break;
+                       case 10:
+                               state = c == '=' ? state + 1 : 0;
+                               break;
+                       case 11:
+                               if (c == '"') {
+                                       state++;
+                                       refStart = index + 1;
+                               } else {
+                                       state = 0;
+                               }
+                               break;
+                       case 12:
+                               if (c == '"') {
+                                       refEnd = index;
+                                       state = 2;
+                               }
+                               break;
+                       case 13:
+                               if (Character.isWhitespace (c)) {
+                                       state = 0;
+                               } else if (c == '='){
+                                       state++;
+                               }
+                               break;
+                       case 14:
+                               state = c == '"' ? state + 1 : 0;
+                               break;
+                       case 15:
+                               if (c == '"') state = 2;
+                               break;
+                       case 16:
+                               if (c == '<') {
+                                       state = 1;
+                               } else {
+                                       state = 0;
+                                       if (c != '&') mnemonic = Character.toUpperCase (c);
+                               }
+                               break;
+                       default:
+                               state = 0;
+                               break;
+               }
+               index++;
+       }
+       ids = Arrays.copyOf(ids, linkIndex);
+       mnemonics = Arrays.copyOf(mnemonics, linkIndex);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+boolean setFocusItem (int index) {
+       int bits = 0;
+       if (index > 0) {
+               bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       }
+       LITEM item = new LITEM ();
+       item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
+       item.stateMask = OS.LIS_FOCUSED;
+       int activeIndex = getFocusItem ();
+       if (activeIndex == index) return true;
+       if (activeIndex >= 0) {
+               /* Feature in Windows. Unfocus any element unfocus all elements.
+                * For example if item 2 is focused and we set unfocus (state = 0)
+                * for item 0 Windows will remove the focus state for item 2
+                * (getFocusItem() == -1) but fail to remove the focus border around
+                * the link. The fix is to only unfocus the element which has focus.
+                */
+               item.iLink = activeIndex;
+               OS.SendMessage (handle, OS.LM_SETITEM, 0, item);
+       }
+       item.iLink = index;
+       item.state = OS.LIS_FOCUSED;
+       long result = OS.SendMessage (handle, OS.LM_SETITEM, 0, item);
+
+       if (index > 0) {
+       /* Feature in Windows. For some reason, setting the focus to
+        * any item but first causes the control to clear the WS_TABSTOP
+        * bit. The fix is always to reset the bit.
+        */
+       OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+       }
+       return result != 0;
+}
+
+/**
+ * Sets the link foreground color to the color specified
+ * by the argument, or to the default system color for the link
+ * 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>
+ * @since 3.105
+ */
+public void setLinkForeground (Color color) {
+       checkWidget ();
+       int pixel = -1;
+       if (color != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == linkForeground) return;
+       linkForeground = pixel;
+       OS.InvalidateRect (handle, null, true);
+}
+
+/**
+ * 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 attribute can be used to distinguish between them.  The string may
+ * include the mnemonic character and line delimiters. The only delimiter
+ * the HREF attribute supports is the quotation mark ("). Text containing
+ * angle-bracket characters &lt; or &gt; may be escaped using \\, however
+ * this operation is a hint and varies from platform to platform.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic. The receiver can have a
+ * mnemonic in the text preceding each link. When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the link that follows the text. Mnemonics in links and in
+ * the trailing text are ignored. 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (string.equals (text)) return;
+       text = string;
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       OS.SetWindowText (handle, buffer);
+       parse(string);
+}
+
+@Override
+int resolveTextDirection() {
+       return BidiUtil.resolveTextDirection(text);
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+               style &= ~SWT.MIRRORED;
+               style &= ~flags;
+               style |= textDirection & flags;
+               updateOrientation ();
+               checkMirrored ();
+               return true;
+       }
+       return false;
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle ();
+       return bits | OS.WS_TABSTOP;
+}
+
+@Override
+TCHAR windowClass () {
+       return LinkClass;
+}
+
+@Override
+long windowProc () {
+       return LinkProc;
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               case SWT.SPACE:
+               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.
+                       */
+                       long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                       return new LRESULT (code);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       long code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+       int count = ids.length;
+       if (count == 0) {
+               code |= OS.DLGC_STATIC;
+       } else if (count > 1) {
+               int limit = (OS.GetKeyState (OS.VK_SHIFT) < 0) ? 0 : count - 1;
+               if (getFocusItem() != limit) {
+                       code |= OS.DLGC_WANTTAB;
+               }
+       }
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)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;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       nextFocusItem = getFocusItem();
+       return super.WM_KILLFOCUS(wParam, lParam);
+}
+
+@Override
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+       if (result != null) return result;
+
+       /*
+       * Feature in Windows. For WM_NCHITTEST, the Syslink window proc
+       * returns HTTRANSPARENT when mouse is over plain text. As a result,
+       * mouse events are not delivered. The fix is to always return HTCLIENT.
+       */
+       return new LRESULT (OS.HTCLIENT);
+}
+
+@Override
+LRESULT WM_SETCURSOR(long wParam, long lParam) {
+       LRESULT result = super.WM_SETCURSOR (wParam, lParam);
+       if (result != null) return result;
+       long fDone = callWindowProc (handle, OS.WM_SETCURSOR, wParam, lParam);
+       /* Take responsibility for cursor over plain text after overriding WM_NCHITTEST. */
+       if (fDone == 0) OS.DefWindowProc (handle, OS.WM_SETCURSOR, wParam, lParam);
+       return LRESULT.ONE;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       /*
+       * Feature in Windows. Upon receiving focus, SysLink control
+       * always activates the first link. This leads to surprising
+       * behavior in multi-link controls.
+       */
+       if (ids.length > 1) {
+               if (OS.GetKeyState (OS.VK_TAB) < 0) {
+                       if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
+                               // reverse tab; focus on last item
+                               setFocusItem(ids.length - 1);
+                       }
+               } else if (nextFocusItem > 0) {
+                       setFocusItem(nextFocusItem);
+               }
+       }
+       return super.WM_SETFOCUS (wParam, lParam);
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.NM_RETURN:
+               case OS.NM_CLICK:
+                       NMLINK item = new NMLINK ();
+                       OS.MoveMemory (item, lParam, NMLINK.sizeof);
+                       Event event = new Event ();
+                       event.text = ids [item.iLink];
+                       sendSelectionEvent (SWT.Selection, event, true);
+                       break;
+               case OS.NM_CUSTOMDRAW:
+                       NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
+                       OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
+                       switch (nmcd.dwDrawStage) {
+                               case OS.CDDS_PREPAINT:
+                                       if (!OS.IsWindowEnabled (handle) || linkForeground != -1) {
+                                               return new LRESULT(OS.CDRF_NOTIFYITEMDRAW);
+                                       }
+                                       break;
+                               case OS.CDDS_ITEMPREPAINT:
+                                       /*
+                                        * Feature in Windows.  SysLink32 control doesn't natively
+                                        * provide disabled state. Emulate it with custom draw.
+                                        */
+                                       if (!OS.IsWindowEnabled (handle)) {
+                                               OS.SetTextColor (nmcd.hdc, OS.GetSysColor (OS.COLOR_GRAYTEXT));
+                                       }
+                                       else if (linkForeground != -1 && nmcd.dwItemSpec != -1) {
+                                               OS.SetTextColor(nmcd.hdc, linkForeground);
+                                       }
+                                       break;
+                       }
+                       break;
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/List.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/List.java
new file mode 100644 (file)
index 0000000..604da20
--- /dev/null
@@ -0,0 +1,1852 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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.
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class List extends Scrollable {
+       static final int INSET = 3;
+       static final long ListProc;
+       static final TCHAR ListClass = new TCHAR (0, "LISTBOX", true);
+       boolean addedUCC = false; // indicates whether Bidi UCC were added; 'state & HAS_AUTO_DIRECTION' isn't a sufficient indicator
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ListClass, lpWndClass);
+               ListProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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 List (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+/**
+ * Adds the argument to the end of the receiver's list.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new item
+ *
+ * @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>
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       int result = (int)OS.SendMessage (handle, OS.LB_ADDSTRING, 0, buffer);
+       if (result == OS.LB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+       if (result == OS.LB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+       if ((style & SWT.H_SCROLL) != 0) setScrollWidth (buffer.chars, 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><p>
+ * Also note, if control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ *    <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 ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (index == -1) error (SWT.ERROR_INVALID_RANGE);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       int result = (int)OS.SendMessage (handle, OS.LB_INSERTSTRING, index, buffer);
+       if (result == OS.LB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+       if (result == OS.LB_ERR) {
+               int count = (int)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) != 0) setScrollWidth (buffer.chars, 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       boolean redraw = false;
+       switch (msg) {
+               case OS.WM_HSCROLL:
+               case OS.WM_VSCROLL: {
+                       redraw = findImageControl () != null && getDrawing() && OS.IsWindowVisible (handle);
+                       if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                       break;
+               }
+       }
+       long code = OS.CallWindowProc (ListProc, hwnd, msg, wParam, lParam);
+       switch (msg) {
+               case OS.WM_HSCROLL:
+               case OS.WM_VSCROLL: {
+                       if (redraw) {
+                               OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                               OS.InvalidateRect (handle, null, true);
+                       }
+                       break;
+               }
+       }
+       return code;
+}
+
+static int checkStyle (int style) {
+       return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width = 0, height = 0;
+       if (wHint == SWT.DEFAULT) {
+               if ((style & SWT.H_SCROLL) != 0) {
+                       width = (int)OS.SendMessage (handle, OS.LB_GETHORIZONTALEXTENT, 0, 0);
+                       width -= INSET;
+               } else {
+                       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+                       long newFont, oldFont = 0;
+                       long hDC = OS.GetDC (handle);
+                       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+                       RECT rect = new RECT ();
+                       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+                       char [] buffer = new char [64 + 1];
+                       for (int i=0; i<count; i++) {
+                               int length = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, i, 0);
+                               if (length != OS.LB_ERR) {
+                                       if (length + 1 > buffer.length) {
+                                               buffer = new char [length + 1];
+                                       }
+                                       int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, i, buffer);
+                                       if (result != OS.LB_ERR) {
+                                               OS.DrawText (hDC, buffer, length, rect, flags);
+                                               width = Math.max (width, rect.right - rect.left);
+                                       }
+                               }
+                       }
+                       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+                       OS.ReleaseDC (handle, hDC);
+               }
+       }
+       if (hHint == SWT.DEFAULT) {
+               int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+               int itemHeight = (int)OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+               height = count * itemHeight;
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int border = getBorderWidthInPixels ();
+       width += border * 2 + INSET;
+       height += border * 2;
+       if ((style & SWT.V_SCROLL) != 0) {
+               width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+       }
+       if ((style & SWT.H_SCROLL) != 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselect (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (indices.length == 0) return;
+       if ((style & SWT.SINGLE) != 0) {
+               int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+               if (oldIndex == OS.LB_ERR) return;
+               for (int i=0; i<indices.length; i++) {
+                       if (oldIndex == 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 != -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 == -1) return;
+       if ((style & SWT.SINGLE) != 0) {
+               int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+               if (oldIndex == OS.LB_ERR) return;
+               if (oldIndex == 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) != 0) {
+               int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+               if (oldIndex == 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 = (int)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) != 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 = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+       if (result == 0) {
+               int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+               if (count == 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 = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, index, 0);
+       if (length != OS.LB_ERR) {
+               char [] buffer = new char [length + 1];
+               int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer);
+               if (result != OS.LB_ERR) return ((state & HAS_AUTO_DIRECTION) != 0) ? new String (buffer, 1, length - 1) : new String (buffer, 0, length);
+       }
+       int count = (int)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 = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (result == 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 ();
+       return DPIUtil.autoScaleDown(getItemHeightInPixels());
+}
+
+int getItemHeightInPixels () {
+       int result = (int)OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+       if (result == 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) != 0) {
+               int result = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+               if (result == OS.LB_ERR) return 0;
+               return 1;
+       }
+       int result = (int)OS.SendMessage (handle, OS.LB_GETSELCOUNT, 0, 0);
+       if (result == 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) != 0) {
+               return (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+       }
+       int count = (int)OS.SendMessage (handle, OS.LB_GETSELCOUNT, 0, 0);
+       if (count == OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_SELECTION);
+       if (count == 0) return -1;
+       int index = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+       int result = (int)OS.SendMessage (handle, OS.LB_GETSEL, index, 0);
+       if (result == OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_SELECTION);
+       if (result != 0) return index;
+       int [] buffer = new int[1];
+       result = (int)OS.SendMessage (handle, OS.LB_GETSELITEMS, 1, buffer);
+       if (result != 1) error (SWT.ERROR_CANNOT_GET_SELECTION);
+       return buffer [0];
+}
+
+/**
+ * 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) != 0) {
+               int result = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+               if (result == OS.LB_ERR) return new int [0];
+               return new int [] {result};
+       }
+       int length = (int)OS.SendMessage (handle, OS.LB_GETSELCOUNT, 0, 0);
+       if (length == OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_SELECTION);
+       int [] indices = new int [length];
+       int result = (int)OS.SendMessage (handle, OS.LB_GETSELITEMS, length, indices);
+       if (result != 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 (int)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 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>
+ */
+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 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>
+ */
+public int indexOf (String string, int start) {
+       checkWidget ();
+       if (string == 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 () == 0) {
+               int count = getItemCount ();
+               for (int i=start; i<count; i++) {
+                       if (string.equals (getItem (i))) return i;
+               }
+               return -1;
+       }
+
+       /* Use LB_FINDSTRINGEXACT to search for the item */
+       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (!(0 <= start && start < count)) return -1;
+       int index = start - 1, last;
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       do {
+               index = (int)OS.SendMessage (handle, OS.LB_FINDSTRINGEXACT, last = index, buffer);
+               if (index == OS.LB_ERR || index <= last) return -1;
+       } while (!string.equals (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 boolean isSelected (int index) {
+       checkWidget ();
+       int result = (int)OS.SendMessage (handle, OS.LB_GETSEL, index, 0);
+       return (result != 0) && (result != 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>
+ *    <li>ERROR_NULL_ARGUMENT - if the indices 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 remove (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (indices.length == 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 = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (!(0 <= start && start <= end && end < count)) {
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       int topIndex = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+       RECT rect = null;
+       long hDC = 0, oldFont = 0, newFont = 0;
+       int newWidth = 0;
+       if ((style & SWT.H_SCROLL) != 0) {
+               rect = new RECT ();
+               hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       }
+       int i = 0, topCount = 0, last = -1;
+       while (i < newIndices.length) {
+               int index = newIndices [i];
+               if (index != last) {
+                       char [] buffer = null;
+                       int length = 0;
+                       if ((style & SWT.H_SCROLL) != 0) {
+                               length = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, index, 0);
+                               if (length == OS.LB_ERR) break;
+                               buffer = new char [length + 1];
+                               int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer);
+                               if (result == OS.LB_ERR) break;
+                       }
+                       int result = (int)OS.SendMessage (handle, OS.LB_DELETESTRING, index, 0);
+                       if (result == OS.LB_ERR) break;
+                       if ((style & SWT.H_SCROLL) != 0) {
+                               int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+                               OS.DrawText (hDC, buffer, length, rect, flags);
+                               newWidth = Math.max (newWidth, rect.right - rect.left);
+                       }
+                       if (index < topIndex) topCount++;
+                       last = index;
+               }
+               i++;
+       }
+       if ((style & SWT.H_SCROLL) != 0) {
+               if (newFont != 0) 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 ();
+       char [] buffer = null;
+       if ((style & SWT.H_SCROLL) != 0) {
+               int length = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, index, 0);
+               if (length == OS.LB_ERR) {
+                       int count = (int)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 = new char [length + 1];
+               int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer);
+               if (result == OS.LB_ERR) {
+                       int count = (int)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 = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+       int result = (int)OS.SendMessage (handle, OS.LB_DELETESTRING, index, 0);
+       if (result == OS.LB_ERR) {
+               int count = (int)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) != 0) setScrollWidth (buffer, false);
+       if (index < topIndex) {
+               topIndex -= 1;
+       }
+       OS.SendMessage (handle, OS.LB_SETTOPINDEX, topIndex, 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 = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (!(0 <= start && start <= end && end < count)) {
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       if (start == 0 && end == count - 1) {
+               removeAll ();
+               return;
+       }
+       int topIndex = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+       RECT rect = null;
+       long hDC = 0, oldFont = 0, newFont = 0;
+       int newWidth = 0;
+       if ((style & SWT.H_SCROLL) != 0) {
+               rect = new RECT ();
+               hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       }
+       int index = start;
+       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+       while (index <= end) {
+               char [] buffer = null;
+               int length = 0;
+               if ((style & SWT.H_SCROLL) != 0) {
+                       length = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, start, 0);
+                       if (length == OS.LB_ERR) break;
+                       buffer = new char [length + 1];
+                       int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, start, buffer);
+                       if (result == OS.LB_ERR) break;
+               }
+               int result = (int)OS.SendMessage (handle, OS.LB_DELETESTRING, start, 0);
+               if (result == OS.LB_ERR) break;
+               if ((style & SWT.H_SCROLL) != 0) {
+                       OS.DrawText (hDC, buffer, length, rect, flags);
+                       newWidth = Math.max (newWidth, rect.right - rect.left);
+               }
+               index++;
+       }
+       if ((style & SWT.H_SCROLL) != 0) {
+               if (newFont != 0) 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_NULL_ARGUMENT - if the string is null</li>
+ *    <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 ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int index = indexOf (string, 0);
+       if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
+       remove (index);
+}
+
+/**
+ * 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 ();
+       OS.SendMessage (handle, OS.LB_RESETCONTENT, 0, 0);
+       if ((style & SWT.H_SCROLL) != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the array of indices 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 List#setSelection(int[])
+ */
+public void select (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int length = indices.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+       select (indices, false);
+}
+
+void select (int [] indices, boolean scroll) {
+       int i = 0;
+       while (i < indices.length) {
+               int index = indices [i];
+               if (index != -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, boolean scroll) {
+       if (index < 0) return;
+       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (index >= count) return;
+       if (scroll) {
+               if ((style & SWT.SINGLE) != 0) {
+                       OS.SendMessage (handle, OS.LB_SETCURSEL, index, 0);
+               } else {
+                       OS.SendMessage (handle, OS.LB_SETSEL, 1, index);
+               }
+               return;
+       }
+       int topIndex = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+       RECT itemRect = new RECT (), selectedRect = null;
+       OS.SendMessage (handle, OS.LB_GETITEMRECT, index, itemRect);
+       boolean redraw = getDrawing () && OS.IsWindowVisible (handle);
+       if (redraw) {
+               OS.UpdateWindow (handle);
+               OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+       }
+       int focusIndex = -1;
+       if ((style & SWT.SINGLE) != 0) {
+               int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+               if (oldIndex != -1) {
+                       selectedRect = new RECT ();
+                       OS.SendMessage (handle, OS.LB_GETITEMRECT, oldIndex, selectedRect);
+               }
+               OS.SendMessage (handle, OS.LB_SETCURSEL, index, 0);
+       } else {
+               focusIndex = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+               OS.SendMessage (handle, OS.LB_SETSEL, 1, index);
+       }
+       if ((style & SWT.MULTI) != 0) {
+               if (focusIndex != -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 (selectedRect != null) {
+                       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) != 0 && start != end)) return;
+       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (count == 0 || start >= count) return;
+       start = Math.max (0, start);
+       end = Math.min (end, count - 1);
+       if ((style & SWT.SINGLE) != 0) {
+               select (start, false);
+       } else {
+               select (start, end, false);
+       }
+}
+
+void select (int start, int end, boolean scroll) {
+       /*
+       * Note that when start = end, LB_SELITEMRANGEEX
+       * deselects the item.
+       */
+       if (start == 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) != 0) return;
+       OS.SendMessage (handle, OS.LB_SETSEL, 1, -1);
+}
+
+void setFocusIndex (int index) {
+//     checkWidget ();
+       int count = (int)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) != 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>
+ *    <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>
+ */
+public void setItem (int index, String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int topIndex = getTopIndex ();
+       boolean 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_NULL_ARGUMENT - if the items array is null</li>
+ *    <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 ();
+       if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i=0; i<items.length; i++) {
+               if (items [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, ListProc);
+       boolean redraw = getDrawing () && OS.IsWindowVisible (handle);
+       if (redraw) {
+               OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+       }
+       RECT rect = null;
+       long hDC = 0, oldFont = 0, newFont = 0;
+       int newWidth = 0;
+       if ((style & SWT.H_SCROLL) != 0) {
+               rect = new RECT ();
+               hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) 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 = new TCHAR (cp, string, true);
+               int result = (int)OS.SendMessage (handle, OS.LB_ADDSTRING, 0, buffer);
+               if (result == OS.LB_ERR || result == OS.LB_ERRSPACE) break;
+               if ((style & SWT.H_SCROLL) != 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) != 0) {
+               if (newFont != 0) 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 = new RECT ();
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       int count = (int)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 = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, i, 0);
+               if (length != OS.LB_ERR) {
+                       char [] buffer = new char [length + 1];
+                       int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, i, buffer);
+                       if (result != OS.LB_ERR) {
+                               OS.DrawText (hDC, buffer, length, rect, flags);
+                               newWidth = Math.max (newWidth, rect.right - rect.left);
+                       }
+               }
+       }
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       OS.SendMessage (handle, OS.LB_SETHORIZONTALEXTENT, newWidth + INSET, 0);
+}
+
+void setScrollWidth (char[] buffer, boolean grow) {
+       RECT rect = new RECT ();
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) 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 != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+       setScrollWidth (rect.right - rect.left, grow);
+}
+
+void setScrollWidth (int newWidth, boolean grow) {
+       newWidth += INSET;
+       int width = (int)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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the array of indices 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 List#deselectAll()
+ * @see List#select(int[])
+ */
+public void setSelection(int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       deselectAll ();
+       int length = indices.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+       select (indices, true);
+       if ((style & SWT.MULTI) != 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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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_NULL_ARGUMENT - if the array of items 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 List#deselectAll()
+ * @see List#select(int[])
+ * @see List#setSelection(int[])
+ */
+public void setSelection (String [] items) {
+       checkWidget ();
+       if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+       deselectAll ();
+       int length = items.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+       int focusIndex = -1;
+       for (int i=length-1; i>=0; --i) {
+               String string = items [i];
+               int index = 0;
+               if (string != null) {
+                       int localFocus = -1;
+                       while ((index = indexOf (string, index)) != -1) {
+                               if (localFocus == -1) localFocus = index;
+                               select (index, false);
+                               if ((style & SWT.SINGLE) != 0 && isSelected (index)) {
+                                       showSelection ();
+                                       return;
+                               }
+                               index++;
+                       }
+                       if (localFocus != -1) focusIndex = localFocus;
+               }
+       }
+       if ((style & SWT.MULTI) != 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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * 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) != 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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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) != 0 && start != end)) return;
+       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (count == 0 || start >= count) return;
+       start = Math.max (0, start);
+       end = Math.min (end, count - 1);
+       if ((style & SWT.SINGLE) != 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 = (int)OS.SendMessage (handle, OS.LB_SETTOPINDEX, index, 0);
+       if (result == OS.LB_ERR) {
+               int count = (int)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) != 0) {
+               index = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+       } else {
+               int [] indices = new int [1];
+               int result = (int)OS.SendMessage (handle, OS.LB_GETSELITEMS, 1, indices);
+               index = indices [0];
+               if (result != 1) index = -1;
+       }
+       if (index == -1) return;
+       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (count == 0) return;
+       int height = (int)OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+       forceResize ();
+       RECT rect = new RECT ();
+       OS.GetClientRect (handle, rect);
+       int topIndex = (int)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
+void updateMenuLocation (Event event) {
+       Rectangle clientArea = getClientAreaInPixels ();
+       int x = clientArea.x, y = clientArea.y;
+       int focusIndex = getFocusIndex();
+       if (focusIndex != -1) {
+               RECT rect = new RECT ();
+               long newFont, oldFont = 0;
+               long hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+               char [] buffer = new char [64 + 1];
+               int length = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, focusIndex, 0);
+               if (length != OS.LB_ERR) {
+                       if (length + 1 > buffer.length) {
+                               buffer = new char [length + 1];
+                       }
+                       int result = (int)OS.SendMessage (handle, OS.LB_GETTEXT, focusIndex, buffer);
+                       if (result != OS.LB_ERR) {
+                               OS.DrawText (hDC, buffer, length, rect, flags);
+                       }
+               }
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+               x = Math.max (x, rect.right / 2);
+               x = Math.min (x, clientArea.x + clientArea.width);
+
+               OS.SendMessage (handle, OS.LB_GETITEMRECT, focusIndex, rect);
+               y = Math.max (y, rect.bottom);
+               y = Math.min (y, clientArea.y + clientArea.height);
+       }
+       Point pt = toDisplayInPixels (x, y);
+       event.setLocationInPixels(pt.x, pt.y);
+}
+
+@Override
+boolean updateTextDirection (int textDirection) {
+       if (textDirection == AUTO_TEXT_DIRECTION) {
+               /* If auto is already in effect, there's nothing to do. */
+               if ((state & HAS_AUTO_DIRECTION) != 0) return false;
+               state |= HAS_AUTO_DIRECTION;
+       } else {
+               state &= ~HAS_AUTO_DIRECTION;
+               if (!addedUCC /*(state & HAS_AUTO_DIRECTION) == 0*/) {
+                       return super.updateTextDirection (textDirection);
+               }
+       }
+       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+       if (count == OS.LB_ERR) return false;
+       int selection = (int)OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+       addedUCC = false;
+       while (count-- > 0) {
+               int length = (int)OS.SendMessage (handle, OS.LB_GETTEXTLEN, count, 0);
+               if (length == OS.LB_ERR) break;
+               if (length == 0) continue;
+               char [] buffer = new char [length + 1];
+               if (OS.SendMessage (handle, OS.LB_GETTEXT, count, buffer) == OS.LB_ERR) break;
+               if (OS.SendMessage (handle, OS.LB_DELETESTRING, count, 0) == OS.LB_ERR) break;
+               if ((state & HAS_AUTO_DIRECTION) == 0) {
+                       /* Should remove UCC */
+                       System.arraycopy(buffer, 1, buffer, 0, length);
+               }
+               /* Adding UCC is handled in OS.LB_INSERTSTRING */
+               if (OS.SendMessage (handle, OS.LB_INSERTSTRING, count, buffer) == OS.LB_ERR) break;
+       }
+       if (selection != OS.LB_ERR) {
+               OS.SendMessage (handle, OS.LB_SETCURSEL, selection, 0);
+       }
+       return textDirection == AUTO_TEXT_DIRECTION || super.updateTextDirection (textDirection);
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.LBS_NOTIFY | OS.LBS_NOINTEGRALHEIGHT;
+       if ((style & SWT.SINGLE) != 0) return bits;
+       if ((style & SWT.MULTI) != 0) {
+               if ((style & SWT.SIMPLE) != 0) return bits | OS.LBS_MULTIPLESEL;
+               return bits | OS.LBS_EXTENDEDSEL;
+       }
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return ListClass;
+}
+
+@Override
+long windowProc () {
+       return ListProc;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       /* Below code is to support auto text direction. */
+       if (handle != 0 && lParam != 0 && (state & HAS_AUTO_DIRECTION) != 0) {
+               switch (msg) {
+                       case OS.LB_ADDSTRING:
+                       case OS.LB_INSERTSTRING:
+                       case OS.LB_FINDSTRINGEXACT:
+                               int length = OS.wcslen (lParam); // we are always Unicode here
+                               int cp = getCodePage ();
+                               TCHAR buffer = new TCHAR (cp, length);
+                               OS.MoveMemory (buffer, lParam, buffer.length () * TCHAR.sizeof);
+                               String string = buffer.toString (0, length);
+                               int direction = BidiUtil.resolveTextDirection (string);
+                               if (direction == SWT.NONE) {
+                                       /*
+                                        * Force adding a UCC even when no strong characters are found.
+                                        * Otherwise, the List items would retain the old direction,
+                                        * which might be inappropriate for the new text.
+                                        */
+                                       direction = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+                               }
+                               string = (direction == SWT.RIGHT_TO_LEFT ? RLE : LRE) + string;
+                               buffer = new TCHAR (cp, string, true);
+                               long hHeap = OS.GetProcessHeap ();
+                               length = buffer.length() * TCHAR.sizeof;
+                               long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, length);
+                               OS.MoveMemory (pszText, buffer, length);
+                               long code = super.windowProc (hwnd, msg, wParam, pszText);
+                               OS.HeapFree (hHeap, 0, pszText);
+                               addedUCC = true;
+                               return code;
+               }
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != 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) != 0) {
+                       switch ((int)wParam) {
+                               case OS.VK_SPACE: {
+                                       int index = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                                       int code = (int)OS.SendMessage (handle, OS.LB_GETSEL, index, 0);
+                                       if (code == OS.LB_ERR) break;
+                                       OS.SendMessage (handle, OS.LB_SETSEL, code != 0 ? 0 : 1, index);
+                                       OS.SendMessage (handle, OS.LB_SETANCHORINDEX, index, 0);
+                                       sendSelectionEvent (SWT.Selection);
+                                       return LRESULT.ZERO;
+                               }
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != 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) != 0) {
+                       int newIndex = -1;
+                       switch ((int)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 oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                                       newIndex = Math.max (0, oldIndex + (((int)wParam) == OS.VK_UP ? -1 : 1));
+                                       break;
+                               }
+                               case OS.VK_PRIOR: {
+                                       int topIndex = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+                                       int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                                       if (oldIndex != topIndex) {
+                                               newIndex = topIndex;
+                                       } else {
+                                               forceResize ();
+                                               RECT rect = new RECT ();
+                                               OS.GetClientRect (handle, rect);
+                                               int itemHeight = (int)OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+                                               int pageSize = Math.max (2, (rect.bottom / itemHeight));
+                                               newIndex = Math.max (0, topIndex - (pageSize - 1));
+                                       }
+                                       break;
+                               }
+                               case OS.VK_NEXT: {
+                                       int topIndex = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+                                       int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                                       forceResize ();
+                                       RECT rect = new RECT ();
+                                       OS.GetClientRect (handle, rect);
+                                       int itemHeight = (int)OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+                                       int pageSize = Math.max (2, (rect.bottom / itemHeight));
+                                       int bottomIndex = topIndex + pageSize - 1;
+                                       if (oldIndex != bottomIndex) {
+                                               newIndex = bottomIndex;
+                                       } else {
+                                               newIndex = bottomIndex + pageSize - 1;
+                                       }
+                                       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+                                       if (count != OS.LB_ERR) newIndex = Math.min (count - 1, newIndex);
+                                       break;
+                               }
+                               case OS.VK_HOME: {
+                                       newIndex = 0;
+                                       break;
+                               }
+                               case OS.VK_END: {
+                                       int count = (int)OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+                                       if (count == OS.LB_ERR) break;
+                                       newIndex = count - 1;
+                                       break;
+                               }
+                       }
+                       if (newIndex != -1) {
+                               /*
+                               * 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 = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((uiState & OS.UISF_HIDEFOCUS) != 0) {
+                                       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
+                                       * control.
+                                       */
+                                       RECT itemRect = new RECT ();
+                                       int oldIndex = (int)OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                                       OS.SendMessage (handle, OS.LB_GETITEMRECT, oldIndex, itemRect);
+                                       OS.InvalidateRect (handle, itemRect, true);
+                               }
+                               OS.SendMessage (handle, OS.LB_SETCARETINDEX, newIndex, 0);
+                               return LRESULT.ZERO;
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETREDRAW (long wParam, long lParam) {
+       LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+       if (result != null) return result;
+       /*
+       * Bug in Windows.  When WM_SETREDRAW is used to turn off
+       * redraw for a list, table or tree, the background of the
+       * control is drawn.  The fix is to call DefWindowProc(),
+       * which stops all graphics output to the control.
+       */
+       OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, 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 = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       if (!isDisposed ()) {
+               SCROLLINFO info = new SCROLLINFO ();
+               info.cbSize = SCROLLINFO.sizeof;
+               info.fMask = OS.SIF_POS;
+               if (OS.GetScrollInfo (handle, OS.SB_HORZ, info)) {
+                       if (info.nPos != 0) OS.InvalidateRect (handle, null, true);
+               }
+               int newIndex = (int)OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+               if (oldIndex != newIndex) OS.InvalidateRect (handle, null, true);
+       }
+       return result;
+}
+
+@Override
+LRESULT wmCommandChild (long wParam, long lParam) {
+       int code = OS.HIWORD (wParam);
+       switch (code) {
+               case OS.LBN_SELCHANGE:
+                       sendSelectionEvent (SWT.Selection);
+                       break;
+               case OS.LBN_DBLCLK:
+                       sendSelectionEvent (SWT.DefaultSelection);
+                       break;
+       }
+       return super.wmCommandChild (wParam, lParam);
+}
+
+
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Listener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Listener.java
new file mode 100644 (file)
index 0000000..37c5212
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+/**
+ * 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);
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Menu.java
new file mode 100644 (file)
index 0000000..0d55d5a
--- /dev/null
@@ -0,0 +1,1360 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Menu extends 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+
+       int x, y;
+       long hBrush;
+       int id0, id1;
+       int foreground = -1, background = -1;
+       Image backgroundImage;
+       boolean hasLocation;
+       MenuItem cascade;
+       Decorations parent;
+       MenuItem selectedMenuItem;
+
+       /* Timer ID for MenuItem ToolTip */
+       static final int ID_TOOLTIP_TIMER = 110;
+
+/**
+ * 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 Menu (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 SWT#NO_RADIO_GROUP
+ * @see SWT#LEFT_TO_RIGHT
+ * @see SWT#RIGHT_TO_LEFT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Decorations parent, int style) {
+       this (parent, checkStyle (style), 0);
+}
+
+/**
+ * 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 Menu (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 Menu (MenuItem parentItem) {
+       this (checkNull (parentItem).parent);
+}
+
+Menu (Decorations parent, int style, long 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 (boolean visible) {
+       if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+       long 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) != 0) flags |= OS.TPM_RIGHTALIGN;
+               if ((parent.style & SWT.MIRRORED) != 0) {
+                       flags &= ~OS.TPM_RIGHTALIGN;
+                       if ((style & SWT.LEFT_TO_RIGHT) != 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);
+               }
+               hasLocation = false;
+               Display display = this.display;
+               display.sendPreExternalEventDispatchEvent ();
+               /*
+               * 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.
+               */
+               boolean success = OS.TrackPopupMenu (handle, flags, nX, nY, 0, hwndParent, null);
+               // widget could be disposed at this point
+               display.sendPostExternalEventDispatchEvent ();
+               if (!success && OS.GetMenuItemCount (handle) == 0) {
+                       OS.SendMessage (hwndParent, OS.WM_MENUSELECT, OS.MAKEWPARAM (0, 0xFFFF), 0);
+               }
+       } else {
+               OS.SendMessage (hwndParent, OS.WM_CANCELMODE, 0, 0);
+       }
+       /*
+       * Bug in Windows.  After closing a popup menu, the accessibility focus
+       * is not returned to the focus control.  This causes confusion for AT users.
+       * The fix is to explicitly set the accessibility focus back to the focus control.
+       */
+       long hFocus = OS.GetFocus();
+       if (hFocus != 0) {
+               OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, hFocus, OS.OBJID_CLIENT, 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 == 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 == 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 == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return control;
+}
+
+static Menu checkNull (Menu menu) {
+       if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return menu;
+}
+
+static MenuItem checkNull (MenuItem item) {
+       if (item == 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 != 0) return;
+       if ((style & SWT.BAR) != 0) {
+               handle = OS.CreateMenu ();
+       } else {
+               handle = OS.CreatePopupMenu ();
+       }
+       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+}
+
+void createItem (MenuItem item, int index) {
+       int count = OS.GetMenuItemCount (handle);
+       if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+       display.addMenuItem (item);
+       /*
+       * 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.
+       */
+       long hHeap = OS.GetProcessHeap ();
+       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, 4);
+       OS.MoveMemory (pszText, new char [] {' ', '\0'}, 4);
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = 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;
+       boolean success = OS.InsertMenuItem (handle, index, true, info);
+       if (pszText != 0) 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) {
+       if (!OS.DeleteMenu (handle, item.id, OS.MF_BYCOMMAND)) {
+               error (SWT.ERROR_ITEM_NOT_REMOVED);
+       }
+       redraw ();
+}
+
+@Override
+void destroyWidget () {
+       MenuItem cascade = this.cascade;
+       long hMenu = handle;
+       releaseHandle ();
+       if (cascade != null) {
+               cascade.setMenu (null, true);
+       } else {
+               if (hMenu != 0) OS.DestroyMenu (hMenu);
+       }
+}
+
+void fixMenus (Decorations newParent) {
+       if (isDisposed()) {
+               return;
+       }
+       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 != -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 ();
+       if ((style & SWT.BAR) != 0) {
+               if (parent.menuBar != this) {
+                       return new Rectangle (0, 0, 0, 0);
+               }
+               long hwndShell = parent.handle;
+               MENUBARINFO info = new MENUBARINFO ();
+               info.cbSize = MENUBARINFO.sizeof;
+               if (OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 0, info)) {
+                       int width = info.right - info.left;
+                       int height = info.bottom - info.top;
+                       return new Rectangle (info.left, info.top, width, height);
+               }
+       } else {
+               int count = OS.GetMenuItemCount (handle);
+               if (count != 0) {
+                       RECT rect1 = new RECT ();
+                       if (OS.GetMenuItemRect (0, handle, 0, rect1)) {
+                               RECT rect2 = new RECT ();
+                               if (OS.GetMenuItemRect (0, 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.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 ();
+       int id = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+       if (id == -1) return null;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = 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 boolean getEnabled () {
+       checkWidget ();
+       return (state & DISABLED) == 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 != -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;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_DATA;
+       if (!OS.GetMenuItemInfo (handle, index, true, info)) {
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       id = (int)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 OS.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 ();
+       int index = 0, count = 0;
+       int length = OS.GetMenuItemCount (handle);
+       if (length < 0) {
+               int error = OS.GetLastError();
+               SWT.error(SWT.ERROR_CANNOT_GET_COUNT, null, " [GetLastError=0x" + Integer.toHexString(error) + "]");//$NON-NLS-1$ $NON-NLS-2$
+       }
+       MenuItem [] items = new MenuItem [length];
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_DATA;
+       while (OS.GetMenuItemInfo (handle, index, true, info)) {
+               if (count == items.length) {
+                       MenuItem [] newItems = new MenuItem [count + 4];
+                       System.arraycopy (items, 0, newItems, 0, count);
+                       items = newItems;
+               }
+               MenuItem item = display.getMenuItem ((int)info.dwItemData);
+               if (item != null) items [count++] = item;
+               index++;
+       }
+       if (count == items.length) return items;
+       MenuItem [] result = new MenuItem [count];
+       System.arraycopy (items, 0, result, 0, count);
+       return result;
+}
+
+@Override
+String getNameText () {
+       String result = "";
+       MenuItem [] items = getItems ();
+       int length = items.length;
+       if (length > 0) {
+               for (int i=0; i<=length-1; i++) {
+                       result += (items [i] == null ? "null" : items [i].getNameText())
+                                       + (i < (length - 1) ? ", " : "");
+               }
+       }
+       return result;
+}
+
+/**
+ * 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 3.7
+ */
+public int getOrientation () {
+       checkWidget ();
+       return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * 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 != 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. Returns null if receiver or its ancestor
+ * is the application menubar.
+ *
+ * @return the receiver's 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>
+ *
+ * @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 boolean getVisible () {
+       checkWidget ();
+       if ((style & SWT.BAR) != 0) {
+               return this == parent.menuShell ().menuBar;
+       }
+       if ((style & SWT.POP_UP) != 0) {
+               Menu [] popups = display.popups;
+               if (popups == null) return false;
+               for (int i=0; i<popups.length; i++) {
+                       if (popups [i] == this) return true;
+               }
+       }
+       Shell shell = getShell ();
+       Menu menu = shell.activeMenu;
+       while (menu != null && menu != this) {
+               menu = menu.getParentMenu ();
+       }
+       return this == menu;
+}
+
+void hideCurrentToolTip () {
+       if (this.selectedMenuItem != null) {
+               selectedMenuItem.hideToolTip ();
+       }
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       if (item.parent != this) return -1;
+       int index = 0;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_DATA;
+       while (OS.GetMenuItemInfo (handle, index, true, info)) {
+               if (info.dwItemData == 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 boolean isEnabled () {
+       checkWidget ();
+       Menu parentMenu = getParentMenu ();
+       if (parentMenu == 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 boolean isVisible () {
+       checkWidget ();
+       return getVisible ();
+}
+
+void redraw () {
+       if (!isVisible ()) return;
+       if ((style & SWT.BAR) != 0) {
+               display.addBar (this);
+       } else {
+               update ();
+       }
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       handle = 0;
+       cascade = null;
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       MenuItem [] items = getItems ();
+       for (int i=0; i<items.length; i++) {
+               MenuItem item = items [i];
+               if (item != null && !item.isDisposed ()) {
+                       item.release (false);
+               }
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if ((style & SWT.BAR) != 0) {
+               display.removeBar (this);
+               if (this == parent.menuBar) {
+                       parent.setMenuBar (null);
+               }
+       } else {
+               if ((style & SWT.POP_UP) != 0) {
+                       display.removePopup (this);
+               }
+       }
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       backgroundImage = null;
+       if (hBrush != 0) OS.DeleteObject (hBrush);
+       hBrush = 0;
+       if (parent != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Hide, listener);
+       eventTable.unhook (SWT.Show, listener);
+}
+
+@Override
+void reskinChildren (int flags) {
+       MenuItem [] items = getItems ();
+       for (int i=0; i<items.length; i++) {
+               MenuItem item = items [i];
+               item.reskin (flags);
+       }
+       super.reskinChildren (flags);
+}
+
+/**
+ * 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 != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == 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 != null) {
+               if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (image.type != SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       if (backgroundImage == 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 != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == 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 != null) {
+               if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if (item.parent != this) return;
+               newID = item.id;
+       }
+       int oldID = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+       if (newID == 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 (boolean 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>
+ * Also note that the actual location of the menu is dependent
+ * on platform specific behavior. For example: on Linux with
+ * Wayland this operation is a hint due to lack of global
+ * coordinates.
+ * </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 ();
+       setLocationInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+void setLocationInPixels (int x, int y) {
+       if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       location = DPIUtil.autoScaleUp(location);
+       setLocationInPixels(location.x, location.y);
+}
+
+/**
+ * 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 3.7
+ */
+public void setOrientation (int orientation) {
+       checkWidget ();
+       if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+       _setOrientation (orientation);
+}
+
+void _setOrientation (int orientation) {
+       int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+       if ((orientation & flags) == 0 || (orientation & flags) == flags) return;
+       style &= ~flags;
+       style |= orientation & flags;
+       style &= ~SWT.FLIP_TEXT_DIRECTION;
+       MenuItem [] itms = getItems ();
+       for (int i=0; i<itms.length; i++) {
+               itms [i].setOrientation (orientation);
+       }
+}
+
+/**
+ * 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 (boolean visible) {
+       checkWidget ();
+       if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+       if (visible) {
+               display.addPopup (this);
+       } else {
+               display.removePopup (this);
+               _setVisible (false);
+       }
+}
+
+void update () {
+       if ((style & SWT.BAR) != 0) {
+               if (this == parent.menuBar) OS.DrawMenuBar (parent.handle);
+               return;
+       }
+       boolean hasCheck = false, hasImage = false;
+       MenuItem [] items = getItems ();
+       for (int i=0; i<items.length; i++) {
+               MenuItem item = items [i];
+               if (item.image != null) {
+                       if ((hasImage = true) && hasCheck) break;
+               }
+               if ((item.style & (SWT.CHECK | SWT.RADIO)) != 0) {
+                       if ((hasCheck = true) && hasImage) break;
+               }
+       }
+
+       /* Update the menu to hide or show the space for bitmaps */
+       MENUINFO lpcmi = new MENUINFO ();
+       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 != 0) OS.DeleteObject (hBrush);
+       hBrush = 0;
+       if (backgroundImage != null) {
+               hBrush = OS.CreatePatternBrush (backgroundImage.handle);
+       } else {
+               if (background != -1) hBrush = OS.CreateSolidBrush (background);
+       }
+       MENUINFO lpcmi = new MENUINFO ();
+       lpcmi.cbSize = MENUINFO.sizeof;
+       lpcmi.fMask = OS.MIM_BACKGROUND;
+       lpcmi.hbrBack = hBrush;
+       OS.SetMenuInfo (handle, lpcmi);
+}
+
+void updateForeground () {
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = 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 ();
+}
+
+LRESULT wmTimer (long wParam, long lParam) {
+       if (wParam == ID_TOOLTIP_TIMER) {
+               POINT pt = new POINT ();
+               OS.GetCursorPos (pt);
+               if (selectedMenuItem != null) {
+                       RECT rect = new RECT ();
+                       boolean success = OS.GetMenuItemRect (0, selectedMenuItem.parent.handle, selectedMenuItem.index, rect);
+                       if (!success) return null;
+                       if (OS.PtInRect (rect, pt)) {
+                               // Mouse cursor is within the bounds of menu item
+                               selectedMenuItem.showTooltip (pt.x, pt.y + OS.GetSystemMetrics(OS.SM_CYCURSOR) / 2 + 5);
+                       } else {
+                               /*
+                                * Mouse cursor is outside the bounds of the menu item:
+                                * Keyboard or mnemonic was used to select menu item
+                                */
+                               selectedMenuItem.showTooltip ((rect.right + rect.left) / 2, rect.bottom + 5);
+                       }
+               }
+       }
+
+       return null;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/MenuItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/MenuItem.java
new file mode 100644 (file)
index 0000000..66b24b1
--- /dev/null
@@ -0,0 +1,1202 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class MenuItem extends Item {
+       Menu parent, menu;
+       long hBitmap;
+       int id, accelerator, userId, index;
+       ToolTip itemToolTip;
+       /* Image margin. */
+       final static int MARGIN_WIDTH = 1;
+       final static int MARGIN_HEIGHT = 1;
+
+/**
+ * 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 MenuItem (Menu parent, int style) {
+       super (parent, checkStyle (style));
+       this.parent = parent;
+       parent.createItem (this, (index = 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 MenuItem (Menu parent, int style, int index) {
+       super (parent, checkStyle (style));
+       this.parent = parent;
+       parent.createItem (this, (this.index = index));
+}
+
+MenuItem (Menu parent, Menu menu, int style, int index) {
+       super (parent, checkStyle (style));
+       this.parent = parent;
+       this.menu = menu;
+       this.index = index;
+       if (menu != 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 == 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 == 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>
+ * <p>
+ * When the <code>SWT.RADIO</code> style bit is set, the <code>widgetSelected</code> method is
+ * also called when the receiver loses selection because another item in the same radio group
+ * was selected by the user. During <code>widgetSelected</code> the application can use
+ * <code>getSelection()</code> to determine the current selected state of the receiver.
+ * </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 == 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 ();
+}
+
+boolean fillAccel (ACCEL accel) {
+       accel.cmd = accel.key = accel.fVirt = 0;
+       if (accelerator == 0 || !getEnabled ()) return false;
+       if ((accelerator & SWT.COMMAND) != 0) return false;
+       int fVirt = OS.FVIRTKEY;
+       int key = accelerator & SWT.KEY_MASK;
+       int vKey = Display.untranslateKey (key);
+       if (vKey != 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: {
+                               if (key == 0) return false;
+                               vKey = OS.VkKeyScan ((short) key);
+                               if (vKey == -1) {
+                                       if (key != (int)OS.CharUpper ((short) key)) {
+                                               fVirt = 0;
+                                       }
+                               } else {
+                                       key = vKey & 0xFF;
+                               }
+                       }
+               }
+       }
+       accel.key = (short) key;
+       accel.cmd = (short) id;
+       accel.fVirt = (byte) fVirt;
+       if ((accelerator & SWT.ALT) != 0) accel.fVirt |= OS.FALT;
+       if ((accelerator & SWT.SHIFT) != 0) accel.fVirt |= OS.FSHIFT;
+       if ((accelerator & SWT.CONTROL) != 0) accel.fVirt |= OS.FCONTROL;
+       return true;
+}
+
+void fixMenus (Decorations newParent) {
+       if (menu != null && !menu.isDisposed() && !newParent.isDisposed()) 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
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 ();
+       int index = parent.indexOf (this);
+       if (index == -1) return new Rectangle (0, 0, 0, 0);
+       if ((parent.style & SWT.BAR) != 0) {
+               Decorations shell = parent.parent;
+               if (shell.menuBar != parent) {
+                       return new Rectangle (0, 0, 0, 0);
+               }
+               long hwndShell = shell.handle;
+               MENUBARINFO info1 = new MENUBARINFO ();
+               info1.cbSize = MENUBARINFO.sizeof;
+               if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 1, info1)) {
+                       return new Rectangle (0, 0, 0, 0);
+               }
+               MENUBARINFO info2 = new MENUBARINFO ();
+               info2.cbSize = MENUBARINFO.sizeof;
+               if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, index + 1, info2)) {
+                       return new Rectangle (0, 0, 0, 0);
+               }
+               int x = info2.left - info1.left;
+               int y = info2.top - info1.top;
+               int width = info2.right - info2.left;
+               int height = info2.bottom - info2.top;
+               return new Rectangle (x, y, width, height);
+       } else {
+               long hMenu = parent.handle;
+               RECT rect1 = new RECT ();
+               if (!OS.GetMenuItemRect (0, hMenu, 0, rect1)) {
+                       return new Rectangle (0, 0, 0, 0);
+               }
+               RECT rect2 = new RECT ();
+               if (!OS.GetMenuItemRect (0, 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 boolean getEnabled () {
+       checkWidget ();
+       /*
+       * 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) != 0) {
+               return (state & DISABLED) == 0;
+       }
+       long hMenu = parent.handle;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_STATE;
+       boolean success = OS.GetMenuItemInfo (hMenu, id, false, info);
+       if (!success) error (SWT.ERROR_CANNOT_GET_ENABLED);
+       return (info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) == 0;
+}
+
+/**
+ * Gets the identifier associated with the receiver.
+ *
+ * @return the receiver's identifier
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.7
+ */
+public int getID () {
+       checkWidget();
+       return userId;
+}
+
+/**
+ * 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) != 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 boolean getSelection () {
+       checkWidget ();
+       if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
+       long hMenu = parent.handle;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_STATE;
+       boolean success = OS.GetMenuItemInfo (hMenu, id, false, info);
+       if (!success) error (SWT.ERROR_CANNOT_GET_SELECTION);
+       return (info.fState & OS.MFS_CHECKED) !=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>
+ *
+ * @since 3.104
+ */
+public String getToolTipText () {
+       checkWidget();
+       return (itemToolTip == null) ? null : itemToolTip.getMessage();
+}
+
+void hideToolTip () {
+       if (itemToolTip == null) return;
+       itemToolTip.setVisible (false);
+}
+
+/**
+ * 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 boolean isEnabled () {
+       return getEnabled () && parent.isEnabled ();
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (menu != 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 != null) menu.dispose ();
+       menu = null;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (hBitmap != 0) OS.DeleteObject (hBitmap);
+       hBitmap = 0;
+       if (accelerator != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+
+@Override
+void reskinChildren (int flags) {
+       if (menu != null) {
+               menu.reskin (flags);
+       }
+       super.reskinChildren (flags);
+}
+
+void selectRadio () {
+       int index = 0;
+       MenuItem [] items = parent.getItems ();
+       while (index < items.length && items [index] != 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
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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 == 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 (boolean enabled) {
+       checkWidget ();
+       /*
+       * 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) != 0) {
+               if (enabled) {
+                       state &= ~DISABLED;
+               } else {
+                       state |= DISABLED;
+               }
+       }
+       long hMenu = parent.handle;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_STATE;
+       boolean success = OS.GetMenuItemInfo (hMenu, id, false, info);
+       if (!success) {
+               int error = OS.GetLastError();
+               SWT.error (SWT.ERROR_CANNOT_SET_ENABLED, null, " [GetLastError=0x" + Integer.toHexString(error) + "]");//$NON-NLS-1$ $NON-NLS-2$
+       }
+       int bits = OS.MFS_DISABLED | OS.MFS_GRAYED;
+       if (enabled) {
+               if ((info.fState & bits) == 0) return;
+               info.fState &= ~bits;
+       } else {
+               if ((info.fState & bits) == bits) return;
+               info.fState |= bits;
+       }
+       success = 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.
+               */
+               success = id == OS.GetMenuDefaultItem (hMenu, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+               if (!success) {
+                       int error = OS.GetLastError();
+                       SWT.error (SWT.ERROR_CANNOT_SET_ENABLED, null, " [GetLastError=0x" + Integer.toHexString(error) + "]");//$NON-NLS-1$ $NON-NLS-2$
+               }
+       }
+       parent.destroyAccelerators ();
+       parent.redraw ();
+}
+
+/**
+ * Sets the identifier associated with the receiver to the argument.
+ *
+ * @param id the new identifier. This must be a non-negative value. System-defined identifiers are negative values.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_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 an negative-valued argument.</li>
+ * </ul>
+ *
+ * @since 3.7
+ */
+public void setID (int id) {
+       checkWidget();
+       if (id < 0) error(SWT.ERROR_INVALID_ARGUMENT);
+       userId = id;
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null indicating that no image should be displayed.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not supported on
+ * platforms that do not have this concept (for example, Windows NT).
+ * Furthermore, some platforms (such as GTK2), cannot display both
+ * a check box and an image at the same time.  Instead, they hide
+ * the image and display the check box. Some platforms (such as GTK3)
+ * support images alongside check boxes.
+ * </p>
+ *
+ * @param image the image to display on 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>
+ */
+@Override
+public void setImage (Image image) {
+       checkWidget ();
+       if ((style & SWT.SEPARATOR) != 0) return;
+       super.setImage (image);
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_BITMAP;
+       if (parent.foreground != -1) {
+               info.hbmpItem = OS.HBMMENU_CALLBACK;
+       } else {
+               if (OS.IsAppThemed ()) {
+                       if (hBitmap != 0) OS.DeleteObject (hBitmap);
+                       info.hbmpItem = hBitmap = image != null ? Display.create32bitDIB (image) : 0;
+               } else {
+                       info.hbmpItem = image != null ? OS.HBMMENU_CALLBACK : 0;
+               }
+       }
+       long 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) == 0) {
+               error (SWT.ERROR_MENUITEM_NOT_CASCADE);
+       }
+       if (menu != null) {
+               if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if ((menu.style & SWT.DROP_DOWN) == 0) {
+                       error (SWT.ERROR_MENU_NOT_DROP_DOWN);
+               }
+               if (menu.parent != parent.parent) {
+                       error (SWT.ERROR_INVALID_PARENT);
+               }
+       }
+       setMenu (menu, false);
+}
+
+void setMenu (Menu menu, boolean dispose) {
+
+       /* Assign the new menu */
+       Menu oldMenu = this.menu;
+       if (oldMenu == menu) return;
+       if (oldMenu != null) oldMenu.cascade = null;
+       this.menu = menu;
+
+       long hMenu = parent.handle;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_DATA;
+       int index = 0;
+       while (OS.GetMenuItemInfo (hMenu, index, true, info)) {
+               if (info.dwItemData == id) break;
+               index++;
+       }
+       if (info.dwItemData != id) return;
+       int cch = 128;
+       long hHeap = OS.GetProcessHeap ();
+       int byteCount = cch * 2;
+       long pszText = 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.
+       */
+       info.fMask |= OS.MIIM_BITMAP | OS.MIIM_STRING;
+       info.dwTypeData = pszText;
+       info.cch = cch;
+       boolean success = OS.GetMenuItemInfo (hMenu, index, true, info);
+       if (menu != null) {
+               menu.cascade = this;
+               info.fMask |= OS.MIIM_SUBMENU;
+               info.hSubMenu = menu.handle;
+       }
+       if (dispose || oldMenu == null) {
+               success = 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);
+       }
+       if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+       if (!success) {
+               int error = OS.GetLastError();
+               SWT.error (SWT.ERROR_CANNOT_SET_MENU, null, " [GetLastError=0x" + Integer.toHexString(error) + "]");//$NON-NLS-1$ $NON-NLS-2$
+       }
+       parent.destroyAccelerators ();
+}
+
+boolean setRadioSelection (boolean value) {
+       if ((style & SWT.RADIO) == 0) return false;
+       if (getSelection () != value) {
+               setSelection (value);
+               sendSelectionEvent (SWT.Selection);
+       }
+       return true;
+}
+
+void setOrientation (int orientation) {
+       long hMenu = parent.handle;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_FTYPE;
+       info.fType = widgetStyle ();
+       OS.SetMenuItemInfo (hMenu, id, false, info);
+       if (menu != null) menu._setOrientation (orientation);
+}
+
+/**
+ * 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 (boolean selected) {
+       checkWidget ();
+       if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
+       long hMenu = parent.handle;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       info.fMask = OS.MIIM_STATE;
+       boolean success = 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 = 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.
+               */
+               success = id == OS.GetMenuDefaultItem (hMenu, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+               if (!success) {
+                       int error = OS.GetLastError();
+                       SWT.error (SWT.ERROR_CANNOT_SET_SELECTION, null, " [GetLastError=0x" + Integer.toHexString(error) + "]");//$NON-NLS-1$ $NON-NLS-2$
+               }
+       }
+       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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 #setAccelerator
+ */
+@Override
+public void setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if ((style & SWT.SEPARATOR) != 0) return;
+       if (text.equals (string)) return;
+       super.setText (string);
+       long hHeap = OS.GetProcessHeap ();
+       long pszText = 0;
+       MENUITEMINFO info = new MENUITEMINFO ();
+       info.cbSize = MENUITEMINFO.sizeof;
+       long hMenu = parent.handle;
+
+       /* Use the character encoding for the default locale */
+       TCHAR buffer = new TCHAR (0, string, true);
+       int byteCount = buffer.length () * TCHAR.sizeof;
+       pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (pszText, buffer, 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.
+       */
+       info.fMask = OS.MIIM_STRING;
+       info.dwTypeData = pszText;
+       boolean success = OS.SetMenuItemInfo (hMenu, id, false, info);
+       if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+       if (!success) {
+               int error = OS.GetLastError();
+               SWT.error (SWT.ERROR_CANNOT_SET_TEXT, null, " [GetLastError=0x" + Integer.toHexString(error) + "]");//$NON-NLS-1$ $NON-NLS-2$
+       }
+       parent.redraw ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a menu item that has a default
+ * tool tip, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: Tooltips are currently not shown for top-level menu items in the
+ * {@link Shell#setMenuBar(Menu) shell menubar} on Windows, Mac, and Ubuntu Unity desktop.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ * @param toolTip 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.104
+ */
+public void setToolTipText (String toolTip) {
+       checkWidget ();
+
+       if (toolTip == null && itemToolTip != null) {
+               itemToolTip.setVisible (false);
+               itemToolTip = null;
+       }
+
+       if (toolTip == null || toolTip.trim().length() == 0
+                       || (itemToolTip != null && toolTip.equals(itemToolTip.getMessage()))) return;
+
+       itemToolTip = new MenuItemToolTip (this.getParent().getShell());
+       itemToolTip.setMessage (toolTip);
+       itemToolTip.setVisible (false);
+}
+
+void showTooltip (int x, int y) {
+       if (itemToolTip == null) return;
+       itemToolTip.setLocationInPixels (x, y);
+       itemToolTip.setVisible (true);
+}
+
+int widgetStyle () {
+       int bits = 0;
+       Decorations shell = parent.parent;
+       if ((shell.style & SWT.MIRRORED) != 0) {
+               if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) {
+                       bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER;
+               }
+       } else {
+               if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) {
+                       bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER;
+               }
+       }
+       if ((style & SWT.SEPARATOR) != 0) return bits | OS.MFT_SEPARATOR;
+       if ((style & SWT.RADIO) != 0) return bits | OS.MFT_RADIOCHECK;
+       return bits | OS.MFT_STRING;
+}
+
+LRESULT wmCommandChild (long wParam, long lParam) {
+       if ((style & SWT.CHECK) != 0) {
+               setSelection (!getSelection ());
+       } else {
+               if ((style & SWT.RADIO) != 0) {
+                       if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) {
+                               setSelection (!getSelection ());
+                       } else {
+                               selectRadio ();
+                       }
+               }
+       }
+       sendSelectionEvent (SWT.Selection);
+       return null;
+}
+
+LRESULT wmDrawChild (long wParam, long lParam) {
+       DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+       if (image != 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) != 0 ? MARGIN_WIDTH * 2 : struct.left;
+               Image image = getEnabled () ? this.image : new Image (display, this.image, SWT.IMAGE_DISABLE);
+               gc.drawImage (image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(struct.top + MARGIN_HEIGHT));
+               if (this.image != image) image.dispose ();
+               gc.dispose ();
+       }
+       if (parent.foreground != -1) OS.SetTextColor (struct.hDC, parent.foreground);
+       return null;
+}
+
+LRESULT wmMeasureChild (long wParam, long lParam) {
+       MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof);
+       int width = 0, height = 0;
+       if (image != null) {
+               Rectangle rect = image.getBoundsInPixels ();
+               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 = new MENUINFO ();
+               lpcmi.cbSize = MENUINFO.sizeof;
+               lpcmi.fMask = OS.MIM_STYLE;
+               long hMenu = parent.handle;
+               OS.GetMenuInfo (hMenu, lpcmi);
+               if ((lpcmi.dwStyle & OS.MNS_CHECKORBMP) == 0) {
+                       MenuItem [] items = parent.getItems ();
+                       for (int i=0; i<items.length; i++) {
+                               MenuItem item = items [i];
+                               if (item.image != null) {
+                                       Rectangle rect = item.image.getBoundsInPixels ();
+                                       width = Math.max (width, rect.width);
+                               }
+                       }
+               }
+       }
+       if (width != 0 || height != 0) {
+               struct.itemWidth = width + MARGIN_WIDTH * 2;
+               struct.itemHeight = height + MARGIN_HEIGHT * 2;
+               OS.MoveMemory (lParam, struct, MEASUREITEMSTRUCT.sizeof);
+       }
+       return null;
+}
+
+private static final class MenuItemToolTip extends ToolTip {
+
+       public MenuItemToolTip(Shell parent) {
+               super(parent, 0);
+       }
+
+       @Override
+       long hwndToolTip() {
+               return parent.menuItemToolTipHandle();
+       }
+
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/MessageBox.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/MessageBox.java
new file mode 100644 (file)
index 0000000..c1fcea2
--- /dev/null
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public  class MessageBox extends Dialog {
+       String message = "";
+
+/**
+ * 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 MessageBox (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>
+ *
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_QUESTION
+ * @see SWT#ICON_WARNING
+ * @see SWT#ICON_WORKING
+ * @see SWT#OK
+ * @see SWT#CANCEL
+ * @see SWT#YES
+ * @see SWT#NO
+ * @see SWT#ABORT
+ * @see SWT#RETRY
+ * @see SWT#IGNORE
+ */
+public MessageBox (Shell parent, int style) {
+       super (parent, checkStyle (parent, checkStyle (style)));
+       checkSubclass ();
+}
+
+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 == SWT.OK || bits == SWT.CANCEL || bits == (SWT.OK | SWT.CANCEL)) return style;
+       if (bits == SWT.YES || bits == SWT.NO || bits == (SWT.YES | SWT.NO) || bits == (SWT.YES | SWT.NO | SWT.CANCEL)) return style;
+       if (bits == (SWT.RETRY | SWT.CANCEL) || bits == (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) == SWT.OK) buttonBits = OS.MB_OK;
+       if ((style & (SWT.OK | SWT.CANCEL)) == (SWT.OK | SWT.CANCEL)) buttonBits = OS.MB_OKCANCEL;
+       if ((style & (SWT.YES | SWT.NO)) == (SWT.YES | SWT.NO)) buttonBits = OS.MB_YESNO;
+       if ((style & (SWT.YES | SWT.NO | SWT.CANCEL)) == (SWT.YES | SWT.NO | SWT.CANCEL)) buttonBits = OS.MB_YESNOCANCEL;
+       if ((style & (SWT.RETRY | SWT.CANCEL)) == (SWT.RETRY | SWT.CANCEL)) buttonBits = OS.MB_RETRYCANCEL;
+       if ((style & (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) == (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) buttonBits = OS.MB_ABORTRETRYIGNORE;
+       if (buttonBits == 0) buttonBits = OS.MB_OK;
+
+       int iconBits = 0;
+       if ((style & SWT.ICON_ERROR) != 0) iconBits = OS.MB_ICONERROR;
+       if ((style & SWT.ICON_INFORMATION) != 0) iconBits = OS.MB_ICONINFORMATION;
+       if ((style & SWT.ICON_QUESTION) != 0) iconBits = OS.MB_ICONQUESTION;
+       if ((style & SWT.ICON_WARNING) != 0) iconBits = OS.MB_ICONWARNING;
+       if ((style & SWT.ICON_WORKING) != 0) iconBits = OS.MB_ICONINFORMATION;
+
+       int modalBits = 0;
+       if ((style & SWT.PRIMARY_MODAL) != 0) modalBits = OS.MB_APPLMODAL;
+       if ((style & SWT.APPLICATION_MODAL) != 0) modalBits = OS.MB_TASKMODAL;
+       if ((style & SWT.SYSTEM_MODAL) != 0) modalBits = OS.MB_SYSTEMMODAL;
+
+       int bits = buttonBits | iconBits | modalBits;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.MB_RTLREADING | OS.MB_RIGHT;
+       if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
+               if (parent != null && (parent.style & SWT.MIRRORED) != 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) != 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.
+       */
+       long hwndOwner = parent != null ? parent.handle : 0;
+       Display display = parent != null ? parent.getDisplay (): Display.getCurrent ();
+       Dialog oldModal = null;
+       if ((bits & OS.MB_TASKMODAL) != 0) {
+               oldModal = display.getModalDialog ();
+               display.setModalDialog (this);
+       }
+
+       /* Open the message box */
+       display.sendPreExternalEventDispatchEvent ();
+       /* Use the character encoding for the default locale */
+       TCHAR buffer1 = new TCHAR (0, message, true);
+       TCHAR buffer2 = new TCHAR (0, title, true);
+       display.externalEventLoop = true;
+       int code = OS.MessageBox (hwndOwner, buffer1, buffer2, bits);
+       display.externalEventLoop = false;
+       display.sendPostExternalEventDispatchEvent ();
+
+       /* Clear the temporarily dialog modal parent */
+       if ((bits & OS.MB_TASKMODAL) != 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 != 0) OS.UpdateWindow (hwndOwner);
+
+       /* Compute and return the result */
+       if (code != 0) {
+               int type = bits & 0x0F;
+               if (type == OS.MB_OK) return SWT.OK;
+               if (type == OS.MB_OKCANCEL) {
+                       return (code == OS.IDOK) ? SWT.OK : SWT.CANCEL;
+               }
+               if (type == OS.MB_YESNO) {
+                       return (code == OS.IDYES) ? SWT.YES : SWT.NO;
+               }
+               if (type == OS.MB_YESNOCANCEL) {
+                       if (code == OS.IDYES) return SWT.YES;
+                       if (code == OS.IDNO) return SWT.NO;
+                       return SWT.CANCEL;
+               }
+               if (type == OS.MB_RETRYCANCEL) {
+                       return (code == OS.IDRETRY) ? SWT.RETRY : SWT.CANCEL;
+               }
+               if (type == OS.MB_ABORTRETRYIGNORE) {
+                       if (code == OS.IDRETRY) return SWT.RETRY;
+                       if (code == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       message = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Monitor.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Monitor.java
new file mode 100644 (file)
index 0000000..7948528
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 {
+       long handle;
+       int x, y, width, height;
+       int clientX, clientY, clientWidth, clientHeight;
+       int zoom;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Monitor () {
+}
+
+/**
+ * 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 boolean equals (Object object) {
+       if (object == this) return true;
+       if (!(object instanceof Monitor)) return false;
+       Monitor monitor = (Monitor) object;
+       return handle == monitor.handle;
+}
+
+/**
+ * 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 the zoom value for the monitor
+ *
+ * @return monitor's zoom value
+ *
+ * @since 3.107
+ */
+public int getZoom () {
+       return zoom;
+}
+
+void setBounds (Rectangle rect) {
+       x = rect.x;
+       y = rect.y;
+       width = rect.width;
+       height = rect.height;
+}
+
+void setClientArea (Rectangle rect) {
+       clientX = rect.x;
+       clientY = rect.y;
+       clientWidth = rect.width;
+       clientHeight = rect.height;
+}
+
+/**
+ * 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 int hashCode () {
+       return (int)/*64*/handle;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ProgressBar.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ProgressBar.java
new file mode 100644 (file)
index 0000000..c761b0a
--- /dev/null
@@ -0,0 +1,454 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ProgressBar extends Control {
+       static final int DELAY = 100;
+       static final int TIMER_ID = 100;
+       static final int MINIMUM_WIDTH = 100;
+       static final long ProgressBarProc;
+       static final TCHAR ProgressBarClass = new TCHAR (0, OS.PROGRESS_CLASS, true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ProgressBarClass, 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.
+               */
+               lpWndClass.hInstance = OS.GetModuleHandle (null);
+               lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+               lpWndClass.style |= OS.CS_DBLCLKS;
+               OS.RegisterClass (ProgressBarClass, lpWndClass);
+       }
+
+/**
+ * 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 SWT#INDETERMINATE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ProgressBar (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int border = getBorderWidthInPixels ();
+       int width = border * 2, height = border * 2;
+       if ((style & SWT.HORIZONTAL) != 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 != SWT.DEFAULT) width = wHint + (border * 2);
+       if (hHint != 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 (int)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 (int)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 (int)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 ();
+       int state = (int)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;
+       }
+       return SWT.NORMAL;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       stopTimer ();
+}
+
+void startTimer () {
+       if ((style & SWT.INDETERMINATE) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.PBS_MARQUEE) == 0) {
+                       OS.SetTimer (handle, TIMER_ID, DELAY, 0);
+               } else {
+                       OS.SendMessage (handle, OS.PBM_SETMARQUEE, 1, DELAY);
+               }
+       }
+}
+
+void stopTimer () {
+       if ((style & SWT.INDETERMINATE) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.PBS_MARQUEE) == 0) {
+                       OS.KillTimer (handle, TIMER_ID);
+               } else {
+                       OS.SendMessage (handle, OS.PBM_SETMARQUEE, 0, 0);
+               }
+       }
+}
+
+@Override
+void setBackgroundPixel (int pixel) {
+       if (pixel == -1) pixel = OS.CLR_DEFAULT;
+       OS.SendMessage (handle, OS.PBM_SETBKCOLOR, 0, pixel);
+}
+
+@Override
+void setForegroundPixel (int pixel) {
+       if (pixel == -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 = (int)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 = (int)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 ();
+       OS.SendMessage (handle, OS.PBM_SETPOS, value, 0);
+
+       /*
+       * Bug in Vista.  For some reason, when the progress bar is not in
+       * a normal state, it shows the selection of previous call to
+       * PBM_SETPOS. This is undocumented. The fix is to call PBM_SETPOS
+       * a second time.
+       */
+       long state = OS.SendMessage (handle, OS.PBM_GETSTATE, 0, 0);
+       if (state != OS.PBST_NORMAL) {
+               OS.SendMessage (handle, OS.PBM_SETPOS, value, 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>
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @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 ();
+       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;
+       }
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle ();
+       if ((style & SWT.SMOOTH) != 0) bits |= OS.PBS_SMOOTH;
+       if ((style & SWT.VERTICAL) != 0) bits |= OS.PBS_VERTICAL;
+       if ((style & SWT.INDETERMINATE) != 0) bits |= OS.PBS_MARQUEE;
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return ProgressBarClass;
+}
+
+@Override
+long windowProc () {
+       return ProgressBarProc;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+       if (result != 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       if (result != 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) != 0) {
+               if (!OS.IsAppThemed()) {
+                       forceResize ();
+                       RECT rect = new 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 != oldBits) {
+                               stopTimer ();
+                               OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+                               startTimer ();
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_TIMER (long wParam, long lParam) {
+       LRESULT result = super.WM_TIMER (wParam, lParam);
+       if (result != null) return result;
+       if ((style & SWT.INDETERMINATE) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.PBS_MARQUEE) == 0) {
+                       if (wParam == TIMER_ID) {
+                               OS.SendMessage (handle, OS.PBM_STEPIT, 0, 0);
+                       }
+               }
+       }
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/RunnableLock.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/RunnableLock.java
new file mode 100644 (file)
index 0000000..5654eca
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+/**
+ * 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 {
+       Runnable runnable;
+       Thread thread;
+       Throwable throwable;
+
+RunnableLock (Runnable runnable) {
+       this.runnable = runnable;
+}
+
+boolean done () {
+       return runnable == null || throwable != null;
+}
+
+void run (Display display) {
+       if (runnable != null) {
+               try {
+                       runnable.run ();
+               } catch (RuntimeException exception) {
+                       display.getRuntimeExceptionHandler ().accept (exception);
+               } catch (Error error) {
+                       display.getErrorHandler ().accept (error);
+               }
+       }
+       runnable = null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Sash.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Sash.java
new file mode 100644 (file)
index 0000000..59eb302
--- /dev/null
@@ -0,0 +1,413 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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 <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Sash extends Control {
+       boolean dragging;
+       int startX, startY, lastX, lastY;
+       final static int INCREMENT = 1;
+       final 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 SWT#SMOOTH
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Sash (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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int border = getBorderWidthInPixels ();
+       int width = border * 2, height = border * 2;
+       if ((style & SWT.HORIZONTAL) != 0) {
+               width += DEFAULT_WIDTH;  height += 3;
+       } else {
+               width += 3; height += DEFAULT_HEIGHT;
+       }
+       if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
+       if (hHint != 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) != 0) return;
+       long hwndTrack = parent.handle;
+       byte [] bits = {-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0};
+       long stippleBitmap = OS.CreateBitmap (8, 8, 1, 1, bits);
+       long stippleBrush = OS.CreatePatternBrush (stippleBitmap);
+       long hDC = OS.GetDCEx (hwndTrack, 0, OS.DCX_CACHE);
+       long 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+@Override
+TCHAR windowClass () {
+       return display.windowClass;
+}
+
+@Override
+long windowProc () {
+       return display.windowProc;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       super.WM_ERASEBKGND (wParam, lParam);
+       drawBackground (wParam);
+       return LRESULT.ONE;
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)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;
+                       if ((style & SWT.VERTICAL) != 0) {
+                               if (wParam == OS.VK_UP || wParam == OS.VK_DOWN) break;
+                               if (wParam == OS.VK_LEFT) step = -step;
+                               if ((parent.style & SWT.MIRRORED) != 0) step = -step;
+                       } else {
+                               if (wParam == OS.VK_LEFT || wParam == OS.VK_RIGHT) break;
+                               if (wParam == OS.VK_UP) step = -step;
+                       }
+                       RECT rect = new RECT ();
+                       OS.GetWindowRect (handle, rect);
+                       int width = rect.right - rect.left;
+                       int height = rect.bottom - rect.top;
+                       long hwndTrack = parent.handle;
+                       RECT clientRect = new RECT ();
+                       OS.GetClientRect (hwndTrack, clientRect);
+                       int clientWidth = clientRect.right - clientRect.left;
+                       int clientHeight = clientRect.bottom - clientRect.top;
+                       OS.MapWindowPoints (0, hwndTrack, rect, 2);
+                       POINT cursorPt = new POINT ();
+                       int newX = rect.left, newY = rect.top;
+                       if ((style & SWT.VERTICAL) != 0) {
+                               cursorPt.x = newX = Math.min (Math.max (clientRect.left, newX + step), clientWidth - width);
+                               cursorPt.y = rect.top + height / 2;
+                       } else {
+                               cursorPt.x = rect.left + width / 2;
+                               cursorPt.y = newY = Math.min (Math.max (clientRect.top, newY + step), clientHeight - height);
+                       }
+                       if (newX == rect.left && newY == rect.top) return result;
+
+                       /* Update the pointer position */
+                       OS.ClientToScreen (hwndTrack, cursorPt);
+                       OS.SetCursorPos (cursorPt.x, cursorPt.y);
+
+                       Event event = new Event ();
+                       event.setBoundsInPixels(new Rectangle(newX, newY, width, height));
+                       sendSelectionEvent  (SWT.Selection, event, true);
+                       if (isDisposed ()) return LRESULT.ZERO;
+                       if (event.doit) {
+                               if ((style & SWT.SMOOTH) != 0) {
+                                       setBoundsInPixels (event.getBoundsInPixels());
+                               }
+                       }
+                       return result;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       return new LRESULT (OS.DLGC_STATIC);
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+
+       /* Compute the banding rectangle */
+       long hwndTrack = parent.handle;
+       POINT pt = new POINT ();
+       OS.POINTSTOPOINT (pt, lParam);
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       OS.MapWindowPoints (handle, 0, pt, 1);
+       startX = pt.x - rect.left;
+       startY = pt.y - rect.top;
+       OS.MapWindowPoints (0, hwndTrack, 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.setBoundsInPixels(new Rectangle(lastX, lastY, width, height));
+       if ((style & SWT.SMOOTH) == 0) {
+               event.detail = SWT.DRAG;
+       }
+       sendSelectionEvent (SWT.Selection, event, true);
+       if (isDisposed ()) return LRESULT.ZERO;
+
+       /* Draw the banding rectangle */
+       Rectangle bounds = event.getBoundsInPixels();
+       if (event.doit) {
+               dragging = true;
+               lastX = bounds.x;
+               lastY = bounds.y;
+               menuShell ().bringToTop ();
+               if (isDisposed ()) return LRESULT.ZERO;
+               int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+               OS.RedrawWindow (hwndTrack, null, 0, flags);
+               drawBand (bounds.x, bounds.y, width, height);
+               if ((style & SWT.SMOOTH) != 0) {
+                       setBoundsInPixels (bounds.x, bounds.y, width, height);
+                       // widget could be disposed at this point
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONUP (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+
+       /* Compute the banding rectangle */
+       if (!dragging) return result;
+       dragging = false;
+       RECT rect = new 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.setBoundsInPixels(new Rectangle(lastX, lastY, width, height));
+       drawBand (lastX, lastY, width, height);
+       sendSelectionEvent (SWT.Selection, event, true);
+       if (isDisposed ()) return result;
+       Rectangle bounds = event.getBoundsInPixels();
+       if (event.doit) {
+               if ((style & SWT.SMOOTH) != 0) {
+                       setBoundsInPixels (bounds.x, bounds.y, width, height);
+                       // widget could be disposed at this point
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEMOVE (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+       if (result != null) return result;
+       if (!dragging || (wParam & OS.MK_LBUTTON) == 0) return result;
+
+       /* Compute the banding rectangle */
+       POINT pt = new POINT ();
+       OS.POINTSTOPOINT (pt, lParam);
+       long hwndTrack = parent.handle;
+       OS.MapWindowPoints (handle, hwndTrack, pt, 1);
+       RECT rect = new RECT (), clientRect = new RECT ();
+       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) != 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 == lastX && newY == lastY) return result;
+       drawBand (lastX, lastY, width, height);
+
+       /* The event must be sent because doit flag is used */
+       Event event = new Event ();
+       event.setBoundsInPixels(new Rectangle(newX, newY, width, height));
+       if ((style & SWT.SMOOTH) == 0) {
+               event.detail = SWT.DRAG;
+       }
+       sendSelectionEvent (SWT.Selection, event, true);
+       if (isDisposed ()) return LRESULT.ZERO;
+       if (event.doit) {
+               Rectangle boundsInPixels = event.getBoundsInPixels();
+               lastX = boundsInPixels.x;
+               lastY = boundsInPixels.y;
+       }
+       int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+       OS.RedrawWindow (hwndTrack, null, 0, flags);
+       drawBand (lastX, lastY, width, height);
+       if ((style & SWT.SMOOTH) != 0) {
+               setBoundsInPixels (lastX, lastY, width, height);
+               // widget could be disposed at this point
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETCURSOR (long wParam, long lParam) {
+       LRESULT result = super.WM_SETCURSOR (wParam, lParam);
+       if (result != null) return result;
+       int hitTest = (short) OS.LOWORD (lParam);
+       if (hitTest == OS.HTCLIENT) {
+               long hCursor = 0;
+               if ((style & SWT.HORIZONTAL) != 0) {
+                       hCursor = OS.LoadCursor (0, OS.IDC_SIZENS);
+               } else {
+                       hCursor = OS.LoadCursor (0, OS.IDC_SIZEWE);
+               }
+               OS.SetCursor (hCursor);
+               return LRESULT.ONE;
+       }
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Scale.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Scale.java
new file mode 100644 (file)
index 0000000..65d41a8
--- /dev/null
@@ -0,0 +1,596 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Scale extends Control {
+       boolean ignoreResize, ignoreSelection;
+       static final long TrackBarProc;
+       static final TCHAR TrackBarClass = new TCHAR (0, OS.TRACKBAR_CLASS, true);
+       boolean createdAsRTL;
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, TrackBarClass, 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.
+               */
+               lpWndClass.hInstance = OS.GetModuleHandle (null);
+               lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+               lpWndClass.style |= OS.CS_DBLCLKS;
+               OS.RegisterClass (TrackBarClass, lpWndClass);
+       }
+
+/**
+ * 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 Scale (Composite parent, int style) {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int border = getBorderWidthInPixels ();
+       int width = border * 2, height = border * 2;
+       RECT rect = new RECT ();
+       OS.SendMessage (handle, OS.TBM_GETTHUMBRECT, 0, rect);
+       if ((style & SWT.HORIZONTAL) != 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 != SWT.DEFAULT) width = wHint + (border * 2);
+       if (hHint != 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);
+       createdAsRTL = (style & SWT.RIGHT_TO_LEFT) != 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 (int)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 (int)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 (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 (int)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 (int)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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+@Override
+void setBackgroundImage (long 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;
+}
+
+@Override
+void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean 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.setBoundsInPixels (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 = (int)OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+       int maximum = (int)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 = (int)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 = (int)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 = (int)OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+       int maximum = (int)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) != 0) return bits | OS.TBS_HORZ | OS.TBS_DOWNISLEFT;
+       return bits | OS.TBS_VERT;
+}
+
+@Override
+TCHAR windowClass () {
+       return TrackBarClass;
+}
+
+@Override
+long windowProc () {
+       return TrackBarProc;
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               case OS.VK_LEFT:
+               case OS.VK_RIGHT:
+                       /*
+                       * Bug in Windows. The behavior for the left and right keys is not
+                       * changed if the orientation changes after the control was created.
+                       * The fix is to replace VK_LEFT by VK_RIGHT and VK_RIGHT by VK_LEFT
+                       * when the current orientation differs from the orientation used to
+                       * create the control.
+                       */
+                       boolean isRTL = (style & SWT.RIGHT_TO_LEFT) != 0;
+                       if (isRTL != createdAsRTL) {
+                               long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam == OS.VK_RIGHT ? OS.VK_LEFT : OS.VK_RIGHT, lParam);
+                               return new LRESULT (code);
+                       }
+                       break;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEWHEEL (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam);
+       if (result != 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 = (int)OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0);
+       ignoreSelection = true;
+       long code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam);
+       ignoreSelection = false;
+       int newPosition = (int)OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0);
+       if (oldPosition != 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.
+               */
+               sendSelectionEvent (SWT.Selection, null, true);
+               // widget could be disposed at this point
+       }
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_PAINT (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+
+       /*
+       * 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.
+       */
+       boolean fixPaint = findBackgroundControl () != null;
+       if (!fixPaint) {
+               if (OS.IsAppThemed ()) {
+                       Control control = findThemeControl ();
+                       fixPaint = control != null;
+               }
+       }
+       if (fixPaint) {
+               boolean redraw = getDrawing () && 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 (long wParam, long lParam) {
+       if (ignoreResize) return null;
+       return super.WM_SIZE (wParam, lParam);
+}
+
+@Override
+LRESULT wmScrollChild (long wParam, long lParam) {
+
+       /* Do nothing when scrolling is ending */
+       int code = OS.LOWORD (wParam);
+       switch (code) {
+               case OS.TB_ENDTRACK:
+               case OS.TB_THUMBPOSITION:
+                       return null;
+       }
+
+       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;
+//             }
+               /*
+               * 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.
+               */
+               sendSelectionEvent (SWT.Selection, event, true);
+               // widget could be disposed at this point
+       }
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ScrollBar.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ScrollBar.java
new file mode 100644 (file)
index 0000000..769bcf0
--- /dev/null
@@ -0,0 +1,1008 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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:</p>
+ * <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>
+ * <p>
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ScrollBar extends 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
+ */
+ScrollBar (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 == 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 () {
+       long hwnd = hwndScrollBar ();
+       int type = scrollBarType ();
+       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 = new RECT ();
+       OS.GetClientRect (parent.scrolledHandle (), rect);
+       int x = 0, y = 0, width, height;
+       if ((style & SWT.HORIZONTAL) != 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 boolean getEnabled () {
+       checkWidget();
+       return (state & DISABLED) == 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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_RANGE;
+       long hwnd = hwndScrollBar ();
+       int 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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_RANGE;
+       long hwnd = hwndScrollBar ();
+       int 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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_POS;
+       long hwnd = hwndScrollBar ();
+       int 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();
+       return DPIUtil.autoScaleDown(getSizeInPixels());
+}
+
+Point getSizeInPixels () {
+       parent.forceResize ();
+       RECT rect = new RECT ();
+       OS.GetClientRect (parent.scrolledHandle (), rect);
+       int width, height;
+       if ((style & SWT.HORIZONTAL) != 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 receiver's thumb value.
+ *
+ * @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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_PAGE;
+       long hwnd = hwndScrollBar ();
+       int type = scrollBarType ();
+       OS.GetScrollInfo (hwnd, type, info);
+       if (info.nPage != 0) --info.nPage;
+       return info.nPage;
+}
+
+/**
+ * Returns a rectangle describing the size and location of the
+ * receiver's thumb relative to its parent.
+ *
+ * @return the thumb bounds, relative to the {@link #getParent() 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.6
+ */
+public Rectangle getThumbBounds () {
+       checkWidget();
+       return DPIUtil.autoScaleDown(getThumbBoundsInPixels());
+}
+
+Rectangle getThumbBoundsInPixels () {
+       parent.forceResize ();
+       SCROLLBARINFO info = new SCROLLBARINFO();
+       info.cbSize = SCROLLBARINFO.sizeof;
+       int x, y, width, height;
+       if ((style & SWT.HORIZONTAL) != 0) {
+               OS.GetScrollBarInfo(parent.handle, OS.OBJID_HSCROLL, info);
+               x = info.rcScrollBar.left + info.xyThumbTop;
+               y = info.rcScrollBar.top;
+               width = info.xyThumbBottom - info.xyThumbTop;
+               height = info.rcScrollBar.bottom - info.rcScrollBar.top;
+       } else {
+               OS.GetScrollBarInfo(parent.handle, OS.OBJID_VSCROLL, info);
+               x = info.rcScrollBar.left;
+               y = info.rcScrollBar.top + info.xyThumbTop;
+               width = info.rcScrollBar.right - info.rcScrollBar.left;
+               height = info.xyThumbBottom - info.xyThumbTop;
+       }
+       RECT rect = new RECT ();
+       rect.left = x;
+       rect.top  = y;
+       rect.right = x + width;
+       rect.bottom = y + height;
+       OS.MapWindowPoints (0, parent.handle, rect, 2);
+       return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+/**
+ * Returns a rectangle describing the size and location of the
+ * receiver's thumb track relative to its parent. This rectangle
+ * comprises the areas 2, 3, and 4 as described in {@link ScrollBar}.
+ *
+ * @return the thumb track bounds, relative to the {@link #getParent() 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.6
+ */
+public Rectangle getThumbTrackBounds () {
+       checkWidget();
+       return DPIUtil.autoScaleDown(getThumbTrackBoundsInPixels());
+}
+
+Rectangle getThumbTrackBoundsInPixels () {
+       parent.forceResize ();
+       SCROLLBARINFO info = new SCROLLBARINFO();
+       info.cbSize = SCROLLBARINFO.sizeof;
+       int x = 0, y = 0, width, height;
+       if ((style & SWT.HORIZONTAL) != 0) {
+               OS.GetScrollBarInfo(parent.handle, OS.OBJID_HSCROLL, info);
+               int size = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+               y = info.rcScrollBar.top;
+               width = info.rcScrollBar.right - info.rcScrollBar.left;
+               height = size;
+               if (width <= 2 * size) {
+                       x = info.rcScrollBar.left + width / 2;
+                       width = 0;
+               } else {
+                       x = info.rcScrollBar.left + size;
+                       width -= 2 * size;
+               }
+       } else {
+               OS.GetScrollBarInfo(parent.handle, OS.OBJID_VSCROLL, info);
+               int size = OS.GetSystemMetrics (OS.SM_CYVSCROLL);
+               x = info.rcScrollBar.left;
+               width = size;
+               height = info.rcScrollBar.bottom - info.rcScrollBar.top;
+               if (height <= 2 * size) {
+                       y = info.rcScrollBar.top + height / 2;
+                       height = 0;
+               } else {
+                       y = info.rcScrollBar.top + size;
+                       height -= 2 * size;
+               }
+       }
+       RECT rect = new RECT ();
+       rect.left = x;
+       rect.top  = y;
+       rect.right = x + width;
+       rect.bottom = y + height;
+       OS.MapWindowPoints (0, parent.handle, rect, 2);
+       return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+/**
+ * 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 boolean getVisible () {
+       checkWidget();
+       SCROLLBARINFO psbi = new SCROLLBARINFO ();
+       psbi.cbSize = SCROLLBARINFO.sizeof;
+       int idObject = (style & SWT.VERTICAL) != 0 ? OS.OBJID_VSCROLL : OS.OBJID_HSCROLL;
+       OS.GetScrollBarInfo (hwndScrollBar (), idObject, psbi);
+       return (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) == 0;
+}
+
+long 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 boolean 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 boolean isVisible () {
+       checkWidget();
+       return getVisible () && parent.isVisible ();
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       parent = null;
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (parent.horizontalBar == this) parent.horizontalBar = null;
+       if (parent.verticalBar == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+int scrollBarType () {
+       return (style & SWT.VERTICAL) != 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 (boolean enabled) {
+       checkWidget();
+       long hwnd = hwndScrollBar ();
+       int 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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       long hwnd = hwndScrollBar ();
+       int 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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       long hwnd = hwndScrollBar ();
+       int 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;
+}
+
+boolean SetScrollInfo (long hwnd, int flags, SCROLLINFO info, boolean 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.
+       */
+       boolean barVisible = false;
+       boolean visible = getVisible ();
+
+       ScrollBar bar = null;
+       switch (flags) {
+               case OS.SB_HORZ:
+                       bar = parent.getVerticalBar ();
+                       break;
+               case OS.SB_VERT:
+                       bar = parent.getHorizontalBar ();
+                       break;
+       }
+       barVisible = bar != null && bar.getVisible ();
+       if (!visible || (state & DISABLED) != 0) fRedraw = false;
+       boolean result = 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) {
+               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 (visible && bar != null && !barVisible) {
+               OS.ShowScrollBar (hwnd, flags == 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) != 0) {
+               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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       long hwnd = hwndScrollBar ();
+       int type = scrollBarType ();
+       info.fMask = OS.SIF_POS;
+       info.nPos = selection;
+       SetScrollInfo (hwnd, type, info, true);
+}
+
+/**
+ * Sets the thumb value. The thumb value should be used to represent
+ * the size of the visual portion of the current range. This value is
+ * usually the same as the page increment value.
+ * <p>
+ * This new value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ * </p>
+ *
+ * @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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       long hwnd = hwndScrollBar ();
+       int type = scrollBarType ();
+       info.fMask = OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+       OS.GetScrollInfo (hwnd, type, info);
+       info.nPage = value;
+       if (info.nPage != 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 = new SCROLLINFO ();
+       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 != 0) info.nPage++;
+       long hwnd = hwndScrollBar ();
+       int 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 (boolean visible) {
+       checkWidget();
+       if (visible == getVisible ()) 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;
+       long hwnd = hwndScrollBar ();
+       int type = scrollBarType ();
+       /*
+       * Bug in Windows 7. Windows will cause pixel corruption
+       * when there is only one scroll bar visible and it is
+       * hidden.  The fix is to temporarily show the other scroll
+       * bar and hide both.
+       */
+       if (!visible) {
+               if (OS.IsAppThemed ()) {
+                       SCROLLBARINFO psbi = new SCROLLBARINFO ();
+                       psbi.cbSize = SCROLLBARINFO.sizeof;
+                       int idObject = (style & SWT.VERTICAL) != 0 ? OS.OBJID_HSCROLL : OS.OBJID_VSCROLL;
+                       OS.GetScrollBarInfo (hwnd, idObject, psbi);
+                       if ((psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) != 0) {
+                               OS.ShowScrollBar (hwnd, type == OS.SB_VERT ? OS.SB_HORZ : OS.SB_VERT, true);
+                               type = OS.SB_BOTH;
+                       }
+               }
+       }
+       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) == 0) {
+                       SCROLLINFO info = new SCROLLINFO ();
+                       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 (long wParam, long lParam) {
+
+       /* Do nothing when scrolling is ending */
+       int code = OS.LOWORD (wParam);
+       if (code == 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;
+       }
+       sendSelectionEvent  (SWT.Selection, event, true);
+       // the widget could be destroyed at this point
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Scrollable.java
new file mode 100644 (file)
index 0000000..c9efef9
--- /dev/null
@@ -0,0 +1,500 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class Scrollable extends Control {
+       ScrollBar horizontalBar, verticalBar;
+
+       /**
+        * The regular expression used to determine the string which should be deleted
+        * when Ctrl+Bs is hit.
+        */
+       static final java.util.regex.Pattern CTRL_BS_PATTERN =
+                       java.util.regex.Pattern.compile ("\\r?\\n\\z|[\\p{Punct}]+[\\t ]*\\z|[^\\p{Punct}\\s\\n\\r]*[\\t ]*\\z");
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Scrollable () {
+}
+
+/**
+ * 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 Scrollable (Composite parent, int style) {
+       super (parent, style);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       return DPIUtil.autoScaleDown(computeTrimInPixels(x, y, width, height));
+}
+
+Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       long scrolledHandle = scrolledHandle ();
+       RECT rect = new 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 != null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+       if (verticalBar != 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) != 0) {
+               bar.setMaximum (100);
+               bar.setThumb (10);
+       }
+       return bar;
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       /*
+        * NOTE: ICON_CANCEL and ICON_SEARCH have the same value as H_SCROLL and
+        * V_SCROLL. The meaning is determined by whether SWT.SEARCH is set.
+        */
+       if ((style & SWT.SEARCH) == 0) {
+               if ((style & SWT.H_SCROLL) != 0) horizontalBar = createScrollBar (SWT.H_SCROLL);
+               if ((style & SWT.V_SCROLL) != 0) verticalBar = createScrollBar (SWT.V_SCROLL);
+       }
+}
+
+@Override
+void updateBackgroundColor () {
+       switch (applyThemeBackground ()) {
+               case 0: state &= ~THEME_BACKGROUND; break;
+               case 1: state |= THEME_BACKGROUND; break;
+               default: /* No change */
+       }
+       super.updateBackgroundColor ();
+}
+
+/**
+ * @return
+ *             <li>0 to remove THEME_BACKGROUND</li>
+ *      <li>1 to apply THEME_BACKGROUND</li>
+ *      <li>otherwise don't change THEME_BACKGROUND state</li>
+ */
+int applyThemeBackground () {
+       return (backgroundAlpha == 0) ? 1 : 0;
+}
+
+void destroyScrollBar (int type) {
+       long hwnd = scrolledHandle ();
+       int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+       if ((type & SWT.HORIZONTAL) != 0) {
+               style &= ~SWT.H_SCROLL;
+               bits &= ~OS.WS_HSCROLL;
+       }
+       if ((type & SWT.VERTICAL) != 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 ();
+       return DPIUtil.autoScaleDown(getClientAreaInPixels());
+}
+
+Rectangle getClientAreaInPixels () {
+       forceResize ();
+       RECT rect = new RECT ();
+       long 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 != handle) {
+               OS.GetClientRect (handle, rect);
+               OS.MapWindowPoints(handle, scrolledHandle, 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 mode of the receiver's scrollbars. This will be
+ * <em>bitwise</em> OR of one or more of the constants defined in class
+ * <code>SWT</code>.<br>
+ * <ul>
+ * <li><code>SWT.SCROLLBAR_OVERLAY</code> - if receiver
+ * uses overlay scrollbars</li>
+ * <li><code>SWT.NONE</code> - otherwise</li>
+ * </ul>
+ *
+ * @return the mode of scrollbars
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if 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#SCROLLBAR_OVERLAY
+ *
+ * @since 3.8
+ */
+public int getScrollbarsMode () {
+       checkWidget();
+       return SWT.NONE;
+}
+
+/**
+ * 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 (boolean destroy) {
+       if (horizontalBar != null) {
+               horizontalBar.release (false);
+               horizontalBar = null;
+       }
+       if (verticalBar != null) {
+               verticalBar.release (false);
+               verticalBar = null;
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (horizontalBar != null) horizontalBar.reskin (flags);
+       if (verticalBar != null) verticalBar.reskin (flags);
+       super.reskinChildren (flags);
+}
+
+long 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) != 0) return OS.WS_EX_CLIENTEDGE;
+//     if ((style & SWT.SHADOW_IN) != 0) return OS.WS_EX_STATICEDGE;
+//     return super.widgetExtStyle ();
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.WS_TABSTOP;
+       /*
+        * NOTE: ICON_CANCEL and ICON_SEARCH have the same value as H_SCROLL and
+        * V_SCROLL. The meaning is determined by whether SWT.SEARCH is set.
+        */
+       if ((style & SWT.SEARCH) == 0) {
+               if ((style & SWT.H_SCROLL) != 0) bits |= OS.WS_HSCROLL;
+               if ((style & SWT.V_SCROLL) != 0) bits |= OS.WS_VSCROLL;
+       }
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return display.windowClass;
+}
+
+@Override
+long windowProc () {
+       return display.windowProc;
+}
+
+@Override
+LRESULT WM_HSCROLL (long wParam, long lParam) {
+       LRESULT result = super.WM_HSCROLL (wParam, lParam);
+       if (result != null) return result;
+       if (horizontalBar != null && lParam == 0) {
+               return wmScroll (horizontalBar, (state & CANVAS) != 0, handle, OS.WM_HSCROLL, wParam, lParam);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEWHEEL (long wParam, long lParam) {
+       return wmScrollWheel ((state & CANVAS) != 0, wParam, lParam);
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       long code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+       super.WM_SIZE (wParam, lParam);
+       // widget may be disposed at this point
+       if (code == 0) return LRESULT.ZERO;
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_VSCROLL (long wParam, long lParam) {
+       LRESULT result = super.WM_VSCROLL (wParam, lParam);
+       if (result != null) return result;
+       if (verticalBar != null && lParam == 0) {
+               return wmScroll (verticalBar, (state & CANVAS) != 0, handle, OS.WM_VSCROLL, wParam, lParam);
+       }
+       return result;
+}
+
+LRESULT wmScrollWheel (boolean update, long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam);
+       if (result != null) return result;
+       /*
+       * Translate WM_MOUSEWHEEL to WM_VSCROLL or WM_HSCROLL.
+       */
+       if (update) {
+               if ((wParam & (OS.MK_SHIFT | OS.MK_CONTROL)) != 0) return result;
+               boolean vertical = verticalBar != null && verticalBar.getEnabled ();
+               boolean horizontal = horizontalBar != null && horizontalBar.getEnabled ();
+               int msg = vertical ? OS.WM_VSCROLL : horizontal ? OS.WM_HSCROLL : 0;
+               if (msg == 0) return result;
+               int [] linesToScroll = new int [1];
+               OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, linesToScroll, 0);
+               int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam);
+               boolean pageScroll = linesToScroll [0] == OS.WHEEL_PAGESCROLL;
+               ScrollBar bar = vertical ? verticalBar : horizontalBar;
+               SCROLLINFO info = new SCROLLINFO ();
+               info.cbSize = SCROLLINFO.sizeof;
+               info.fMask = OS.SIF_POS;
+               OS.GetScrollInfo (handle, bar.scrollBarType (), info);
+               if (vertical && !pageScroll) delta *= linesToScroll [0];
+               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);
+               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 == null ? 0 : verticalBar.getSelection ();
+       int hPosition = horizontalBar == null ? 0 : horizontalBar.getSelection ();
+       long code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam);
+       if (verticalBar != null) {
+               int position = verticalBar.getSelection ();
+               if (position != vPosition) {
+                       Event event = new Event ();
+                       event.detail = position < vPosition ? SWT.PAGE_UP : SWT.PAGE_DOWN;
+                       verticalBar.sendSelectionEvent (SWT.Selection, event, true);
+               }
+       }
+       if (horizontalBar != null) {
+               int position = horizontalBar.getSelection ();
+               if (position != hPosition) {
+                       Event event = new Event ();
+                       event.detail = position < hPosition ? SWT.PAGE_UP : SWT.PAGE_DOWN;
+                       horizontalBar.sendSelectionEvent (SWT.Selection, event, true);
+               }
+       }
+       return new LRESULT (code);
+}
+
+LRESULT wmScroll (ScrollBar bar, boolean update, long hwnd, int msg, long wParam, long lParam) {
+       LRESULT result = null;
+       if (update) {
+               int type = msg == OS.WM_HSCROLL ? OS.SB_HORZ : OS.SB_VERT;
+               SCROLLINFO info = new SCROLLINFO ();
+               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:
+                               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;
+               }
+               OS.SetScrollInfo (hwnd, type, info, true);
+       } else {
+               long code = callWindowProc (hwnd, msg, wParam, lParam);
+               result = code == 0 ? LRESULT.ZERO : new LRESULT (code);
+       }
+       bar.wmScrollChild (wParam, lParam);
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Shell.java
new file mode 100644 (file)
index 0000000..d41e3d9
--- /dev/null
@@ -0,0 +1,2500 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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:</p>
+ * <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>
+ * 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>.</p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER, CLOSE, MIN, MAX, NO_MOVE, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, SHEET</dd>
+ * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
+ * </dl>
+ * <p>
+ * Class <code>SWT</code> provides two "convenience constants"
+ * for the most commonly required style combinations:</p>
+ * <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>
+ * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
+ * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Shell extends Decorations {
+       Menu activeMenu;
+       ToolTip [] toolTips;
+       long hIMC, hwndMDIClient, lpstrTip, toolTipHandle, balloonTipHandle, menuItemToolTipHandle;
+       int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT;
+       long [] brushes;
+       boolean showWithParent, fullScreen, wasMaximized, modified, center;
+       String toolTitle, balloonTitle;
+       long toolIcon, balloonIcon;
+       long windowProc;
+       Control lastActive;
+       static /*final*/ long ToolTipProc;
+       static final long DialogProc;
+       static final TCHAR DialogClass = new TCHAR (0, "#32770", true);
+       final 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;
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, DialogClass, lpWndClass);
+               DialogProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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 Shell () {
+       this ((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#TOOL
+ * @see SWT#NO_TRIM
+ * @see SWT#NO_MOVE
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ * @see SWT#SHEET
+ */
+public Shell (int style) {
+       this ((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 Shell (Display display) {
+       this (display, 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#TOOL
+ * @see SWT#NO_TRIM
+ * @see SWT#NO_MOVE
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ * @see SWT#SHEET
+ */
+public Shell (Display display, int style) {
+       this (display, null, style, 0, false);
+}
+
+Shell (Display display, Shell parent, int style, long handle, boolean embedded) {
+       super ();
+       checkSubclass ();
+       if (display == null) display = Display.getCurrent ();
+       if (display == null) display = Display.getDefault ();
+       if (!display.isValidThread ()) {
+               error (SWT.ERROR_THREAD_INVALID_ACCESS);
+       }
+       if (parent != null && parent.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       this.center = parent != null && (style & SWT.SHEET) != 0;
+       this.style = checkStyle (parent, style);
+       this.parent = parent;
+       this.display = display;
+       this.handle = handle;
+       if (handle != 0 && !embedded) {
+               state |= FOREIGN_HANDLE;
+       }
+       reskinWidget();
+       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 Shell (Shell parent) {
+       this (parent, 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#NO_MOVE
+ * @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
+ * @see SWT#SHEET
+ */
+public Shell (Shell parent, int style) {
+       this (parent != null ? parent.display : null, parent, style, 0, 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Shell win32_new (Display display, long 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ *
+ * @since 3.3
+ */
+public static Shell internal_new (Display display, long handle) {
+       return new Shell (display, null, SWT.NO_TRIM, handle, false);
+}
+
+static int checkStyle (Shell parent, int style) {
+       style = Decorations.checkStyle (style);
+       style &= ~SWT.TRANSPARENT;
+       int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
+       if ((style & SWT.SHEET) != 0) {
+               style &= ~SWT.SHEET;
+               style |= parent == null ? SWT.SHELL_TRIM : SWT.DIALOG_TRIM;
+               if ((style & mask) == 0) {
+                       style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
+               }
+       }
+       int bits = style & ~mask;
+       if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
+       if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
+       if ((style & SWT.PRIMARY_MODAL) != 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 == 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);
+}
+
+long balloonTipHandle () {
+       if (balloonTipHandle == 0) createBalloonTipHandle ();
+       return balloonTipHandle;
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if (hwnd == toolTipHandle || hwnd == balloonTipHandle || hwnd == menuItemToolTipHandle) {
+               return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam);
+       }
+       if (hwndMDIClient != 0) {
+               return OS.DefFrameProc (hwnd, hwndMDIClient, msg, wParam, lParam);
+       }
+       if (windowProc != 0) {
+               return OS.CallWindowProc (windowProc, hwnd, msg, wParam, lParam);
+       }
+       if ((style & SWT.TOOL) != 0) {
+               int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+               if ((style & trim) == 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+       }
+       if ((style & SWT.NO_MOVE) != 0) {
+               setItemEnabled (OS.SC_MOVE, false);
+       }
+       if (parent != null) {
+               switch (msg) {
+                       case OS.WM_KILLFOCUS:
+                       case OS.WM_SETFOCUS:
+                               return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+               }
+               return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
+       }
+       return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+void center () {
+       if (parent == null) return;
+       Rectangle rect = getBoundsInPixels ();
+       Rectangle parentRect = display.mapInPixels (parent, null, parent.getClientAreaInPixels());
+       int x = Math.max (parentRect.x, parentRect.x + (parentRect.width - rect.width) / 2);
+       int y = Math.max (parentRect.y, parentRect.y + (parentRect.height - rect.height) / 2);
+       Rectangle monitorRect = parent.getMonitor ().getClientArea();
+       if (x + rect.width > monitorRect.x + monitorRect.width) {
+               x = Math.max (monitorRect.x, monitorRect.x + monitorRect.width - rect.width);
+       } else {
+               x = Math.max (x, monitorRect.x);
+       }
+       if (y + rect.height > monitorRect.y + monitorRect.height) {
+               y = Math.max (monitorRect.y, monitorRect.y + monitorRect.height - rect.height);
+       } else {
+               y = Math.max (y, monitorRect.y);
+       }
+       setLocationInPixels (x, y);
+}
+
+/**
+ * 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,
+               new TCHAR (0, OS.TOOLTIPS_CLASS, true),
+               null,
+               OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON,
+               OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+               handle,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (balloonTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
+       if (ToolTipProc == 0) {
+               ToolTipProc = 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 () {
+       boolean embedded = handle != 0 && (state & FOREIGN_HANDLE) == 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) != 0) display.lockActiveWindow = true;
+       if (handle == 0 || embedded) {
+               super.createHandle ();
+       } else {
+               state |= CANVAS;
+               if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
+                       state |= THEME_BACKGROUND;
+               }
+               windowProc = OS.GetWindowLongPtr (handle, OS.GWL_WNDPROC);
+       }
+
+       /*
+       * The following code is intentionally commented.
+       */
+//     if ((style & SWT.ON_TOP) != 0)  display.lockActiveWindow = false;
+
+       if (!embedded) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
+               bits |= OS.WS_POPUP;
+               if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
+               if ((style & SWT.NO_TRIM) == 0) {
+                       if ((style & (SWT.BORDER | SWT.RESIZE)) == 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;
+               OS.SetWindowPos (handle, 0, 0, 0, 0, 0, flags);
+       }
+       if (OS.IsDBLocale) {
+               hIMC = OS.ImmCreateContext ();
+               if (hIMC != 0) OS.ImmAssociateContext (handle, hIMC);
+       }
+}
+
+void createMenuItemToolTipHandle() {
+       menuItemToolTipHandle = createToolTipHandle (0);
+}
+
+void createToolTip (ToolTip toolTip) {
+       int id = 0;
+       if (toolTips == null) toolTips = new ToolTip [4];
+       while (id < toolTips.length && toolTips [id] != null) id++;
+       if (id == 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;
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = 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 = createToolTipHandle (handle);
+}
+
+long createToolTipHandle (long parent) {
+       long toolTipHandle = OS.CreateWindowEx (
+               0,
+               new TCHAR (0, OS.TOOLTIPS_CLASS, true),
+               null,
+               OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX,
+               OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+               parent,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (toolTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
+       if (ToolTipProc == 0) {
+               ToolTipProc = 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);
+       return toolTipHandle;
+}
+
+@Override
+void deregister () {
+       super.deregister ();
+       if (toolTipHandle != 0) display.removeControl (toolTipHandle);
+       if (balloonTipHandle != 0) display.removeControl (balloonTipHandle);
+       if (menuItemToolTipHandle != 0) display.removeControl (menuItemToolTipHandle);
+}
+
+void destroyToolTip (ToolTip toolTip) {
+       if (toolTips == null) return;
+       toolTips [toolTip.id - Display.ID_START] = null;
+       if (balloonTipHandle != 0) {
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = 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 ();
+
+       /*
+       * Destroy context only after the controls that used it were destroyed.
+       * Technically, that shouldn't be necessary, because 'Control.releaseWidget'
+       * clears up association by calling 'OS.ImmAssociateContext (handle, 0)'.
+       * However, there's a bug in Windows 10 (see bug 526758), and this is the workaround.
+       */
+       if (OS.IsDBLocale) {
+               if (hIMC != 0) OS.ImmDestroyContext (hIMC);
+       }
+}
+
+@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 != null) oldDisplay.update ();
+}
+
+@Override
+void enableWidget (boolean enabled) {
+       if (enabled) {
+               state &= ~DISABLED;
+       } else {
+               state |= DISABLED;
+       }
+       if (Display.TrimEnabled) {
+               if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled);
+       } else {
+               OS.EnableWindow (handle, enabled);
+       }
+}
+
+@Override
+long findBrush (long value, int lbStyle) {
+       if (lbStyle == OS.BS_SOLID) {
+               for (int i=0; i<SYSTEM_COLORS.length; i++) {
+                       if (value == OS.GetSysColor (SYSTEM_COLORS [i])) {
+                               return OS.GetSysColorBrush (SYSTEM_COLORS [i]);
+                       }
+               }
+       }
+       if (brushes == null) brushes = new long [BRUSHES_SIZE];
+       LOGBRUSH logBrush = new LOGBRUSH ();
+       for (int i=0; i<brushes.length; i++) {
+               long hBrush = brushes [i];
+               if (hBrush == 0) break;
+               OS.GetObject (hBrush, LOGBRUSH.sizeof, logBrush);
+               switch (logBrush.lbStyle) {
+                       case OS.BS_SOLID:
+                               if (lbStyle == OS.BS_SOLID) {
+                                       if (logBrush.lbColor == value) return hBrush;
+                               }
+                               break;
+                       case OS.BS_PATTERN:
+                               if (lbStyle == OS.BS_PATTERN) {
+                                       if (logBrush.lbHatch == value) return hBrush;
+                               }
+                               break;
+               }
+       }
+       int length = brushes.length;
+       long hBrush = brushes [--length];
+       if (hBrush != 0) OS.DeleteObject (hBrush);
+       System.arraycopy (brushes, 0, brushes, 1, length);
+       switch (lbStyle) {
+               case OS.BS_SOLID:
+                       hBrush = OS.CreateSolidBrush ((int)value);
+                       break;
+               case OS.BS_PATTERN:
+                       hBrush = OS.CreatePatternBrush (value);
+                       break;
+       }
+       return brushes [0] = hBrush;
+}
+
+@Override
+Control findBackgroundControl () {
+       return background != -1 || backgroundImage != null ? this : null;
+}
+
+@Override
+Cursor findCursor () {
+       return cursor;
+}
+
+@Override
+Control findThemeControl () {
+       return null;
+}
+
+ToolTip findToolTip (int id) {
+       if (toolTips == 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.
+       */
+       long hwndParent = OS.GetParent (handle);
+       if (hwndParent != 0 && handle == OS.GetActiveWindow ()) {
+               if (!OS.IsWindowEnabled (hwndParent) && OS.IsWindowVisible (hwndParent)) {
+                       OS.SetActiveWindow (hwndParent);
+               }
+       }
+}
+
+void fixShell (Shell newShell, Control control) {
+       if (this == newShell) return;
+       if (control == lastActive) setActiveControl (null);
+       String toolTipText = control.toolTipText;
+       if (toolTipText != 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 (toolTipHandle == 0) return;
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = TOOLINFO.sizeof;
+       if (OS.SendMessage (toolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+               if ((lpti.uFlags & OS.TTF_IDISHWND) != 0) {
+                       OS.SendMessage (toolTipHandle, OS.TTM_DELTOOL, 0, lpti);
+                       OS.SendMessage (toolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+       TOOLINFO lptiMt = new TOOLINFO ();
+       lptiMt.cbSize = TOOLINFO.sizeof;
+       if (OS.SendMessage (menuItemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lptiMt) != 0) {
+               if ((lptiMt.uFlags & OS.TTF_IDISHWND) != 0) {
+                       OS.SendMessage (menuItemToolTipHandle, OS.TTM_DELTOOL, 0, lptiMt);
+                       OS.SendMessage (menuItemToolTipHandle, OS.TTM_ADDTOOL, 0, lptiMt);
+               }
+       }
+}
+
+/**
+ * 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 ();
+       byte [] pbAlpha = new byte [1];
+       if (OS.GetLayeredWindowAttributes (handle, null, pbAlpha, null)) {
+               return pbAlpha [0] & 0xFF;
+       }
+       return 0xFF;
+}
+
+@Override Rectangle getBoundsInPixels () {
+       if (OS.IsIconic (handle)) return super.getBoundsInPixels ();
+       RECT rect = new 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 != 0) {
+               ToolTip tip = getCurrentToolTip (toolTipHandle);
+               if (tip != null) return tip;
+       }
+       if (balloonTipHandle != 0) {
+               ToolTip tip = getCurrentToolTip (balloonTipHandle);
+               if (tip != null) return tip;
+       }
+       if (menuItemToolTipHandle != 0) {
+               ToolTip tip = getCurrentToolTip (menuItemToolTipHandle);
+               if (tip != null) return tip;
+       }
+       return null;
+}
+
+ToolTip getCurrentToolTip (long hwndToolTip) {
+       if (hwndToolTip == 0) return null;
+       if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = TOOLINFO.sizeof;
+               if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+                       if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) return findToolTip ((int)lpti.uId);
+               }
+       }
+       return null;
+}
+
+@Override
+public boolean getEnabled () {
+       checkWidget ();
+       return (state & DISABLED) == 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 boolean 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;
+       long hIMC = OS.ImmGetContext (handle);
+       int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
+       boolean open = OS.ImmGetOpenStatus (hIMC);
+       if (open) open = OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
+       OS.ImmReleaseContext (handle, hIMC);
+       if (!open) return SWT.NONE;
+       int result = 0;
+       if ((lpfdwConversion [0] & OS.IME_CMODE_ROMAN) != 0) result |= SWT.ROMAN;
+       if ((lpfdwConversion [0] & OS.IME_CMODE_FULLSHAPE) != 0) result |= SWT.DBCS;
+       if ((lpfdwConversion [0] & OS.IME_CMODE_KATAKANA) != 0) return result | SWT.PHONETIC;
+       if ((lpfdwConversion [0] & OS.IME_CMODE_NATIVE) != 0) return result | SWT.NATIVE;
+       return result | SWT.ALPHA;
+}
+
+@Override Point getLocationInPixels () {
+       if (OS.IsIconic (handle)) return super.getLocationInPixels ();
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       return new Point (rect.left, rect.top);
+}
+
+@Override
+public boolean 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 ();
+       return DPIUtil.autoScaleDown(getMinimumSizeInPixels());
+}
+
+Point getMinimumSizeInPixels () {
+       int width = Math.max (0, minWidth);
+       int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+       if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+               width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+       }
+       int height = Math.max (0, minHeight);
+       if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+               if ((style & SWT.RESIZE) != 0) {
+                       height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+               } else {
+                       RECT rect = new 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);
+}
+
+/**
+ * Gets the receiver's modified state.
+ *
+ * @return <code>true</code> if the receiver is marked as modified, or <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.5
+ */
+public boolean getModified () {
+       checkWidget ();
+       return modified;
+}
+
+/**
+ * Returns the region that defines the shape of the shell,
+ * or <code>null</code> if the shell has the default shape.
+ *
+ * @return the region that defines the shape of the shell, 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.0
+ *
+ */
+@Override
+public Region getRegion () {
+       /* This method is needed for the @since 3.0 Javadoc */
+       checkWidget ();
+       return region;
+}
+
+@Override
+public Shell getShell () {
+       checkWidget ();
+       return this;
+}
+
+@Override Point getSizeInPixels () {
+       if (OS.IsIconic (handle)) return super.getSizeInPixels ();
+       RECT rect = new 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 != null && shell != this);
+               if (shell == 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 != null && shell != this);
+               if (shell == this) {
+                       result [index++] = shells [i];
+               }
+       }
+       return result;
+}
+
+/**
+ * Returns a ToolBar object representing the tool bar that can be shown in the receiver's
+ * trim. This will return <code>null</code> if the platform does not support tool bars that
+ * are not part of the content area of the shell, or if the Shell's style does not support
+ * having a tool bar.
+ * <p>
+ *
+ * @return a ToolBar object representing the Shell's tool bar, 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.7
+ */
+public ToolBar getToolBar() {
+       checkWidget ();
+       return null;
+}
+
+@Override
+Composite findDeferredControl () {
+       return layoutCount > 0 ? this : null;
+}
+
+@Override
+public boolean isEnabled () {
+       checkWidget ();
+       return getEnabled ();
+}
+
+@Override
+public boolean isVisible () {
+       checkWidget ();
+       return getVisible ();
+}
+
+long hwndMDIClient () {
+       if (hwndMDIClient == 0) {
+               int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
+               hwndMDIClient = OS.CreateWindowEx (
+                       0,
+                       new TCHAR (0, "MDICLIENT", true),
+                       null,
+                       widgetStyle,
+                       0, 0, 0, 0,
+                       handle,
+                       0,
+                       OS.GetModuleHandle (null),
+                       new CREATESTRUCT ());
+//             OS.ShowWindow (hwndMDIClient, OS.SW_SHOW);
+       }
+       return hwndMDIClient;
+}
+
+long menuItemToolTipHandle () {
+       if (menuItemToolTipHandle == 0) createMenuItemToolTipHandle ();
+       return menuItemToolTipHandle;
+}
+
+/**
+ * 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 == null || (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) == 0) {
+               bringToTop ();
+               if (isDisposed ()) return;
+       }
+       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 = new MSG ();
+       int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
+       OS.PeekMessage (msg, 0, 0, 0, flags);
+       /*
+        * When no widget has been given focus, or another push button has focus,
+        * give focus to the default button. This avoids overriding the default
+        * button.
+        */
+       boolean restored = restoreFocus ();
+       if (!restored) {
+               restored = traverseGroup (true);
+       }
+       if (restored) {
+               Control focusControl = display.getFocusControl ();
+               if (focusControl instanceof Button && (focusControl.style & SWT.PUSH) != 0) {
+                       restored = false;
+               }
+       }
+       if (!restored) {
+               if (saveDefault != null && !saveDefault.isDisposed ()) {
+                       saveDefault.setFocus ();
+               } else {
+                       setFocus ();
+               }
+       }
+}
+
+@Override
+public boolean print (GC gc) {
+       checkWidget ();
+       if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       return false;
+}
+
+@Override
+void register () {
+       super.register ();
+       if (toolTipHandle != 0) display.addControl (toolTipHandle, this);
+       if (balloonTipHandle != 0) display.addControl (balloonTipHandle, this);
+       if (menuItemToolTipHandle != 0) display.addControl (menuItemToolTipHandle, this);
+}
+
+void releaseBrushes () {
+       if (brushes != null) {
+               for (int i=0; i<brushes.length; i++) {
+                       if (brushes [i] != 0) OS.DeleteObject (brushes [i]);
+               }
+       }
+       brushes = null;
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       Shell [] shells = getShells ();
+       for (int i=0; i<shells.length; i++) {
+               Shell shell = shells [i];
+               if (shell != null && !shell.isDisposed ()) {
+                       shell.release (false);
+               }
+       }
+       if (toolTips != null) {
+               for (int i=0; i<toolTips.length; i++) {
+                       ToolTip toolTip = toolTips [i];
+                       if (toolTip != null && !toolTip.isDisposed ()) {
+                               toolTip.release (false);
+                       }
+               }
+       }
+       toolTips = null;
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       hwndMDIClient = 0;
+}
+
+@Override
+void releaseParent () {
+       /* Do nothing */
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       releaseBrushes ();
+       activeMenu = null;
+       display.clearModal (this);
+       if (lpstrTip != 0) {
+               long hHeap = OS.GetProcessHeap ();
+               OS.HeapFree (hHeap, 0, lpstrTip);
+       }
+       lpstrTip = 0;
+       toolTipHandle = balloonTipHandle = menuItemToolTipHandle = 0;
+       lastActive = null;
+       toolTitle = balloonTitle = null;
+}
+
+@Override
+void removeMenu (Menu menu) {
+       super.removeMenu (menu);
+       if (menu == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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);
+}
+
+@Override
+public void requestLayout () {
+       layout (null, SWT.DEFER);
+}
+
+@Override
+void reskinChildren (int flags) {
+       Shell [] shells = getShells ();
+       for (int i=0; i<shells.length; i++) {
+               Shell shell = shells [i];
+               if (shell != null) shell.reskin (flags);
+       }
+       if (toolTips != null) {
+               for (int i=0; i<toolTips.length; i++) {
+                       ToolTip toolTip = toolTips [i];
+                       if (toolTip != null) toolTip.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+@Override
+boolean sendKeyEvent (int type, int msg, long wParam, 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) {
+       setActiveControl (control, SWT.None);
+}
+
+void setActiveControl (Control control, int type) {
+       if (control != null && control.isDisposed ()) control = null;
+       if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
+       if (lastActive == control) return;
+
+       /*
+       * Compute the list of controls to be activated and
+       * deactivated by finding the first common parent
+       * control.
+       */
+       Control [] activate = (control == null) ? new Control [0] : control.getPath ();
+       Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath ();
+       lastActive = control;
+       int index = 0, length = Math.min (activate.length, deactivate.length);
+       while (index < length) {
+               if (activate [index] != 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 ()) {
+                       Event event = new Event ();
+                       event.detail = type;
+                       activate [i].sendEvent (SWT.Activate, event);
+               }
+       }
+}
+
+/**
+ * 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 ();
+       alpha &= 0xFF;
+       int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+       if (alpha == 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, 0, flags);
+       } else {
+               OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYERED);
+               OS.SetLayeredWindowAttributes (handle, 0, (byte)alpha, OS.LWA_ALPHA);
+       }
+}
+
+@Override
+void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean 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) != 0) {
+               flags &= ~OS.SWP_DRAWFRAME;
+       }
+       super.setBoundsInPixels (x, y, width, height, flags, false);
+}
+
+@Override
+public void setEnabled (boolean enabled) {
+       checkWidget ();
+       if (((state & DISABLED) == 0) == enabled) return;
+       super.setEnabled (enabled);
+       if (enabled && handle == 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 maximized 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 (boolean fullScreen) {
+       checkWidget();
+       if (this.fullScreen == 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) != 0) {
+               if (fullScreen) {
+                       styleFlags &= ~(OS.WS_CAPTION | OS.WS_MAXIMIZEBOX | OS.WS_MINIMIZEBOX | OS.WS_THICKFRAME);
+               } else {
+                       styleFlags |= OS.WS_CAPTION;
+                       if ((style & SWT.MAX) != 0) styleFlags |= OS.WS_MAXIMIZEBOX;
+                       if ((style & SWT.MIN) != 0) styleFlags |= OS.WS_MINIMIZEBOX;
+                       if ((style & SWT.RESIZE) != 0) styleFlags |= OS.WS_THICKFRAME;
+               }
+       }
+       if (fullScreen) wasMaximized = getMaximized ();
+       boolean 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;
+       boolean imeOn = mode != SWT.NONE;
+       long hIMC = OS.ImmGetContext (handle);
+       OS.ImmSetOpenStatus (hIMC, imeOn);
+       if (imeOn) {
+               int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
+               if (OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence)) {
+                       int newBits = 0;
+                       int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA;
+                       if ((mode & SWT.PHONETIC) != 0) {
+                               newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE;
+                               oldBits = 0;
+                       } else {
+                               if ((mode & SWT.NATIVE) != 0) {
+                                       newBits = OS.IME_CMODE_NATIVE;
+                                       oldBits = OS.IME_CMODE_KATAKANA;
+                               }
+                       }
+                       boolean fullShape = (mode & SWT.DBCS) != 0;
+                       if ((mode & SWT.NATIVE) != 0) {
+                               long hkl = OS.GetKeyboardLayout (0);
+                               int langid = OS.PRIMARYLANGID (OS.LOWORD (hkl));
+                               if (langid == OS.LANG_JAPANESE) {
+                                       fullShape = true;
+                               }
+                       }
+                       if (fullShape) {
+                               newBits |= OS.IME_CMODE_FULLSHAPE;
+                       } else {
+                               oldBits |= OS.IME_CMODE_FULLSHAPE;
+                       }
+                       if ((mode & SWT.ROMAN) != 0) {
+                               newBits |= OS.IME_CMODE_ROMAN;
+                       } else {
+                               oldBits |= OS.IME_CMODE_ROMAN;
+                       }
+                       lpfdwConversion [0] |= newBits;
+                       lpfdwConversion [0] &= ~oldBits;
+                       OS.ImmSetConversionStatus (hIMC, lpfdwConversion [0], lpfdwSentence [0]);
+               }
+       }
+       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 ();
+       setMinimumSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+}
+
+void setMinimumSizeInPixels (int width, int height) {
+       int widthLimit = 0, heightLimit = 0;
+       int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+       if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+               widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
+               if ((style & SWT.RESIZE) != 0) {
+                       heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
+               } else {
+                       RECT rect = new 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 = getSizeInPixels ();
+       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 != size.x || newHeight != size.y) setSizeInPixels (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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       size = DPIUtil.autoScaleUp(size);
+       setMinimumSizeInPixels(size.x, size.y);
+}
+
+/**
+ * Sets the receiver's modified state as specified by the argument.
+ *
+ * @param modified the new modified state 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.5
+ */
+public void setModified (boolean modified) {
+       checkWidget ();
+       this.modified = modified;
+}
+
+void setItemEnabled (int cmd, boolean enabled) {
+       long hMenu = OS.GetSystemMenu (handle, false);
+       if (hMenu == 0) 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.
+ * <p>
+ * NOTE: This method also sets the size of the shell. Clients should
+ * not call {@link #setSize} or {@link #setBounds} on this shell.
+ * Furthermore, the passed region should not be modified any more.
+ * </p>
+ *
+ * @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
+ */
+@Override
+public void setRegion (Region region) {
+       checkWidget ();
+       if ((style & SWT.NO_TRIM) == 0) return;
+       if (region != null) {
+               Rectangle bounds = region.getBounds ();
+               setSize (bounds.x + bounds.width, bounds.y + bounds.height);
+       }
+       super.setRegion (region);
+}
+
+void setToolTipText (long hwnd, String text) {
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = TOOLINFO.sizeof;
+       lpti.hwnd = handle;
+       lpti.uId = hwnd;
+       long hwndToolTip = toolTipHandle ();
+       if (text == null) {
+               OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
+       } else {
+               if (OS.SendMessage (hwndToolTip, OS.TTM_GETTOOLINFO, 0, lpti) != 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, 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;
+       long hHeap = OS.GetProcessHeap ();
+       if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
+       int byteCount = buffer.length * 2;
+       lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (lpstrTip, buffer, byteCount);
+       lpnmtdi.lpszText = lpstrTip;
+}
+
+void setToolTipTitle (long hwndToolTip, String text, int 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 != toolTipHandle && hwndToolTip != balloonTipHandle && hwndToolTip != menuItemToolTipHandle) {
+               return;
+       }
+       if (hwndToolTip == toolTipHandle || hwndToolTip == menuItemToolTipHandle) {
+               if (text == toolTitle || (toolTitle != null && toolTitle.equals (text))) {
+                       if (icon == toolIcon) return;
+               }
+               toolTitle = text;
+               toolIcon = icon;
+       } else {
+               if (hwndToolTip == balloonTipHandle) {
+                       if (text == balloonTitle || (balloonTitle != null && balloonTitle.equals (text))) {
+                               if (icon == toolIcon) return;
+                       }
+                       balloonTitle = text;
+                       balloonIcon = icon;
+               }
+       }
+       if (text != null) {
+               /*
+               * Feature in Windows. The text point to by pszTitle
+               * must not exceed 100 characters in length, including
+               * the null terminator.
+               */
+               if (text.length () > 99) text = text.substring (0, 99);
+               TCHAR pszTitle = new TCHAR (getCodePage (), text, true);
+               OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, pszTitle);
+       } else {
+               OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
+       }
+}
+
+@Override
+public void setVisible (boolean 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) != 0) {
+               if (visible) {
+                       display.setModalShell (this);
+                       if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
+                               display.setModalDialog (null);
+                       }
+                       Control control = display._getFocusControl ();
+                       if (control != null && !control.isActive ()) {
+                               bringToTop ();
+                               if (isDisposed ()) return;
+                       }
+                       long hwndShell = OS.GetActiveWindow ();
+                       if (hwndShell == 0) {
+                               if (parent != null) hwndShell = parent.handle;
+                       }
+                       if (hwndShell != 0) {
+                               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) {
+               OS.ShowOwnedPopups (handle, false);
+       }
+       if (!visible) fixActiveShell ();
+       if (visible && center && !moved) {
+               center ();
+               if (isDisposed ()) return;
+       }
+       super.setVisible (visible);
+       if (isDisposed ()) return;
+       if (showWithParent != visible) {
+               showWithParent = visible;
+               if (visible) {
+                       OS.ShowOwnedPopups (handle, true);
+               }
+       }
+
+       /* Make the foreign window parent appear in the task bar */
+       if (visible) {
+               if (parent != null && (parent.state & FOREIGN_HANDLE) != 0) {
+                       long hwndParent = parent.handle;
+                       int style = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                       if ((style & OS.WS_EX_TOOLWINDOW) != 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 != 0) {
+               long newProc = display.windowProc;
+               if (toolTipHandle != 0) {
+                       OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, newProc);
+               }
+               if (balloonTipHandle != 0) {
+                       OS.SetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC, newProc);
+               }
+               if (menuItemToolTipHandle != 0) {
+                       OS.SetWindowLongPtr (menuItemToolTipHandle, OS.GWLP_WNDPROC, newProc);
+               }
+       }
+}
+
+long toolTipHandle () {
+       if (toolTipHandle == 0) createToolTipHandle ();
+       return toolTipHandle;
+}
+
+@Override
+boolean translateAccelerator (MSG msg) {
+       if (!isEnabled () || !isActive ()) return false;
+       if (menuBar != null && !menuBar.isEnabled ()) return false;
+       return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
+}
+
+@Override
+boolean traverseEscape () {
+       if (parent == null) return false;
+       if (!isVisible () || !isEnabled ()) return false;
+       close ();
+       return true;
+}
+
+@Override
+void unsubclass () {
+       super.unsubclass ();
+       if (ToolTipProc != 0) {
+               if (toolTipHandle != 0) {
+                       OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
+               }
+               if (toolTipHandle != 0) {
+                       OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
+               }
+               if (menuItemToolTipHandle != 0) {
+                       OS.SetWindowLongPtr (menuItemToolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
+               }
+       }
+}
+
+void updateModal () {
+       if (Display.TrimEnabled) {
+               setItemEnabled (OS.SC_CLOSE, isActive ());
+       } else {
+               OS.EnableWindow (handle, isActive ());
+       }
+}
+
+@Override
+CREATESTRUCT widgetCreateStruct () {
+       return null;
+}
+
+@Override
+long widgetParent () {
+       if (handle != 0) return handle;
+       return parent != null ? parent.handle : 0;
+}
+
+@Override
+int widgetExtStyle () {
+       int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD;
+       if ((style & SWT.TOOL) != 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.
+       */
+       if (parent == null) {
+               if ((style & SWT.ON_TOP) != 0) {
+                       int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+                       if ((style & SWT.NO_TRIM) != 0 || (style & trim) == 0) {
+                               bits |= OS.WS_EX_TOOLWINDOW;
+                       }
+               }
+       }
+
+       if ((style & SWT.ON_TOP) != 0) bits |= OS.WS_EX_TOPMOST;
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       if ((style & SWT.TOOL) != 0) {
+               int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+               if ((style & trim) == 0) return display.windowShadowClass;
+       }
+       return parent != null ? DialogClass : super.windowClass ();
+}
+
+@Override
+long windowProc () {
+       if (windowProc != 0) return windowProc;
+       if ((style & SWT.TOOL) != 0) {
+               int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+               if ((style & trim) == 0) return super.windowProc ();
+       }
+       return parent != null ? DialogProc : super.windowProc ();
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if((style & SWT.NO_MOVE) != 0 && msg == OS.WM_NCLBUTTONDOWN && wParam == OS.HTCAPTION) return 0;
+       if (hwnd == toolTipHandle || hwnd == balloonTipHandle || hwnd == menuItemToolTipHandle) {
+               switch (msg) {
+                       case OS.WM_TIMER: {
+                               if (wParam != ToolTip.TIMER_ID) break;
+                               ToolTip tip = getCurrentToolTip (hwnd);
+                               if (tip != null && tip.autoHide) {
+                                       tip.setVisible (false);
+                               }
+                               break;
+                       }
+                       case OS.WM_LBUTTONDOWN: {
+                               ToolTip tip = getCurrentToolTip (hwnd);
+                               if (tip != null) {
+                                       tip.setVisible (false);
+                                       tip.sendSelectionEvent (SWT.Selection);
+                               }
+                               break;
+                       }
+               }
+               return callWindowProc (hwnd, msg, wParam, lParam);
+       }
+       if (hwnd == handle) {
+               if ((int)msg == Display.TASKBARBUTTONCREATED) {
+                       if (display.taskBar != null) {
+                               for (TaskItem item : display.taskBar.items) {
+                                       if (item != null && item.shell == this) {
+                                               item.recreate ();
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle ();
+       if (handle != 0) return bits | OS.WS_CHILD;
+       bits &= ~OS.WS_CHILD;
+
+       /*
+       * 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 (long wParam, long lParam) {
+       /*
+       * 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.LOWORD (wParam) == 0 && OS.IsDBLocale && hIMC != 0) {
+               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) == 0) {
+               if (lParam == 0 || (lParam != toolTipHandle && lParam != balloonTipHandle
+                               && lParam != menuItemToolTipHandle)) {
+                       ToolTip tip = getCurrentToolTip ();
+                       if (tip != null) tip.setVisible (false);
+               }
+       }
+       return parent != null ? LRESULT.ZERO : result;
+}
+
+@Override
+LRESULT WM_DESTROY (long wParam, long 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) != 0) {
+               releaseParent ();
+               release (false);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if (result != 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.WIN32_VERSION == OS.VERSION (6, 0)) {
+               drawBackground (wParam);
+               return LRESULT.ONE;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_ENTERIDLE (long wParam, long lParam) {
+       LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
+       if (result != null) return result;
+       Display display = this.display;
+       if (display.runAsyncMessages (false)) display.wakeThread ();
+       return result;
+}
+
+@Override
+LRESULT WM_GETMINMAXINFO (long wParam, long lParam) {
+       LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam);
+       if (result != null) return result;
+       if (minWidth != SWT.DEFAULT || minHeight != SWT.DEFAULT) {
+               MINMAXINFO info = new MINMAXINFO ();
+               OS.MoveMemory (info, lParam, MINMAXINFO.sizeof);
+               if (minWidth != SWT.DEFAULT) info.ptMinTrackSize_x = minWidth;
+               if (minHeight != SWT.DEFAULT) info.ptMinTrackSize_y = minHeight;
+               OS.MoveMemory (lParam, info, MINMAXINFO.sizeof);
+               return LRESULT.ZERO;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEACTIVATE (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam);
+       if (result != 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 = (short) OS.LOWORD (lParam);
+       switch (hittest) {
+               case OS.HTERROR:
+               case OS.HTTRANSPARENT:
+               case OS.HTNOWHERE:
+                       break;
+               default: {
+                       Control control = display._getFocusControl ();
+                       if (control != null) {
+                               Decorations decorations = control.menuShell ();
+                               if (decorations.getShell () == this && decorations != this) {
+                                       display.ignoreRestoreFocus = true;
+                                       display.lastHittest = hittest;
+                                       display.lastHittestControl = null;
+                                       if (hittest == OS.HTMENU || hittest == OS.HTSYSMENU) {
+                                               display.lastHittestControl = control;
+                                               return null;
+                                       }
+                                       return new LRESULT (OS.MA_NOACTIVATE);
+                               }
+                       }
+               }
+       }
+       if (hittest == 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 = new POINT ();
+       if (!OS.GetCursorPos (pt)) {
+               int pos = OS.GetMessagePos ();
+               OS.POINTSTOPOINT (pt, pos);
+       }
+       long hwnd = OS.WindowFromPoint (pt);
+       if (hwnd == 0) 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 != null && (control.state & CANVAS) != 0) {
+               if ((control.style & SWT.NO_FOCUS) != 0) {
+                       int bits = SWT.ON_TOP | SWT.NO_FOCUS;
+                       if ((style & bits) == bits) {
+                               if (hittest == OS.HTBORDER || hittest == OS.HTCLIENT) {
+                                       return new LRESULT (OS.MA_NOACTIVATE);
+                               }
+                       }
+               }
+       }
+
+       long code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam);
+       setActiveControl (control, SWT.MouseDown);
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_MOVE (long wParam, long lParam) {
+       LRESULT result = super.WM_MOVE (wParam, lParam);
+       if (result != null) return result;
+       ToolTip tip = getCurrentToolTip ();
+       if (tip != null) tip.setVisible (false);
+       return result;
+}
+
+@Override
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       if (!OS.IsWindowEnabled (handle)) return null;
+       if (!isEnabled () || !isActive ()) {
+               if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE);
+               long hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+               if (hittest == OS.HTCLIENT || hittest == OS.HTMENU) hittest = OS.HTBORDER;
+               return new LRESULT (hittest);
+       }
+       if (menuBar != null && !menuBar.getEnabled ()) {
+               long hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+               if (hittest == OS.HTMENU) hittest = OS.HTBORDER;
+               return new LRESULT (hittest);
+       }
+       return null;
+}
+
+@Override
+LRESULT WM_NCLBUTTONDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam);
+       if (result != 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;
+       display.lockActiveWindow = true;
+       long code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
+       display.lockActiveWindow = false;
+       Control focusControl = display.lastHittestControl;
+       if (focusControl != null && !focusControl.isDisposed ()) {
+               focusControl.setFocus ();
+       }
+       display.lastHittestControl = null;
+       display.ignoreRestoreFocus = false;
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_SETCURSOR (long wParam, long 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 == OS.WM_LBUTTONDOWN) {
+               if (!Display.TrimEnabled) {
+                       Shell modalShell = display.getModalShell ();
+                       if (modalShell != null && !isActive ()) {
+                               long hwndModal = modalShell.handle;
+                               if (OS.IsWindowEnabled (hwndModal)) {
+                                       OS.SetActiveWindow (hwndModal);
+                               }
+                       }
+               }
+               if (!OS.IsWindowEnabled (handle)) {
+                       long hwndPopup = OS.GetLastActivePopup (handle);
+                       if (hwndPopup != 0 && hwndPopup != handle) {
+                               if (display.getControl (hwndPopup) == 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 = (short) OS.LOWORD (lParam);
+       if (hitTest == OS.HTERROR) {
+               if (!getEnabled ()) {
+                       Control control = display.getControl (wParam);
+                       if (control == this && cursor != null) {
+                               POINT pt = new POINT ();
+                               int pos = OS.GetMessagePos ();
+                               OS.POINTSTOPOINT (pt, pos);
+                               OS.ScreenToClient (handle, pt);
+                               RECT rect = new 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);
+                                       }
+                                       return LRESULT.ONE;
+                               }
+                       }
+               }
+       }
+       return super.WM_SETCURSOR (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SHOWWINDOW (long wParam, long lParam) {
+       LRESULT result = super.WM_SHOWWINDOW (wParam, lParam);
+       if (result != 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 == OS.SW_PARENTOPENING) {
+               Control control = this;
+               while (control != null) {
+                       Shell shell = control.getShell ();
+                       if (!shell.showWithParent) return LRESULT.ZERO;
+                       control = control.parent;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
+       LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam);
+       if (result != null) return result;
+       WINDOWPOS lpwp = new WINDOWPOS ();
+       OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+       if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
+               lpwp.cx = Math.max (lpwp.cx, minWidth);
+               int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+               if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+                       lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+               }
+               lpwp.cy = Math.max (lpwp.cy, minHeight);
+               if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+                       if ((style & SWT.RESIZE) != 0) {
+                               lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+                       } else {
+                               RECT rect = new 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;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Slider.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Slider.java
new file mode 100644 (file)
index 0000000..eece947
--- /dev/null
@@ -0,0 +1,803 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * 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:
+ * </p>
+ * <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>
+ * <p>
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Slider extends Control {
+       int increment, pageIncrement;
+       boolean ignoreFocus;
+       static final long ScrollBarProc;
+       static final TCHAR ScrollBarClass = new TCHAR (0, "SCROLLBAR", true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ScrollBarClass, lpWndClass);
+               ScrollBarProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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 Slider (Composite parent, int style) {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener(listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 ();
+       }
+       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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int border = getBorderWidthInPixels ();
+       int width = border * 2, height = border * 2;
+       if ((style & SWT.HORIZONTAL) != 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 != SWT.DEFAULT) width = wHint + (border * 2);
+       if (hHint != 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 = new SCROLLINFO ();
+       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 (boolean enabled) {
+       super.enableWidget (enabled);
+       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 boolean getEnabled () {
+       checkWidget ();
+       return (state & DISABLED) == 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 = new SCROLLINFO ();
+       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 = new SCROLLINFO ();
+       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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_POS;
+       OS.GetScrollInfo (handle, OS.SB_CTL, info);
+       return info.nPos;
+}
+
+/**
+ * Returns the receiver's thumb value.
+ *
+ * @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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_PAGE;
+       OS.GetScrollInfo (handle, OS.SB_CTL, info);
+       if (info.nPage != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+@Override
+void setBoundsInPixels (int x, int y, int width, int height, int flags) {
+       super.setBoundsInPixels (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 () == 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 = new SCROLLINFO ();
+       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 = new SCROLLINFO ();
+       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;
+}
+
+boolean SetScrollInfo (long hwnd, int flags, SCROLLINFO info, boolean 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) != 0) fRedraw = false;
+       boolean result = OS.SetScrollInfo (hwnd, flags, info, fRedraw);
+       if ((state & DISABLED) != 0) {
+               OS.EnableWindow (handle, false);
+               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 () == 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 = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_POS;
+       info.nPos = value;
+       SetScrollInfo (handle, OS.SB_CTL, info, true);
+}
+
+/**
+ * Sets the thumb value. The thumb value should be used to represent
+ * the size of the visual portion of the current range. This value is
+ * usually the same as the page increment value.
+ * <p>
+ * This new value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ * </p>
+ *
+ * @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 = new SCROLLINFO ();
+       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 != 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 = new SCROLLINFO ();
+       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 != 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) != 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) != 0) bits &= ~OS.WS_BORDER;
+       if ((style & SWT.HORIZONTAL) != 0) return bits | OS.SBS_HORZ;
+       return bits | OS.SBS_VERT;
+}
+
+@Override
+TCHAR windowClass () {
+       return ScrollBarClass;
+}
+
+@Override
+long windowProc () {
+       return ScrollBarProc;
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       if ((style & SWT.VERTICAL) != 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) != 0) {
+               switch ((int)wParam) {
+                       case OS.VK_LEFT:
+                       case OS.VK_RIGHT: {
+                               int key = wParam == OS.VK_LEFT ? OS.VK_RIGHT : OS.VK_LEFT;
+                               long code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam);
+                               return new LRESULT (code);
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDBLCLK (long wParam, long 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 == 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.
+       */
+       if (OS.GetCapture () == handle) OS.ReleaseCapture ();
+       if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
+               return LRESULT.ZERO;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long 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 == 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.
+       */
+       if (OS.GetCapture () == handle) OS.ReleaseCapture ();
+       if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
+               return LRESULT.ONE;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       if (ignoreFocus) return null;
+       return super.WM_SETFOCUS (wParam, lParam);
+}
+
+@Override
+LRESULT wmScrollChild (long wParam, long lParam) {
+
+       /* Do nothing when scrolling is ending */
+       int code = OS.LOWORD (wParam);
+       if (code == OS.SB_ENDSCROLL) return null;
+
+       /* Move the thumb */
+       Event event = new Event ();
+       SCROLLINFO info = new SCROLLINFO ();
+       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;
+       }
+       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.
+       */
+       sendSelectionEvent (SWT.Selection, event, true);
+       // the widget could be destroyed at this point
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Spinner.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Spinner.java
new file mode 100644 (file)
index 0000000..ba046b9
--- /dev/null
@@ -0,0 +1,1487 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>READ_ONLY, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, Modify, Verify</dd>
+ * </dl>
+ * <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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Spinner extends Composite {
+       long hwndText, hwndUpDown;
+       boolean ignoreModify, ignoreCharacter;
+       int pageIncrement, digits;
+       static final long EditProc;
+       static final TCHAR EditClass = new TCHAR (0, "EDIT", true);
+       static final long UpDownProc;
+       static final TCHAR UpDownClass = new TCHAR (0, OS.UPDOWN_CLASS, true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, EditClass, lpWndClass);
+               EditProc = lpWndClass.lpfnWndProc;
+               OS.GetClassInfo (0, UpDownClass, lpWndClass);
+               UpDownProc = lpWndClass.lpfnWndProc;
+       }
+
+       /**
+        * 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 final 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 {
+               LIMIT = 0x7FFFFFFF;
+       }
+
+/**
+ * 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 Spinner (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if (hwnd == hwndText) {
+               return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
+       }
+       if (hwnd == 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
+boolean checkHandle (long hwnd) {
+       return hwnd == handle || hwnd == hwndText || hwnd == hwndUpDown;
+}
+
+@Override
+protected void checkSubclass () {
+       if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       state &= ~(CANVAS | THEME_BACKGROUND);
+       long hInstance = OS.GetModuleHandle (null);
+       int textExStyle = (style & SWT.BORDER) != 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) != 0) textStyle |= OS.ES_READONLY;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) textExStyle |= OS.WS_EX_LAYOUTRTL;
+       hwndText = OS.CreateWindowEx (
+               textExStyle,
+               EditClass,
+               null,
+               textStyle,
+               0, 0, 0, 0,
+               handle,
+               0,
+               hInstance,
+               null);
+       if (hwndText == 0) error (SWT.ERROR_NO_HANDLES);
+       OS.SetWindowLongPtr (hwndText, OS.GWLP_ID, hwndText);
+       int upDownStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.UDS_AUTOBUDDY;
+       if ((style & SWT.WRAP) != 0) upDownStyle |= OS.UDS_WRAP;
+       if ((style & SWT.BORDER) != 0) {
+               if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                       upDownStyle |= OS.UDS_ALIGNLEFT;
+               } else {
+                       upDownStyle |= OS.UDS_ALIGNRIGHT;
+               }
+       }
+       hwndUpDown = OS.CreateWindowEx (
+               0,
+               UpDownClass,
+               null,
+               upDownStyle,
+               0, 0, 0, 0,
+               handle,
+               0,
+               hInstance,
+               null);
+       if (hwndUpDown == 0) error (SWT.ERROR_NO_HANDLES);
+       int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+       OS.SetWindowPos (hwndText, hwndUpDown, 0, 0, 0, 0, flags);
+       OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_ID, hwndUpDown);
+       if (OS.IsDBLocale) {
+               long 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.UDM_SETPOS32, 0, 0);
+       pageIncrement = 10;
+       digits = 0;
+       OS.SetWindowText (hwndText, new char [] {'0', '\0'});
+}
+
+/**
+ * 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 == 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 == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Verify, typedListener);
+}
+
+@Override
+long borderHandle () {
+       return hwndText;
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int width = 0, height = 0;
+       if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+               long newFont, oldFont = 0;
+               long hDC = OS.GetDC (hwndText);
+               newFont = OS.SendMessage (hwndText, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               TEXTMETRIC tm = new TEXTMETRIC ();
+               OS.GetTextMetrics (hDC, tm);
+               height = tm.tmHeight;
+               RECT rect = new RECT ();
+               int [] max = new int [1];
+               OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
+               String string = String.valueOf (max [0]);
+               if (digits > 0) {
+                       StringBuilder buffer = new StringBuilder ();
+                       buffer.append (string);
+                       buffer.append (getDecimalSeparator ());
+                       int count = digits - string.length ();
+                       while (count >= 0) {
+                               buffer.append ("0");
+                               count--;
+                       }
+                       string = buffer.toString ();
+               }
+               char [] buffer = string.toCharArray ();
+               int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
+               OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+               width = rect.right - rect.left;
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (hwndText, hDC);
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       Rectangle trim = computeTrimInPixels (0, 0, width, height);
+       if (hHint == SWT.DEFAULT) {
+               int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL) + 2 * getBorderWidthInPixels ();
+               upDownHeight += (style & SWT.BORDER) != 0 ? 1 : 3;
+               trim.height = Math.max (trim.height, upDownHeight);
+       }
+       return new Point (trim.width, trim.height);
+}
+
+@Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       checkWidget ();
+
+       /* Get the trim of the text control */
+       RECT rect = new 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.
+       */
+       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) != 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) != 0) return;
+       OS.SendMessage (hwndText, OS.WM_CUT, 0, 0);
+}
+
+@Override
+int defaultBackground () {
+       return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+@Override
+void enableWidget (boolean enabled) {
+       super.enableWidget (enabled);
+       OS.EnableWindow (hwndText, enabled);
+       OS.EnableWindow (hwndUpDown, enabled);
+}
+
+@Override
+void deregister () {
+       super.deregister ();
+       display.removeControl (hwndText);
+       display.removeControl (hwndUpDown);
+}
+
+@Override
+boolean hasFocus () {
+       long hwndFocus = OS.GetFocus ();
+       if (hwndFocus == handle) return true;
+       if (hwndFocus == hwndText) return true;
+       if (hwndFocus == 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 () {
+       char [] data = new char [4];
+       int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SDECIMAL, data, 4);
+       return size != 0 ? new String (data, 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 = new 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 = new int [1];
+       OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
+       return max [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 ();
+       int [] min = new int [1];
+       OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
+       return min [0];
+}
+
+/**
+ * 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 ();
+       return (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+}
+
+int getSelectionText (boolean [] parseFail) {
+       int length = OS.GetWindowTextLength (hwndText);
+       char [] buffer = new char [length + 1];
+       OS.GetWindowText (hwndText, buffer, length + 1);
+       String string = new String (buffer, 0, length);
+       try {
+               int value;
+               if (digits > 0) {
+                       String decimalSeparator = getDecimalSeparator ();
+                       int index = string.indexOf (decimalSeparator);
+                       if (index != -1)  {
+                               int startIndex = string.startsWith ("+") || string.startsWith ("-") ? 1 : 0;
+                               String wholePart = startIndex != 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 = new int [1], min = new int [1];
+               OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
+               if (min [0] <= value && value <= max [0]) 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 == 0) return "";
+       char [] buffer = new char [length + 1];
+       OS.GetWindowText (hwndText, buffer, length + 1);
+       return new String (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 (int)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+}
+
+/**
+ * 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) != 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 = 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Verify, listener);
+}
+
+@Override
+boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
+       if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+               return false;
+       }
+       if ((style & SWT.READ_ONLY) != 0) return true;
+       if (type != SWT.KeyDown) return true;
+       if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
+               return true;
+       }
+       if (event.character == 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 != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
+                       // FALL THROUGH
+               case OS.WM_KEYDOWN:
+                       if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
+                       break;
+       }
+
+       /*
+       * 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 = new int [1], end = new int [1];
+       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+       switch (key) {
+               case 0x08:      /* Bs */
+                       if (start [0] == end [0]) {
+                               if (start [0] == 0) return true;
+                               start [0] = start [0] - 1;
+                               start [0] = Math.max (start [0], 0);
+                       }
+                       break;
+               case 0x7F:      /* Del */
+                       if (start [0] == end [0]) {
+                               int length = OS.GetWindowTextLength (hwndText);
+                               if (start [0] == length) return true;
+                               end [0] = end [0] + 1;
+                               end [0] = Math.min (end [0], length);
+                       }
+                       break;
+               case '\r':      /* Return */
+                       return true;
+               default:        /* Tab and other characters */
+                       if (key != '\t' && key < 0x20) return true;
+                       oldText = new String (new char [] {key});
+                       break;
+       }
+       String newText = verifyText (oldText, start [0], end [0], event);
+       if (newText == null) return false;
+       if (newText == oldText) return true;
+       TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+       OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+       OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+       return false;
+}
+
+@Override
+void setBackgroundImage (long 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 == this.digits) return;
+       this.digits = value;
+       int pos = (int)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;
+       long hHeap = OS.GetProcessHeap ();
+       int count = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 0, (UDACCEL)null);
+       long udaccels = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, UDACCEL.sizeof * count);
+       OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, count, udaccels);
+       int first = -1;
+       UDACCEL udaccel = new UDACCEL ();
+       for (int i = 0; i < count; i++) {
+               long offset = udaccels + (i * UDACCEL.sizeof);
+               OS.MoveMemory (udaccel, offset, UDACCEL.sizeof);
+               if (first == -1) first = udaccel.nInc;
+               udaccel.nInc  = udaccel.nInc / first * value;
+               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 less 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 or equal to 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 = new int [1];
+       OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
+       if (value < min [0]) return;
+       int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+       OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, min [0], 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 greater 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 or equal to 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 = new int [1];
+       OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
+       if (value > max [0]) return;
+       int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+       OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, value, max [0]);
+       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 = new int [1], min = new int [1];
+       OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
+       value = Math.min (Math.max (min [0], value), max [0]);
+       setSelection (value, true, true, false);
+}
+
+void setSelection (int value, boolean setPos, boolean setText, boolean notify) {
+       if (setPos) {
+               OS.SendMessage (hwndUpDown, OS.UDM_SETPOS32, 0, value);
+       }
+       if (setText) {
+               String string;
+               if (digits == 0) {
+                       string = String.valueOf (value);
+               } else {
+                       string = String.valueOf (Math.abs (value));
+                       String decimalSeparator = getDecimalSeparator ();
+                       int index = string.length () - digits;
+                       StringBuilder buffer = new StringBuilder ();
+                       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 == null) return;
+               }
+               TCHAR buffer = new TCHAR (getCodePage (), string, true);
+               OS.SetWindowText (hwndText, buffer);
+               OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
+               OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, hwndText, OS.OBJID_CLIENT, 0);
+       }
+       if (notify) sendSelectionEvent (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 == 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 ();
+       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, EditProc);
+       OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, UpDownProc);
+}
+
+@Override
+void updateOrientation () {
+       super.updateOrientation ();
+       int bits  = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
+       int bits1  = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
+       if ((style & SWT.RIGHT_TO_LEFT) != 0){
+               bits |= OS.WS_EX_RIGHT;
+               bits1 |= OS.ES_RIGHT;
+       }
+       else{
+               bits &= ~OS.WS_EX_RIGHT;
+               bits1 &= ~OS.ES_RIGHT;
+       }
+       OS.SetWindowLong (hwndText, OS.GWL_STYLE, bits1);
+       OS.SetWindowLong (hwndText, OS.GWL_EXSTYLE, bits);
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       int width = rect.right - rect.left, height = rect.bottom - rect.top;
+       OS.SetWindowPos (handle, 0, 0, 0, width - 1, height - 1, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       OS.SetWindowPos (handle, 0, 0, 0, width, height, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+}
+
+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 != 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 != -1) {
+                       string = string.substring (0, index) + string.substring (index + 1);
+               }
+               index = 0;
+       }
+       if (string.length() > 0) {
+               int [] min = new int [1];
+               OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
+               if (min [0] < 0 && string.charAt (0) == '-') index++;
+       }
+       while (index < string.length ()) {
+               if (!Character.isDigit (string.charAt (index))) break;
+               index++;
+       }
+       event.doit = index == string.length ();
+       sendEvent (SWT.Verify, event);
+       if (!event.doit || isDisposed ()) return null;
+       return event.text;
+}
+
+@Override
+int widgetExtStyle () {
+       return super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (hwnd == hwndText || hwnd == 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 == hwndText) {
+                                       result = wmClipboard (hwnd, msg, wParam, lParam);
+                               }
+                               break;
+               }
+               if (result != null) return result.value;
+               return callWindowProc (hwnd, msg, wParam, lParam);
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       super.WM_ERASEBKGND (wParam, lParam);
+       drawBackground (wParam);
+       return LRESULT.ONE;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       return null;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       OS.SetFocus (hwndText);
+       OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
+       return null;
+}
+
+@Override
+LRESULT WM_SETFONT (long wParam, long lParam) {
+       LRESULT result = super.WM_SETFONT (wParam, lParam);
+       if (result != null) return result;
+       OS.SendMessage (hwndText, OS.WM_SETFONT, wParam, lParam);
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long 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;
+       OS.SetWindowPos (hwndText, 0, 0, 0, textWidth + border, height, flags);
+       OS.SetWindowPos (hwndUpDown, 0, textWidth, 0, upDownWidth, height, flags);
+       return result;
+}
+
+@Override
+LRESULT wmIMEChar(long hwnd, long wParam, long lParam) {
+
+       /* Process a DBCS character */
+       Display display = this.display;
+       display.lastKey = 0;
+       display.lastAscii = (int)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;
+       long result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam);
+       MSG msg = new 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 wmChar (long hwnd, long wParam, long lParam) {
+       if (ignoreCharacter) return null;
+       LRESULT result = super.wmChar (hwnd, wParam, lParam);
+       if (result != 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 ((int)wParam) {
+               case SWT.CR:
+                       sendSelectionEvent (SWT.DefaultSelection);
+                       // FALL THROUGH
+               case SWT.TAB:
+               case SWT.ESC: return LRESULT.ZERO;
+       }
+       return result;
+}
+
+LRESULT wmClipboard (long hwndText, int msg, long wParam, long lParam) {
+       if ((style & SWT.READ_ONLY) != 0) return null;
+//     if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+       boolean call = false;
+       int [] start = new int [1], end = new int [1];
+       String newText = null;
+       switch (msg) {
+               case OS.WM_CLEAR:
+               case OS.WM_CUT:
+                       OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+                       if (start [0] != end [0]) {
+                               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) != 0) {
+                               ignoreModify = true;
+                               OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                               int length = OS.GetWindowTextLength (hwndText);
+                               int [] newStart = new int [1], newEnd = new int [1];
+                               OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
+                               if (length != 0 && newStart [0] != newEnd [0]) {
+                                       char [] buffer = new char [length + 1];
+                                       OS.GetWindowText (hwndText, buffer, length + 1);
+                                       newText = new String (buffer, newStart [0], newEnd [0] - newStart [0]);
+                               } else {
+                                       newText = "";
+                               }
+                               OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                               OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+                               ignoreModify = false;
+                       }
+                       break;
+       }
+       if (newText != null) {
+               String oldText = newText;
+               newText = verifyText (newText, start [0], end [0], null);
+               if (newText == null) return LRESULT.ZERO;
+               if (!newText.equals (oldText)) {
+                       if (call) {
+                               OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                       }
+                       TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+                       if (msg == OS.WM_SETTEXT) {
+                               long hHeap = OS.GetProcessHeap ();
+                               int byteCount = buffer.length () * TCHAR.sizeof;
+                               long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                               OS.MoveMemory (pszText, buffer, byteCount);
+                               long code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText);
+                               OS.HeapFree (hHeap, 0, pszText);
+                               return new LRESULT (code);
+                       } else {
+                               OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+                               return LRESULT.ZERO;
+                       }
+               }
+       }
+       return null;
+}
+
+@Override
+LRESULT wmCommandChild (long wParam, long lParam) {
+       int code = OS.HIWORD (wParam);
+       switch (code) {
+               case OS.EN_CHANGE:
+                       if (ignoreModify) break;
+                       boolean [] parseFail = new boolean [1];
+                       int value = getSelectionText (parseFail);
+                       if (!parseFail [0]) {
+                               int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+                               if (pos != value) setSelection (value, true, false, true);
+                       }
+                       sendEvent (SWT.Modify);
+                       if (isDisposed ()) return LRESULT.ZERO;
+                       break;
+       }
+       return super.wmCommandChild (wParam, lParam);
+}
+
+@Override
+LRESULT wmKeyDown (long hwnd, long wParam, long lParam) {
+       if (ignoreCharacter) return null;
+       LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+       if (result != null) return result;
+
+       /* Increment the value */
+       UDACCEL udaccel = new UDACCEL ();
+       OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel);
+       int delta = 0;
+       switch ((int)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;
+       }
+       if (delta != 0) {
+               boolean [] parseFail = new boolean [1];
+               int value = getSelectionText (parseFail);
+               if (parseFail [0]) {
+                       value = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+               }
+               int newValue = value + delta;
+               int [] max = new int [1], min = new int [1];
+               OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
+               if ((style & SWT.WRAP) != 0) {
+                       if (newValue < min [0]) newValue = max [0];
+                       if (newValue > max [0]) newValue = min [0];
+               }
+               newValue = Math.min (Math.max (min [0], newValue), max [0]);
+               if (value != newValue) setSelection (newValue, true, true, true);
+       }
+
+       /*  Stop the edit control from moving the caret */
+       switch ((int)wParam) {
+               case OS.VK_UP:
+               case OS.VK_DOWN:
+                       return LRESULT.ZERO;
+       }
+       return result;
+}
+
+@Override
+LRESULT wmKillFocus (long hwnd, long wParam, long lParam) {
+       boolean [] parseFail = new boolean [1];
+       int value = getSelectionText (parseFail);
+       if (parseFail [0]) {
+               value = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+               setSelection (value, false, true, false);
+       }
+       return super.wmKillFocus (hwnd, wParam, lParam);
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.UDN_DELTAPOS:
+                       NMUPDOWN lpnmud = new NMUPDOWN ();
+                       OS.MoveMemory (lpnmud, lParam, NMUPDOWN.sizeof);
+                       int value = lpnmud.iPos + lpnmud.iDelta;
+                       int [] max = new int [1], min = new int [1];
+                       OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
+                       if ((style & SWT.WRAP) != 0) {
+                               if (value < min [0]) value = max [0];
+                               if (value > max [0]) value = min [0];
+                       }
+                       /*
+                       * 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 [0], value), max [0]);
+                       if (value != lpnmud.iPos) {
+                               setSelection (value, true, true, true);
+                       }
+                       return LRESULT.ONE;
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+@Override
+LRESULT wmScrollChild (long wParam, long lParam) {
+       int code = OS.LOWORD (wParam);
+       switch (code) {
+               case OS.SB_THUMBPOSITION:
+                       sendSelectionEvent (SWT.Selection);
+                       break;
+       }
+       return super.wmScrollChild (wParam, lParam);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Synchronizer.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Synchronizer.java
new file mode 100644 (file)
index 0000000..2546b36
--- /dev/null
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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 = new Object ();
+       Thread syncThread;
+       static final int GROW_SIZE = 4;
+       static final int MESSAGE_LIMIT = 64;
+
+       //TEMPORARY CODE
+       static final boolean IS_COCOA = "cocoa".equals (SWT.getPlatform ());
+       static final boolean IS_GTK = "gtk".equals (SWT.getPlatform ());
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param display the display to create the synchronizer on
+ */
+public Synchronizer (Display display) {
+       this.display = display;
+}
+
+/**
+ * Removes all pending events from the receiver and inserts them into the beginning of the given
+ * synchronizer's queue
+ *
+ * @param toReceiveTheEvents the synchronizer that will receive the events
+ */
+void moveAllEventsTo (Synchronizer toReceiveTheEvents) {
+       RunnableLock[] oldMessages;
+       int oldMessageCount;
+       synchronized (messageLock) {
+               oldMessages = messages;
+               messages = null;
+               oldMessageCount = messageCount;
+               messageCount = 0;
+       }
+       toReceiveTheEvents.addFirst(oldMessages, oldMessageCount);
+}
+
+/**
+ * Adds the given events to the beginning of the message queue, to
+ * be processed in order.
+ *
+ * @param toAdd events to add. Permits null if and only if numToAdd is 0.
+ * @param numToAdd number of events to add from the beginning of the given array.
+ */
+void addFirst (RunnableLock[] toAdd, int numToAdd) {
+       if (numToAdd <= 0) {
+               return;
+       }
+       boolean wake = false;
+       synchronized (messageLock) {
+               int nextSize = messageCount + Math.max(numToAdd, GROW_SIZE);
+               if (messages == null)
+                       messages = new RunnableLock[nextSize];
+               if (messages.length < messageCount + numToAdd) {
+                       RunnableLock[] newMessages = new RunnableLock[nextSize];
+                       System.arraycopy(messages, 0, newMessages, numToAdd, messageCount);
+                       messages = newMessages;
+               } else {
+                       System.arraycopy(messages, 0, messages, numToAdd, messageCount);
+               }
+               System.arraycopy(toAdd, 0, messages, 0, numToAdd);
+               wake = (messageCount == 0);
+               messageCount += numToAdd;
+       }
+       if (wake)
+               display.wakeThread();
+}
+
+void addLast (RunnableLock lock) {
+       boolean wake = false;
+       synchronized (messageLock) {
+               if (messages == null) messages = new RunnableLock [GROW_SIZE];
+               if (messageCount == messages.length) {
+                       RunnableLock[] newMessages = new RunnableLock [messageCount + GROW_SIZE];
+                       System.arraycopy (messages, 0, newMessages, 0, messageCount);
+                       messages = newMessages;
+               }
+               messages [messageCount++] = lock;
+               wake = messageCount == 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
+ */
+protected void asyncExec (Runnable runnable) {
+       if (runnable == null) {
+               //TEMPORARY CODE
+               if (!(IS_GTK || IS_COCOA)) {
+                       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 == 0) return null;
+               RunnableLock lock = messages [0];
+               System.arraycopy (messages, 1, messages, 0, --messageCount);
+               messages [messageCount] = null;
+               if (messageCount == 0) {
+                       if (messages.length > MESSAGE_LIMIT) messages = null;
+               }
+               return lock;
+       }
+}
+
+boolean runAsyncMessages () {
+       return runAsyncMessages (false);
+}
+
+boolean runAsyncMessages (boolean all) {
+       boolean run = false;
+       do {
+               RunnableLock lock = removeFirst ();
+               if (lock == null) return run;
+               run = true;
+               synchronized (lock) {
+                       syncThread = lock.thread;
+                       display.sendPreEvent(SWT.None);
+                       try {
+                               lock.run (display);
+                       } catch (Throwable t) {
+                               lock.throwable = t;
+                               SWT.error (SWT.ERROR_FAILED_EXEC, t);
+                       } finally {
+                               if (display != null && !display.isDisposed()) {
+                                       display.sendPostEvent(SWT.None);
+                               }
+                               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
+ */
+protected void syncExec (Runnable runnable) {
+       RunnableLock lock = null;
+       synchronized (Device.class) {
+               if (display == null || display.isDisposed ()) SWT.error (SWT.ERROR_DEVICE_DISPOSED);
+               if (!display.isValidThread ()) {
+                       if (runnable == null) {
+                               display.wake ();
+                               return;
+                       }
+                       lock = new RunnableLock (runnable);
+                       /*
+                        * Only remember the syncThread for syncExec.
+                        */
+                       lock.thread = Thread.currentThread();
+                       addLast (lock);
+               }
+       }
+       if (lock == null) {
+               if (runnable != null) {
+                       display.sendPreEvent(SWT.None);
+                       try {
+                               runnable.run();
+                       } catch (RuntimeException exception) {
+                               display.getRuntimeExceptionHandler ().accept (exception);
+                       } catch (Error error) {
+                               display.getErrorHandler ().accept (error);
+                       } finally {
+                               if (display != null && !display.isDisposed()) {
+                                       display.sendPostEvent(SWT.None);
+                               }
+                       }
+               }
+               return;
+       }
+       synchronized (lock) {
+               boolean interrupted = false;
+               while (!lock.done ()) {
+                       try {
+                               lock.wait ();
+                       } catch (InterruptedException e) {
+                               interrupted = true;
+                       }
+               }
+               if (interrupted) {
+                       Thread.currentThread().interrupt();
+               }
+               if (lock.throwable != null) {
+                       SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable);
+               }
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TabFolder.java
new file mode 100644 (file)
index 0000000..ce6d7e3
--- /dev/null
@@ -0,0 +1,1136 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TabFolder extends Composite {
+       TabItem [] items;
+       ImageList imageList;
+       static final long TabFolderProc;
+       static final TCHAR TabFolderClass = new TCHAR (0, OS.WC_TABCONTROL, true);
+       boolean createdAsRTL;
+
+       /*
+       * 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 final int ID_UPDOWN = 1;
+
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, TabFolderClass, 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.
+               */
+               lpWndClass.hInstance = OS.GetModuleHandle (null);
+               lpWndClass.style &= ~(OS.CS_HREDRAW | OS.CS_VREDRAW | OS.CS_GLOBALCLASS);
+               OS.RegisterClass (TabFolderClass, lpWndClass);
+       }
+
+/**
+ * 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 SWT#TOP
+ * @see SWT#BOTTOM
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TabFolder (Composite parent, int style) {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener(listener);
+       addListener(SWT.Selection,typedListener);
+       addListener(SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       return OS.CallWindowProc (TabFolderProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+       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 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       Point size = super.computeSizeInPixels (wHint, hHint, changed);
+       RECT insetRect = new RECT (), itemRect = new RECT ();
+       OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 0, insetRect);
+       int width = insetRect.left - insetRect.right;
+       int count = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+       if (count != 0) {
+               OS.SendMessage (handle, OS.TCM_GETITEMRECT, count - 1, itemRect);
+               width = Math.max (width, itemRect.right - insetRect.right);
+       }
+       RECT rect = new RECT ();
+       OS.SetRect (rect, 0, 0, width, size.y);
+       OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 1, rect);
+       int border = getBorderWidthInPixels ();
+       rect.left -= border;  rect.right += border;
+       width = rect.right - rect.left;
+       size.x = Math.max (width, size.x);
+       return size;
+}
+
+@Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       checkWidget ();
+       RECT rect = new RECT ();
+       OS.SetRect (rect, x, y, x + width, y + height);
+       OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 1, rect);
+       int border = getBorderWidthInPixels ();
+       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 = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+       if (count == items.length) {
+               TabItem [] newItems = new TabItem [items.length + 4];
+               System.arraycopy (items, 0, newItems, 0, items.length);
+               items = newItems;
+       }
+       TCITEM tcItem = new TCITEM ();
+       if (OS.SendMessage (handle, OS.TCM_INSERTITEM, index, tcItem) == -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 == 0) {
+               Event event = new Event ();
+               event.item = items [0];
+               sendSelectionEvent (SWT.Selection, event, true);
+               // the widget could be destroyed at this point
+       }
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       state &= ~(CANVAS | THEME_BACKGROUND);
+
+       /*
+       * 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.
+       */
+       long hwndToolTip = OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0);
+       OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+
+       createdAsRTL = (style & SWT.RIGHT_TO_LEFT) != 0;
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       items = new TabItem [4];
+}
+
+void destroyItem (TabItem item) {
+       int count = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+       int index = 0;
+       while (index < count) {
+               if (items [index] == item) break;
+               index++;
+       }
+       if (index == count) return;
+       int selectionIndex = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+       if (OS.SendMessage (handle, OS.TCM_DELETEITEM, index, 0) == 0) {
+               error (SWT.ERROR_ITEM_NOT_REMOVED);
+       }
+       System.arraycopy (items, index + 1, items, index, --count - index);
+       items [count] = null;
+       if (count == 0) {
+               if (imageList != null) {
+                       OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, 0);
+                       display.releaseImageList (imageList);
+               }
+               imageList = null;
+               items = new TabItem [4];
+       }
+       if (count > 0 && index == selectionIndex) {
+               setSelection (Math.max (0, selectionIndex - 1), true);
+       }
+}
+
+@Override
+void drawThemeBackground (long hDC, long hwnd, RECT rect) {
+       RECT rect2 = new RECT ();
+       OS.GetClientRect (handle, rect2);
+       OS.MapWindowPoints (handle, hwnd, rect2, 2);
+       if (OS.IntersectRect (new RECT (), 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 Rectangle getClientAreaInPixels () {
+       checkWidget ();
+       forceResize ();
+       RECT rect = new 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 = (int)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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TCHITTESTINFO pinfo = new TCHITTESTINFO ();
+       pinfo.x = point.x;
+       pinfo.y = point.y;
+       int index = (int)OS.SendMessage (handle, OS.TCM_HITTEST, 0, pinfo);
+       if (index == -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 (int)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 = (int)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 = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+       if (index == -1) return new TabItem [0];
+       return new TabItem [] {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 (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+}
+
+int imageIndex (Image image) {
+       /*
+        * Bug 497387: Return -1 if there is no image for the tab, for more details
+        * refer: https://msdn.microsoft.com/pt-br/library/windows/hardware/bb760554
+        */
+       if (image == null) return -1;
+       if (imageList == null) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+               int index = imageList.add (image);
+               long hImageList = imageList.getHandle ();
+               OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, hImageList);
+               return index;
+       }
+       int index = imageList.indexOf (image);
+       if (index == -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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int count = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+       for (int i=0; i<count; i++) {
+               if (items [i] == item) return i;
+       }
+       return -1;
+}
+
+@Override
+Point minimumSize (int wHint, int hHint, boolean 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 = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+               while (index < count) {
+                       if (items [index].control == child) break;
+                       index++;
+               }
+               if (index == count) {
+                       Rectangle rect = DPIUtil.autoScaleUp(child.getBounds ());
+                       width = Math.max (width, rect.x + rect.width);
+                       height = Math.max (height, rect.y + rect.height);
+               } else {
+                       /*
+                        * Since computeSize can be overridden by subclasses, we cannot
+                        * call computeSizeInPixels directly.
+                        */
+                       Point size = DPIUtil.autoScaleUp(child.computeSize (DPIUtil.autoScaleDown(wHint), DPIUtil.autoScaleDown(hHint), flushCache));
+                       width = Math.max (width, size.x);
+                       height = Math.max (height, size.y);
+               }
+       }
+       return new Point (width, height);
+}
+
+@Override
+boolean mnemonicHit (char key) {
+       for (int i=0; i<items.length; i++) {
+               TabItem item = items [i];
+               if (item != null) {
+                       char ch = findMnemonic (item.getText ());
+                       if (Character.toUpperCase (key) == Character.toUpperCase (ch)) {
+                               if (forceFocus ()) {
+                                       if (i != getSelectionIndex ()) setSelection (i, true);
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
+@Override
+boolean mnemonicMatch (char key) {
+       for (int i=0; i<items.length; i++) {
+               TabItem item = items [i];
+               if (item != null) {
+                       char ch = findMnemonic (item.getText ());
+                       if (Character.toUpperCase (key) == Character.toUpperCase (ch)) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (items != null) {
+               int count = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+               for (int i=0; i<count; i++) {
+                       TabItem item = items [i];
+                       if (item != null && !item.isDisposed ()) {
+                               item.release (false);
+                       }
+               }
+               items = null;
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (imageList != null) {
+               OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, 0);
+               display.releaseImageList (imageList);
+       }
+       imageList = null;
+}
+
+@Override
+void removeControl (Control control) {
+       super.removeControl (control);
+       int count = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+       for (int i=0; i<count; i++) {
+               TabItem item = items [i];
+               if (item.control == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               int count = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+               for (int i=0; i<count; i++) {
+                       TabItem item = items [i];
+                       if (item != null) item.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       setSelection (new TabItem [] {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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if 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 setSelection (TabItem [] items) {
+       checkWidget ();
+       if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (items.length == 0) {
+               setSelection (-1, false);
+       } else {
+               for (int i=items.length-1; i>=0; --i) {
+                       int index = indexOf (items [i]);
+                       if (index != -1) setSelection (index, false);
+               }
+       }
+}
+
+@Override
+public void setFont (Font font) {
+       checkWidget ();
+       Rectangle oldRect = getClientAreaInPixels ();
+       super.setFont (font);
+       Rectangle newRect = getClientAreaInPixels ();
+       if (!oldRect.equals (newRect)) {
+               sendResize ();
+               int index = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+               if (index != -1) {
+                       TabItem item = items [index];
+                       Control control = item.control;
+                       if (control != null && !control.isDisposed ()) {
+                               control.setBoundsInPixels (getClientAreaInPixels ());
+                       }
+               }
+       }
+}
+
+/**
+ * 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 = (int)OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= index && index < count)) return;
+       setSelection (index, false);
+}
+
+void setSelection (int index, boolean notify) {
+       int oldIndex = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+       if (oldIndex == index) return;
+       if (oldIndex != -1) {
+               TabItem item = items [oldIndex];
+               Control control = item.control;
+               if (control != null && !control.isDisposed ()) {
+                       control.setVisible (false);
+               }
+       }
+       OS.SendMessage (handle, OS.TCM_SETCURSEL, index, 0);
+       int newIndex = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+       if (newIndex != -1) {
+               TabItem item = items [newIndex];
+               Control control = item.control;
+               if (control != null && !control.isDisposed ()) {
+                       control.setBoundsInPixels (getClientAreaInPixels ());
+                       control.setVisible (true);
+               }
+               if (notify) {
+                       Event event = new Event ();
+                       event.item = item;
+                       sendSelectionEvent (SWT.Selection, event, true);
+               }
+       }
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               if (textDirection != AUTO_TEXT_DIRECTION) {
+                       textDirection = style & SWT.FLIP_TEXT_DIRECTION;
+               }
+               for (int i = 0, n = items.length; i < n && items[i] != null; i++) {
+                       items[i].updateTextDirection (textDirection);
+               }
+               return true;
+       }
+       return false;
+}
+
+@Override
+String toolTipText (NMTTDISPINFO hdr) {
+       if ((hdr.uFlags & OS.TTF_IDISHWND) != 0) {
+               return null;
+       }
+       int index = (int)hdr.idFrom;
+       long hwndToolTip = OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0);
+       if (hwndToolTip == 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.
+               */
+               int flags = SWT.RIGHT_TO_LEFT | SWT.FLIP_TEXT_DIRECTION;
+               if ((style & flags) != 0 && (style & flags) != flags) {
+                       hdr.uFlags |= OS.TTF_RTLREADING;
+               } else {
+                       hdr.uFlags &= ~OS.TTF_RTLREADING;
+               }
+               if (toolTipText != null) return "";
+               if (0 <= index && index < items.length) {
+                       TabItem item = items [index];
+                       if (item != null) return item.toolTipText;
+               }
+       }
+       return super.toolTipText (hdr);
+}
+
+@Override
+boolean traversePage (boolean next) {
+       int count = getItemCount ();
+       if (count <= 1) return false;
+       int index = getSelectionIndex ();
+       if (index == -1) {
+               index = 0;
+       } else {
+               int offset = (next) ? 1 : -1;
+               index = (index + offset + count) % count;
+       }
+       setSelection (index, true);
+       if (index == getSelectionIndex ()) {
+               OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+               return true;
+       }
+       return false;
+}
+
+@Override
+void updateOrientation () {
+       super.updateOrientation ();
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               char [] buffer = new char [128];
+               int length = OS.GetClassName (hwndChild, buffer, buffer.length);
+               String className = new String (buffer, 0, length);
+               if (className.equals ("msctls_updown32")) { //$NON-NLS-1$
+                       int bits = OS.GetWindowLong (hwndChild, OS.GWL_EXSTYLE);
+                       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                               bits |= OS.WS_EX_LAYOUTRTL;
+                       } else {
+                               bits &= ~OS.WS_EX_LAYOUTRTL;
+                       }
+                       bits &= ~OS.WS_EX_RTLREADING;
+                       OS.SetWindowLong (hwndChild, OS.GWL_EXSTYLE, bits);
+                       OS.InvalidateRect (hwndChild, null, true);
+                       break;
+               }
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       int width = rect.right - rect.left, height = rect.bottom - rect.top;
+       OS.SetWindowPos (handle, 0, 0, 0, width - 1, height - 1, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       OS.SetWindowPos (handle, 0, 0, 0, width, height, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       if (imageList != null) {
+               Point size = imageList.getImageSize ();
+               display.releaseImageList (imageList);
+               imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+               long hImageList = imageList.getHandle ();
+               OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, hImageList);
+               TCITEM tcItem = new TCITEM ();
+               tcItem.mask = OS.TCIF_IMAGE;
+               for (int i = 0; i < items.length; i++) {
+                       TabItem item = items [i];
+                       if (item == null) break;
+                       Image image = item.image;
+                       if (image != null) {
+                               tcItem.iImage = imageIndex (image);
+                               OS.SendMessage (handle, OS.TCM_SETITEM, i, tcItem);
+                       }
+               }
+       }
+}
+
+@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) != 0) bits |= OS.TCS_FOCUSNEVER;
+       if ((style & SWT.BOTTOM) != 0) bits |= OS.TCS_BOTTOM;
+       return bits | OS.TCS_TABS | OS.TCS_TOOLTIPS;
+}
+
+@Override
+TCHAR windowClass () {
+       return TabFolderClass;
+}
+
+@Override
+long windowProc () {
+       return TabFolderProc;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long 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 != null) return result;
+       return new LRESULT (OS.DLGC_BUTTON | OS.DLGC_WANTARROWS);
+}
+
+@Override
+LRESULT WM_GETOBJECT (long wParam, long lParam) {
+       /*
+       * Ensure that there is an accessible object created for this
+       * control because support for publishing the keyboard shortcut
+       * for page switching is implemented in the accessibility package.
+       */
+       if (accessible == null) accessible = new_Accessible (this);
+       return super.WM_GETOBJECT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               case OS.VK_LEFT:
+               case OS.VK_RIGHT:
+                       /*
+                       * Bug in Windows. The behavior for the left and right keys is not
+                       * changed if the orientation changes after the control was created.
+                       * The fix is to replace VK_LEFT by VK_RIGHT and VK_RIGHT by VK_LEFT
+                       * when the current orientation differs from the orientation used to
+                       * create the control.
+                       */
+                       boolean isRTL = (style & SWT.RIGHT_TO_LEFT) != 0;
+                       if (isRTL != createdAsRTL) {
+                               long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam == OS.VK_RIGHT ? OS.VK_LEFT : OS.VK_RIGHT, lParam);
+                               return new LRESULT (code);
+                       }
+                       break;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSELEAVE (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSELEAVE (wParam, lParam);
+       if (result != 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.
+       */
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = TOOLINFO.sizeof;
+       long hwndToolTip = OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0);
+       if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+               if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) {
+                       OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
+                       OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+       if (result != 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.
+       */
+       long hittest = OS.DefWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+       return new LRESULT (hittest);
+}
+
+@Override
+LRESULT WM_NOTIFY (long wParam, long 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 != null) return result;
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_PARENTNOTIFY (long wParam, long lParam) {
+       LRESULT result = super.WM_PARENTNOTIFY (wParam, lParam);
+       if (result != 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.
+       */
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               int code = OS.LOWORD (wParam);
+               switch (code) {
+                       case OS.WM_CREATE: {
+                               int id = OS.HIWORD (wParam);
+                               long hwnd = lParam;
+                               if (id == ID_UPDOWN) {
+                                       int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                                       OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYOUTRTL);
+                               }
+                               break;
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long 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 = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+       if (index != -1) {
+               TabItem item = items [index];
+               Control control = item.control;
+               if (control != null && !control.isDisposed ()) {
+                       control.setBoundsInPixels (getClientAreaInPixels ());
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
+       LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+       if (result != null) return result;
+       if (!OS.IsWindowVisible (handle)) return result;
+       WINDOWPOS lpwp = new WINDOWPOS ();
+       OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+       if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) != 0) {
+               return result;
+       }
+       // TEMPORARY CODE
+//     if (OS.IsAppThemed ()) {
+//             OS.InvalidateRect (handle, null, true);
+//             return result;
+//     }
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.TCS_MULTILINE) != 0) {
+               OS.InvalidateRect (handle, null, true);
+               return result;
+       }
+       RECT rect = new 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 == oldWidth && newHeight == oldHeight) {
+               return result;
+       }
+       RECT inset = new RECT ();
+       OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 0, inset);
+       int marginX = -inset.right, marginY = -inset.bottom;
+       if (newWidth != oldWidth) {
+               int left = oldWidth;
+               if (newWidth < oldWidth) left = newWidth;
+               OS.SetRect (rect, left - marginX, 0, newWidth, newHeight);
+               OS.InvalidateRect (handle, rect, true);
+       }
+       if (newHeight != 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, long wParam, long lParam) {
+       int code = hdr.code;
+       switch (code) {
+               case OS.TCN_SELCHANGE:
+               case OS.TCN_SELCHANGING:
+                       TabItem item = null;
+                       int index = (int)OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+                       if (index != -1) item = items [index];
+                       if (item != null) {
+                               Control control = item.control;
+                               if (control != null && !control.isDisposed ()) {
+                                       if (code == OS.TCN_SELCHANGE) {
+                                               control.setBoundsInPixels (getClientAreaInPixels ());
+                                       }
+                                       control.setVisible (code == OS.TCN_SELCHANGE);
+                               }
+                       }
+                       if (code == OS.TCN_SELCHANGE) {
+                               Event event = new Event ();
+                               event.item = item;
+                               sendSelectionEvent (SWT.Selection, event, false);
+                       }
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TabItem.java
new file mode 100644 (file)
index 0000000..ac4a3f8
--- /dev/null
@@ -0,0 +1,414 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TabItem extends 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 TabItem (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 TabItem (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 (image != null) {
+               if (string.indexOf ('&') != -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] != '&') text [j++] = text [i];
+                       }
+                       if (j < i) string = new String (text, 0, j);
+               }
+       }
+       long hwnd = parent.handle;
+       long hHeap = OS.GetProcessHeap ();
+       TCHAR buffer = new TCHAR (parent.getCodePage (), string, true);
+       int byteCount = buffer.length () * TCHAR.sizeof;
+       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (pszText, buffer, byteCount);
+       TCITEM tcItem = new 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();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels() {
+       int index = parent.indexOf(this);
+       if (index == -1) return new Rectangle (0, 0, 0, 0);
+       RECT itemRect = new RECT ();
+       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 == parent.getSelectionIndex ()) {
+               if (control != 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 != null) {
+               if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+       }
+       if (this.control != null && this.control.isDisposed ()) {
+               this.control = null;
+       }
+       Control oldControl = this.control, newControl = control;
+       this.control = control;
+       int index = parent.indexOf (this), selectionIndex = parent.getSelectionIndex();
+       if (index != selectionIndex) {
+               if (newControl != null) {
+                       if (selectionIndex != -1) {
+                               Control selectedControl = parent.getItem(selectionIndex).getControl();
+                               if (selectedControl == newControl) return;
+                       }
+                       newControl.setVisible(false);
+                       return;
+               }
+       }
+       if (newControl != null) {
+               newControl.setBounds (parent.getClientAreaInPixels ());
+               newControl.setVisible (true);
+       }
+       if (oldControl != null && newControl != null && oldControl != newControl)
+               oldControl.setVisible (false);
+}
+
+@Override
+public void setImage (Image image) {
+       checkWidget();
+       int index = parent.indexOf (this);
+       if (index == -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 (text.indexOf ('&') != -1) _setText (index, text);
+       long hwnd = parent.handle;
+       TCITEM tcItem = new 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>
+ * 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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>
+ *
+ */
+@Override
+public void setText (String string) {
+       checkWidget();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (string.equals (text)) return;
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       super.setText (string);
+       /*
+        * Need to update direction since it is set via UCC which the new text
+        * overrides
+        */
+       int textDirection = (state & HAS_AUTO_DIRECTION) != 0 ? AUTO_TEXT_DIRECTION : style & SWT.FLIP_TEXT_DIRECTION;
+       if (!updateTextDirection (textDirection)) {
+               _setText (index, string);
+       }
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       /* AUTO is handled by super */
+       if (super.updateTextDirection(textDirection)) {
+               int index = parent.indexOf (this);
+               if (index != -1) {
+                       if ((textDirection & SWT.RIGHT_TO_LEFT) != 0) {
+                               _setText(index, RLE + text);
+                               return true;
+                       } else if ((textDirection & SWT.LEFT_TO_RIGHT) != 0) {
+                               _setText(index, LRE + text);
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ *
+ * @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;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Table.java
new file mode 100644 (file)
index 0000000..f9f18ba
--- /dev/null
@@ -0,0 +1,7347 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Roland Oldenburg <r.oldenburg@hsp-software.de> - Bug 292199
+ *     Conrad Groth - Bug 384906
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+//import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>:</p>
+ * <pre><code>
+ *  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 ());
+ *      }
+ *  });
+ * </code></pre>
+ * <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>
+ * <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>
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Table extends Composite {
+       TableItem [] items;
+       int [] keys;
+       TableColumn [] columns;
+       int columnCount, customCount, keyCount;
+       ImageList imageList, headerImageList;
+       TableItem currentItem;
+       TableColumn sortColumn;
+       RECT focusRect;
+       boolean [] columnVisible;
+       long headerToolTipHandle, hwndHeader;
+       boolean ignoreCustomDraw, ignoreDrawForeground, ignoreDrawBackground, ignoreDrawFocus, ignoreDrawSelection, ignoreDrawHot;
+       boolean customDraw, dragStarted, explorerTheme, firstColumnImage, fixScrollWidth, tipRequested, wasSelected, wasResized, painted;
+       boolean ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize, ignoreColumnMove, ignoreColumnResize, fullRowSelect, settingItemHeight;
+       boolean headerItemDragging;
+       int itemHeight, lastIndexOf, lastWidth, sortDirection, resizeCount, selectionForeground, hotIndex;
+       int headerBackground = -1;
+       int headerForeground = -1;
+       static /*final*/ long HeaderProc;
+       static final int INSET = 4;
+       static final int GRID_WIDTH = 1;
+       static final int SORT_WIDTH = 10;
+       static final int HEADER_MARGIN = 12;
+       static final int HEADER_EXTRA = 3;
+       static final int VISTA_EXTRA = 2;
+       static final int EXPLORER_EXTRA = 2;
+       static final int H_SCROLL_LIMIT = 32;
+       static final int V_SCROLL_LIMIT = 16;
+       static final int DRAG_IMAGE_SIZE = 301;
+       static boolean COMPRESS_ITEMS = true;
+       static final long TableProc;
+       static final TCHAR TableClass = new TCHAR (0, OS.WC_LISTVIEW, true);
+       static final TCHAR HeaderClass = new TCHAR (0, OS.WC_HEADER, true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, TableClass, lpWndClass);
+               TableProc = lpWndClass.lpfnWndProc;
+               OS.GetClassInfo (0, HeaderClass, lpWndClass);
+               HeaderProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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 Table (Composite parent, int style) {
+       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);
+                       break;
+       }
+}
+
+boolean _checkGrow (int count) {
+       //TODO - code could be shared but it would mix keyed and non-keyed logic
+       if (keys == null) {
+               if (count == 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.
+                       */
+                       boolean small = getDrawing () && 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;
+               }
+       } else {
+               //TODO - don't shrink when count is very small (ie. 2 or 4 elements)?
+               //TODO - why? if setItemCount(1000000) is used after a shrink, then we won't compress
+               //TODO - get rid of ignoreShrink?
+               if (!ignoreShrink && keyCount > count / 2) {
+                       boolean small = getDrawing () && OS.IsWindowVisible (handle);
+                       int length = small ? count + 4 : Math.max (4, count * 3 / 2);
+                       TableItem [] newItems = new TableItem [length];
+                       for (int i=0; i<keyCount; i++) {
+                               newItems [keys [i]] = items [i];
+                       }
+                       items = newItems;
+                       keys = null;
+                       keyCount = 0;
+                       return true;
+               } else {
+                       //TODO - grow by page size or screen height?
+                       //TODO - experiment to determine an optimal growth rate for keys
+                       if (keyCount == keys.length) {
+                               boolean small = getDrawing () && OS.IsWindowVisible (handle);
+                               int length = small ? keys.length + 4 : Math.max (4, keys.length * 3 / 2);
+                               int [] newKeys = new int [length];
+                               System.arraycopy (keys, 0, newKeys, 0, keys.length);
+                               keys = newKeys;
+                               TableItem [] newItems = new TableItem [length];
+                               System.arraycopy (items, 0, newItems, 0, items.length);
+                               items = newItems;
+                       }
+               }
+       }
+       return false;
+}
+
+void _checkShrink () {
+       //TODO - code could be shared but it would mix keyed and non-keyed logic
+       //TODO - move ignoreShrink test back to the caller
+       if (keys == null) {
+               if (!ignoreShrink) {
+                       /* Resize the item array to match the item count */
+                       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+
+                       /*
+                       * Bug in Windows. Call to OS.LVM_GETITEMCOUNT unexpectedly returns zero,
+                       * leading to a possible "ArrayIndexOutOfBoundsException: 4" in SWT table.
+                       * So, double check for any existing living items in the table and fixing
+                       * the count value. Refer bug 292199.
+                       */
+                       if (count == 0 && items.length > 4) {
+                               while (count<items.length && items[count] != null && !items[count].isDisposed()) {
+                                       count++;
+                               }
+                       }
+
+                       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;
+                       }
+               }
+       } else {
+               if (!ignoreShrink) {
+                       if (keys.length > 4 && keys.length - keyCount > 3) {
+                               int length = Math.max (4, (keyCount + 3) / 4 * 4);
+                               int [] newKeys = new int [length];
+                               System.arraycopy (keys, 0, newKeys, 0, keyCount);
+                               keys = newKeys;
+                               TableItem [] newItems = new TableItem [length];
+                               System.arraycopy (items, 0, newItems, 0, keyCount);
+                               items = newItems;
+                       }
+               }
+       }
+}
+
+void _clearItems () {
+       items = null;
+       keys = null;
+       keyCount = 0;
+}
+
+TableItem _getItem (int index) {
+       return _getItem (index, true);
+}
+
+//TODO - check senders who have count (watch methods that change the count)
+TableItem _getItem (int index, boolean create) {
+       return _getItem (index, create, -1);
+}
+
+TableItem _getItem (int index, boolean create, int count) {
+       //TODO - code could be shared but it would mix keyed and non-keyed logic
+       if (keys == null) {
+               if (index >= items.length) return null;
+               if ((style & SWT.VIRTUAL) == 0 || !create) return items [index];
+               if (items [index] != null) return items [index];
+               return items [index] = new TableItem (this, SWT.NONE, -1, false);
+       } else {
+               if ((style & SWT.VIRTUAL) == 0 || !create) {
+                       if (keyCount == 0) return null;
+                       if (index > keys [keyCount - 1]) return null;
+               }
+               int keyIndex = binarySearch (keys, 0, keyCount, index);
+               if ((style & SWT.VIRTUAL) == 0 || !create) {
+                       return keyIndex < 0 ? null : items [keyIndex];
+               }
+               if (keyIndex < 0) {
+                       if (count == -1) {
+                               count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+                       }
+                       //TODO - _checkGrow() doesn't return a value, check keys == null instead
+                       if (_checkGrow (count)) {
+                               if (items [index] != null) return items [index];
+                               return items [index] = new TableItem (this, SWT.NONE, -1, false);
+                       }
+                       keyIndex = -keyIndex - 1;
+                       if (keyIndex < keyCount) {
+                               System.arraycopy(keys, keyIndex, keys, keyIndex + 1, keyCount - keyIndex);
+                               System.arraycopy(items, keyIndex, items, keyIndex + 1, keyCount - keyIndex);
+                       }
+                       keyCount++;
+                       keys [keyIndex] = index;
+               } else {
+                       if (items [keyIndex] != null) return items [keyIndex];
+               }
+               return items [keyIndex] = new TableItem (this, SWT.NONE, -1, false);
+       }
+}
+
+void _getItems (TableItem [] result, int count) {
+       if (keys == null) {
+               System.arraycopy (items, 0, result, 0, count);
+       } else {
+               /* NOTE: Null items will be in the array when keyCount != count */
+               for (int i=0; i<keyCount; i++) {
+                       if (keys [i] >= count) break;
+                       result [keys [i]] = items [keys [i]];
+               }
+       }
+}
+
+boolean _hasItems () {
+       return items != null;
+}
+
+void _initItems () {
+       items = new TableItem [4];
+       if (COMPRESS_ITEMS) {
+               if ((style & SWT.VIRTUAL) != 0) {
+                       keyCount = 0;
+                       keys = new int [4];
+               }
+       }
+}
+
+/* NOTE: The array has already been grown to have space for the new item */
+void _insertItem (int index, TableItem item, int count) {
+       if (keys == null) {
+               System.arraycopy (items, index, items, index + 1, count - index);
+               items [index] = item;
+       } else {
+               int keyIndex = binarySearch (keys, 0, keyCount, index);
+               if (keyIndex < 0) keyIndex = -keyIndex - 1;
+               System.arraycopy(keys, keyIndex, keys, keyIndex + 1, keyCount - keyIndex);
+               keys [keyIndex] = index;
+               System.arraycopy(items, keyIndex, items, keyIndex + 1, keyCount - keyIndex);
+               items [keyIndex] = item;
+               keyCount++;
+               for (int i=keyIndex + 1; i<keyCount; i++) keys[i]++;
+       }
+}
+
+void _removeItem (int index, int count) {
+       if (keys == null) {
+               System.arraycopy (items, index + 1, items, index, --count - index);
+               items [count] = null;
+       } else {
+               int keyIndex = binarySearch (keys, 0, keyCount, index);
+               if (keyIndex < 0) {
+                       keyIndex = -keyIndex - 1;
+               } else {
+                       --keyCount;
+                       System.arraycopy (keys, keyIndex + 1, keys, keyIndex, keyCount - keyIndex);
+                       keys [keyCount] = 0;
+                       System.arraycopy (items, keyIndex + 1, items, keyIndex, keyCount - keyIndex);
+                       items [keyCount] = null;
+               }
+               for (int i=keyIndex; i<keyCount; i++) --keys[i];
+       }
+}
+
+/* NOTE: Removes from start to index - 1 */
+void _removeItems (int start, int index, int count) {
+       if (keys == null) {
+               System.arraycopy (items, index, items, start, count - index);
+               for (int i=count-(index-start); i<count; i++) items [i] = null;
+       } else {
+               int end = index;
+               int left = binarySearch (keys, 0, keyCount, start);
+               if (left < 0) left = -left - 1;
+               int right = binarySearch (keys, left, keyCount, end);
+               if (right < 0) right = -right - 1;
+               //TODO - optimize when left and right are the same
+               System.arraycopy (keys, right, keys, left, keyCount - right);
+               for (int i=keyCount-(right-left); i<keyCount; i++) keys [i] = 0;
+               System.arraycopy (items, right, items, left, keyCount - right);
+               for (int i=keyCount-(right-left); i<keyCount; i++) items [i] = null;
+               keyCount -= (right - left);
+               for (int i=left; i<keyCount; i++) keys[i] -= (right - left);
+       }
+}
+
+void _setItemCount (int count, int itemCount) {
+       if (keys == null) {
+               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;
+       } else {
+               int index = Math.min (count, itemCount);
+               keyCount = binarySearch (keys, 0, keyCount, index);
+               if (keyCount < 0) keyCount = -keyCount - 1;
+               int length = Math.max (4, (keyCount + 3) / 4 * 4);
+               int [] newKeys = new int [length];
+               System.arraycopy (keys, 0, newKeys, 0, keyCount);
+               keys = newKeys;
+               TableItem [] newItems = new TableItem [length];
+               System.arraycopy (items, 0, newItems, 0, keyCount);
+               items = newItems;
+       }
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       return callWindowProc (hwnd, msg, wParam, lParam, false);
+}
+
+long callWindowProc (long hwnd, int msg, long wParam, long lParam, boolean forceSelect) {
+       if (handle == 0) return 0;
+       if (hwndHeader != 0 && hwnd == hwndHeader) {
+               return OS.CallWindowProc (HeaderProc, hwnd, msg, wParam, lParam);
+       }
+       int topIndex = 0;
+       boolean 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 () != null && getDrawing () && 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 () != null) {
+                               topIndex = (int)OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+                       }
+               }
+       }
+       boolean 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.
+       */
+       boolean fixPaint = false;
+       if (msg == OS.WM_PAINT) {
+               int bits0 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits0 & OS.LVS_NOCOLUMNHEADER) == 0) {
+                       long hwndParent = OS.GetParent (handle), hwndOwner = 0;
+                       while (hwndParent != 0) {
+                               int bits1 = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                               if ((bits1 & OS.WS_EX_COMPOSITED) != 0) {
+                                       fixPaint = true;
+                                       break;
+                               }
+                               hwndOwner = OS.GetWindow (hwndParent, OS.GW_OWNER);
+                               if (hwndOwner != 0) break;
+                               hwndParent = OS.GetParent (hwndParent);
+                       }
+               }
+       }
+
+       /* Remove the scroll bars that Windows keeps automatically adding */
+       boolean fixScroll = false;
+       if ((style & SWT.H_SCROLL) == 0 || (style & SWT.V_SCROLL) == 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) == 0 && (bits & OS.WS_HSCROLL) != 0) {
+                                       fixScroll = true;
+                                       bits &= ~OS.WS_HSCROLL;
+                               }
+                               if ((style & SWT.V_SCROLL) == 0 && (bits & OS.WS_VSCROLL) != 0) {
+                                       fixScroll = true;
+                                       bits &= ~OS.WS_VSCROLL;
+                               }
+                               if (fixScroll) OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+                       }
+               }
+       }
+       long code = 0;
+       if (fixPaint) {
+               PAINTSTRUCT ps = new PAINTSTRUCT ();
+               long hDC = OS.BeginPaint (hwnd, ps);
+               code = OS.CallWindowProc (TableProc, hwnd, OS.WM_PAINT, 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, 0, flags);
+       }
+
+       if (checkActivate) ignoreActivate = false;
+       if (checkSelection) {
+               if (wasSelected || forceSelect) {
+                       Event event = new Event ();
+                       int index = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+                       if (index != -1) event.item = _getItem (index);
+                       sendSelectionEvent (SWT.Selection, event, false);
+               }
+               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);
+                               long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                               if (hwndHeader != 0) 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 () != null) {
+                               if (topIndex != OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) {
+                                       OS.InvalidateRect (handle, null, true);
+                               }
+                       }
+                       break;
+               }
+
+               case OS.WM_PAINT:
+                       painted = true;
+                       break;
+       }
+       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) == 0) {
+               style |= SWT.H_SCROLL | SWT.V_SCROLL;
+       }
+       return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+LRESULT CDDS_ITEMPOSTPAINT (NMLVCUSTOMDRAW nmcd, long wParam, long lParam) {
+       long hDC = nmcd.hdc;
+       if (explorerTheme && !ignoreCustomDraw) {
+               hotIndex = -1;
+               if (hooks (SWT.EraseItem) && nmcd.left != nmcd.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.left != nmcd.right) {
+               if (OS.IsWindowVisible (handle) && OS.IsWindowEnabled (handle)) {
+                       if (!explorerTheme && (style & SWT.FULL_SELECTION) != 0) {
+                               if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) == OS.CLR_NONE) {
+                                       int dwExStyle = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                                       if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) == 0) {
+//                                             if ((nmcd.uItemState & OS.CDIS_FOCUS) != 0) {
+                                               if (OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED) == nmcd.dwItemSpec) {
+                                                       if (handle == OS.GetFocus ()) {
+                                                               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                                                               if ((uiState & OS.UISF_HIDEFOCUS) == 0) {
+                                                                       RECT rect = new RECT ();
+                                                                       rect.left = OS.LVIR_BOUNDS;
+                                                                       boolean oldIgnore = ignoreCustomDraw;
+                                                                       ignoreCustomDraw = true;
+                                                                       OS.SendMessage (handle, OS. LVM_GETITEMRECT, nmcd.dwItemSpec, rect);
+                                                                       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                                                                       int index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+                                                                       RECT itemRect = new RECT ();
+                                                                       if (index == 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.dwItemSpec, itemRect);
+                                                                       }
+                                                                       ignoreCustomDraw = oldIgnore;
+                                                                       rect.left = itemRect.left;
+                                                                       OS.DrawFocusRect (nmcd.hdc, rect);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return null;
+}
+
+LRESULT CDDS_ITEMPREPAINT (NMLVCUSTOMDRAW nmcd, long wParam, long 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) != 0) {
+                               if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) == OS.CLR_NONE) {
+                                       int dwExStyle = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                                       if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) == 0) {
+                                               if ((nmcd.uItemState & OS.CDIS_FOCUS) != 0) {
+                                                       nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                                                       OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       if (explorerTheme && !ignoreCustomDraw) {
+               hotIndex = (nmcd.uItemState & OS.CDIS_HOT) != 0 ? (int)nmcd.dwItemSpec : -1;
+               if (hooks (SWT.EraseItem) && nmcd.left != nmcd.right) {
+                       OS.SaveDC (nmcd.hdc);
+                       long hrgn = OS.CreateRectRgn (0, 0, 0, 0);
+                       OS.SelectClipRgn (nmcd.hdc, hrgn);
+                       OS.DeleteObject (hrgn);
+               }
+       }
+       return new LRESULT (OS.CDRF_NOTIFYSUBITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+}
+
+LRESULT CDDS_POSTPAINT (NMLVCUSTOMDRAW nmcd, long wParam, long 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 == 0 && OS.IsWindowVisible (handle)) {
+               if (!explorerTheme && (style & SWT.FULL_SELECTION) != 0) {
+                       if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) == OS.CLR_NONE) {
+                               int dwExStyle = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                               if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) == 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.
+                                       */
+                                       long hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, 0, 0);
+                                       long 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 != 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, long wParam, long 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++ == 0 && OS.IsWindowVisible (handle)) {
+               if (!explorerTheme && (style & SWT.FULL_SELECTION) != 0) {
+                       if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) == OS.CLR_NONE) {
+                               int dwExStyle = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                               if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) != 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.
+                                       */
+                                       long hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, 0, 0);
+                                       long 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 != 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)) {
+               /*
+               * 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.
+               */
+               RECT rect = new RECT ();
+               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+               if (explorerTheme && columnCount == 0) {
+                       long hDC = nmcd.hdc;
+                       if (OS.IsWindowEnabled (handle) || findImageControl () != null) {
+                               drawBackground (hDC, rect);
+                       } else {
+                               fillBackground (hDC, OS.GetSysColor (OS.COLOR_3DFACE), rect);
+                       }
+               } else {
+                       Control control = findBackgroundControl ();
+                       if (control != null && control.backgroundImage != null) {
+                               fillImageBackground (nmcd.hdc, control, rect, 0, 0);
+                       } else {
+                               final boolean enabled = OS.IsWindowEnabled (handle);
+                               if (enabled && (int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) == OS.CLR_NONE || !enabled && hasCustomBackground()) {
+                                       if (control == null) control = this;
+                                       fillBackground (nmcd.hdc, control.getBackgroundPixel (), rect);
+                                       if (OS.IsAppThemed ()) {
+                                               if (sortColumn != null && sortDirection != SWT.NONE) {
+                                                       int index = indexOf (sortColumn);
+                                                       if (index != -1) {
+                                                               parent.forceResize ();
+                                                               int clrSortBk = getSortColumnPixel ();
+                                                               RECT columnRect = new RECT (), headerRect = new RECT ();
+                                                               OS.GetClientRect (handle, columnRect);
+                                                               long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                                                               if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect) != 0) {
+                                                                       OS.MapWindowPoints (hwndHeader, handle, headerRect, 2);
+                                                                       columnRect.left = headerRect.left;
+                                                                       columnRect.right = headerRect.right;
+                                                                       if (OS.IntersectRect(columnRect, columnRect, rect)) {
+                                                                               fillBackground (nmcd.hdc, clrSortBk, columnRect);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+}
+
+LRESULT CDDS_SUBITEMPOSTPAINT (NMLVCUSTOMDRAW nmcd, long wParam, long lParam) {
+       if (ignoreCustomDraw) return null;
+       if (nmcd.left == nmcd.right) return new LRESULT (OS.CDRF_DODEFAULT);
+       long hDC = 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.
+               *
+               * Update region is saved and restored around LVM_SETSELECTEDCOLUMN
+               * to prevent infinite WM_PAINT on Vista.
+               */
+               if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) != OS.CLR_NONE) {
+                       if ((sortDirection & (SWT.UP | SWT.DOWN)) != 0) {
+                               if (sortColumn != null && !sortColumn.isDisposed ()) {
+                                       int oldColumn = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+                                       if (oldColumn == -1) {
+                                               int newColumn = indexOf (sortColumn);
+                                               long rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                                               int result = OS.GetUpdateRgn (handle, rgn, true);
+                                               OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, newColumn, 0);
+                                               OS.ValidateRect (handle, null);
+                                               if (result != OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true);
+                                               OS.DeleteObject (rgn);
+                                       }
+                               }
+                       }
+               }
+               if (hooks (SWT.PaintItem)) {
+                       TableItem item = _getItem ((int)nmcd.dwItemSpec);
+                       sendPaintItemEvent (item, nmcd);
+                       //widget could be disposed at this point
+               }
+               if (!ignoreDrawFocus && focusRect != null) {
+                       OS.SetTextColor (nmcd.hdc, 0);
+                       OS.SetBkColor (nmcd.hdc, 0xFFFFFF);
+                       OS.DrawFocusRect (nmcd.hdc, focusRect);
+                       focusRect = null;
+               }
+       }
+       return null;
+}
+
+LRESULT CDDS_SUBITEMPREPAINT (NMLVCUSTOMDRAW nmcd, long wParam, long lParam) {
+       long hDC = nmcd.hdc;
+       if (explorerTheme && !ignoreCustomDraw && hooks (SWT.EraseItem) && (nmcd.left != nmcd.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.
+       *
+       * NOTE: Force the item to be created if it does not exist.
+       */
+       TableItem item = _getItem ((int)nmcd.dwItemSpec);
+       if (item == null || item.isDisposed ()) return null;
+       long hFont = item.fontHandle (nmcd.iSubItem);
+       if (hFont != -1) OS.SelectObject (hDC, hFont);
+       if (ignoreCustomDraw || (nmcd.left == nmcd.right)) {
+               return new LRESULT (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, (int)nmcd.dwItemSpec, nmcd.iSubItem, 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 != null ? item.cellForeground [nmcd.iSubItem] : -1;
+       if (clrText == -1) clrText = item.foreground;
+       int clrTextBk = item.cellBackground != null ? item.cellBackground [nmcd.iSubItem] : -1;
+       if (clrTextBk == -1) clrTextBk = item.background;
+       if (selectionForeground != -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.
+       */
+       final boolean enabled = OS.IsWindowEnabled (handle);
+       if (OS.IsWindowVisible (handle) && enabled) {
+               if (!explorerTheme && !ignoreDrawSelection && (style & SWT.FULL_SELECTION) != 0) {
+                       int bits = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                       if ((bits & OS.LVS_EX_FULLROWSELECT) == 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 = new LVITEM ();
+                               lvItem.mask = OS.LVIF_STATE;
+                               lvItem.stateMask = OS.LVIS_SELECTED;
+                               lvItem.iItem = (int)nmcd.dwItemSpec;
+                               long result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem);
+                               if ((result != 0 && (lvItem.state & OS.LVIS_SELECTED) != 0)) {
+                                       int clrSelection = -1;
+                                       if (nmcd.iSubItem == 0) {
+                                               if (OS.GetFocus () == handle || display.getHighContrast ()) {
+                                                       clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+                                               } else {
+                                                       if ((style & SWT.HIDE_SELECTION) == 0) {
+                                                               clrSelection = OS.GetSysColor (OS.COLOR_3DFACE);
+                                                       }
+                                               }
+                                       } else {
+                                               if (OS.GetFocus () == handle || display.getHighContrast ()) {
+                                                       clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+                                                       clrTextBk = clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+                                               } else {
+                                                       if ((style & SWT.HIDE_SELECTION) == 0) {
+                                                               clrTextBk = clrSelection = OS.GetSysColor (OS.COLOR_3DFACE);
+                                                       }
+                                               }
+                                       }
+                                       if (clrSelection != -1) {
+                                               RECT rect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, nmcd.iSubItem != 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.
+               */
+               boolean hasAttributes = true;
+               if (hFont == -1 && clrText == -1 && clrTextBk == -1) {
+                       if (item.cellForeground == null && item.cellBackground == null && item.cellFont == null) {
+                               int count = (int)OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+                               if (count == 1) hasAttributes = false;
+                       }
+               }
+               if (hasAttributes) {
+                       if (hFont == -1) hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                       OS.SelectObject (hDC, hFont);
+                       if (enabled) {
+                               nmcd.clrText = clrText == -1 ? getForegroundPixel () : clrText;
+                               if (clrTextBk == -1) {
+                                       nmcd.clrTextBk = OS.CLR_NONE;
+                                       if (selectionForeground == -1) {
+                                               Control control = findBackgroundControl ();
+                                               if (control == null) control = this;
+                                               if (control.backgroundImage == null) {
+                                                       if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) != OS.CLR_NONE) {
+                                                               nmcd.clrTextBk = control.getBackgroundPixel ();
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       nmcd.clrTextBk = selectionForeground != -1 ? OS.CLR_NONE : clrTextBk;
+                               }
+                               OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+                       }
+                       code |= OS.CDRF_NEWFONT;
+               }
+       }
+       /*
+       * 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.
+       *
+       * Update region is saved and restored around LVM_SETSELECTEDCOLUMN
+       * to prevent infinite WM_PAINT on Vista.
+       */
+       if ((enabled && clrTextBk != -1) || (!enabled && hasCustomBackground())) {
+               int oldColumn = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+               if (oldColumn != -1 && oldColumn == nmcd.iSubItem) {
+                       long rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                       int result = OS.GetUpdateRgn (handle, rgn, true);
+                       OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, -1, 0);
+                       OS.ValidateRect (handle, null);
+                       if (result != OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true);
+                       OS.DeleteObject (rgn);
+                       code |= OS.CDRF_NOTIFYPOSTPAINT;
+               }
+       }
+       if (!enabled) {
+               /*
+               * 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, but only, when it wasn't customized.
+               */
+               nmcd.clrText = OS.GetSysColor (OS.COLOR_GRAYTEXT);
+               if (findImageControl () != null || hasCustomBackground()) {
+                       nmcd.clrTextBk = OS.CLR_NONE;
+               }
+               nmcd.uItemState &= ~OS.CDIS_SELECTED;
+               OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+               code |= OS.CDRF_NEWFONT;
+       }
+       return new LRESULT (code);
+}
+
+@Override
+void checkBuffered () {
+       super.checkBuffered ();
+       style |= SWT.DOUBLE_BUFFERED;
+}
+
+boolean checkData (TableItem item, boolean redraw) {
+       if ((style & SWT.VIRTUAL) == 0) return true;
+       return checkData (item, indexOf (item), redraw);
+}
+
+boolean checkData (TableItem item, int index, boolean redraw) {
+       if ((style & SWT.VIRTUAL) == 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
+boolean checkHandle (long hwnd) {
+       if (hwnd == handle) return true;
+       return 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+       TableItem item = _getItem (index, false);
+       if (item != null) {
+               if (item != 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) == 0 && item.cached) {
+                       LVITEM lvItem = new 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 == null && getDrawing () && 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= start && start <= end && end < count)) {
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       if (start == 0 && end == count - 1) {
+               clearAll ();
+       } else {
+               LVITEM lvItem = null;
+               boolean cleared = false;
+               for (int i=start; i<=end; i++) {
+                       TableItem item = _getItem (i, false);
+                       if (item != null) {
+                               if (item != 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) == 0 && item.cached) {
+                                       if (lvItem == 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 == null && getDrawing () && OS.IsWindowVisible (handle)) {
+                               OS.SendMessage (handle, OS.LVM_REDRAWITEMS, start, end);
+                       }
+                       TableItem item = start == end ? _getItem (start, false) : 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>
+ *    <li>ERROR_NULL_ARGUMENT - if the indices 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>
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (indices.length == 0) return;
+       int count = (int)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 = null;
+       boolean cleared = false;
+       for (int i=0; i<indices.length; i++) {
+               int index = indices [i];
+               TableItem item = _getItem (index, false);
+               if (item != null) {
+                       if (item != 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) == 0 && item.cached) {
+                               if (lvItem == 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 == null && getDrawing () && 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 = null;
+       boolean cleared = false;
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       for (int i=0; i<count; i++) {
+               TableItem item = _getItem (i, false);
+               if (item != null) {
+                       if (item != 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) == 0 && item.cached) {
+                               if (lvItem == 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 == null && getDrawing () && OS.IsWindowVisible (handle)) {
+                       OS.SendMessage (handle, OS.LVM_REDRAWITEMS, 0, count - 1);
+               }
+               setScrollWidth (null, false);
+       }
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       if (fixScrollWidth) setScrollWidth (null, true);
+       //This code is intentionally commented
+//     if (itemHeight == -1 && hooks (SWT.MeasureItem)) {
+//             int i = 0;
+//             TableItem item = items [i];
+//             if (item != null) {
+//                     int hDC = OS.GetDC (handle);
+//                     int oldFont = 0, newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+//                     if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+//                     int index = 0, count = Math.max (1, columnCount);
+//                     while (index < count) {
+//                             int hFont = item.cellFont != null ? item.cellFont [index] : -1;
+//                             if (hFont == -1) hFont = item.font;
+//                             if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+//                             sendMeasureItemEvent (item, i, index, hDC);
+//                             if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+//                             if (isDisposed () || item.isDisposed ()) break;
+//                             index++;
+//                     }
+//                     if (newFont != 0) OS.SelectObject (hDC, oldFont);
+//                     OS.ReleaseDC (handle, hDC);
+//             }
+//     }
+       RECT rect = new RECT ();
+       OS.GetWindowRect (hwndHeader, rect);
+       int height = rect.bottom - rect.top;
+       int bits = 0;
+       if (wHint != SWT.DEFAULT) {
+               bits |= wHint & 0xFFFF;
+       } else {
+               int width = 0;
+               int count = (int)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;
+       }
+       long result = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, -1, OS.MAKELPARAM (bits, 0xFFFF));
+       int width = OS.LOWORD (result);
+       long empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+       long oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+       int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty);
+       height += (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0) * itemHeight;
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int border = getBorderWidthInPixels ();
+       width += border * 2;  height += border * 2;
+       if ((style & SWT.V_SCROLL) != 0) {
+               width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+       }
+       if ((style & SWT.H_SCROLL) != 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 (OS.IsAppThemed ()) {
+               explorerTheme = true;
+               OS.SetWindowTheme (handle, Display.EXPLORER, null);
+       }
+
+       /* Get the header window handle */
+       hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 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) != 0) {
+               long empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+               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.
+       */
+       long 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 = new LVCOLUMN ();
+       lvColumn.mask = OS.LVCF_TEXT | OS.LVCF_WIDTH;
+       long hHeap = OS.GetProcessHeap ();
+       long pszText = 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 | OS.LVS_EX_DOUBLEBUFFER;
+       if ((style & SWT.FULL_SELECTION) != 0) bits1 |= OS.LVS_EX_FULLROWSELECT;
+       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.
+       */
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+               int bits2 = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE);
+               OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_LAYOUTRTL);
+               long hwndTooltop = 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);
+       }
+}
+
+@Override
+int applyThemeBackground () {
+       /*
+        * Just inheriting the THEME_BACKGROUND doesn't turn complete Table
+        * background transparent, TableItem background remains as-is.
+        */
+       return -1; /* No Change */
+}
+
+void createHeaderToolTips () {
+       if (headerToolTipHandle != 0) return;
+       int bits = 0;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL;
+       headerToolTipHandle = OS.CreateWindowEx (
+               bits,
+               new TCHAR (0, OS.TOOLTIPS_CLASS, true),
+               null,
+               OS.TTS_NOPREFIX,
+               OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+               handle,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (headerToolTipHandle == 0) 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 = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+       if (oldColumn >= index) {
+               OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, oldColumn + 1, 0);
+       }
+       if (columnCount == columns.length) {
+               TableColumn [] newColumns = new TableColumn [columns.length + 4];
+               System.arraycopy (columns, 0, newColumns, 0, columns.length);
+               columns = newColumns;
+       }
+       int itemCount = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       for (int i=0; i<itemCount; i++) {
+               TableItem item = _getItem (i, false);
+               if (item != null) {
+                       String [] strings = item.strings;
+                       if (strings != 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 != 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 == 0) {
+                               if (columnCount != 0) {
+                                       if (strings == null) {
+                                               item.strings = new String [columnCount + 1];
+                                               item.strings [1] = item.text;
+                                       }
+                                       item.text = ""; //$NON-NLS-1$
+                                       if (images == null) {
+                                               item.images = new Image [columnCount + 1];
+                                               item.images [1] = item.image;
+                                       }
+                                       item.image = null;
+                               }
+                       }
+                       if (item.cellBackground != 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 != 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 != 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 == 0) {
+               if (columnCount > 1) {
+                       LVCOLUMN lvColumn = new 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;
+                       long hHeap = OS.GetProcessHeap ();
+                       int byteCount = cchTextMax * TCHAR.sizeof;
+                       long pszText = 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 = 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 != 0) 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) == 0) {
+                       LVITEM lvItem = new 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) == SWT.CENTER) fmt = OS.LVCFMT_CENTER;
+               if ((column.style & SWT.RIGHT) == SWT.RIGHT) fmt = OS.LVCFMT_RIGHT;
+               LVCOLUMN lvColumn = new 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 != 0) {
+               RECT rect = new RECT ();
+               if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, rect) != 0) {
+                       TOOLINFO lpti = new TOOLINFO ();
+                       lpti.cbSize = TOOLINFO.sizeof;
+                       lpti.uFlags = OS.TTF_SUBCLASS;
+                       lpti.hwnd = hwndHeader;
+                       lpti.uId = column.id = display.nextToolTipId++;
+                       lpti.left = rect.left;
+                       lpti.top = rect.top;
+                       lpti.right = rect.right;
+                       lpti.bottom = rect.bottom;
+                       lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+                       OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+}
+
+void createItem (TableItem item, int index) {
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+       _checkGrow (count);
+       LVITEM lvItem = new 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 = (int)OS.SendMessage (handle, OS.LVM_INSERTITEM, 0, lvItem);
+       ignoreSelect = ignoreShrink = false;
+       if (result == -1) error (SWT.ERROR_ITEM_NOT_ADDED);
+       _insertItem (index, item, count);
+       setDeferResize (false);
+
+       /* Resize to show the first item */
+       if (count == 0) setScrollWidth (item, false);
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       itemHeight = hotIndex = -1;
+       _initItems ();
+       columns = new TableColumn [4];
+}
+
+private boolean customHeaderDrawing() {
+       return headerBackground != -1 || headerForeground != -1;
+}
+
+@Override
+int defaultBackground () {
+       return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+@Override
+void deregister () {
+       super.deregister ();
+       if (hwndHeader != 0) 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselect (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (indices.length == 0) return;
+       LVITEM lvItem = new 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 = new 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (start == 0 && end == count - 1) {
+               deselectAll ();
+       } else {
+               LVITEM lvItem = new 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 = new 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] == column) break;
+               index++;
+       }
+       int oldColumn = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+       if (oldColumn == 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);
+       while (orderIndex < columnCount) {
+               if (oldOrder [orderIndex] == index) break;
+               orderIndex++;
+       }
+       ignoreColumnResize = true;
+       boolean first = false;
+       if (index == 0) {
+               first = true;
+               /*
+               * Changing the content of a column using LVM_SETCOLUMN causes
+               * the table control to send paint events. At this point the
+               * partially disposed column is still part of the table and
+               * paint handler can try to access it. This can cause exceptions.
+               * The fix is to turn redraw off.
+               */
+               setRedraw (false);
+               if (columnCount > 1) {
+                       index = 1;
+                       int cchTextMax = 1024;
+                       long hHeap = OS.GetProcessHeap ();
+                       int byteCount = cchTextMax * TCHAR.sizeof;
+                       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                       LVCOLUMN lvColumn = new 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 != 0) OS.HeapFree (hHeap, 0, pszText);
+               } else {
+                       long hHeap = OS.GetProcessHeap ();
+                       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+                       LVCOLUMN lvColumn = new 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 != 0) OS.HeapFree (hHeap, 0, pszText);
+                       HDITEM hdItem = new HDITEM ();
+                       hdItem.mask = OS.HDI_FORMAT;
+                       hdItem.fmt = OS.HDF_LEFT;
+                       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                       OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, hdItem);
+               }
+               setRedraw (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 ((style & SWT.VIRTUAL) == 0) {
+                       LVITEM lvItem = new LVITEM ();
+                       lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE;
+                       lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                       lvItem.iImage = OS.I_IMAGECALLBACK;
+                       int itemCount = (int)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) == 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       for (int i=0; i<itemCount; i++) {
+               TableItem item = _getItem (i, false);
+               if (item != null) {
+                       if (columnCount == 0) {
+                               item.strings = null;
+                               item.images = null;
+                               item.cellBackground = null;
+                               item.cellForeground = null;
+                               item.cellFont = null;
+                       } else {
+                               if (item.strings != null) {
+                                       String [] strings = item.strings;
+                                       if (index == 0) {
+                                               item.text = strings [1] != 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 == 0) item.text = ""; //$NON-NLS-1$
+                               }
+                               if (item.images != null) {
+                                       Image [] images = item.images;
+                                       if (index == 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 == 0) item.image = null;
+                               }
+                               if (item.cellBackground != 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 != 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 != 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 == 0) setScrollWidth (null, true);
+       updateMoveable ();
+       ignoreColumnResize = false;
+       if (columnCount != 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] != oldIndex) {
+                               int newIndex = oldOrder [i] <= oldIndex ? oldOrder [i] : oldOrder [i] - 1;
+                               newOrder [count++] = newIndex;
+                       }
+               }
+               OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, oldOrder);
+               int j = 0;
+               while (j < newOrder.length) {
+                       if (oldOrder [j] != newOrder [j]) break;
+                       j++;
+               }
+               if (j != newOrder.length) {
+                       OS.SendMessage (handle, OS.LVM_SETCOLUMNORDERARRAY, newOrder.length, newOrder);
+                       /*
+                       * 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 != 0) {
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = TOOLINFO.sizeof;
+               lpti.uId = column.id;
+               lpti.hwnd = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+               OS.SendMessage (headerToolTipHandle, OS.TTM_DELTOOL, 0, lpti);
+       }
+}
+
+void destroyItem (TableItem item) {
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       int index = 0;
+       while (index < count) {
+               if (_getItem (index, false) == item) break;
+               index++;
+       }
+       if (index == count) return;
+       setDeferResize (true);
+       ignoreSelect = ignoreShrink = true;
+       long code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+       ignoreSelect = ignoreShrink = false;
+       if (code == 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+       _removeItem (index, count);
+       --count;
+       if (count == 0) setTableEmpty ();
+       setDeferResize (false);
+}
+
+void fixCheckboxImageList (boolean 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) == 0) return;
+       long hImageList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+       if (hImageList == 0) return;
+       int [] cx = new int [1], cy = new int [1];
+       OS.ImageList_GetIconSize (hImageList, cx, cy);
+       long hStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+       if (hStateList == 0) return;
+       int [] stateCx = new int [1], stateCy = new int [1];
+       OS.ImageList_GetIconSize (hStateList, stateCx, stateCy);
+       if (cx [0] == stateCx [0] && cy [0] == stateCy [0]) return;
+       setCheckboxImageList (cx [0], cy [0], fixScroll);
+}
+
+void fixCheckboxImageListColor (boolean fixScroll) {
+       if ((style & SWT.CHECK) == 0) return;
+       long hStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+       if (hStateList == 0) return;
+       int [] cx = new int [1], cy = new int [1];
+       OS.ImageList_GetIconSize (hStateList, cx, cy);
+       setCheckboxImageList (cx [0], cy [0], fixScroll);
+}
+
+/**
+ * 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(boolean)
+ * @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(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public int[] getColumnOrder () {
+       checkWidget ();
+       if (columnCount == 0) return new int [0];
+       int [] order = new int [columnCount];
+       OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order);
+       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(boolean)
+ * @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 (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+}
+
+/**
+ * Returns the width in points of a grid line.
+ *
+ * @return the width of a grid line in points
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if 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 DPIUtil.autoScaleDown(getGridLineWidthInPixels());
+}
+
+int getGridLineWidthInPixels () {
+       return GRID_WIDTH;
+}
+
+/**
+ * Returns the header background color.
+ *
+ * @return the receiver's header 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.106
+ */
+public Color getHeaderBackground () {
+       checkWidget ();
+       return Color.win32_new (display, getHeaderBackgroundPixel());
+}
+
+private int getHeaderBackgroundPixel() {
+       return headerBackground != -1 ? headerBackground : defaultBackground();
+}
+
+/**
+ * Returns the header foreground color.
+ *
+ * @return the receiver's header 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.106
+ */
+public Color getHeaderForeground () {
+       checkWidget ();
+       return Color.win32_new (display, getHeaderForegroundPixel());
+}
+
+private int getHeaderForegroundPixel() {
+       return headerForeground != -1 ? headerForeground : defaultForeground();
+}
+
+/**
+ * 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 ();
+       return DPIUtil.autoScaleDown(getHeaderHeightInPixels ());
+}
+
+int getHeaderHeightInPixels () {
+       if (hwndHeader == 0) return 0;
+       RECT rect = new 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 boolean getHeaderVisible () {
+       checkWidget ();
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       return (bits & OS.LVS_NOCOLUMNHEADER) == 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 = (int)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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       return getItemInPixels (DPIUtil.autoScaleUp(point));
+}
+
+TableItem getItemInPixels (Point point) {
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (count == 0) return null;
+       LVHITTESTINFO pinfo = new LVHITTESTINFO ();
+       pinfo.x = point.x;
+       pinfo.y = point.y;
+       if ((style & SWT.FULL_SELECTION) == 0) {
+               if (hooks (SWT.MeasureItem)) {
+                       /*
+                       *  Bug in Windows.  When LVM_SUBITEMHITTEST is used to hittest
+                       *  a point that is above the table, instead of returning -1 to
+                       *  indicate that the hittest failed, a negative index is returned.
+                       *  The fix is to consider any value that is negative a failure.
+                       */
+                       if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, pinfo) < 0) {
+                               RECT rect = new RECT ();
+                               rect.left = OS.LVIR_ICON;
+                               ignoreCustomDraw = true;
+                               long code = OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, rect);
+                               ignoreCustomDraw = false;
+                               if (code != 0) {
+                                       pinfo.x = rect.left;
+                                       /*
+                                       *  Bug in Windows.  When LVM_SUBITEMHITTEST is used to hittest
+                                       *  a point that is above the table, instead of returning -1 to
+                                       *  indicate that the hittest failed, a negative index is returned.
+                                       *  The fix is to consider any value that is negative a failure.
+                                       */
+                                       OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, pinfo);
+                                       if (pinfo.iItem < 0) pinfo.iItem = -1;
+                               }
+                       }
+                       if (pinfo.iItem != -1 && pinfo.iSubItem == 0) {
+                               if (hitTestSelection (pinfo.iItem, pinfo.x, pinfo.y)) {
+                                       return _getItem (pinfo.iItem);
+                               }
+                       }
+                       return null;
+               }
+       }
+       OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+       if (pinfo.iItem != -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 == 0) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.LVS_NOCOLUMNHEADER) == 0) {
+                               if (hwndHeader != 0) {
+                                       RECT rect = new RECT ();
+                                       OS.GetWindowRect (hwndHeader, rect);
+                                       POINT pt = new POINT ();
+                                       pt.x = pinfo.x;
+                                       pt.y = pinfo.y;
+                                       OS.MapWindowPoints (handle, 0, 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 (int)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 ();
+       return DPIUtil.autoScaleDown(getItemHeightInPixels());
+}
+
+int getItemHeightInPixels () {
+       if (!painted && hooks (SWT.MeasureItem)) hitTestSelection (0, 0, 0);
+       long empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+       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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       TableItem [] result = new TableItem [count];
+       if ((style & SWT.VIRTUAL) != 0) {
+               for (int i=0; i<count; i++) {
+                       result [i] = _getItem (i);
+               }
+       } else {
+               _getItems (result, count);
+       }
+       return result;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's lines are visible,
+ * and <code>false</code> otherwise. Note that some platforms draw
+ * grid lines while others may draw alternating row colors.
+ * <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 boolean getLinesVisible () {
+       checkWidget ();
+       return _getLinesVisible();
+}
+
+private boolean _getLinesVisible() {
+       int bits = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+       return (bits & OS.LVS_EX_GRIDLINES) != 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 = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+       TableItem [] result = new TableItem [count];
+       while ((i = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, i, OS.LVNI_SELECTED)) != -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 (int)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 = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+       int selectedIndex = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_SELECTED);
+       if (focusIndex == selectedIndex) return selectedIndex;
+       int i = -1;
+       while ((i = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, i, OS.LVNI_SELECTED)) != -1) {
+               if (i == 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 = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+       int [] result = new int [count];
+       while ((i = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, i, OS.LVNI_SELECTED)) != -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) || hasCustomBackground() ? getBackgroundPixel () : OS.GetSysColor (OS.COLOR_3DFACE);
+       return getSlightlyDifferentBackgroundColor(pixel);
+}
+
+/**
+ * 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, (int)OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0));
+}
+
+boolean hasChildren () {
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               if (hwndChild != hwndHeader) return true;
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       return false;
+}
+
+boolean hitTestSelection (int index, int x, int y) {
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (count == 0) return false;
+       if (!hooks (SWT.MeasureItem)) return false;
+       boolean result = false;
+       if (0 <= index && index < count) {
+               TableItem item = _getItem (index);
+               long hDC = OS.GetDC (handle);
+               long oldFont = 0, newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               long hFont = item.fontHandle (0);
+               if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+               Event event = sendMeasureItemEvent (item, index, 0, hDC);
+               if (event.getBoundsInPixels ().contains (x, y)) result = true;
+               if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+//             if (isDisposed () || item.isDisposed ()) return false;
+       }
+       return result;
+}
+
+int imageIndex (Image image, int column) {
+       if (image == null) return OS.I_IMAGENONE;
+       if (column == 0) {
+               firstColumnImage = true;
+       } else {
+               setSubImagesVisible (true);
+       }
+       if (imageList == null) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+               int index = imageList.indexOf (image);
+               if (index == -1) index = imageList.add (image);
+               long 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 != 0) {
+                       setRedraw (false);
+                       setTopIndex (0);
+               }
+               OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+               if (headerImageList != null) {
+                       long hHeaderImageList = headerImageList.getHandle ();
+                       OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hHeaderImageList);
+               }
+               fixCheckboxImageList (false);
+               setItemHeight (false);
+               if (topIndex != 0) {
+                       setTopIndex (topIndex);
+                       setRedraw (true);
+               }
+               return index;
+       }
+       int index = imageList.indexOf (image);
+       if (index != -1) return index;
+       return imageList.add (image);
+}
+
+int imageIndexHeader (Image image) {
+       if (image == null) return OS.I_IMAGENONE;
+       if (headerImageList == null) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+               int index = headerImageList.indexOf (image);
+               if (index == -1) index = headerImageList.add (image);
+               long hImageList = headerImageList.getHandle ();
+               OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageList);
+               return index;
+       }
+       int index = headerImageList.indexOf (image);
+       if (index != -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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i=0; i<columnCount; i++) {
+               if (columns [i] == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       //TODO - find other loops that can be optimized
+       if (keys == null) {
+               int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+               if (1 <= lastIndexOf && lastIndexOf < count - 1) {
+                       if (_getItem (lastIndexOf, false) == item) return lastIndexOf;
+                       if (_getItem (lastIndexOf + 1, false) == item) return ++lastIndexOf;
+                       if (_getItem (lastIndexOf - 1, false) == item) return --lastIndexOf;
+               }
+               if (lastIndexOf < count / 2) {
+                       for (int i=0; i<count; i++) {
+                               if (_getItem (i, false) == item) return lastIndexOf = i;
+                       }
+               } else {
+                       for (int i=count - 1; i>=0; --i) {
+                               if (_getItem (i, false) == item) return lastIndexOf = i;
+                       }
+               }
+       } else {
+               for (int i=0; i<keyCount; i++) {
+                       if (items [i] == item) return keys [i];
+               }
+       }
+       return -1;
+}
+
+boolean isCustomToolTip () {
+       return hooks (SWT.MeasureItem);
+}
+
+boolean isOptimizedRedraw () {
+       if ((style & SWT.H_SCROLL) == 0 || (style & SWT.V_SCROLL) == 0) return false;
+       return !hasChildren () && !hooks (SWT.Paint) && !filters (SWT.Paint) && !customHeaderDrawing();
+}
+
+/**
+ * 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 boolean isSelected (int index) {
+       checkWidget ();
+       LVITEM lvItem = new LVITEM ();
+       lvItem.mask = OS.LVIF_STATE;
+       lvItem.stateMask = OS.LVIS_SELECTED;
+       lvItem.iItem = index;
+       long result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem);
+       return (result != 0) && ((lvItem.state & OS.LVIS_SELECTED) != 0);
+}
+
+@Override
+void register () {
+       super.register ();
+       if (hwndHeader != 0) display.addControl (hwndHeader, this);
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (_hasItems ()) {
+               int itemCount = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+               if (keys == null) {
+                       for (int i=0; i<itemCount; i++) {
+                               TableItem item = _getItem (i, false);
+                               if (item != null && !item.isDisposed ()) item.release (false);
+                       }
+               } else {
+                       for (int i=0; i<keyCount; i++) {
+                               TableItem item = items [i];
+                               if (item != null && !item.isDisposed ()) item.release (false);
+                       }
+               }
+               _clearItems ();
+       }
+       if (columns != 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 != null) {
+               OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, 0);
+               display.releaseImageList (imageList);
+       }
+       if (headerImageList != null) {
+               OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, 0);
+               display.releaseImageList (headerImageList);
+       }
+       imageList = headerImageList = null;
+       long hStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+       OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_STATE, 0);
+       if (hStateList != 0) OS.ImageList_Destroy (hStateList);
+       if (headerToolTipHandle != 0) OS.DestroyWindow (headerToolTipHandle);
+       headerToolTipHandle = 0;
+}
+
+/**
+ * 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>
+ *    <li>ERROR_NULL_ARGUMENT - if the indices 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 remove (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (indices.length == 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 = (int)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 != last) {
+                       TableItem item = _getItem (index, false);
+                       if (item != null && !item.isDisposed ()) item.release (false);
+                       ignoreSelect = ignoreShrink = true;
+                       long code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+                       ignoreSelect = ignoreShrink = false;
+                       if (code == 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+                       _removeItem(index, count);
+                       --count;
+                       last = index;
+               }
+       }
+       if (count == 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+       TableItem item = _getItem (index, false);
+       if (item != null && !item.isDisposed ()) item.release (false);
+       setDeferResize (true);
+       ignoreSelect = ignoreShrink = true;
+       long code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+       ignoreSelect = ignoreShrink = false;
+       if (code == 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+       _removeItem (index, count);
+       --count;
+       if (count == 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (!(0 <= start && start <= end && end < count)) {
+               error (SWT.ERROR_INVALID_RANGE);
+       }
+       if (start == 0 && end == count - 1) {
+               removeAll ();
+       } else {
+               setDeferResize (true);
+               int index = start;
+               while (index <= end) {
+                       TableItem item = _getItem (index, false);
+                       if (item != null && !item.isDisposed ()) item.release (false);
+                       ignoreSelect = ignoreShrink = true;
+                       long code = OS.SendMessage (handle, OS.LVM_DELETEITEM, start, 0);
+                       ignoreSelect = ignoreShrink = false;
+                       if (code == 0) break;
+                       index++;
+               }
+               _removeItems (start, index, count);
+               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 == 0 and end == count - 1.
+               */
+               //if (count - index == 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       for (int i=0; i<itemCount; i++) {
+               TableItem item = _getItem (i, false);
+               if (item != null && !item.isDisposed ()) item.release (false);
+       }
+       setDeferResize (true);
+       ignoreSelect = ignoreShrink = true;
+       long code = OS.SendMessage (handle, OS.LVM_DELETEALLITEMS, 0, 0);
+       ignoreSelect = ignoreShrink = false;
+       if (code == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the array of indices 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 Table#setSelection(int[])
+ */
+public void select (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int length = indices.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+       LVITEM lvItem = new 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;
+               }
+       }
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (_hasItems ()) {
+               int itemCount = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+               for (int i=0; i<itemCount; i++) {
+                       TableItem item = _getItem (i, false);
+                       if (item != null) item.reskin (flags);
+               }
+       }
+       if (columns != null) {
+               for (int i=0; i<columnCount; i++) {
+                       TableColumn column = columns [i];
+                       if (!column.isDisposed ()) column.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+/**
+ * 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 = new 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) != 0 && start != end)) return;
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (count == 0 || start >= count) return;
+       start = Math.max (0, start);
+       end = Math.min (end, count - 1);
+       if (start == 0 && end == count - 1) {
+               selectAll ();
+       } else {
+               /*
+               * An index of -1 will apply the change to all
+               * items.  Indices must be greater than -1.
+               */
+               LVITEM lvItem = new 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) != 0) return;
+       LVITEM lvItem = new 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, long lParam, Event measureEvent) {
+       long hDC = nmcd.hdc;
+       int clrText = item.cellForeground != null ? item.cellForeground [nmcd.iSubItem] : -1;
+       if (clrText == -1) clrText = item.foreground;
+       int clrTextBk = -1;
+       if (OS.IsAppThemed ()) {
+               if (sortColumn != null && sortDirection != SWT.NONE) {
+                       if (findImageControl () == null) {
+                               if (indexOf (sortColumn) == nmcd.iSubItem) {
+                                       clrTextBk = getSortColumnPixel ();
+                               }
+                       }
+               }
+       }
+       clrTextBk = item.cellBackground != null ? item.cellBackground [nmcd.iSubItem] : -1;
+       if (clrTextBk == -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 = new LVITEM ();
+       lvItem.mask = OS.LVIF_STATE;
+       lvItem.stateMask = OS.LVIS_SELECTED;
+       lvItem.iItem = (int)nmcd.dwItemSpec;
+       long result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem);
+       boolean selected = (result != 0 && (lvItem.state & OS.LVIS_SELECTED) != 0);
+       GCData data = new GCData ();
+       data.device = display;
+       int clrSelectionBk = -1;
+       boolean drawSelected = false, drawBackground = false, drawHot = false, drawDrophilited = false;
+       if (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0) {
+               drawHot = hotIndex == nmcd.dwItemSpec;
+               drawDrophilited = (nmcd.uItemState & OS.CDIS_DROPHILITED) != 0;
+       }
+       if (OS.IsWindowEnabled (handle)) {
+               if (selected && (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0)) {
+                       if (OS.GetFocus () == 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) == 0;
+                               data.foreground = OS.GetTextColor (hDC);
+                               data.background = clrSelectionBk = OS.GetSysColor (OS.COLOR_3DFACE);
+                       }
+                       if (explorerTheme) {
+                               data.foreground = clrText != -1 ? clrText : getForegroundPixel ();
+                       }
+               } else {
+                       drawBackground = clrTextBk != -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 == -1 || clrTextBk == -1) {
+                               Control control = findBackgroundControl ();
+                               if (control == null) control = this;
+                               if (clrText == -1) clrText = control.getForegroundPixel ();
+                               if (clrTextBk == -1) clrTextBk = control.getBackgroundPixel ();
+                       }
+                       data.foreground = clrText != -1 ? clrText : OS.GetTextColor (hDC);
+                       data.background = clrTextBk != -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 = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+       int nSavedDC = OS.SaveDC (hDC);
+       GC gc = GC.win32_new (hDC, data);
+       RECT cellRect = item.getBounds ((int)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.uItemState & OS.CDIS_FOCUS) != 0) {
+       if (OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED) == nmcd.dwItemSpec) {
+               if (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0) {
+                       if (handle == OS.GetFocus ()) {
+                               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((uiState & OS.UISF_HIDEFOCUS) == 0) event.detail |= SWT.FOCUSED;
+                       }
+               }
+       }
+       boolean focused = (event.detail & SWT.FOCUSED) != 0;
+       if (drawHot) event.detail |= SWT.HOT;
+       if (drawSelected) event.detail |= SWT.SELECTED;
+       if (drawBackground) event.detail |= SWT.BACKGROUND;
+       Rectangle boundsInPixels = new Rectangle (cellRect.left, cellRect.top, cellRect.right - cellRect.left, cellRect.bottom - cellRect.top);
+       event.setBoundsInPixels (boundsInPixels);
+       gc.setClipping (DPIUtil.autoScaleDown(boundsInPixels));
+       sendEvent (SWT.EraseItem, event);
+       event.gc = null;
+       int clrSelectionText = data.foreground;
+       gc.dispose ();
+       OS.RestoreDC (hDC, nSavedDC);
+       if (isDisposed () || item.isDisposed ()) return;
+       if (event.doit) {
+               ignoreDrawForeground = (event.detail & SWT.FOREGROUND) == 0;
+               ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0;
+               ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0;
+               ignoreDrawFocus = (event.detail & SWT.FOCUSED) == 0;
+               ignoreDrawHot = (event.detail & SWT.HOT) == 0;
+       } else {
+               ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = true;
+       }
+       if (drawSelected) {
+               if (ignoreDrawSelection) {
+                       ignoreDrawHot = true;
+                       if (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0) {
+                               selectionForeground = clrSelectionText;
+                       }
+                       nmcd.uItemState &= ~OS.CDIS_SELECTED;
+                       OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+               }
+       } else {
+               if (ignoreDrawSelection) {
+                       nmcd.uItemState |= OS.CDIS_SELECTED;
+                       OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+               }
+       }
+       boolean firstColumn = nmcd.iSubItem == OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+       if (ignoreDrawForeground && ignoreDrawHot && !drawDrophilited) {
+               if (!ignoreDrawBackground && drawBackground) {
+                       RECT backgroundRect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, false, true, false, hDC);
+                       fillBackground (hDC, clrTextBk, backgroundRect);
+               }
+       }
+       focusRect = null;
+       if (!ignoreDrawHot || !ignoreDrawSelection || !ignoreDrawFocus || drawDrophilited) {
+               boolean fullText = (style & SWT.FULL_SELECTION) != 0 || !firstColumn;
+               RECT textRect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, false, fullText, false, hDC);
+               if ((style & SWT.FULL_SELECTION) == 0) {
+                       if (measureEvent != null) {
+                               Rectangle boundInPixels = measureEvent.getBoundsInPixels();
+                               textRect.right = Math.min (cellRect.right, boundInPixels.x + boundInPixels.width);
+                       }
+                       if (!ignoreDrawFocus) {
+                               nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                               OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+                               focusRect = textRect;
+                       }
+               }
+               if (explorerTheme) {
+                       if (!ignoreDrawHot || drawDrophilited || (!ignoreDrawSelection && clrSelectionBk != -1)) {
+                               RECT pClipRect = new RECT ();
+                               OS.SetRect (pClipRect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                               RECT rect = new RECT ();
+                               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                               if ((style & SWT.FULL_SELECTION) != 0) {
+                                       int count = (int)OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+                                       int index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0);
+                                       RECT headerRect = new RECT ();
+                                       OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+                                       OS.MapWindowPoints (hwndHeader, handle, headerRect, 2);
+                                       rect.right = headerRect.right;
+                                       index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+                                       OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+                                       OS.MapWindowPoints (hwndHeader, handle, headerRect, 2);
+                                       rect.left = headerRect.left;
+                                       pClipRect.left = cellRect.left;
+                                       pClipRect.right += EXPLORER_EXTRA;
+                               } else {
+                                       rect.right += EXPLORER_EXTRA;
+                                       pClipRect.right += EXPLORER_EXTRA;
+                               }
+                               long hTheme = OS.OpenThemeData (handle, Display.LISTVIEW);
+                               int iStateId = selected ? OS.LISS_SELECTED : OS.LISS_HOT;
+                               if (OS.GetFocus () != handle && selected && !drawHot) iStateId = OS.LISS_SELECTEDNOTFOCUS;
+                               if (drawDrophilited) iStateId = OS.LISS_SELECTED;
+                               OS.DrawThemeBackground (hTheme, hDC, OS.LVP_LISTITEM, iStateId, rect, pClipRect);
+                               OS.CloseThemeData (hTheme);
+                       }
+               } else {
+                       if (!ignoreDrawSelection && clrSelectionBk != -1) fillBackground (hDC, clrSelectionBk, textRect);
+               }
+       }
+       if (focused && ignoreDrawFocus) {
+               nmcd.uItemState &= ~OS.CDIS_FOCUS;
+               OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+       }
+       if (ignoreDrawForeground) {
+               RECT clipRect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, false, hDC);
+               OS.SaveDC (hDC);
+               OS.SelectClipRgn (hDC, 0);
+               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.hdc);
+       RECT insetRect = toolTipInset (cellRect);
+       OS.SetWindowOrgEx (nmcd.hdc, insetRect.left, insetRect.top, null);
+       GCData data = new GCData ();
+       data.device = display;
+       data.foreground = OS.GetTextColor (nmcd.hdc);
+       data.background = OS.GetBkColor (nmcd.hdc);
+       data.font = item.getFont (column);
+       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+       GC gc = GC.win32_new (nmcd.hdc, data);
+       Event event = new Event ();
+       event.item = item;
+       event.index = column;
+       event.gc = gc;
+       event.detail |= SWT.FOREGROUND;
+       event.setBoundsInPixels(new Rectangle(cellRect.left, cellRect.top, cellRect.right - cellRect.left, 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.hdc, nSavedDC);
+       return event;
+}
+
+Event sendMeasureItemEvent (TableItem item, int row, int column, long 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.setBoundsInPixels(new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top));
+       boolean drawSelected = false;
+       if (OS.IsWindowEnabled (handle)) {
+               LVITEM lvItem = new LVITEM ();
+               lvItem.mask = OS.LVIF_STATE;
+               lvItem.stateMask = OS.LVIS_SELECTED;
+               lvItem.iItem = (int)row;
+               long result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem);
+               boolean selected = (result != 0 && (lvItem.state & OS.LVIS_SELECTED) != 0);
+               if (selected && (column == 0 || (style & SWT.FULL_SELECTION) != 0)) {
+                       if (OS.GetFocus () == handle || display.getHighContrast ()) {
+                               drawSelected = true;
+                       } else {
+                               drawSelected = (style & SWT.HIDE_SELECTION) == 0;
+                       }
+               }
+       }
+       if (drawSelected) event.detail |= SWT.SELECTED;
+       sendEvent (SWT.MeasureItem, event);
+       event.gc = null;
+       gc.dispose ();
+       OS.RestoreDC (hDC, nSavedDC);
+       if (!isDisposed () && !item.isDisposed ()) {
+               Rectangle boundsInPixels = event.getBoundsInPixels();
+               if (columnCount == 0) {
+                       int width = (int)OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+                       if (boundsInPixels.x + boundsInPixels.width > width) setScrollWidth (boundsInPixels.x + boundsInPixels.width);
+               }
+               long empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+               long oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+               int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty);
+               /*
+                * Possible recursion: when setItemHeight() is called during
+                * SWT.MeasureItem event processing with a non-zero table-row
+                * selection. Refer bug 400174 and 458786
+                */
+               if (!settingItemHeight && boundsInPixels.height > itemHeight) {
+                       settingItemHeight = true;
+                       setItemHeight (boundsInPixels.height);
+                       settingItemHeight = false;
+               }
+       }
+       return event;
+}
+
+LRESULT sendMouseDownEvent (int type, int button, int msg, long wParam, long lParam) {
+       Display display = this.display;
+       display.captureChanged = false;
+       if (!sendMouseEvent (type, button, handle, msg, wParam, lParam)) {
+               if (!display.captureChanged && !isDisposed ()) {
+                       if (OS.GetCapture () != 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 = new LVHITTESTINFO ();
+       pinfo.x = OS.GET_X_LPARAM (lParam);
+       pinfo.y = OS.GET_Y_LPARAM (lParam);
+       OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+       if ((style & SWT.FULL_SELECTION) == 0) {
+               if (hooks (SWT.MeasureItem)) {
+                       /*
+                       *  Bug in Windows.  When LVM_SUBITEMHITTEST is used to hittest
+                       *  a point that is above the table, instead of returning -1 to
+                       *  indicate that the hittest failed, a negative index is returned.
+                       *  The fix is to consider any value that is negative a failure.
+                       */
+                       if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, pinfo) < 0) {
+                               int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+                               if (count != 0) {
+                                       RECT rect = new RECT ();
+                                       rect.left = OS.LVIR_ICON;
+                                       ignoreCustomDraw = true;
+                                       long code = OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, rect);
+                                       ignoreCustomDraw = false;
+                                       if (code != 0) {
+                                               pinfo.x = rect.left;
+                                               /*
+                                               *  Bug in Windows.  When LVM_SUBITEMHITTEST is used to hittest
+                                               *  a point that is above the table, instead of returning -1 to
+                                               *  indicate that the hittest failed, a negative index is returned.
+                                               *  The fix is to consider any value that is negative a failure.
+                                               */
+                                               OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, pinfo);
+                                               if (pinfo.iItem < 0) pinfo.iItem = -1;
+                                               pinfo.flags &= ~(OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL);
+                                       }
+                               }
+                       } else {
+                               if (pinfo.iSubItem != 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) != 0 || hooks (SWT.MouseDown) || hooks (SWT.MouseUp)) {
+               if (pinfo.iItem == -1) {
+                       if (!display.captureChanged && !isDisposed ()) {
+                               if (OS.GetCapture () != 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.
+       */
+       boolean forceSelect = false;
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+       if (count == 1 && pinfo.iItem != -1) {
+               LVITEM lvItem = new 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) != 0) {
+                       forceSelect = true;
+               }
+       }
+
+       /* Determine whether the user has selected an item based on SWT.MeasureItem */
+       fullRowSelect = false;
+       if (pinfo.iItem != -1) {
+               if ((style & SWT.FULL_SELECTION) == 0) {
+                       if (hooks (SWT.MeasureItem)) {
+                               fullRowSelect = hitTestSelection (pinfo.iItem, pinfo.x, pinfo.y);
+                               if (fullRowSelect) {
+                                       int flags = OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL;
+                                       if ((pinfo.flags & flags) != 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.
+       */
+       boolean dragDetect = (state & DRAG_DETECT) != 0 && hooks (SWT.DragDetect);
+       if (!dragDetect) {
+               int flags = OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL;
+               dragDetect = pinfo.iItem == -1 || (pinfo.flags & flags) == 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;
+       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 () != handle) OS.SetCapture (handle);
+               }
+       } else {
+               int flags = OS.LVHT_ONITEMLABEL | OS.LVHT_ONITEMICON;
+               boolean fakeMouseUp = (pinfo.flags & flags) != 0;
+               if (!fakeMouseUp && (style & SWT.MULTI) != 0) {
+                       fakeMouseUp = (pinfo.flags & OS.LVHT_ONITEMSTATEICON) == 0;
+               }
+               if (fakeMouseUp) {
+                       sendMouseEvent (SWT.MouseUp, button, handle, msg, wParam, lParam);
+               }
+       }
+       return new LRESULT (code);
+}
+
+void sendPaintItemEvent (TableItem item, NMLVCUSTOMDRAW nmcd) {
+       long hDC = 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 = new LVITEM ();
+       lvItem.mask = OS.LVIF_STATE;
+       lvItem.stateMask = OS.LVIS_SELECTED;
+       lvItem.iItem = (int)nmcd.dwItemSpec;
+       long result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem);
+       boolean selected = result != 0 && (lvItem.state & OS.LVIS_SELECTED) != 0;
+       boolean drawSelected = false, drawBackground = false, drawHot = false;
+       if (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0) {
+               drawHot = hotIndex == nmcd.dwItemSpec;
+       }
+       if (OS.IsWindowEnabled (handle)) {
+               if (selected && (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0)) {
+                       if (OS.GetFocus () == handle || display.getHighContrast ()) {
+                               drawSelected = true;
+                               if (selectionForeground != -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) == 0;
+                               data.foreground = OS.GetTextColor (hDC);
+                               data.background = OS.GetSysColor (OS.COLOR_3DFACE);
+                       }
+                       if (explorerTheme && selectionForeground == -1) {
+                               int clrText = item.cellForeground != null ? item.cellForeground [nmcd.iSubItem] : -1;
+                               if (clrText == -1) clrText = item.foreground;
+                               data.foreground = clrText != -1 ? clrText : getForegroundPixel ();
+                       }
+               } else {
+                       int clrText = item.cellForeground != null ? item.cellForeground [nmcd.iSubItem] : -1;
+                       if (clrText == -1) clrText = item.foreground;
+                       int clrTextBk = item.cellBackground != null ? item.cellBackground [nmcd.iSubItem] : -1;
+                       if (clrTextBk == -1) clrTextBk = item.background;
+                       drawBackground = clrTextBk != -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 == -1 || clrTextBk == -1) {
+                               Control control = findBackgroundControl ();
+                               if (control == null) control = this;
+                               if (clrText == -1) clrText = control.getForegroundPixel ();
+                               if (clrTextBk == -1) clrTextBk = control.getBackgroundPixel ();
+                       }
+                       data.foreground = clrText != -1 ? clrText : OS.GetTextColor (hDC);
+                       data.background = clrTextBk != -1 ? clrTextBk : OS.GetBkColor (hDC);
+               }
+       } else {
+               data.foreground = OS.GetSysColor (OS.COLOR_GRAYTEXT);
+               data.background = OS.GetSysColor (OS.COLOR_3DFACE);
+       }
+       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+       int nSavedDC = OS.SaveDC (hDC);
+       GC gc = GC.win32_new (hDC, data);
+       RECT itemRect = item.getBounds ((int)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.uItemState & OS.CDIS_FOCUS) != 0) {
+       if (OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED) == nmcd.dwItemSpec) {
+               if (nmcd.iSubItem == 0 || (style & SWT.FULL_SELECTION) != 0) {
+                       if (handle == OS.GetFocus ()) {
+                               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((uiState & OS.UISF_HIDEFOCUS) == 0) event.detail |= SWT.FOCUSED;
+                       }
+               }
+       }
+       if (drawHot) event.detail |= SWT.HOT;
+       if (drawSelected) event.detail |= SWT.SELECTED;
+       if (drawBackground) event.detail |= SWT.BACKGROUND;
+       event.setBoundsInPixels(new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top));
+       RECT cellRect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, true, hDC);
+       int cellWidth = cellRect.right - cellRect.left;
+       int cellHeight = cellRect.bottom - cellRect.top;
+       gc.setClipping (DPIUtil.autoScaleDown(new Rectangle (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.hdc);
+       RECT insetRect = toolTipInset (itemRect);
+       OS.SetWindowOrgEx (nmcd.hdc, insetRect.left, insetRect.top, null);
+       GCData data = new GCData ();
+       data.device = display;
+       data.font = item.getFont (column);
+       data.foreground = OS.GetTextColor (nmcd.hdc);
+       data.background = OS.GetBkColor (nmcd.hdc);
+       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+       GC gc = GC.win32_new (nmcd.hdc, data);
+       Event event = new Event ();
+       event.item = item;
+       event.index = column;
+       event.gc = gc;
+       event.detail |= SWT.FOREGROUND;
+       event.setBoundsInPixels(new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top));
+       //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+       sendEvent (SWT.PaintItem, event);
+       event.gc = null;
+       gc.dispose ();
+       OS.RestoreDC (nmcd.hdc, nSavedDC);
+       return event;
+}
+
+@Override
+void setBackgroundImage (long hBitmap) {
+       super.setBackgroundImage (hBitmap);
+       if (hBitmap != 0) {
+               setBackgroundTransparent (true);
+       } else {
+               if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                       setBackgroundTransparent (false);
+               }
+       }
+}
+
+@Override
+void setBackgroundPixel (int newPixel) {
+       int oldPixel = (int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+       if (oldPixel != OS.CLR_NONE) {
+               if (findImageControl () != null) return;
+               if (newPixel == -1) newPixel = defaultBackground ();
+               if (oldPixel != newPixel) {
+                       OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel);
+                       OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel);
+                       if ((style & SWT.CHECK) != 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 (boolean 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 = (int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+       if (transparent) {
+               if (oldPixel != 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) != 0) {
+                               int bits = OS.LVS_EX_FULLROWSELECT;
+                               OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, 0);
+                       }
+
+                       /* Clear LVM_SETSELECTEDCOLUMN */
+                       if ((sortDirection & (SWT.UP | SWT.DOWN)) != 0) {
+                               if (sortColumn != 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 == OS.CLR_NONE) {
+                       Control control = findBackgroundControl ();
+                       if (control == null) control = this;
+                       if (control.backgroundImage == 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) != 0) fixCheckboxImageListColor (true);
+                               OS.InvalidateRect (handle, null, true);
+                       }
+
+                       /* Set LVS_EX_FULLROWSELECT */
+                       if (!explorerTheme && (style & SWT.FULL_SELECTION) != 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)) != 0) {
+                               if (sortColumn != null && !sortColumn.isDisposed ()) {
+                                       int column = indexOf (sortColumn);
+                                       if (column != -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 setBoundsInPixels (int x, int y, int width, int height, int flags, boolean 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.setBoundsInPixels (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_NULL_ARGUMENT - if the item order is null</li>
+ *    <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(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public void setColumnOrder (int [] order) {
+       checkWidget ();
+       if (order == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (columnCount == 0) {
+               if (order.length != 0) error (SWT.ERROR_INVALID_ARGUMENT);
+               return;
+       }
+       if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+       int [] oldOrder = new int [columnCount];
+       OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, oldOrder);
+       boolean reorder = false;
+       boolean [] seen = new boolean [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 != 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);
+               /*
+               * 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 = new RECT ();
+               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 != oldRects [i].left) {
+                                       column.updateToolTip (i);
+                                       column.sendEvent (SWT.Move);
+                               }
+                       }
+               }
+       }
+}
+
+void setCustomDraw (boolean customDraw) {
+       if (this.customDraw == customDraw) return;
+       if (!this.customDraw && customDraw && currentItem != null) {
+               OS.InvalidateRect (handle, null, true);
+       }
+       this.customDraw = customDraw;
+}
+
+void setDeferResize (boolean defer) {
+       if (defer) {
+               if (resizeCount++ == 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++ == 0 && OS.IsWindowVisible (handle)) {
+                                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                                       OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF);
+                               }
+                       }
+               }
+       } else {
+               if (--resizeCount == 0) {
+                       if (hooks (SWT.MeasureItem) || hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+                               if (--drawCount == 0 /*&& OS.IsWindowVisible (handle)*/) {
+                                       OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE);
+                                       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, 0, flags);
+                               }
+                       }
+                       if (wasResized) {
+                               wasResized = false;
+                               setResizeChildren (false);
+                               sendEvent (SWT.Resize);
+                               if (isDisposed ()) return;
+                               if (layout != null) {
+                                       markLayout (false, false);
+                                       updateLayout (false, false);
+                               }
+                               setResizeChildren (true);
+                       }
+               }
+       }
+}
+
+void setCheckboxImageList (int width, int height, boolean fixScroll) {
+       if ((style & SWT.CHECK) == 0) return;
+       int count = 8, flags = OS.ILC_COLOR32;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.ILC_MIRROR;
+       if (!OS.IsAppThemed ()) flags |= OS.ILC_MASK;
+       long hStateList = OS.ImageList_Create (width, height, flags, count, count);
+       long hDC = OS.GetDC (handle);
+       long memDC = OS.CreateCompatibleDC (hDC);
+       long hBitmap = OS.CreateCompatibleBitmap (hDC, width * count, height);
+       long hOldBitmap = OS.SelectObject (memDC, hBitmap);
+       RECT rect = new RECT ();
+       OS.SetRect (rect, 0, 0, width * count, height);
+       int clrBackground;
+       if (OS.IsAppThemed ()) {
+               Control control = findBackgroundControl ();
+               if (control == null) control = this;
+               clrBackground = control.getBackgroundPixel ();
+       } else {
+               clrBackground = 0x020000FF;
+               if ((clrBackground & 0xFFFFFF) == OS.GetSysColor (OS.COLOR_WINDOW)) {
+                       clrBackground = 0x0200FF00;
+               }
+       }
+       long hBrush = OS.CreateSolidBrush (clrBackground);
+       OS.FillRect (memDC, rect, hBrush);
+       OS.DeleteObject (hBrush);
+       long oldFont = OS.SelectObject (hDC, defaultFont ());
+       TEXTMETRIC tm = new TEXTMETRIC ();
+       OS.GetTextMetrics (hDC, tm);
+       OS.SelectObject (hDC, oldFont);
+       int itemWidth = Math.min (tm.tmHeight, width);
+       int itemHeight = Math.min (tm.tmHeight, height);
+       if (OS.IsAppThemed()) {
+               /*
+                * Feature in Windows. DrawThemeBackground stretches the checkbox
+                * bitmap to fill the provided rectangle. To avoid stretching
+                * artifacts, limit the rectangle to actual checkbox bitmap size.
+                */
+               SIZE size = new SIZE();
+               OS.GetThemePartSize(display.hButtonTheme(), memDC, OS.BP_CHECKBOX, 0, null, OS.TS_TRUE, size);
+               itemWidth = Math.min (size.cx, itemWidth);
+               itemHeight = Math.min (size.cy, itemHeight);
+       }
+       int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2;
+       OS.SetRect (rect, left, top, left + itemWidth, top + itemHeight);
+       if (OS.IsAppThemed ()) {
+               long 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);
+               rect.left += width;  rect.right += width;
+               OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDDISABLED, rect, null);
+               rect.left += width;  rect.right += width;
+               OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDDISABLED, rect, null);
+               rect.left += width;  rect.right += width;
+               OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDDISABLED, rect, null);
+               rect.left += width;  rect.right += width;
+               OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_MIXEDDISABLED, 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);
+               rect.left += width;  rect.right += width;
+               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.IsAppThemed ()) {
+               OS.ImageList_Add (hStateList, hBitmap, 0);
+       } 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 != 0) {
+               setRedraw (false);
+               setTopIndex (0);
+       }
+       long hOldStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+       OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_STATE, hStateList);
+       if (hOldStateList != 0) 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.
+       */
+       long hImageList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+       OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+       if (fixScroll && topIndex != 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 = new 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 != 0) {
+               setRedraw (false);
+               setTopIndex (0);
+       }
+       if (itemHeight != -1) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.LVS_OWNERDRAWFIXED);
+       }
+       super.setFont (font);
+       if (itemHeight != -1) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               OS.SetWindowLong (handle, OS.GWL_STYLE, bits & ~OS.LVS_OWNERDRAWFIXED);
+       }
+       setScrollWidth (null, true);
+       if (topIndex != 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.
+       */
+       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 == -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);
+       OS.InvalidateRect (hwndHeader, null, true);
+}
+
+/**
+ * Sets the header background color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
+ * </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 3.106
+ */
+public void setHeaderBackground (Color color) {
+       checkWidget ();
+       int pixel = -1;
+       if (color != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == headerBackground) return;
+       headerBackground = pixel;
+       if (getHeaderVisible()) {
+               OS.InvalidateRect (hwndHeader, null, true);
+       }
+}
+
+/**
+ * Sets the header foreground color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the table style.
+ * </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 3.106
+ */
+public void setHeaderForeground (Color color) {
+       checkWidget ();
+       int pixel = -1;
+       if (color != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == headerForeground) return;
+       headerForeground = pixel;
+       if (getHeaderVisible()) {
+               OS.InvalidateRect (hwndHeader, 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 (boolean 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 != 0) {
+               setRedraw (false);
+               setTopIndex (0);
+       }
+       setTopIndex (oldIndex);
+       if (newIndex != 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (count == itemCount) return;
+       setDeferResize (true);
+       boolean isVirtual = (style & SWT.VIRTUAL) != 0;
+       if (!isVirtual) setRedraw (false);
+       int index = count;
+       while (index < itemCount) {
+               TableItem item = _getItem (index, false);
+               if (item != null && !item.isDisposed ()) item.release (false);
+               if (!isVirtual) {
+                       ignoreSelect = ignoreShrink = true;
+                       long code = OS.SendMessage (handle, OS.LVM_DELETEITEM, count, 0);
+                       ignoreSelect = ignoreShrink = false;
+                       if (code == 0) break;
+               }
+               index++;
+       }
+       if (index < itemCount) error (SWT.ERROR_ITEM_NOT_REMOVED);
+       _setItemCount (count, itemCount);
+       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 == 0 && itemCount != 0) {
+                       OS.InvalidateRect (handle, null, true);
+               }
+       } else {
+               for (int i=itemCount; i<count; i++) {
+                       new TableItem (this, SWT.NONE, i, true);
+               }
+       }
+       if (!isVirtual) setRedraw (true);
+       if (itemCount == 0) setScrollWidth (null, false);
+       setDeferResize (false);
+}
+
+void setItemHeight (boolean 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 != 0) {
+               setRedraw (false);
+               setTopIndex (0);
+       }
+       if (itemHeight == -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.
+               */
+               long 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 = new 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;
+               OS.SetWindowPos (handle, 0 , 0, 0, width, height + 1, flags);
+               OS.SetWindowPos (handle, 0 , 0, 0, width, height, flags);
+               ignoreResize = false;
+               OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+       }
+       if (fixScroll && topIndex != 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. Note that some platforms draw grid lines
+ * while others may draw alternating row colors.
+ * <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 (boolean show) {
+       checkWidget ();
+       int newBits = show  ? OS.LVS_EX_GRIDLINES : 0;
+       OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_GRIDLINES, newBits);
+       OS.InvalidateRect (hwndHeader, null, true);
+}
+
+@Override
+public void setRedraw (boolean 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 == 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.WS_VISIBLE) == 0) state |= HIDDEN;
+       }
+       if (redraw) {
+               if (--drawCount == 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);
+                       if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 1, 0);
+                       if ((state & HIDDEN) != 0) {
+                               state &= ~HIDDEN;
+                               OS.ShowWindow (handle, OS.SW_HIDE);
+                       } else {
+                               int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                               OS.RedrawWindow (handle, null, 0, flags);
+                       }
+                       setDeferResize (false);
+               }
+       } else {
+               if (drawCount++ == 0) {
+                       OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+                       if (hwndHeader != 0) 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 ();
+               }
+       }
+}
+
+void setScrollWidth (int width) {
+       if (width != (int)OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0)) {
+               /*
+               * 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.
+               */
+               boolean redraw = false;
+               if (hooks (SWT.MeasureItem)) {
+                       redraw = getDrawing () && OS.IsWindowVisible (handle);
+               }
+               if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+               OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, width);
+               if (redraw) {
+                       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, 0, flags);
+               }
+       }
+}
+
+boolean setScrollWidth (TableItem item, boolean force) {
+       if (currentItem != null) {
+               if (currentItem != item) fixScrollWidth = true;
+               return false;
+       }
+       if (!force && (!getDrawing () || !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 == 0) {
+               int newWidth = 0, imageIndent = 0, index = 0;
+               int itemCount = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+               while (index < itemCount) {
+                       String string = null;
+                       long hFont = -1;
+                       if (item != null) {
+                               string = item.text;
+                               imageIndent = Math.max (imageIndent, item.imageIndent);
+                               hFont = item.fontHandle (0);
+                       } else {
+                               TableItem tableItem = _getItem (index, false);
+                               if (tableItem != null) {
+                                       string = tableItem.text;
+                                       imageIndent = Math.max (imageIndent, tableItem.imageIndent);
+                                       hFont = tableItem.fontHandle (0);
+                               }
+                       }
+                       if (string != null && string.length () != 0) {
+                               if (hFont != -1) {
+                                       long hDC = OS.GetDC (handle);
+                                       long oldFont = OS.SelectObject (hDC, hFont);
+                                       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+                                       char [] buffer = string.toCharArray ();
+                                       RECT rect = new RECT ();
+                                       OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+                                       OS.SelectObject (hDC, oldFont);
+                                       OS.ReleaseDC (handle, hDC);
+                                       newWidth = Math.max (newWidth, rect.right - rect.left);
+                               } else {
+                                       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+                                       newWidth = Math.max (newWidth, (int)OS.SendMessage (handle, OS.LVM_GETSTRINGWIDTH, 0, buffer));
+                               }
+                       }
+                       if (item != 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 == 0) {
+                       char [] buffer = {' ', '\0'};
+                       newWidth = Math.max (newWidth, (int)OS.SendMessage (handle, OS.LVM_GETSTRINGWIDTH, 0, buffer));
+               }
+               long hStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+               if (hStateList != 0) {
+                       int [] cx = new int [1], cy = new int [1];
+                       OS.ImageList_GetIconSize (hStateList, cx, cy);
+                       newWidth += cx [0] + INSET;
+               }
+               long hImageList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+               if (hImageList != 0) {
+                       int [] cx = new int [1], cy = new int [1];
+                       OS.ImageList_GetIconSize (hImageList, cx, cy);
+                       newWidth += (imageIndent + 1) * cx [0];
+               } 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 + VISTA_EXTRA;
+               int oldWidth = (int)OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+               if (newWidth > oldWidth) {
+                       setScrollWidth (newWidth);
+                       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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the array of indices 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 Table#deselectAll()
+ * @see Table#select(int[])
+ */
+public void setSelection (int [] indices) {
+       checkWidget ();
+       if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+       deselectAll ();
+       int length = indices.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+       select (indices);
+       int focusIndex = indices [0];
+       if (focusIndex != -1) setFocusIndex (focusIndex);
+       showSelection ();
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selection is cleared before the new item is selected,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       setSelection (new TableItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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_NULL_ARGUMENT - if the array of items is null</li>
+ *    <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 ();
+       if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+       deselectAll ();
+       int length = items.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+       int focusIndex = -1;
+       for (int i=length-1; i>=0; --i) {
+               int index = indexOf (items [i]);
+               if (index != -1) {
+                       select (focusIndex = index);
+               }
+       }
+       if (focusIndex != -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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ *
+ * @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 != -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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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) != 0 && start != end)) return;
+       int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (count == 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 != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (sortColumn != null && !sortColumn.isDisposed ()) {
+               sortColumn.setSortDirection (SWT.NONE);
+       }
+       sortColumn = column;
+       if (sortColumn != null && sortDirection != 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)) == 0 && direction != SWT.NONE) return;
+       sortDirection = direction;
+       if (sortColumn != null && !sortColumn.isDisposed ()) {
+               sortColumn.setSortDirection (direction);
+       }
+}
+
+void setSubImagesVisible (boolean visible) {
+       int dwExStyle = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+       if ((dwExStyle & OS.LVS_EX_SUBITEMIMAGES) != 0 == 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 != 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.
+               */
+               long 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 != null) {
+                       long hHeaderImageList = headerImageList.getHandle ();
+                       long hwndHeader = 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 != -1) setItemHeight (false);
+       }
+       if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+               Control control = findBackgroundControl ();
+               if (control == null) control = this;
+               if (control.backgroundImage == null) {
+                       setCustomDraw (false);
+                       setBackgroundTransparent (false);
+               }
+       }
+       _initItems ();
+       if (columnCount == 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 = (int)OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+       if (index == topIndex) return;
+       if (!painted && hooks (SWT.MeasureItem)) hitTestSelection (index, 0, 0);
+
+       /*
+       * 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 != 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 = new 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       if (column.parent != 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 = new RECT ();
+       itemRect.left = OS.LVIR_BOUNDS;
+       if (index == 0) {
+               itemRect.top = 1;
+               ignoreCustomDraw = true;
+               OS.SendMessage (handle, OS.LVM_GETSUBITEMRECT, -1, itemRect);
+               ignoreCustomDraw = false;
+               itemRect.right = itemRect.left;
+               int width = (int)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;
+       if (_getLinesVisible()) {
+               SCROLLINFO info = new SCROLLINFO ();
+               info.cbSize = SCROLLINFO.sizeof;
+               info.fMask = OS.SIF_POS;
+               OS.GetScrollInfo (handle, OS.SB_HORZ, info);
+               oldPos = info.nPos;
+       }
+       RECT rect = new 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 (_getLinesVisible()) {
+               SCROLLINFO info = new SCROLLINFO ();
+               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) {
+       if (!painted && hooks (SWT.MeasureItem)) hitTestSelection (index, 0, 0);
+       /*
+       * 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.
+       */
+       long counterPage = OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0);
+       if (counterPage <= 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 != OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) {
+                       OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+               }
+       } else {
+               /*
+                * Bug in Windows Vista and onwards: For some reason,
+                * LVM_ENSUREVISIBLE command scrolls the table to the leftmost
+                * column even if the item is already visible, refer Bug 334234
+                */
+               long  topIndex = OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+               if (topIndex > index || index >= topIndex + counterPage ) {
+                       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       int index = indexOf (item);
+       if (index != -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 = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_SELECTED);
+       if (index != -1) {
+               /*
+                * Bug in Windows. For some reason, when a table had vertically
+                * scrolled down, followed by clearAll or clear items call such that
+                * vertical scroll bar is no more visible/needed, even then top of
+                * the table is not visible. Fix is to make sure on show selection
+                * table gets vertically scrolled back to the top, refer bug 442275
+                *
+                * Make sure above fix is only applied to the active shell, see bug 450391.
+                */
+               if (display.getActiveShell() == getShell() && (style & SWT.NO_SCROLL) == 0
+                                       && (verticalBar == null || !verticalBar.isVisible())) {
+                       showItem (0);
+               } else {
+                       showItem (index);
+               }
+       }
+}
+
+/*public*/ void sort () {
+       checkWidget ();
+//     if ((style & SWT.VIRTUAL) != 0) return;
+//     int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+//     if (itemCount == 0 || itemCount == 1) return;
+//     Comparator comparator = new Comparator () {
+//             int index = sortColumn == null ? 0 : indexOf (sortColumn);
+//             public int compare (Object object1, Object object2) {
+//                     TableItem item1 = (TableItem) object1, item2 = (TableItem) object2;
+//                     if (sortDirection == SWT.UP || sortDirection == 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 != 0) {
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc);
+       }
+}
+
+RECT toolTipInset (RECT rect) {
+       RECT insetRect = new RECT ();
+       OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+       return insetRect;
+}
+
+RECT toolTipRect (RECT rect) {
+       RECT toolRect = new RECT ();
+       OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+       return toolRect;
+}
+
+@Override
+String toolTipText (NMTTDISPINFO hdr) {
+       long hwndToolTip = OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+       if (hwndToolTip == hdr.hwndFrom && toolTipText != null) return ""; //$NON-NLS-1$
+       if (headerToolTipHandle == hdr.hwndFrom) {
+               for (int i=0; i<columnCount; i++) {
+                       TableColumn column = columns [i];
+                       if (column.id == hdr.idFrom) return column.toolTipText;
+               }
+       }
+       return super.toolTipText (hdr);
+}
+
+@Override
+void unsubclass () {
+       super.unsubclass ();
+       if (HeaderProc != 0) {
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, HeaderProc);
+       }
+}
+
+@Override
+void update (boolean 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.
+       */
+       long oldHeaderProc = 0, oldTableProc = 0;
+       boolean fixSubclass = isOptimizedRedraw ();
+       if (fixSubclass) {
+               oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TableProc);
+               oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, HeaderProc);
+       }
+       super.update (all);
+       if (fixSubclass) {
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldTableProc);
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, oldHeaderProc);
+       }
+}
+
+void updateHeaderToolTips () {
+       if (headerToolTipHandle == 0) return;
+       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+       RECT rect = new RECT ();
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = 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) != 0) {
+                       lpti.uId = column.id = display.nextToolTipId++;
+                       lpti.left = rect.left;
+                       lpti.top = rect.top;
+                       lpti.right = rect.right;
+                       lpti.bottom = rect.bottom;
+                       OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+}
+
+@Override
+void updateMenuLocation (Event event) {
+       Rectangle clientArea = getClientAreaInPixels ();
+       int x = clientArea.x, y = clientArea.y;
+       int focusIndex = getFocusIndex ();
+       if (focusIndex != -1) {
+               TableItem focusItem = getItem (focusIndex);
+               Rectangle bounds = focusItem.getBoundsInPixels (0);
+               if (focusItem.text != null && focusItem.text.length () != 0) {
+                       bounds = focusItem.getBoundsInPixels ();
+               }
+               x = Math.max (x, bounds.x + bounds.width / 2);
+               x = Math.min (x, clientArea.x + clientArea.width);
+               y = Math.max (y, bounds.y + bounds.height);
+               y = Math.min (y, clientArea.y + clientArea.height);
+       }
+       Point pt = toDisplayInPixels (x, y);
+       event.setLocationInPixels(pt.x, pt.y);
+}
+
+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
+void updateOrientation () {
+       super.updateOrientation ();
+       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+       if (hwndHeader != 0) {
+               int bits = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE);
+               if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                       bits |= OS.WS_EX_LAYOUTRTL;
+               } else {
+                       bits &= ~OS.WS_EX_LAYOUTRTL;
+               }
+               bits &= ~OS.WS_EX_RTLREADING;
+               OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits);
+               OS.InvalidateRect (hwndHeader, null, true);
+               RECT rect = new RECT ();
+               OS.GetWindowRect (handle, rect);
+               int width = rect.right - rect.left, height = rect.bottom - rect.top;
+               OS.SetWindowPos (handle, 0, 0, 0, width - 1, height - 1, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+               OS.SetWindowPos (handle, 0, 0, 0, width, height, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       }
+       if ((style & SWT.CHECK) != 0) fixCheckboxImageListColor (false);
+       if (imageList != null) {
+               Point size = imageList.getImageSize ();
+               display.releaseImageList (imageList);
+               imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+               int count = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+               for (int i = 0; i < count; i++) {
+                       TableItem item = _getItem (i, false);
+                       if (item != null) {
+                               Image image = item.image;
+                               if (image != null) {
+                                       int index = imageList.indexOf (image);
+                                       if (index == -1) imageList.add (image);
+                               }
+                       }
+               }
+               long hImageList = imageList.getHandle ();
+               OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+       }
+       if (hwndHeader != 0) {
+               if (headerImageList != null) {
+                       Point size = headerImageList.getImageSize ();
+                       display.releaseImageList (headerImageList);
+                       headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+                       if (columns != null) {
+                               for (int i = 0; i < columns.length; i++) {
+                                       TableColumn column = columns [i];
+                                       if (column != null) {
+                                               Image image = column.image;
+                                               if (image != null) {
+                                                       LVCOLUMN lvColumn = new LVCOLUMN ();
+                                                       lvColumn.mask = OS.LVCF_FMT;
+                                                       OS.SendMessage (hwndHeader, OS.LVM_GETCOLUMN, i, lvColumn);
+                                                       if ((lvColumn.fmt & OS.LVCFMT_IMAGE) != 0) {
+                                                               int index = headerImageList.indexOf (image);
+                                                               if (index == -1) headerImageList.add (image);
+                                                               lvColumn.iImage = index;
+                                                               lvColumn.mask = OS.LVCF_IMAGE;
+                                                               OS.SendMessage (hwndHeader, OS.LVM_SETCOLUMN, i, lvColumn);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       long hHeaderImageList = headerImageList.getHandle ();
+                       OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hHeaderImageList);
+               }
+       }
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               if (textDirection == AUTO_TEXT_DIRECTION || (state & HAS_AUTO_DIRECTION) != 0) {
+                       for (int i = 0, n = items.length; i < n; i++) {
+                               if (items[i] != null) {
+                                       items[i].updateTextDirection(textDirection == AUTO_TEXT_DIRECTION ? AUTO_TEXT_DIRECTION : style & SWT.FLIP_TEXT_DIRECTION);
+                               }
+                       }
+               }
+               OS.InvalidateRect (handle, null, true);
+               return true;
+       }
+       return false;
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.LVS_SHAREIMAGELISTS;
+       if ((style & SWT.HIDE_SELECTION) == 0) bits |= OS.LVS_SHOWSELALWAYS;
+       if ((style & SWT.SINGLE) != 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) != 0) bits |= OS.LVS_NOSORTHEADER;
+       bits |= OS.LVS_REPORT | OS.LVS_NOCOLUMNHEADER;
+       if ((style & SWT.VIRTUAL) != 0) bits |= OS.LVS_OWNERDATA;
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return TableClass;
+}
+
+@Override
+long windowProc () {
+       return TableProc;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if (hwnd != handle) {
+               switch (msg) {
+                       case OS.WM_CONTEXTMENU: {
+                               LRESULT result = wmContextMenu (hwnd, wParam, lParam);
+                               if (result != null) return result.value;
+                               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.
+                               */
+                               updateHeaderToolTips ();
+                               updateHeaderToolTips ();
+                               break;
+                       }
+                       case OS.WM_NOTIFY: {
+                               NMHDR hdr = new NMHDR ();
+                               OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+                               switch (hdr.code) {
+                                       case OS.TTN_SHOW:
+                                       case OS.TTN_POP:
+                                       case OS.TTN_GETDISPINFO:
+                                               return OS.SendMessage (handle, msg, wParam, lParam);
+                               }
+                               break;
+                       }
+                       case OS.WM_SETCURSOR: {
+                               if (wParam == hwnd) {
+                                       int hitTest = (short) OS.LOWORD (lParam);
+                                       if (hitTest == OS.HTCLIENT) {
+                                               HDHITTESTINFO pinfo = new HDHITTESTINFO ();
+                                               int pos = OS.GetMessagePos ();
+                                               POINT pt = new POINT ();
+                                               OS.POINTSTOPOINT (pt, pos);
+                                               OS.ScreenToClient (hwnd, pt);
+                                               pinfo.x = pt.x;
+                                               pinfo.y = pt.y;
+                                               long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                                               int index = (int)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)) != 0) {
+                                                               OS.SetCursor (OS.LoadCursor (0, OS.IDC_ARROW));
+                                                               return 1;
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+                       }
+               }
+               return callWindowProc (hwnd, msg, wParam, lParam);
+       }
+       if (msg == 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().
+               */
+               int topIndex = (int)OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+               int selection = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, topIndex - 1, OS.LVNI_SELECTED);
+               if (selection == -1) return 0;
+               POINT mousePos = new POINT ();
+               OS.POINTSTOPOINT (mousePos, OS.GetMessagePos ());
+               OS.MapWindowPoints(0, handle, mousePos, 1);
+               RECT clientRect = new RECT ();
+               OS.GetClientRect (handle, clientRect);
+               TableItem item = _getItem (selection);
+               RECT rect = item.getBounds (selection, 0, true, true, true);
+               if ((style & SWT.FULL_SELECTION) != 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);
+                       }
+               }
+               long hRgn = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+               while ((selection = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, selection, OS.LVNI_SELECTED)) != -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);
+                       long 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 */
+               long hdc = OS.GetDC (handle);
+               long memHdc = OS.CreateCompatibleDC (hdc);
+               BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+               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, bmiHeader, BITMAPINFOHEADER.sizeof);
+               long [] pBits = new long [1];
+               long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+               if (memDib == 0) error (SWT.ERROR_NO_HANDLES);
+               long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+               int colorKey = 0x0000FD;
+               POINT pt = new POINT();
+               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 (0, hdc);
+               OS.DeleteObject (hRgn);
+
+               SHDRAGIMAGE shdi = new SHDRAGIMAGE ();
+               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) != 0) {
+                       shdi.ptOffset.x = shdi.sizeDragImage.cx - shdi.ptOffset.x;
+               }
+               OS.MoveMemory (lParam, shdi, SHDRAGIMAGE.sizeof);
+               return 1;
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               case ' ':
+                       if ((style & SWT.CHECK) != 0) {
+                               int index = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+                               if (index != -1) {
+                                       TableItem item = _getItem (index);
+                                       item.setChecked (!item.getChecked (), true);
+                                       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.
+                       */
+                       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 = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+                       if (index != -1) {
+                               Event event = new Event ();
+                               event.item = _getItem (index);
+                               sendSelectionEvent (SWT.DefaultSelection, event, false);
+                       }
+                       return LRESULT.ZERO;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_CONTEXTMENU (long wParam, long 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if (findImageControl () != null) return LRESULT.ONE;
+       return result;
+}
+
+@Override
+LRESULT WM_GETOBJECT (long wParam, long 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) != 0) {
+               if (accessible == null) accessible = new_Accessible (this);
+       }
+       return super.WM_GETOBJECT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)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 != 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.
+                       */
+                       long oldHeaderProc = 0, oldTableProc = 0;
+                       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                       boolean fixSubclass = isOptimizedRedraw ();
+                       if (fixSubclass) {
+                               oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TableProc);
+                               oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, HeaderProc);
+                       }
+                       long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                       result = code == 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;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long 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 != null || (style & SWT.CHECK) != 0) {
+               OS.InvalidateRect (handle, null, false);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDBLCLK (long wParam, long 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 = new LVHITTESTINFO ();
+       pinfo.x = OS.GET_X_LPARAM (lParam);
+       pinfo.y = OS.GET_Y_LPARAM (lParam);
+       int index = (int)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 () != handle) OS.SetCapture (handle);
+               }
+               return LRESULT.ZERO;
+       }
+       if (pinfo.iItem != -1) callWindowProc (handle, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+       if (!display.captureChanged && !isDisposed ()) {
+               if (OS.GetCapture () != handle) OS.SetCapture (handle);
+       }
+
+       /* Look for check/uncheck */
+       if ((style & SWT.CHECK) != 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 != -1 && pinfo.flags == OS.LVHT_ONITEMSTATEICON) {
+                       TableItem item = _getItem (index);
+                       if (item != null && !item.isDisposed ()) {
+                               item.setChecked (!item.getChecked (), true);
+                               OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+                       }
+               }
+       }
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long 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 == LRESULT.ZERO) return result;
+
+       /* Look for check/uncheck */
+       if ((style & SWT.CHECK) != 0) {
+               LVHITTESTINFO pinfo = new LVHITTESTINFO ();
+               pinfo.x = OS.GET_X_LPARAM (lParam);
+               pinfo.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 = (int)OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+               if (index != -1 && pinfo.flags == OS.LVHT_ONITEMSTATEICON) {
+                       TableItem item = _getItem (index);
+                       if (item != null && !item.isDisposed ()) {
+                               item.setChecked (!item.getChecked (), true);
+                               OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEHOVER (long wParam, long 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 = (int)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) != 0) return result;
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_PAINT (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+
+       _checkShrink();
+       if (fixScrollWidth) setScrollWidth (null, true);
+       return super.WM_PAINT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_RBUTTONDBLCLK (long wParam, long 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 = new LVHITTESTINFO ();
+       pinfo.x = OS.GET_X_LPARAM (lParam);
+       pinfo.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 != -1) callWindowProc (handle, OS.WM_RBUTTONDBLCLK, wParam, lParam);
+       }
+       if (!display.captureChanged && !isDisposed ()) {
+               if (OS.GetCapture () != handle) OS.SetCapture (handle);
+       }
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_RBUTTONDOWN (long wParam, long 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 (long wParam, long 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 != null || (style & SWT.CHECK) != 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 = (int)OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+       if (count == 0) return result;
+       int index = (int)OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+       if (index == -1) {
+               LVITEM lvItem = new 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_SETFONT (wParam, lParam);
+       if (result != 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.
+       */
+       OS.SendMessage (hwndHeader, OS.WM_SETFONT, 0, lParam);
+
+       if (headerToolTipHandle != 0) {
+               OS.SendMessage (headerToolTipHandle, OS.WM_SETFONT, wParam, lParam);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETREDRAW (long wParam, long lParam) {
+       LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+       if (result != 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 == 1) {
+               if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) != OS.CLR_NONE) {
+                       if (hooks (SWT.MeasureItem) || hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+                               OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE);
+                       }
+               }
+       }
+       /*
+       * Bug in Windows.  When WM_SETREDRAW is used to turn off
+       * redraw for a list, table or tree, the background of the
+       * control is drawn.  The fix is to call DefWindowProc(),
+       * which stops all graphics output to the control.
+       */
+       OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+       long code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+       if (wParam == 0) {
+               if ((int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) == OS.CLR_NONE) {
+                       OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF);
+               }
+       }
+       return code == 0 ? LRESULT.ZERO : new LRESULT (code);
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       if (ignoreResize) return null;
+       if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+               OS.InvalidateRect (handle, null, true);
+       }
+       if (resizeCount != 0) {
+               wasResized = true;
+               return null;
+       }
+       return super.WM_SIZE (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+       if (result != null) return result;
+       if (findBackgroundControl () == null) {
+               setBackgroundPixel (defaultBackground ());
+       } else {
+               int oldPixel = (int)OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+               if (oldPixel != OS.CLR_NONE) {
+                       if (findImageControl () == null) {
+                               if ((style & SWT.CHECK) != 0) fixCheckboxImageListColor (true);
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_HSCROLL (long wParam, long 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;
+       if (_getLinesVisible()) {
+               SCROLLINFO info = new SCROLLINFO ();
+               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.
+       */
+       long oldHeaderProc = 0, oldTableProc = 0;
+       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+       boolean fixSubclass = isOptimizedRedraw ();
+       if (fixSubclass) {
+               oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TableProc);
+               oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, 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.
+       */
+       boolean fixScroll = false;
+       if (OS.LOWORD (wParam) != OS.SB_ENDSCROLL) {
+               if (columnCount > H_SCROLL_LIMIT) {
+                       int rowCount = (int)OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0);
+                       if (rowCount > V_SCROLL_LIMIT) fixScroll = getDrawing () && 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, 0, 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.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                       RECT headerRect = new RECT (), rect = new RECT ();
+                       OS.GetClientRect (handle, rect);
+                       boolean [] visible = new boolean [columnCount];
+                       for (int i=0; i<columnCount; i++) {
+                               visible [i] = true;
+                               headerRect.top = i;
+                               headerRect.left = OS.LVIR_BOUNDS;
+                               if (OS.SendMessage (handle, OS.LVM_GETSUBITEMRECT, 0, headerRect) != 0) {
+                                       headerRect.top = rect.top;
+                                       headerRect.bottom = rect.bottom;
+                                       visible [i] = OS.IntersectRect(headerRect, rect, headerRect);
+                               }
+                       }
+                       try {
+                               columnVisible = visible;
+                               OS.UpdateWindow (handle);
+                       } finally {
+                               columnVisible = null;
+                       }
+               }
+       }
+
+       if (fixSubclass) {
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldTableProc);
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, 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 (_getLinesVisible()) {
+               SCROLLINFO info = new SCROLLINFO ();
+               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 = new RECT ();
+                       OS.GetClientRect (handle, rect);
+                       rect.right = oldPos - newPos + GRID_WIDTH;
+                       OS.InvalidateRect (handle, rect, true);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_VSCROLL (long wParam, long 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.
+       */
+       long oldHeaderProc = 0, oldTableProc = 0;
+       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+       boolean fixSubclass = isOptimizedRedraw ();
+       if (fixSubclass) {
+               oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TableProc);
+               oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, 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.
+       */
+       boolean fixScroll = false;
+       if (OS.LOWORD (wParam) != OS.SB_ENDSCROLL) {
+               if (columnCount > H_SCROLL_LIMIT) {
+                       int rowCount = (int)OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0);
+                       if (rowCount > V_SCROLL_LIMIT) fixScroll = getDrawing () && 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, 0, 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.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                       RECT headerRect = new RECT (), rect = new RECT ();
+                       OS.GetClientRect (handle, rect);
+                       boolean [] visible = new boolean [columnCount];
+                       for (int i=0; i<columnCount; i++) {
+                               visible [i] = true;
+                               headerRect.top = i;
+                               headerRect.left = OS.LVIR_BOUNDS;
+                               if (OS.SendMessage (handle, OS.LVM_GETSUBITEMRECT, 0, headerRect) != 0) {
+                                       headerRect.top = rect.top;
+                                       headerRect.bottom = rect.bottom;
+                                       visible [i] = OS.IntersectRect(headerRect, rect, headerRect);
+                               }
+                       }
+                       try {
+                               columnVisible = visible;
+                               OS.UpdateWindow (handle);
+                       } finally {
+                               columnVisible = null;
+                       }
+               }
+       }
+
+       if (fixSubclass) {
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldTableProc);
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, 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.
+       */
+       if (_getLinesVisible()) {
+               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 = new RECT ();
+                               OS.GetWindowRect (hwndHeader, rect);
+                               int headerHeight = rect.bottom - rect.top;
+                               RECT clientRect = new RECT ();
+                               OS.GetClientRect (handle, clientRect);
+                               clientRect.top += headerHeight;
+                               long empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+                               long oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+                               int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty);
+                               if (code == 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;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT wmMeasureChild (long wParam, long lParam) {
+       MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof);
+       if (itemHeight == -1) {
+               long empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+               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, long wParam, long lParam) {
+       long hwndToolTip = OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+       if (hdr.hwndFrom == hwndToolTip) {
+               LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
+               if (result != null) return result;
+       }
+       if (hdr.hwndFrom == hwndHeader) {
+               LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
+               if (result != null) return result;
+       }
+       return super.wmNotify (hdr, wParam, lParam);
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.LVN_ODFINDITEM: {
+                       if ((style & SWT.VIRTUAL) != 0) return new LRESULT (-1);
+                       break;
+               }
+               case OS.LVN_ODSTATECHANGED: {
+                       if ((style & SWT.VIRTUAL) != 0) {
+                               if (!ignoreSelect) {
+                                       NMLVODSTATECHANGE lpStateChange  = new NMLVODSTATECHANGE ();
+                                       OS.MoveMemory (lpStateChange, lParam, NMLVODSTATECHANGE.sizeof);
+                                       boolean oldSelected = (lpStateChange.uOldState & OS.LVIS_SELECTED) != 0;
+                                       boolean newSelected = (lpStateChange.uNewState & OS.LVIS_SELECTED) != 0;
+                                       if (oldSelected != newSelected) wasSelected = true;
+                               }
+                       }
+                       break;
+               }
+               case OS.LVN_GETDISPINFO: {
+//                     if (drawCount != 0 || !OS.IsWindowVisible (handle)) break;
+                       NMLVDISPINFO plvfi = new NMLVDISPINFO ();
+                       OS.MoveMemory (plvfi, lParam, NMLVDISPINFO.sizeof);
+
+                       if (columnVisible != null && !columnVisible [plvfi.iSubItem]) {
+                               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.
+                       *
+                       * NOTE: Force the item to be created if it does not exist.
+                       */
+                       TableItem item = _getItem (plvfi.iItem);
+                       if (item == null) break;
+
+                       /*
+                       * Feature in Windows. On Vista, the list view expects the item array
+                       * to be up to date when a LVM_DELETEITEM message is being processed.
+                       *
+                       * Also, when the table is virtual, 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.
+                       *
+                       * On both cases, Rather than answering the data right away, queue a
+                       * redraw for later.
+                       */
+                       if (ignoreShrink) {
+                               /*
+                               * Feature in Windows Vista and newer. Using LVM_REDRAWITEMS causes LVN_GETDISPINFO
+                               * to be sent before the method returns. For this reason, LVM_REDRAWITEMS
+                               * can never be used from a LVN_GETDISPINFO handler. The fix is to
+                               * InvalidateRect() passing the bounds for the entire item.
+                               */
+                               if (OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                                       RECT rect = new RECT ();
+                                       rect.left = OS.LVIR_BOUNDS;
+                                       ignoreCustomDraw = true;
+                                       long code = OS.SendMessage (handle, OS. LVM_GETITEMRECT, plvfi.iItem, rect);
+                                       ignoreCustomDraw = false;
+                                       if (code != 0) OS.InvalidateRect (handle, rect, true);
+                                       break;
+                               } else {
+                                       if ((style & SWT.VIRTUAL) != 0 && !item.cached) {
+                                               OS.SendMessage (handle, OS.LVM_REDRAWITEMS, plvfi.iItem, plvfi.iItem);
+                                               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) != 0) {
+                                       lastIndexOf = plvfi.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.mask & OS.LVIF_TEXT) != 0) {
+                               String string = null;
+                               if (plvfi.iSubItem == 0) {
+                                       string = item.text;
+                               } else {
+                                       String [] strings  = item.strings;
+                                       if (strings != null && plvfi.iSubItem < strings.length) string = strings [plvfi.iSubItem];
+                               }
+                               if (string != 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 (), Math.max (0, plvfi.cchTextMax - 1));
+                                       if (!tipRequested && plvfi.iSubItem == 0 && length == 0) {
+                                               string = " "; //$NON-NLS-1$
+                                               length = 1;
+                                       }
+                                       if (length > 1 && (state & HAS_AUTO_DIRECTION) != 0) {
+                                               switch (BidiUtil.resolveTextDirection(string)) {
+                                                       case SWT.LEFT_TO_RIGHT:
+                                                               string = LRE + string;
+                                                               length++;
+                                                               break;
+                                                       case SWT.RIGHT_TO_LEFT:
+                                                               string = RLE + string;
+                                                               length++;
+                                                               break;
+                                               }
+                                       }
+                                       char [] buffer = display.tableBuffer;
+                                       if (buffer == null || plvfi.cchTextMax > buffer.length) {
+                                               buffer = display.tableBuffer = new char [plvfi.cchTextMax];
+                                       }
+                                       string.getChars (0, length, buffer, 0);
+                                       if (tipRequested) {
+                                               /*
+                                                * Bug in Windows. The tooltip is only displayed up to
+                                                * the first line delimiter. The fix is to remove all
+                                                * line delimiter characters.
+                                                */
+                                               int shift = 0;
+                                               for (int i = 0; i < length; i++) {
+                                                       switch (buffer [i]) {
+                                                               case '\r':
+                                                               case '\n':
+                                                                       shift++;
+                                                                       break;
+                                                               default:
+                                                                       if (shift != 0) buffer [i - shift] = buffer [i];
+                                                       }
+                                               }
+                                               length -= shift;
+                                       }
+                                       buffer [length++] = 0;
+                                       OS.MoveMemory (plvfi.pszText, buffer, length * 2);
+                               }
+                       }
+                       boolean move = false;
+                       if ((plvfi.mask & OS.LVIF_IMAGE) != 0) {
+                               Image image = null;
+                               if (plvfi.iSubItem == 0) {
+                                       image = item.image;
+                               } else {
+                                       Image [] images = item.images;
+                                       if (images != null && plvfi.iSubItem < images.length) image = images [plvfi.iSubItem];
+                               }
+                               if (image != null) {
+                                       plvfi.iImage = imageIndex (image, plvfi.iSubItem);
+                                       move = true;
+                               }
+                       }
+                       if ((plvfi.mask & OS.LVIF_STATE) != 0) {
+                               if (plvfi.iSubItem == 0) {
+                                       int state = 1;
+                                       if (item.checked) state++;
+                                       if (item.grayed) state +=2;
+                                       if (!OS.IsWindowEnabled (handle)) state += 4;
+                                       plvfi.state = state << 12;
+                                       plvfi.stateMask = OS.LVIS_STATEIMAGEMASK;
+                                       move = true;
+                               }
+                       }
+                       if ((plvfi.mask & OS.LVIF_INDENT) != 0) {
+                               if (plvfi.iSubItem == 0) {
+                                       plvfi.iIndent = item.imageIndent;
+                                       move = true;
+                               }
+                       }
+                       if (move) OS.MoveMemory (lParam, plvfi, NMLVDISPINFO.sizeof);
+                       break;
+               }
+               case OS.NM_CUSTOMDRAW: {
+                       long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                       if (hdr.hwndFrom == hwndHeader) break;
+                       if (!customDraw && findImageControl () == 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 != 0) break;
+                               }
+                       }
+                       NMLVCUSTOMDRAW nmcd = new NMLVCUSTOMDRAW ();
+                       OS.MoveMemory (nmcd, lParam, NMLVCUSTOMDRAW.sizeof);
+                       switch (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);
+                       }
+                       break;
+               }
+               case OS.LVN_MARQUEEBEGIN: {
+                       if ((style & SWT.SINGLE) != 0) return LRESULT.ONE;
+                       if (hooks (SWT.MouseDown) || hooks (SWT.MouseUp)) {
+                               return LRESULT.ONE;
+                       }
+                       if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                               if (findImageControl () != 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 == OS.LVN_BEGINDRAG) {
+                               int pos = OS.GetMessagePos ();
+                               POINT pt = new POINT ();
+                               OS.POINTSTOPOINT (pt, pos);
+                               OS.ScreenToClient (handle, pt);
+                               sendDragEvent (1, pt.x, pt.y);
+                       }
+                       break;
+               }
+               case OS.LVN_COLUMNCLICK: {
+                       NMLISTVIEW pnmlv = new NMLISTVIEW ();
+                       OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof);
+                       TableColumn column = columns [pnmlv.iSubItem];
+                       if (column != null) {
+                               column.sendSelectionEvent (SWT.Selection);
+                       }
+                       break;
+               }
+               case OS.LVN_ITEMACTIVATE: {
+                       if (ignoreActivate) break;
+                       NMLISTVIEW pnmlv = new NMLISTVIEW ();
+                       OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof);
+                       if (pnmlv.iItem != -1) {
+                               Event event = new Event ();
+                               event.item = _getItem (pnmlv.iItem);
+                               sendSelectionEvent (SWT.DefaultSelection, event, false);
+                       }
+                       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 = new NMLISTVIEW ();
+                               OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof);
+                               if ((pnmlv.uChanged & OS.LVIF_STATE) != 0) {
+                                       if (pnmlv.iItem == -1) {
+                                               wasSelected = true;
+                                       } else {
+                                               boolean oldSelected = (pnmlv.uOldState & OS.LVIS_SELECTED) != 0;
+                                               boolean newSelected = (pnmlv.uNewState & OS.LVIS_SELECTED) != 0;
+                                               if (oldSelected != newSelected) wasSelected = true;
+                                       }
+                               }
+                       }
+                       if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+                               long hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                               int count = (int)OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+                               if (count != 0) {
+                                       forceResize ();
+                                       RECT rect = new RECT ();
+                                       OS.GetClientRect (handle, rect);
+                                       NMLISTVIEW pnmlv = new NMLISTVIEW ();
+                                       OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof);
+                                       if (pnmlv.iItem != -1) {
+                                               RECT itemRect = new RECT ();
+                                               itemRect.left = OS.LVIR_BOUNDS;
+                                               ignoreCustomDraw = true;
+                                               OS.SendMessage (handle, OS. LVM_GETITEMRECT, pnmlv.iItem, itemRect);
+                                               ignoreCustomDraw = false;
+                                               RECT headerRect = new RECT ();
+                                               int index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0);
+                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+                                               OS.MapWindowPoints (hwndHeader, handle, headerRect, 2);
+                                               rect.left = headerRect.right;
+                                               rect.top = itemRect.top;
+                                               rect.bottom = itemRect.bottom;
+                                               OS.InvalidateRect (handle, rect, true);
+                                       }
+                               }
+                       }
+                       break;
+               }
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+LRESULT wmNotifyHeader (NMHDR hdr, long wParam, 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_BEGINTRACK:
+               case OS.HDN_DIVIDERDBLCLICK: {
+                       if (columnCount == 0) return LRESULT.ONE;
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       TableColumn column = columns [phdn.iItem];
+                       if (column != null && !column.getResizable ()) {
+                               return LRESULT.ONE;
+                       }
+                       ignoreColumnMove = true;
+                       if (hdr.code == OS.HDN_DIVIDERDBLCLICK) {
+                               if (column != null && hooks (SWT.MeasureItem)) {
+                                       column.pack ();
+                                       return LRESULT.ONE;
+                               }
+                       }
+                       break;
+               }
+               case OS.NM_CUSTOMDRAW: {
+                       NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW();
+                       OS.MoveMemory(nmcd, lParam, NMCUSTOMDRAW.sizeof);
+                       switch (nmcd.dwDrawStage) {
+                               case OS.CDDS_PREPAINT: {
+                                       /* Drawing here will be deleted by further drawing steps, even with OS.CDRF_SKIPDEFAULT.
+                                          Changing the TextColor and returning OS.CDRF_NEWFONT has no effect. */
+                                       return new LRESULT (customHeaderDrawing() ? OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT : OS.CDRF_DODEFAULT);
+                               }
+                               case OS.CDDS_ITEMPREPAINT: {
+                                       // draw background
+                                       RECT rect = new RECT();
+                                       OS.SetRect(rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                                       int pixel = getHeaderBackgroundPixel();
+                                       if ((nmcd.uItemState & OS.CDIS_SELECTED) != 0) {
+                                               pixel = getDifferentColor(pixel);
+                                       } else if (columns[(int) nmcd.dwItemSpec] == sortColumn && sortDirection != SWT.NONE) {
+                                               pixel = getSlightlyDifferentColor(pixel);
+                                       }
+                                       long brush = OS.CreateSolidBrush(pixel);
+                                       OS.FillRect(nmcd.hdc, rect, brush);
+                                       OS.DeleteObject(brush);
+
+                                       return new LRESULT(OS.CDRF_SKIPDEFAULT); // if we got here, we will paint everything ourself
+                               }
+                               case OS.CDDS_POSTPAINT: {
+                                       // get the cursor position
+                                       POINT cursorPos = new POINT();
+                                       OS.GetCursorPos(cursorPos);
+                                       OS.MapWindowPoints(0, hwndHeader, cursorPos, 1);
+
+                                       // drawing all cells
+                                       int highlightedHeaderDividerX = -1;
+                                       int lastColumnRight = -1;
+                                       RECT [] rects = new RECT [columnCount];
+                                       for (int i=0; i<columnCount; i++) {
+                                               rects [i] = new RECT ();
+                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, rects [i]);
+                                               if (rects[i].right > lastColumnRight) {
+                                                       lastColumnRight = rects[i].right;
+                                               }
+
+                                               if (columns[i] == sortColumn && sortDirection != SWT.NONE) {
+                                                       // the display.getSortImage looks terrible after scaling up.
+                                                       long pen = OS.CreatePen (OS.PS_SOLID, 1, getHeaderForegroundPixel());
+                                                       long oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                                       int center = rects[i].left + (rects[i].right - rects[i].left) / 2;
+                                                       /*
+                                                        * Sort indicator size needs to scale as per the Native Windows OS DPI level
+                                                        * when header is custom drawn. For more details refer bug 537097.
+                                                        */
+                                                       int leg = DPIUtil.autoScaleUpUsingNativeDPI(3);
+                                                       if (sortDirection == SWT.UP) {
+                                                               OS.Polyline(nmcd.hdc, new int[] {center-leg, 1+leg, center+1, 0}, 2);
+                                                               OS.Polyline(nmcd.hdc, new int[] {center+leg, 1+leg, center-1, 0}, 2);
+                                                       } else if (sortDirection == SWT.DOWN) {
+                                                               OS.Polyline(nmcd.hdc, new int[] {center-leg, 1, center+1, 1+leg+1}, 2);
+                                                               OS.Polyline(nmcd.hdc, new int[] {center+leg, 1, center-1, 1+leg+1}, 2);
+                                                       }
+                                                       OS.SelectObject (nmcd.hdc, oldPen);
+                                                       OS.DeleteObject (pen);
+                                               }
+
+                                               /* Windows 7 and 10 always draw a nearly invisible vertical line between the columns, even if lines are disabled.
+                                                  This line uses no fixed color constant, but calculates it from the background color.
+                                                  The method getSlightlyDifferentColor gives us a color, that is near enough to the windows algorithm. */
+                                               long pen = OS.CreatePen (OS.PS_SOLID, getGridLineWidthInPixels(), getSlightlyDifferentColor(getHeaderBackgroundPixel()));
+                                               long oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                               int alignmentCorrection = _getLinesVisible () ? 0 : 1;
+                                               OS.Polyline(nmcd.hdc, new int[] {rects[i].right-alignmentCorrection, rects[i].top, rects[i].right-alignmentCorrection, rects[i].bottom}, 2);
+                                               OS.SelectObject (nmcd.hdc, oldPen);
+                                               OS.DeleteObject (pen);
+
+                                               pen = OS.CreatePen (OS.PS_SOLID, getGridLineWidthInPixels(), OS.GetSysColor(OS.COLOR_3DFACE));
+                                               oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                               /* To differentiate headers, always draw header column separator. */
+                                               OS.Polyline(nmcd.hdc, new int[] {rects[i].right - alignmentCorrection, rects[i].top, rects[i].right - alignmentCorrection, rects[i].bottom}, 2);
+                                               /* To differentiate header & content area, always draw the line separator between header & first row. */
+                                               if (i == 0) OS.Polyline(nmcd.hdc, new int[] {nmcd.left, nmcd.bottom-1, nmcd.right+1, nmcd.bottom-1}, 2);
+                                               OS.SelectObject (nmcd.hdc, oldPen);
+                                               OS.DeleteObject (pen);
+
+                                               if (headerItemDragging && highlightedHeaderDividerX == -1) {
+                                                       int distanceToLeftBorder = cursorPos.x - rects[i].left;
+                                                       int distanceToRightBorder = rects[i].right - cursorPos.x;
+                                                       if (distanceToLeftBorder >= 0 && distanceToRightBorder >= 0) {
+                                                               // the cursor is in the current rectangle
+                                                               highlightedHeaderDividerX = distanceToLeftBorder <= distanceToRightBorder ? rects[i].left-1 : rects[i].right;
+                                                       }
+                                               }
+
+                                               int x = rects[i].left + INSET + 2;
+                                               if (columns[i].image != null) {
+                                                       GCData data = new GCData();
+                                                       data.device = display;
+                                                       GC gc = GC.win32_new (nmcd.hdc, data);
+                                                       int y = Math.max (0, (nmcd.bottom - columns[i].image.getBoundsInPixels().height) / 2);
+                                                       gc.drawImage (columns[i].image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y));
+                                                       x += columns[i].image.getBoundsInPixels().width + 12;
+                                                       gc.dispose ();
+                                               }
+
+                                               if (columns[i].text != null) {
+                                                       int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                                       if ((columns[i].style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+                                                       if ((columns[i].style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+                                                       char [] buffer = columns[i].text.toCharArray ();
+                                                       OS.SetBkMode(nmcd.hdc, OS.TRANSPARENT);
+                                                       OS.SetTextColor(nmcd.hdc, getHeaderForegroundPixel());
+                                                       RECT textRect = new RECT();
+                                                       textRect.left = x;
+                                                       textRect.top = rects[i].top;
+                                                       textRect.right = rects[i].right - (x - rects[i].left);
+                                                       textRect.bottom = rects[i].bottom;
+                                                       OS.DrawText (nmcd.hdc, buffer, buffer.length, textRect, flags);
+                                               }
+                                       }
+
+                                       if (lastColumnRight < nmcd.right) {
+                                               // draw background of the 'no column' area
+                                               RECT rect = new RECT();
+                                               lastColumnRight += _getLinesVisible() ? 1 : 0;
+                                               OS.SetRect(rect, lastColumnRight, nmcd.top, nmcd.right, nmcd.bottom-1);
+                                               long brush = OS.CreateSolidBrush(getHeaderBackgroundPixel());
+                                               OS.FillRect(nmcd.hdc, rect, brush);
+                                               OS.DeleteObject(brush);
+                                       }
+
+                                       // always draw the highlighted border at the end, to avoid overdrawing by other borders.
+                                       if (highlightedHeaderDividerX != -1) {
+                                               long pen = OS.CreatePen (OS.PS_SOLID, 4, OS.GetSysColor(OS.COLOR_HIGHLIGHT));
+                                               long oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                               OS.Polyline(nmcd.hdc, new int[] {highlightedHeaderDividerX, nmcd.top, highlightedHeaderDividerX, nmcd.bottom}, 2);
+                                               OS.SelectObject (nmcd.hdc, oldPen);
+                                               OS.DeleteObject (pen);
+                                       }
+
+                                       return new LRESULT(OS.CDRF_DODEFAULT);
+                               }
+                       }
+                       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 = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                       if ((bits & OS.LVS_EX_HEADERDRAGDROP) != 0) {
+                               if (columnCount == 0) return LRESULT.ONE;
+                               NMHEADER phdn = new NMHEADER ();
+                               OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                               if (phdn.iItem != -1) {
+                                       TableColumn column = columns [phdn.iItem];
+                                       if (column != null && !column.getMoveable ()) {
+                                               ignoreColumnMove = true;
+                                               return LRESULT.ONE;
+                                       }
+                               }
+                               headerItemDragging = true;
+                       }
+                       break;
+               }
+               case OS.HDN_ENDDRAG: {
+                       headerItemDragging = false;
+                       int bits = (int)OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                       if ((bits & OS.LVS_EX_HEADERDRAGDROP) == 0) break;
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       if (phdn.iItem != -1 && phdn.pitem != 0) {
+                               HDITEM pitem = new HDITEM ();
+                               OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
+                               if ((pitem.mask & OS.HDI_ORDER) != 0 && pitem.iOrder != -1) {
+                                       if (columnCount == 0) break;
+                                       int [] order = new int [columnCount];
+                                       OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order);
+                                       int index = 0;
+                                       while (index < order.length) {
+                                               if (order [index] == phdn.iItem) break;
+                                               index++;
+                                       }
+                                       if (index == order.length) index = 0;
+                                       if (index == 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_ITEMCHANGED: {
+                       /*
+                       * 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 = (int)OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+                       if (lastWidth == 0 && width > 0) {
+                               if (_getLinesVisible()) {
+                                       RECT rect = new RECT ();
+                                       OS.GetClientRect (handle, rect);
+                                       rect.right = rect.left + width;
+                                       OS.InvalidateRect (handle, rect, true);
+                               }
+                       }
+                       lastWidth = width;
+                       if (!ignoreColumnResize) {
+                               NMHEADER phdn = new NMHEADER ();
+                               OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                               if (phdn.pitem != 0) {
+                                       HDITEM pitem = new HDITEM ();
+                                       OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
+                                       if ((pitem.mask & OS.HDI_WIDTH) != 0) {
+                                               TableColumn column = columns [phdn.iItem];
+                                               if (column != 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);
+                                                       boolean 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 == column) moved = true;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+               }
+               case OS.HDN_ITEMDBLCLICK: {
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       TableColumn column = columns [phdn.iItem];
+                       if (column != null) {
+                               column.sendSelectionEvent (SWT.DefaultSelection);
+                       }
+                       break;
+               }
+       }
+       return null;
+}
+
+LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.NM_CUSTOMDRAW: {
+                       if (toolTipText != null) break;
+                       if (isCustomToolTip ()) {
+                               NMTTCUSTOMDRAW nmcd = new NMTTCUSTOMDRAW ();
+                               OS.MoveMemory (nmcd, lParam, NMTTCUSTOMDRAW.sizeof);
+                               return wmNotifyToolTip (nmcd, lParam);
+                       }
+                       break;
+               }
+               case OS.TTN_GETDISPINFO:
+               case OS.TTN_SHOW: {
+                       LRESULT result = super.wmNotify (hdr, wParam, lParam);
+                       if (result != null) return result;
+                       if (hdr.code != OS.TTN_SHOW) tipRequested = true;
+                       long code = callWindowProc (handle, OS.WM_NOTIFY, wParam, lParam);
+                       if (hdr.code != OS.TTN_SHOW) tipRequested = false;
+                       if (toolTipText != null) break;
+                       if (isCustomToolTip ()) {
+                               LVHITTESTINFO pinfo = new LVHITTESTINFO ();
+                               int pos = OS.GetMessagePos ();
+                               POINT pt = new POINT();
+                               OS.POINTSTOPOINT (pt, pos);
+                               OS.ScreenToClient (handle, pt);
+                               pinfo.x = pt.x;
+                               pinfo.y = pt.y;
+                               /*
+                               *  Bug in Windows.  When LVM_SUBITEMHITTEST is used to hittest
+                               *  a point that is above the table, instead of returning -1 to
+                               *  indicate that the hittest failed, a negative index is returned.
+                               *  The fix is to consider any value that is negative a failure.
+                               */
+                               if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, pinfo) >= 0) {
+                                       TableItem item = _getItem (pinfo.iItem);
+                                       long hDC = OS.GetDC (handle);
+                                       long oldFont = 0, newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                                       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+                                       long hFont = item.fontHandle (pinfo.iSubItem);
+                                       if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                                       Event event = sendMeasureItemEvent (item, pinfo.iItem, pinfo.iSubItem, hDC);
+                                       if (!isDisposed () && !item.isDisposed ()) {
+                                               RECT itemRect = new RECT ();
+                                               Rectangle boundsInPixels = event.getBoundsInPixels();
+                                               OS.SetRect (itemRect, boundsInPixels.x, boundsInPixels.y, boundsInPixels.x + boundsInPixels.width, boundsInPixels.y + boundsInPixels.height);
+                                               if (hdr.code == OS.TTN_SHOW) {
+                                                       RECT toolRect = toolTipRect (itemRect);
+                                                       OS.MapWindowPoints (handle, 0, toolRect, 2);
+                                                       long hwndToolTip = 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;
+                                                       OS.SetWindowPos (hwndToolTip, 0, toolRect.left , toolRect.top, width, height, flags);
+                                               } else {
+                                                       NMTTDISPINFO lpnmtdi = new NMTTDISPINFO ();
+                                                       OS.MoveMemory (lpnmtdi, lParam, NMTTDISPINFO.sizeof);
+                                                       if (lpnmtdi.lpszText != 0) {
+                                                               OS.MoveMemory (lpnmtdi.lpszText, new char [1], 2);
+                                                               OS.MoveMemory (lParam, lpnmtdi, NMTTDISPINFO.sizeof);
+                                                       }
+                                                       RECT cellRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, true, true, true, true, hDC);
+                                                       RECT clientRect = new RECT ();
+                                                       OS.GetClientRect (handle, clientRect);
+                                                       if (itemRect.right > cellRect.right || itemRect.right > clientRect.right) {
+                                                               //TEMPORARY CODE
+                                                               String string = " ";
+//                                                             String string = null;
+//                                                             if (pinfo.iSubItem == 0) {
+//                                                                     string = item.text;
+//                                                             } else {
+//                                                                     String [] strings  = item.strings;
+//                                                                     if (strings != null) string = strings [pinfo.iSubItem];
+//                                                             }
+                                                               if (string != null) {
+                                                                       Shell shell = getShell ();
+                                                                       char [] chars = new char [string.length () + 1];
+                                                                       string.getChars (0, string.length (), chars, 0);
+                                                                       shell.setToolTipText (lpnmtdi, chars);
+                                                                       OS.MoveMemory (lParam, lpnmtdi, NMTTDISPINFO.sizeof);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                                       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+                                       OS.ReleaseDC (handle, hDC);
+                               }
+                       }
+                       return new LRESULT (code);
+               }
+       }
+       return null;
+}
+
+LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW nmcd, long lParam) {
+       switch (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 = new LVHITTESTINFO ();
+                       int pos = OS.GetMessagePos ();
+                       POINT pt = new POINT();
+                       OS.POINTSTOPOINT (pt, pos);
+                       OS.ScreenToClient (handle, pt);
+                       pinfo.x = pt.x;
+                       pinfo.y = pt.y;
+                       /*
+                       *  Bug in Windows.  When LVM_SUBITEMHITTEST is used to hittest
+                       *  a point that is above the table, instead of returning -1 to
+                       *  indicate that the hittest failed, a negative index is returned.
+                       *  The fix is to consider any value that is negative a failure.
+                       */
+                       if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, pinfo) >= 0) {
+                               TableItem item = _getItem (pinfo.iItem);
+                               long hDC = OS.GetDC (handle);
+                               long hFont = item.fontHandle (pinfo.iSubItem);
+                               if (hFont == -1) hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                               long oldFont = OS.SelectObject (hDC, hFont);
+                               boolean 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) != 0;
+                                       } else {
+                                               drawForeground = false;
+                                       }
+                               }
+                               if (drawForeground) {
+                                       int nSavedDC = OS.SaveDC (nmcd.hdc);
+                                       int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0;
+                                       RECT insetRect = toolTipInset (cellRect);
+                                       OS.SetWindowOrgEx (nmcd.hdc, insetRect.left, insetRect.top, null);
+                                       GCData data = new GCData ();
+                                       data.device = display;
+                                       data.foreground = OS.GetTextColor (nmcd.hdc);
+                                       data.background = OS.GetBkColor (nmcd.hdc);
+                                       data.font = Font.win32_new (display, hFont);
+                                       GC gc = GC.win32_new (nmcd.hdc, data);
+                                       int x = cellRect.left;
+                                       if (pinfo.iSubItem != 0) x -= gridWidth;
+                                       Image image = item.getImage (pinfo.iSubItem);
+                                       if (image != null) {
+                                               Rectangle rect = image.getBoundsInPixels ();
+                                               RECT imageRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, false, true, false, false, hDC);
+                                               Point size = imageList == null ? new Point (rect.width, rect.height) : imageList.getImageSize ();
+                                               int y = imageRect.top + Math.max (0, (imageRect.bottom - imageRect.top - size.y) / 2);
+                                               rect = DPIUtil.autoScaleDown(rect);
+                                               gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y), DPIUtil.autoScaleDown(size.x), DPIUtil.autoScaleDown(size.y));
+                                               x += size.x + INSET + (pinfo.iSubItem == 0 ? -2 : 4);
+                                       } else {
+                                               x += INSET + 2;
+                                       }
+                                       String string = item.getText (pinfo.iSubItem);
+                                       if (string != null) {
+                                               int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                               TableColumn column = columns != null ? columns [pinfo.iSubItem] : null;
+                                               if (column != null) {
+                                                       if ((column.style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+                                                       if ((column.style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+                                               }
+                                               char [] buffer = string.toCharArray ();
+                                               RECT textRect = new RECT ();
+                                               OS.SetRect (textRect, x, cellRect.top, cellRect.right, cellRect.bottom);
+                                               OS.DrawText (nmcd.hdc, buffer, buffer.length, textRect, flags);
+                                       }
+                                       gc.dispose ();
+                                       OS.RestoreDC (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);
+                       }
+               }
+       }
+       return null;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TableColumn.java
new file mode 100644 (file)
index 0000000..b29a01f
--- /dev/null
@@ -0,0 +1,848 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent a column in a table widget.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd> Move, Resize, Selection</dd>
+ * </dl>
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TableColumn extends Item {
+       Table parent;
+       boolean 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 TableColumn (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 TableColumn (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 == 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 == 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) != 0) return SWT.LEFT;
+       if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+       if ((style & SWT.RIGHT) != 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(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public boolean 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 boolean 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 ();
+       return DPIUtil.autoScaleDown(getWidthInPixels());
+}
+
+int getWidthInPixels () {
+       int index = parent.indexOf (this);
+       if (index == -1) return 0;
+       long hwnd = parent.handle;
+       return (int)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 == -1) return;
+       long hwnd = parent.handle;
+       int oldWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+       TCHAR buffer = new TCHAR (parent.getCodePage (), text, true);
+       int headerWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer) + Table.HEADER_MARGIN;
+       if (OS.IsAppThemed ()) headerWidth += Table.HEADER_EXTRA;
+       boolean hasHeaderImage = false;
+       if (image != null || parent.sortColumn == this) {
+               hasHeaderImage = true;
+               if (parent.sortColumn == this && parent.sortDirection != SWT.NONE) {
+                       headerWidth += Table.SORT_WIDTH;
+               } else if (image != null) {
+                       Rectangle bounds = image.getBoundsInPixels ();
+                       headerWidth += bounds.width;
+               }
+               long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+               int margin = (int)OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
+               headerWidth += margin * 4;
+       }
+       parent.ignoreColumnResize = true;
+       int columnWidth = 0;
+       if (parent.hooks (SWT.MeasureItem)) {
+               RECT headerRect = new RECT ();
+               long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+               OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
+               long hDC = OS.GetDC (hwnd);
+               long oldFont = 0, newFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               int count = (int)OS.SendMessage (hwnd, OS.LVM_GETITEMCOUNT, 0, 0);
+               for (int i=0; i<count; i++) {
+                       TableItem item = parent._getItem (i, false);
+                       if (item != null) {
+                               long hFont = item.fontHandle (index);
+                               if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                               Event event = parent.sendMeasureItemEvent (item, i, index, hDC);
+                               if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                               if (isDisposed () || parent.isDisposed ()) break;
+                               Rectangle bounds = event.getBoundsInPixels();
+                               columnWidth = Math.max (columnWidth, bounds.x + bounds.width - headerRect.left);
+                       }
+               }
+               if (newFont != 0) 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 = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+               if (index == 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 == 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) != 0) {
+                               long hStateList = OS.SendMessage (hwnd, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+                               if (hStateList != 0) {
+                                       int [] cx = new int [1], cy = new int [1];
+                                       OS.ImageList_GetIconSize (hStateList, cx, cy);
+                                       columnWidth += cx [0];
+                               }
+                       }
+               }
+       }
+       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 = null;
+                       boolean fixWidth = index == 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;
+                               OS.SetWindowPos (hwnd, 0, 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;
+                               OS.SetWindowPos (hwnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
+                       }
+               } else {
+                       OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth);
+               }
+       } else {
+               if (index == 0) {
+                       OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth);
+               }
+       }
+       parent.ignoreColumnResize = false;
+       int newWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+       if (oldWidth != newWidth) {
+               updateToolTip (index);
+               sendEvent (SWT.Resize);
+               if (isDisposed ()) return;
+               boolean 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 == this) moved = true;
+               }
+       }
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       parent = null;
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (parent.sortColumn == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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)) == 0) return;
+       int index = parent.indexOf (this);
+       if (index == -1 || index == 0) return;
+       style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+       style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+       long hwnd = parent.handle;
+       LVCOLUMN lvColumn = new 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) == SWT.LEFT) fmt = OS.LVCFMT_LEFT;
+       if ((style & SWT.CENTER) == SWT.CENTER) fmt = OS.LVCFMT_CENTER;
+       if ((style & SWT.RIGHT) == 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 != 0) {
+               parent.forceResize ();
+               RECT rect = new RECT (), headerRect = new RECT ();
+               OS.GetClientRect (hwnd, rect);
+               long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+               OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
+               rect.left = headerRect.left;
+               rect.right = headerRect.right;
+               OS.InvalidateRect (hwnd, rect, true);
+       }
+}
+
+@Override
+public void setImage (Image image) {
+       checkWidget();
+       if (image != null && image.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       super.setImage (image);
+       if (parent.sortColumn != this || parent.sortDirection != SWT.NONE) {
+               setImage (image, false, false);
+       }
+}
+
+void setImage (Image image, boolean sort, boolean right) {
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       long hwnd = parent.handle;
+       LVCOLUMN lvColumn = new LVCOLUMN ();
+       lvColumn.mask = OS.LVCF_FMT | OS.LVCF_IMAGE;
+       OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, lvColumn);
+       if (image != 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 (boolean 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 (boolean resizable) {
+       checkWidget ();
+       this.resizable = resizable;
+}
+
+void setSortDirection (int direction) {
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       long hwnd = parent.handle;
+       long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+       HDITEM hdItem = new 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 == 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 == null) hdItem.mask &= ~OS.HDI_IMAGE;
+                       break;
+               case SWT.NONE:
+                       hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
+                       if (image != null) {
+                               hdItem.fmt |= OS.HDF_IMAGE;
+                               hdItem.iImage = parent.imageIndexHeader (image);
+                       } else {
+                               hdItem.fmt &= ~OS.HDF_IMAGE;
+                               hdItem.mask &= ~OS.HDI_IMAGE;
+                       }
+                       break;
+       }
+       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 = new RECT ();
+       OS.GetClientRect (hwnd, rect);
+       if ((int)OS.SendMessage (hwnd, OS.LVM_GETBKCOLOR, 0, 0) != OS.CLR_NONE) {
+               int oldColumn = (int)OS.SendMessage (hwnd, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+               int newColumn = direction == SWT.NONE ? -1 : index;
+               OS.SendMessage (hwnd, OS.LVM_SETSELECTEDCOLUMN, newColumn, 0);
+               RECT headerRect = new RECT ();
+               if (oldColumn != -1) {
+                       if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, oldColumn, headerRect) != 0) {
+                               OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
+                               rect.left = headerRect.left;
+                               rect.right = headerRect.right;
+                               OS.InvalidateRect (hwnd, rect, true);
+                       }
+               }
+       }
+       RECT headerRect = new RECT ();
+       if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect) != 0) {
+               OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
+               rect.left = headerRect.left;
+               rect.right = headerRect.right;
+               OS.InvalidateRect (hwnd, rect, true);
+       }
+}
+
+@Override
+public void setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (string.equals (text)) return;
+       int index = parent.indexOf (this);
+       if (index == -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.
+       */
+       long hwnd = parent.handle;
+       LVCOLUMN lvColumn = new LVCOLUMN ();
+       lvColumn.mask = OS.LVCF_FMT;
+       OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, 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.
+       */
+       long hHeap = OS.GetProcessHeap ();
+       char [] buffer = fixMnemonic (string);
+       int byteCount = buffer.length * TCHAR.sizeof;
+       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (pszText, buffer, byteCount);
+       lvColumn.mask |= OS.LVCF_TEXT;
+       lvColumn.pszText = pszText;
+       long result = OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn);
+       if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+       if (result == 0) error (SWT.ERROR_CANNOT_SET_TEXT);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ *
+ * @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;
+       long hwndHeaderToolTip = parent.headerToolTipHandle;
+       if (hwndHeaderToolTip == 0) {
+               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 ();
+       setWidthInPixels(DPIUtil.autoScaleUp(width));
+}
+
+void setWidthInPixels (int width) {
+       if (width < 0) return;
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       long hwnd = parent.handle;
+       if (width != (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0)) {
+               OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, width);
+       }
+}
+
+void updateToolTip (int index) {
+       long hwndHeaderToolTip = parent.headerToolTipHandle;
+       if (hwndHeaderToolTip != 0) {
+               long hwnd = parent.handle;
+               long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+               RECT rect = new RECT ();
+               if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, rect) != 0) {
+                       TOOLINFO lpti = new TOOLINFO ();
+                       lpti.cbSize = TOOLINFO.sizeof;
+                       lpti.hwnd = hwndHeader;
+                       lpti.uId = id;
+                       lpti.left = rect.left;
+                       lpti.top = rect.top;
+                       lpti.right = rect.right;
+                       lpti.bottom = rect.bottom;
+                       OS.SendMessage (hwndHeaderToolTip, OS.TTM_NEWTOOLRECT, 0, lpti);
+               }
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TableItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TableItem.java
new file mode 100644 (file)
index 0000000..0206d30
--- /dev/null
@@ -0,0 +1,1269 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TableItem extends Item {
+       Table parent;
+       String [] strings;
+       Image [] images;
+       Font font;
+       Font [] cellFont;
+       boolean 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 TableItem (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 TableItem (Table parent, int style, int index) {
+       this (parent, style, index, true);
+}
+
+TableItem (Table parent, int style, int index, boolean create) {
+       super (parent, style);
+       this.parent = parent;
+       if (create) parent.createItem (this, index);
+}
+
+static Table checkNull (Table control) {
+       if (control == 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;
+       if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
+}
+
+@Override
+void destroyWidget () {
+       parent.destroyItem (this);
+       releaseHandle ();
+}
+
+long fontHandle (int index) {
+       if (cellFont != null && cellFont [index] != null) return cellFont [index].handle;
+       if (font != null) return font.handle;
+       return -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 == -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 != null ? cellBackground [index] : -1;
+       return pixel == -1 ? getBackground () : Color.win32_new (display, pixel);
+}
+
+/**
+ * Returns a rectangle describing the size and location of the receiver's
+ * text relative to its parent.
+ *
+ * @return the bounding rectangle of 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.2
+ */
+public Rectangle getBounds () {
+       checkWidget();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels () {
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       int itemIndex = parent.indexOf (this);
+       if (itemIndex == -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();
+       return DPIUtil.autoScaleDown(getBoundsInPixels(index));
+}
+
+Rectangle getBoundsInPixels (int index) {
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       int itemIndex = parent.indexOf (this);
+       if (itemIndex == -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, boolean getText, boolean getImage, boolean fullText) {
+       return getBounds (row, column, getText, getImage, fullText, false, 0);
+}
+
+RECT getBounds (int row, int column, boolean getText, boolean getImage, boolean fullText, boolean fullImage, long hDC) {
+       if (!getText && !getImage) return new RECT ();
+       int columnCount = parent.getColumnCount ();
+       if (!(0 <= column && column < Math.max (1, columnCount))) {
+               return new RECT ();
+       }
+       if (parent.fixScrollWidth) parent.setScrollWidth (null, true);
+       RECT rect = new RECT ();
+       long hwnd = parent.handle;
+       int bits = (int)OS.SendMessage (hwnd, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+       if (column == 0 && (bits & OS.LVS_EX_FULLROWSELECT) == 0) {
+               if (parent.explorerTheme) {
+                       rect.left = OS.LVIR_ICON;
+                       parent.ignoreCustomDraw = true;
+                       long code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, rect);
+                       parent.ignoreCustomDraw = false;
+                       if (code == 0) return new RECT ();
+                       if (getText) {
+                               int width = 0;
+                               long hFont = fontHandle (column);
+                               if (hFont == -1 && hDC == 0) {
+                                       TCHAR buffer = new TCHAR (parent.getCodePage (), text, true);
+                                       width = (int)OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer);
+                               } else {
+                                       char [] buffer = text.toCharArray ();
+                                       long textDC = hDC != 0 ? hDC : OS.GetDC (hwnd), oldFont = -1;
+                                       if (hDC == 0) {
+                                               if (hFont == -1) hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+                                               oldFont = OS.SelectObject (textDC, hFont);
+                                       }
+                                       RECT textRect = new RECT ();
+                                       int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
+                                       OS.DrawText (textDC, buffer, buffer.length, textRect, flags);
+                                       width = textRect.right - textRect.left;
+                                       if (hDC == 0) {
+                                               if (oldFont != -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;
+                               long code = OS.SendMessage (hwnd, OS.LVM_GETITEMRECT, row, rect);
+                               parent.ignoreCustomDraw = false;
+                               if (code == 0) return new RECT ();
+                               if (!getImage) {
+                                       RECT iconRect = new RECT ();
+                                       iconRect.left = OS.LVIR_ICON;
+                                       parent.ignoreCustomDraw = true;
+                                       code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, iconRect);
+                                       parent.ignoreCustomDraw = false;
+                                       if (code != 0) rect.left = iconRect.right;
+                               }
+                       } else {
+                               rect.left = OS.LVIR_ICON;
+                               parent.ignoreCustomDraw = true;
+                               long code = OS.SendMessage (hwnd, OS.LVM_GETITEMRECT, row, rect);
+                               parent.ignoreCustomDraw = false;
+                               if (code == 0) return new RECT ();
+                       }
+               }
+               if (fullText || fullImage) {
+                       RECT headerRect = new RECT ();
+                       long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+                       OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, 0, headerRect);
+                       OS.MapWindowPoints (hwndHeader, hwnd, 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.
+               */
+               boolean hasImage = (column == 0 && image != null) || (images != null && images [column] != null);
+               rect.top = column;
+               if (fullText || fullImage || hDC == 0) {
+                       /*
+                       * 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;
+                       long code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, rect);
+                       parent.ignoreCustomDraw = false;
+                       if (code == 0) return new RECT ();
+                       /*
+                       * 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 == 0 && getText && getImage) {
+                               RECT iconRect = new RECT ();
+                               iconRect.left = OS.LVIR_ICON;
+                               parent.ignoreCustomDraw = true;
+                               code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, iconRect);
+                               parent.ignoreCustomDraw = false;
+                               if (code != 0) rect.left = iconRect.left;
+                       }
+                       if (hasImage) {
+                               if (column != 0 && getText && !getImage) {
+                                       RECT iconRect = new RECT ();
+                                       iconRect.top = column;
+                                       iconRect.left = OS.LVIR_ICON;
+                                       if (OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, iconRect) != 0) {
+                                               rect.left = iconRect.right + Table.INSET / 2;
+                                       }
+                               }
+                       } else {
+                               if (getImage && !getText) rect.right = rect.left;
+                       }
+                       if (column == 0 && fullImage) {
+                               RECT headerRect = new RECT ();
+                               long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+                               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, 0, headerRect);
+                               OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
+                               rect.left = headerRect.left;
+                       }
+               } else {
+                       rect.left = OS.LVIR_ICON;
+                       parent.ignoreCustomDraw = true;
+                       long code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, rect);
+                       parent.ignoreCustomDraw = false;
+                       if (code == 0) return new RECT ();
+                       if (!hasImage) rect.right = rect.left;
+                       if (getText) {
+                               String string = column == 0 ? text : strings != null ? strings [column] : null;
+                               if (string != null) {
+                                       RECT textRect = new RECT ();
+                                       char [] buffer = string.toCharArray ();
+                                       int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
+                                       OS.DrawText (hDC, buffer, buffer.length, textRect, flags);
+                                       rect.right += textRect.right - textRect.left + Table.INSET * 3 + 2;
+                               }
+                       }
+               }
+       }
+       /*
+       * 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;
+       rect.top -= gridWidth;
+       if (column != 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 boolean getChecked () {
+       checkWidget();
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       if ((parent.style & SWT.CHECK) == 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 != 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 == null || cellFont [index] == 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 == -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 != null ? cellForeground [index] : -1;
+       return pixel == -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 boolean getGrayed () {
+       checkWidget();
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       if ((parent.style & SWT.CHECK) == 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 == 0) return getImage ();
+       if (images != 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();
+       return DPIUtil.autoScaleDown(getImageBoundsInPixels(index));
+}
+
+Rectangle getImageBoundsInPixels (int index) {
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       int itemIndex = parent.indexOf (this);
+       if (itemIndex == -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) != 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 == 0) return getText ();
+       if (strings != null) {
+               if (0 <= index && index < strings.length) {
+                       String string = strings [index];
+                       return string != 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();
+       return DPIUtil.autoScaleDown(getTextBoundsInPixels(index));
+}
+
+Rectangle getTextBoundsInPixels (int index) {
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       int itemIndex = parent.indexOf (this);
+       if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
+       RECT rect = getBounds (itemIndex, index, true, false, true);
+       rect.left += 2;
+       if (index != 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 == this || !parent.getDrawing ()) return;
+       long hwnd = parent.handle;
+       if (!OS.IsWindowVisible (hwnd)) return;
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       OS.SendMessage (hwnd, OS.LVM_REDRAWITEMS, index, index);
+}
+
+void redraw (int column, boolean drawText, boolean drawImage) {
+       if (parent.currentItem == this || !parent.getDrawing ()) return;
+       long hwnd = parent.handle;
+       if (!OS.IsWindowVisible (hwnd)) return;
+       int index = parent.indexOf (this);
+       if (index == -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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int pixel = -1;
+       if (color != null) {
+               parent.setCustomDraw (true);
+               pixel = color.handle;
+       }
+       if (background == pixel) return;
+       background = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       int pixel = -1;
+       if (color != null) {
+               parent.setCustomDraw (true);
+               pixel = color.handle;
+       }
+       if (cellBackground == null) {
+               cellBackground = new int [count];
+               for (int i = 0; i < count; i++) {
+                       cellBackground [i] = -1;
+               }
+       }
+       if (cellBackground [index] == pixel) return;
+       cellBackground [index] = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 (boolean checked) {
+       checkWidget();
+       if ((parent.style & SWT.CHECK) == 0) return;
+       if (this.checked == checked) return;
+       setChecked (checked, false);
+}
+
+void setChecked (boolean checked, boolean notify) {
+       this.checked = checked;
+       if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+       if (notify) {
+               Event event = new Event();
+               event.item = this;
+               event.detail = SWT.CHECK;
+               parent.sendSelectionEvent (SWT.Selection, event, false);
+       }
+       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 != null && font.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       Font oldFont = this.font;
+       if (oldFont == font) return;
+       this.font = font;
+       if (oldFont != null && oldFont.equals (font)) return;
+       if (font != null) parent.setCustomDraw (true);
+       if ((parent.style & SWT.VIRTUAL) != 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) == 0 && cached) {
+               int itemIndex = parent.indexOf (this);
+               if (itemIndex != -1) {
+                       long hwnd = parent.handle;
+                       LVITEM lvItem = new LVITEM ();
+                       lvItem.mask = OS.LVIF_TEXT;
+                       lvItem.iItem = itemIndex;
+                       lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                       OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, 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 != null && font.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       if (cellFont == null) {
+               if (font == null) return;
+               cellFont = new Font [count];
+       }
+       Font oldFont = cellFont [index];
+       if (oldFont == font) return;
+       cellFont [index] = font;
+       if (oldFont != null && oldFont.equals (font)) return;
+       if (font != null) parent.setCustomDraw (true);
+       if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+       if (index == 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) == 0 && cached) {
+                       int itemIndex = parent.indexOf (this);
+                       if (itemIndex != -1) {
+                               long hwnd = parent.handle;
+                               LVITEM lvItem = new LVITEM ();
+                               lvItem.mask = OS.LVIF_TEXT;
+                               lvItem.iItem = itemIndex;
+                               lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                               OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, 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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int pixel = -1;
+       if (color != null) {
+               parent.setCustomDraw (true);
+               pixel = color.handle;
+       }
+       if (foreground == pixel) return;
+       foreground = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       int pixel = -1;
+       if (color != null) {
+               parent.setCustomDraw (true);
+               pixel = color.handle;
+       }
+       if (cellForeground == null) {
+               cellForeground = new int [count];
+               for (int i = 0; i < count; i++) {
+                       cellForeground [i] = -1;
+               }
+       }
+       if (cellForeground [index] == pixel) return;
+       cellForeground [index] = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 (boolean grayed) {
+       checkWidget();
+       if ((parent.style & SWT.CHECK) == 0) return;
+       if (this.grayed == grayed) return;
+       this.grayed = grayed;
+       if ((parent.style & SWT.VIRTUAL) != 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_NULL_ARGUMENT - if the array of images is null</li>
+ *    <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();
+       if (images == 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>
+ */
+public void setImage (int index, Image image) {
+       checkWidget();
+       if (image != null && image.isDisposed ()) {
+               error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       Image oldImage = null;
+       if (index == 0) {
+               if (image != null && image.type == SWT.ICON) {
+                       if (image.equals (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 == null && index != 0) {
+               images = new Image [count];
+               images [0] = image;
+       }
+       if (images != null) {
+               if (image != null && image.type == SWT.ICON) {
+                       if (image.equals (images [index])) return;
+               }
+               oldImage = images [index];
+               images [index] = image;
+       }
+       if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+       /* Ensure that the image list is created */
+       parent.imageIndex (image, index);
+
+       if (index == 0) parent.setScrollWidth (this, false);
+       boolean drawText = (image == null && oldImage != null) || (image != null && oldImage == 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
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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
+ */
+@Deprecated
+public void setImageIndent (int indent) {
+       checkWidget();
+       if (indent < 0) return;
+       if (imageIndent == indent) return;
+       imageIndent = indent;
+       if ((parent.style & SWT.VIRTUAL) != 0) {
+               cached = true;
+       } else {
+               int index = parent.indexOf (this);
+               if (index != -1) {
+                       long hwnd = parent.handle;
+                       LVITEM lvItem = new LVITEM ();
+                       lvItem.mask = OS.LVIF_INDENT;
+                       lvItem.iItem = index;
+                       lvItem.iIndent = indent;
+                       OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
+               }
+       }
+       parent.setScrollWidth (this, false);
+       redraw ();
+}
+
+/**
+ * Sets the text for multiple columns in the table.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param strings the array of new strings
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String [] strings) {
+       checkWidget();
+       if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i=0; i<strings.length; i++) {
+               String string = strings [i];
+               if (string != null) setText (i, string);
+       }
+}
+
+/**
+ * Sets the receiver's text at a column
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param index the column index
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (int index, String string) {
+       checkWidget();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (index == 0) {
+               if (string.equals (text)) return;
+               super.setText (string);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       if (strings == null && index != 0)  {
+               strings = new String [count];
+               strings [0] = text;
+       }
+       if (strings != null) {
+               if (string.equals (strings [index])) return;
+               strings [index] = string;
+       }
+       if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+       if (index == 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) == 0 && cached) {
+                       int itemIndex = parent.indexOf (this);
+                       if (itemIndex != -1) {
+                               long hwnd = parent.handle;
+                               LVITEM lvItem = new LVITEM ();
+                               lvItem.mask = OS.LVIF_TEXT;
+                               lvItem.iItem = itemIndex;
+                               lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                               OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
+                               cached = false;
+                       }
+               }
+               parent.setScrollWidth (this, false);
+       }
+       redraw (index, true, false);
+}
+
+@Override
+public void setText (String string) {
+       checkWidget();
+       setText (0, string);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskBar.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskBar.java
new file mode 100644 (file)
index 0000000..f8b2ec6
--- /dev/null
@@ -0,0 +1,442 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.io.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent the system task bar.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ *
+ * @see Display#getSystemTaskBar
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.6
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TaskBar extends Widget {
+       int itemCount;
+       TaskItem [] items = new TaskItem [4];
+       ITaskbarList3 mTaskbarList3;
+       String iconsDir;
+
+       static final char [] EXE_PATH;
+       static final PROPERTYKEY PKEY_Title = new PROPERTYKEY ();
+       static final PROPERTYKEY PKEY_AppUserModel_IsDestListSeparator = new PROPERTYKEY ();
+       static final String EXE_PATH_KEY = "org.eclipse.swt.win32.taskbar.executable";  //$NON-NLS-1$
+       static final String EXE_ARGS_KEY = "org.eclipse.swt.win32.taskbar.arguments";  //$NON-NLS-1$
+       static final String ICON_KEY = "org.eclipse.swt.win32.taskbar.icon";  //$NON-NLS-1$
+       static final String ICON_INDEX_KEY = "org.eclipse.swt.win32.taskbar.icon.index";  //$NON-NLS-1$
+       static {
+               OS.PSPropertyKeyFromString ("{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2\0".toCharArray (), PKEY_Title); //$NON-NLS-1$
+               OS.PSPropertyKeyFromString ("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 6\0".toCharArray (), PKEY_AppUserModel_IsDestListSeparator); //$NON-NLS-1$
+               char [] buffer = new char [OS.MAX_PATH];
+               while (OS.GetModuleFileName (0, buffer, buffer.length) == buffer.length) {
+                       buffer = new char [buffer.length + OS.MAX_PATH];
+               }
+               EXE_PATH = buffer;
+       }
+
+TaskBar (Display display, int style) {
+       this.display = display;
+       createHandle ();
+       reskinWidget ();
+}
+
+void createHandle () {
+       long[] ppv = new long [1];
+       int hr = COM.CoCreateInstance (COM.CLSID_TaskbarList, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ITaskbarList3, ppv);
+       if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+       mTaskbarList3 = new ITaskbarList3 (ppv [0]);
+}
+
+void createItem (TaskItem item, int index) {
+       if (index == -1) index = itemCount;
+       if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+       if (itemCount == items.length) {
+               TaskItem [] newItems = new TaskItem [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 createItems () {
+       Shell [] shells = display.getShells ();
+       for (int i = 0; i < shells.length; i++) {
+               getItem (shells[i]);
+       }
+       getItem (null);
+}
+
+IShellLink createShellLink (MenuItem item) {
+       int style = item.getStyle ();
+       if ((style & SWT.CASCADE) != 0) return null;
+       long [] ppv = new long [1];
+       int hr = COM.CoCreateInstance (COM.CLSID_ShellLink, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IShellLinkW, ppv);
+       if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+       IShellLink pLink = new IShellLink (ppv [0]);
+
+       long hHeap = OS.GetProcessHeap ();
+       long pv = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, OS.PROPVARIANT_sizeof());
+       long titlePtr = 0;
+       PROPERTYKEY key;
+       if ((style & SWT.SEPARATOR) != 0) {
+               OS.MoveMemory (pv, new short [] {OS.VT_BOOL}, 2);
+               OS.MoveMemory (pv + 8, new short [] {OS.VARIANT_TRUE}, 2);
+               key = PKEY_AppUserModel_IsDestListSeparator;
+       } else {
+               String text = item.getText ();
+               int length = text.length ();
+               char [] buffer = new char [length + 1];
+               text.getChars (0, length, buffer, 0);
+               titlePtr = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, buffer.length * 2);
+               OS.MoveMemory (titlePtr, buffer, buffer.length * 2);
+               OS.MoveMemory (pv, new short [] {OS.VT_LPWSTR}, 2);
+               OS.MoveMemory (pv + 8, new long [] {titlePtr}, C.PTR_SIZEOF);
+               key = PKEY_Title;
+
+               String exePath = (String)item.getData (EXE_PATH_KEY);
+               if (exePath != null) {
+                       length = exePath.length ();
+                       buffer = new char [length + 1];
+                       exePath.getChars (0, length, buffer, 0);
+               } else {
+                       buffer = EXE_PATH;
+               }
+               hr = pLink.SetPath(buffer);
+               if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+
+               text = (String)item.getData (EXE_ARGS_KEY);
+               if (text == null) text = Display.LAUNCHER_PREFIX + Display.TASKBAR_EVENT + item.id;
+               length = text.length ();
+               buffer = new char [length + 1];
+               text.getChars (0, length, buffer, 0);
+               hr = pLink.SetArguments(buffer);
+               if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+
+               /* This code is intentionally commented */
+//             String tooltip = item.tooltip;
+//             if (tooltip != null) {
+//                     length = tooltip.length ();
+//                     buffer = new char [length + 1];
+//                     tooltip.getChars (0, length, buffer, 0);
+//                     hr = pLink.SetDescription (buffer);
+//                     if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+//             }
+
+               String icon = (String)item.getData (ICON_KEY);
+               int index = 0;
+               if (icon != null) {
+                       text = (String)item.getData (ICON_INDEX_KEY);
+                       if (text != null) index = Integer.parseInt (text);
+               } else {
+                       String directory = null;
+                       Image image = item.getImage ();
+                       if (image != null) directory = getIconsDir ();
+                       if (directory != null) {
+                               icon = directory + "\\" + "menu" + item.id + ".ico";
+                               ImageData data;
+                               if (item.hBitmap != 0) {
+                                       Image image2 = Image.win32_new (display, SWT.BITMAP, item.hBitmap);
+                                       data = image2.getImageData (DPIUtil.getDeviceZoom ());
+                               } else {
+                                       data = image.getImageData (DPIUtil.getDeviceZoom ());
+                               }
+                               ImageLoader loader = new ImageLoader ();
+                               loader.data = new ImageData [] {data};
+                               loader.save (icon, SWT.IMAGE_ICO);
+                       }
+               }
+               if (icon != null) {
+                       length = icon.length ();
+                       buffer = new char [length + 1];
+                       icon.getChars (0, length, buffer, 0);
+                       hr = pLink.SetIconLocation(buffer, index);
+                       if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+
+       hr = pLink.QueryInterface(COM.IID_IPropertyStore, ppv);
+       if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+       IPropertyStore pPropStore = new IPropertyStore (ppv [0]);
+       hr = pPropStore.SetValue(key, pv);
+       if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+       pPropStore.Commit();
+       pPropStore.Release();
+
+       OS.HeapFree (hHeap, 0, pv);
+       if (titlePtr != 0) OS.HeapFree (hHeap, 0, titlePtr);
+       return pLink;
+}
+
+IObjectArray createShellLinkArray (MenuItem [] items) {
+       if (items == null) return null;
+       if (items.length == 0) return null;
+       long [] ppv = new long [1];
+       int hr = COM.CoCreateInstance (COM.CLSID_EnumerableObjectCollection, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IObjectCollection, ppv);
+       if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+       IObjectCollection pObjColl = new IObjectCollection (ppv [0]);
+       for (int i = 0; i < items.length; i++) {
+               IShellLink pLink = createShellLink (items[i]);
+               if (pLink != null) {
+                       /*IObjectCollection::AddObject*/
+                       pObjColl.AddObject (pLink);
+                       if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+                       pLink.Release ();
+               }
+       }
+       /*IUnknown::QueryInterface*/
+       hr = pObjColl.QueryInterface(COM.IID_IObjectArray, ppv);
+       if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+       IObjectArray poa = new IObjectArray (ppv [0]);
+       pObjColl.Release ();
+       return poa;
+}
+
+void destroyItem (TaskItem item) {
+       int index = 0;
+       while (index < itemCount) {
+               if (items [index] == item) break;
+               index++;
+       }
+       if (index == itemCount) return;
+       System.arraycopy (items, index + 1, items, index, --itemCount - index);
+       items [itemCount] = null;
+}
+
+String getIconsDir() {
+       if (iconsDir != null) return iconsDir;
+       String appData = System.getenv("LOCALAPPDATA");
+       String appName = Display.APP_NAME;
+       if (appData == null || appName == null) return null;
+       appName = appName.replaceAll("[\\\\/:*?\"<>|]", "_");
+       File dir = new File(appData + "\\" + appName + "\\ico_dir");
+       if (dir.exists()) {
+               // remove old icons
+               for (File file : dir.listFiles()) file.delete();
+       } else if (!dir.mkdirs()) {
+               return null;
+       }
+       return iconsDir = dir.getPath();
+}
+
+/**
+ * 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 TaskItem getItem (int index) {
+       checkWidget ();
+       createItems ();
+       if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+       return items [index];
+}
+
+/**
+ * Returns the <code>TaskItem</code> for the given <code>Shell</code> or the <code>TaskItem</code>
+ * for the application if the <code>Shell</code> parameter is <code>null</code>.
+ * If the requested item is not supported by the platform it returns <code>null</code>.
+ *
+ * @param shell the shell for which the task item is requested, or null to request the application item
+ * @return the task item for the given shell or the application
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public TaskItem getItem (Shell shell) {
+       checkWidget ();
+       for (int i = 0; i < items.length; i++) {
+               if (items [i] != null && items [i].shell == shell) {
+                       return items [i];
+               }
+       }
+       TaskItem item = new TaskItem (this, SWT.NONE);
+       if (shell != null) item.setShell (shell);
+       return item;
+}
+
+/**
+ * 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 ();
+       createItems ();
+       return itemCount;
+}
+
+/**
+ * Returns an array of <code>TaskItem</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 TaskItem [] getItems () {
+       checkWidget ();
+       createItems ();
+       TaskItem [] result = new TaskItem [itemCount];
+       System.arraycopy (items, 0, result, 0, result.length);
+       return result;
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       TaskItem item = items [i];
+                       if (item != null && !item.isDisposed ()) {
+                               item.release (false);
+                       }
+               }
+               items = null;
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (display.taskBar == this) display.taskBar = null;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       mTaskbarList3.Release();
+       mTaskbarList3 = null;
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       TaskItem item = items [i];
+                       if (item != null) item.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+void setMenu (Menu menu) {
+       long [] ppv = new long [1];
+       int hr = COM.CoCreateInstance (COM.CLSID_DestinationList, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ICustomDestinationList, ppv);
+       if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+       ICustomDestinationList pDestList = new ICustomDestinationList (ppv [0]);
+       String appName = Display.APP_NAME;
+       char [] buffer = {'S', 'W', 'T', '\0'};
+       if (appName != null && appName.length () > 0) {
+               int length = appName.length ();
+               buffer = new char [length + 1];
+               appName.getChars (0, length, buffer, 0);
+       }
+       MenuItem [] items = null;
+       if (menu != null && (items = menu.getItems ()).length != 0) {
+               IObjectArray poa = createShellLinkArray (items);
+               if (poa != null) {
+                       hr = pDestList.SetAppID (buffer);
+                       if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+
+                       int [] cMaxSlots = new int [1];
+                       pDestList.BeginList(cMaxSlots, COM.IID_IObjectArray, ppv);
+                       if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+                       IObjectArray pRemovedItems = new IObjectArray (ppv [0]);
+
+                       int [] count = new int [1];
+                       poa.GetCount (count);
+                       if (count [0] != 0) {
+                               hr = pDestList.AddUserTasks (poa);
+                               if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+                       }
+
+                       for (int i = 0; i < items.length; i++) {
+                               MenuItem item = items [i];
+                               if ((item.getStyle () & SWT.CASCADE) != 0) {
+                                       Menu subMenu = item.getMenu ();
+                                       if (subMenu != null) {
+                                               MenuItem [] subItems = subMenu.getItems ();
+                                               IObjectArray poa2 = createShellLinkArray (subItems);
+                                               if (poa2 != null) {
+                                                       poa2.GetCount (count);
+                                                       if (count [0] != 0) {
+                                                               String text = item.getText ();
+                                                               int length = text.length ();
+                                                               char [] buffer2 = new char [length + 1];
+                                                               text.getChars (0, length, buffer2, 0);
+                                                               hr = pDestList.AppendCategory (buffer2, poa2);
+                                                               if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+                                                       }
+                                                       /*IUnknown::Release*/
+                                                       poa2.Release ();
+                                               }
+                                       }
+                               }
+                       }
+                       poa.Release();
+                       hr = pDestList.CommitList ();
+                       if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+                       pRemovedItems.Release ();
+               }
+       } else {
+               hr = pDestList.DeleteList (buffer);
+               if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       pDestList.Release ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskItem.java
new file mode 100644 (file)
index 0000000..e1c26b5
--- /dev/null
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent a task item.
+ *
+ * <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>
+ *
+ * @since 3.6
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TaskItem extends Item {
+       TaskBar parent;
+       Shell shell;
+       int progress, progressState = SWT.DEFAULT;
+       Image overlayImage;
+       String overlayText = "";
+       boolean showingText = false;
+       Menu menu;
+
+       static final int PROGRESS_MAX = 100;
+
+/**
+ * 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
+ */
+TaskItem (TaskBar parent, int style) {
+       super (parent, style);
+       this.parent = parent;
+       parent.createItem (this, -1);
+}
+
+@Override
+protected void checkSubclass () {
+       if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+@Override
+void destroyWidget () {
+       parent.destroyItem (this);
+       releaseHandle ();
+}
+
+/**
+ * Returns the receiver's pop up menu if it has one, or null
+ * if it does not.
+ *
+ * @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 overlay image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's overlay 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 getOverlayImage () {
+       checkWidget ();
+       return overlayImage;
+}
+
+/**
+ * Returns the receiver's overlay text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's overlay 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 getOverlayText () {
+       checkWidget ();
+       return overlayText;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>TaskBar</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 TaskBar getParent () {
+       checkWidget ();
+       return parent;
+}
+
+/**
+ * Returns the receiver's progress.
+ *
+ * @return the receiver's 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>
+ */
+public int getProgress () {
+       checkWidget ();
+       return progress;
+}
+
+/**
+ * Returns the receiver's progress state.
+ *
+ * @return the receiver's progress 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 int getProgressState () {
+       checkWidget ();
+       return progressState;
+}
+
+void recreate () {
+       if (showingText) {
+               if (overlayText.length () != 0) updateText ();
+       } else {
+               if (overlayImage != null) updateImage ();
+       }
+       if (progress != 0) updateProgress ();
+       if (progressState != SWT.DEFAULT) updateProgressState ();
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       parent = null;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       overlayImage = null;
+       overlayText = null;
+}
+
+/**
+ * Sets the receiver's pop up menu to the argument. The way the menu is
+ * shown is platform specific.
+ *
+ * <p>
+ * This feature might not be available for the receiver on all
+ * platforms. The application code can check if it is supported
+ * by calling the respective get method. When the feature is not
+ * available, the get method will always return the NULL.</p>
+ *
+ * <p>
+ * For better cross platform support, the application code should
+ * set this feature on the <code>TaskItem</code> for application.<br>
+ * On Windows, this feature will only work on RCP applications.</p>
+ *
+ * <p>
+ * The menu should be fully created before this method is called.
+ * Dynamic changes to the menu after the method is called will not be reflected
+ * in the native menu.</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_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 != null) {
+               if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               if ((menu.style & SWT.POP_UP) == 0) {
+                       error (SWT.ERROR_MENU_NOT_POP_UP);
+               }
+       }
+       if (shell != null) return;
+       this.menu = menu;
+       parent.setMenu (menu);
+}
+
+/**
+ * Sets the receiver's overlay image, which may be null
+ * indicating that no image should be displayed. The bounds
+ * for the overlay image is determined by the platform and in
+ * general it should be a small image.
+ *
+ * <p>
+ * This feature might not be available for the receiver on all
+ * platforms. The application code can check if it is supported
+ * by calling the respective get method. When the feature is not
+ * available, the get method will always return the NULL.</p>
+ *
+ * <p>
+ * For better cross platform support, the application code should
+ * first try to set this feature on the <code>TaskItem</code> for the
+ * main shell then on the <code>TaskItem</code> for the application.</p>
+ *
+ * @param overlayImage the new overlay image (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the overlayImage 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 setOverlayImage (Image overlayImage) {
+       checkWidget ();
+       if (overlayImage != null && overlayImage.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (shell == null) return;
+       this.overlayImage = overlayImage;
+       if (overlayImage != null) {
+               updateImage ();
+       } else {
+               if (overlayText.length () != 0) {
+                       updateText ();
+               } else {
+                       parent.mTaskbarList3.SetOverlayIcon(shell.handle, 0, 0);
+               }
+       }
+}
+
+/**
+ * Sets the receiver's overlay text. The space available to display the
+ * overlay text is platform dependent and in general it should be no longer
+ * than a few characters.
+ *
+ * <p>
+ * This feature might not be available for the receiver on all
+ * platforms. The application code can check if it is supported
+ * by calling the respective get method. When the feature is not
+ * available, the get method will always return an empty string.</p>
+ *
+ * <p>
+ * For better cross platform support, the application code should
+ * first try to set this feature on the <code>TaskItem</code> for the
+ * main shell then on the <code>TaskItem</code> for the application.</p>
+ *
+ * @param overlayText the new overlay text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the overlayText 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 setOverlayText (String overlayText) {
+       checkWidget ();
+       if (overlayText == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (shell == null) return;
+       this.overlayText = overlayText;
+       if (overlayText.length () != 0) {
+               updateText ();
+       } else {
+               if (overlayImage != null) {
+                       updateImage ();
+               } else {
+                       parent.mTaskbarList3.SetOverlayIcon(shell.handle, 0, 0);
+               }
+       }
+}
+
+/**
+ * Sets the receiver's progress, the progress represents a percentage and
+ * should be in range from 0 to 100. The progress is only shown when the progress
+ * state is different than <code>SWT#DEFAULT</code>.
+ *
+ * <p>
+ * This feature might not be available for the receiver on all
+ * platforms. The application code can check if it is supported
+ * by calling the respective get method. When the feature is not
+ * available, the get method will always return zero.</p>
+ *
+ * <p>
+ * For better cross platform support, the application code should
+ * first try to set this feature on the <code>TaskItem</code> for the
+ * main shell then on the <code>TaskItem</code> for the application.</p>
+ *
+ * @param progress the new 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 {@link #setProgressState(int)}
+ */
+public void setProgress (int progress) {
+       checkWidget ();
+       if (shell == null) return;
+       progress = Math.max (0, Math.min (progress, PROGRESS_MAX));
+       if (this.progress == progress) return;
+       this.progress = progress;
+       updateProgress ();
+}
+
+/**
+ * Sets the receiver's progress state, the state can be one of
+ * the following:
+ * <ul>
+ * <li>{@link SWT#DEFAULT}</li>
+ * <li>{@link SWT#NORMAL}</li>
+ * <li>{@link SWT#PAUSED}</li>
+ * <li>{@link SWT#ERROR}</li>
+ * <li>{@link SWT#INDETERMINATE}</li>
+ * </ul>
+ *
+ * The percentage of progress shown by the states <code>SWT#NORMAL</code>, <code>SWT#PAUSED</code>,
+ * <code>SWT#ERROR</code> is set with <code>setProgress()</code>. <br>
+ * The state <code>SWT#DEFAULT</code> indicates that no progress should be shown.
+ *
+ * <p>
+ * This feature might not be available for the receiver on all
+ * platforms. The application code can check if it is supported
+ * by calling the respective get method. When the feature is not
+ * available, the get method will always return <code>SWT#DEFAULT</code>.</p>
+ *
+ * <p>
+ * For better cross platform support, the application code should
+ * first try to set this feature on the <code>TaskItem</code> for the
+ * main shell then on the <code>TaskItem</code> for the application.</p>
+ *
+ * @param progressState the new progress 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 {@link #setProgress(int)}
+ */
+public void setProgressState (int progressState) {
+       checkWidget ();
+       if (shell == null) return;
+       if (this.progressState == progressState) return;
+       this.progressState = progressState;
+       updateProgressState ();
+}
+
+void setShell (Shell shell) {
+       this.shell = shell;
+       shell.addListener (SWT.Dispose, new Listener () {
+               @Override
+               public void handleEvent (Event event) {
+                       if (isDisposed ()) return;
+                       dispose ();
+               }
+       });
+}
+
+void updateImage () {
+       showingText = false;
+       Image image2 = null;
+       long hIcon = 0;
+       switch (overlayImage.type) {
+               case SWT.BITMAP:
+                       image2 = Display.createIcon (overlayImage);
+                       hIcon = image2.handle;
+                       break;
+               case SWT.ICON:
+                       hIcon = overlayImage.handle;
+                       break;
+       }
+       parent.mTaskbarList3.SetOverlayIcon(shell.handle, hIcon, 0);
+       if (image2 != null) image2.dispose ();
+}
+
+void updateProgress () {
+       if (progressState == SWT.INDETERMINATE) return;
+       if (progressState == SWT.DEFAULT) return;
+       parent.mTaskbarList3.SetProgressValue(shell.handle, progress, PROGRESS_MAX);
+}
+
+void updateProgressState () {
+       int tbpFlags = OS.TBPF_NOPROGRESS;
+       switch (progressState) {
+               case SWT.NORMAL: tbpFlags = OS.TBPF_NORMAL; break;
+               case SWT.ERROR: tbpFlags = OS.TBPF_ERROR; break;
+               case SWT.PAUSED: tbpFlags = OS.TBPF_PAUSED; break;
+               case SWT.INDETERMINATE: tbpFlags = OS.TBPF_INDETERMINATE; break;
+       }
+       parent.mTaskbarList3.SetProgressValue(shell.handle, progress, PROGRESS_MAX);
+       parent.mTaskbarList3.SetProgressState(shell.handle, tbpFlags);
+}
+
+void updateText () {
+       showingText = true;
+       /* Create resources */
+       int width = 16, height = 16;
+       long hdc = OS.GetDC (0);
+       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+       bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+       bmiHeader.biWidth = width;
+       bmiHeader.biHeight = -height;
+       bmiHeader.biPlanes = 1;
+       bmiHeader.biBitCount = 32;
+       bmiHeader.biCompression = OS.BI_RGB;
+       byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
+       OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+       long [] pBits = new long [1];
+       long hBitmap = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+       if (hBitmap == 0) error (SWT.ERROR_NO_HANDLES);
+       long dstHdc = OS.CreateCompatibleDC (hdc);
+       long oldBitmap = OS.SelectObject (dstHdc, hBitmap);
+       long hMask = OS.CreateBitmap (width, height, 1, 1, null);
+       if (hMask == 0) error (SWT.ERROR_NO_HANDLES);
+       long maskHdc = OS.CreateCompatibleDC (hdc);
+       long oldMask = OS.SelectObject (maskHdc, hMask);
+
+       /* Draw content */
+       OS.PatBlt (maskHdc, 0, 0, width, height, OS.WHITENESS);
+       long oldBrush = OS.SelectObject (maskHdc, OS.GetStockObject (OS.BLACK_BRUSH));
+       OS.RoundRect (maskHdc, 0, 0, width, height, 8, 8);
+       OS.SelectObject (maskHdc, oldBrush);
+
+       long brush = OS.CreateSolidBrush (OS.GetSysColor (OS.COLOR_HIGHLIGHT));
+       oldBrush = OS.SelectObject (dstHdc, brush);
+       OS.RoundRect (dstHdc, 0, 0, width, height, 8, 8);
+       OS.SelectObject (dstHdc, oldBrush);
+       OS.DeleteObject (brush);
+
+       int uFormat = OS.DT_LEFT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+       RECT rect = new RECT ();
+       char [] buffer = overlayText.toCharArray ();
+       int length = buffer.length;
+       long hFont = 0, oldHFont = 0;
+       NONCLIENTMETRICS info = new NONCLIENTMETRICS ();
+       info.cbSize = NONCLIENTMETRICS.sizeof;
+       if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, info, 0)) {
+               LOGFONT logFont = info.lfMessageFont;
+               logFont.lfHeight = -10;
+               hFont = OS.CreateFontIndirect (logFont);
+               oldHFont = OS.SelectObject (dstHdc, hFont);
+               OS.DrawText (dstHdc, buffer, length, rect, uFormat | OS.DT_CALCRECT);
+               if (rect.right > width - 2) {
+                       OS.SelectObject (dstHdc, oldHFont);
+                       OS.DeleteObject (hFont);
+                       logFont.lfHeight = -8;
+                       hFont = OS.CreateFontIndirect (logFont);
+                       OS.SelectObject (dstHdc, hFont);
+               }
+       }
+       OS.DrawText (dstHdc, buffer, length, rect, uFormat | OS.DT_CALCRECT);
+       OS.OffsetRect (rect, (width - rect.right) / 2, (height - rect.bottom) / 2);
+       int oldBkMode = OS.SetBkMode (dstHdc, OS.TRANSPARENT);
+       OS.SetTextColor (dstHdc, OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT));
+       OS.DrawText (dstHdc, buffer, length, rect, uFormat);
+       if (hFont != 0) {
+               OS.SelectObject (dstHdc, oldHFont);
+               OS.DeleteObject (hFont);
+       }
+       OS.SetBkMode(dstHdc, oldBkMode);
+
+       /* Release resources */
+       OS.SelectObject (dstHdc, oldBitmap);
+       OS.DeleteDC (dstHdc);
+       OS.SelectObject (maskHdc, oldMask);
+       OS.DeleteDC (maskHdc);
+       OS.ReleaseDC (0, hdc);
+
+       ICONINFO iconInfo = new ICONINFO ();
+       iconInfo.fIcon = true;
+       iconInfo.hbmColor = hBitmap;
+       iconInfo.hbmMask = hMask;
+       long hIcon = OS.CreateIconIndirect (iconInfo);
+       if (hIcon == 0) error (SWT.ERROR_NO_HANDLES);
+       OS.DeleteObject (hBitmap);
+       OS.DeleteObject (hMask);
+
+       parent.mTaskbarList3.SetOverlayIcon(shell.handle, hIcon, 0);
+       OS.DestroyIcon (hIcon);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Text.java
new file mode 100644 (file)
index 0000000..fa06e8a
--- /dev/null
@@ -0,0 +1,3089 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>CENTER, ICON_CANCEL, ICON_SEARCH, LEFT, MULTI, PASSWORD, SEARCH, SINGLE, RIGHT, READ_ONLY, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, Modify, Verify, OrientationChange</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>
+ * Note: The styles ICON_CANCEL and ICON_SEARCH are hints used in combination with SEARCH.
+ * When the platform supports the hint, the text control shows these icons.  When an icon
+ * is selected, a default selection event is sent with the detail field set to one of
+ * ICON_CANCEL or ICON_SEARCH.  Normally, application code does not need to check the
+ * detail.  In the case of ICON_CANCEL, the text is cleared before the default selection
+ * event is sent causing the application to search for an empty string.
+ * </p>
+ * <p>
+ * Note: Some text actions such as Undo are not natively supported on all platforms.
+ * </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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Text extends Scrollable {
+       int tabs, oldStart, oldEnd;
+       boolean doubleClick, ignoreModify, ignoreVerify, ignoreCharacter, allowPasswordChar;
+       String message;
+       int[] segments;
+       int clearSegmentsCount = 0;
+       long hwndSearch, hwndCancel, hwndActive;
+
+       static final char LTR_MARK = '\u200e';
+       static final char RTL_MARK = '\u200f';
+
+       /* Custom icons defined in swt.rc */
+       static final int IDI_SEARCH = 101;
+       static final int IDI_CANCEL = 102;
+
+       /**
+       * 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>
+       */
+       public static final int 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 final String DELIMITER;
+
+       /*
+       * 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.
+       */
+       static {
+               LIMIT = 0x7FFFFFFF;
+               DELIMITER = "\r\n";
+       }
+
+       static final long EditProc;
+       static final TCHAR EditClass = new TCHAR (0, "EDIT", true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, EditClass, lpWndClass);
+               EditProc = lpWndClass.lpfnWndProc;
+               /*
+               * This code is intentionally commented.
+               */
+//             long 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 != 0 ? echo : '*';
+       }
+
+/**
+ * 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 SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see SWT#PASSWORD
+ * @see SWT#SEARCH
+ * @see SWT#ICON_SEARCH
+ * @see SWT#ICON_CANCEL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Text (Composite parent, int style) {
+       super (parent, checkStyle (style));
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       boolean redraw = false;
+       switch (msg) {
+               case OS.WM_ERASEBKGND: {
+                       if (findImageControl () != null) return 0;
+                       break;
+               }
+               case OS.WM_HSCROLL:
+               case OS.WM_VSCROLL: {
+                       redraw = findImageControl () != null && getDrawing () && OS.IsWindowVisible (handle);
+                       if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                       break;
+               }
+               case OS.WM_PAINT: {
+                       boolean doubleBuffer = findImageControl () != null;
+                       boolean drawMessage = false;
+                       if ((style & SWT.SINGLE) != 0 && (style & SWT.READ_ONLY) != 0 && message.length () > 0 ) {
+                               drawMessage = hwnd != OS.GetFocus () && OS.GetWindowTextLength (handle) == 0;
+                       }
+                       if (doubleBuffer || drawMessage) {
+                               long paintDC = 0;
+                               PAINTSTRUCT ps = new PAINTSTRUCT ();
+                               paintDC = OS.BeginPaint (handle, ps);
+                               int width = ps.right - ps.left;
+                               int height = ps.bottom - ps.top;
+                               if (width != 0 && height != 0) {
+                                       long hDC = paintDC, hBitmap = 0, hOldBitmap = 0;
+                                       POINT lpPoint1 = null, lpPoint2 = null;
+                                       if (doubleBuffer) {
+                                               hDC = OS.CreateCompatibleDC (paintDC);
+                                               lpPoint1 = new POINT ();
+                                               lpPoint2 = new POINT ();
+                                               OS.SetWindowOrgEx (hDC, ps.left, ps.top, lpPoint1);
+                                               OS.SetBrushOrgEx (hDC, ps.left, ps.top, lpPoint2);
+                                               hBitmap = OS.CreateCompatibleBitmap (paintDC, width, height);
+                                               hOldBitmap = OS.SelectObject (hDC, hBitmap);
+                                               RECT rect = new RECT ();
+                                               OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                               drawBackground (hDC, rect);
+                                       }
+
+                                       OS.CallWindowProc (EditProc, hwnd, OS.WM_PAINT, hDC, lParam);
+                                       /*
+                                       * Bug in Windows.  Windows does not draw the cue message when the Edit
+                                       * control is read-only. The fix is to draw the cue messages ourselves.
+                                       */
+                                       if (drawMessage) {
+                                               RECT rect = new RECT();
+                                               OS.GetClientRect(handle, rect);
+                                               long margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
+                                               rect.left += OS.LOWORD (margins);
+                                               rect.right -= OS.HIWORD (margins);
+                                               if ((style & SWT.BORDER) != 0) {
+                                                       rect.left++;
+                                                       rect.top++;
+                                                       rect.right--;
+                                                       rect.bottom--;
+                                               }
+                                               char [] buffer = message.toCharArray ();
+                                               int uFormat = OS.DT_EDITCONTROL;
+                                               boolean rtl = (style & SWT.RIGHT_TO_LEFT) != 0;
+                                               if (rtl) uFormat |= OS.DT_RTLREADING;
+                                               int alignment = style & (SWT.LEFT | SWT.CENTER | SWT.RIGHT);
+                                               switch (alignment) {
+                                                       case SWT.LEFT: uFormat |= (rtl ? OS.DT_RIGHT : OS.DT_LEFT); break;
+                                                       case SWT.CENTER: uFormat |= OS.DT_CENTER;
+                                                       case SWT.RIGHT: uFormat |= (rtl ? OS.DT_LEFT : OS.DT_RIGHT); break;
+                                               }
+                                               long hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+                                               long hOldFont = OS.SelectObject (hDC, hFont);
+                                               OS.SetTextColor (hDC, OS.GetSysColor (OS.COLOR_GRAYTEXT));
+                                               OS.SetBkMode (hDC, OS.TRANSPARENT);
+                                               OS.DrawText (hDC, buffer, buffer.length, rect, uFormat);
+                                               OS.SelectObject (hDC, hOldFont);
+                                       }
+
+                                       if (doubleBuffer) {
+                                               OS.SetWindowOrgEx (hDC, lpPoint1.x, lpPoint1.y, null);
+                                               OS.SetBrushOrgEx (hDC, lpPoint2.x, lpPoint2.y, null);
+                                               OS.BitBlt (paintDC, ps.left, ps.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;
+               }
+       }
+       if ((style & SWT.SEARCH) != 0) {
+               switch (msg) {
+                       case OS.WM_MOUSEMOVE: {
+                               POINT pt = new POINT ();
+                               OS.POINTSTOPOINT(pt, lParam);
+                               long prevActive = hwndActive;
+                               hwndActive = OS.ChildWindowFromPointEx (handle, pt, OS.CWP_SKIPINVISIBLE);
+                               if (hwndActive == handle) hwndActive = 0;
+                               if (prevActive != hwndActive) {
+                                       if (prevActive != 0) OS.InvalidateRect (prevActive, null, false);
+                                       if (hwndActive != 0) OS.InvalidateRect (hwndActive, null, false);
+                               }
+                               break;
+                       }
+                       case OS.WM_MOUSELEAVE:
+                               if (hwndActive != 0) {
+                                       OS.InvalidateRect (hwndActive, null, false);
+                                       hwndActive = 0;
+                               }
+                               break;
+                       case OS.WM_LBUTTONDOWN:
+                               if (hwndActive != 0) {
+                                       OS.InvalidateRect (hwndActive, null, false);
+                                       return 0; // prevent mouse selection
+                               }
+                               break;
+                       case OS.WM_LBUTTONUP: {
+                               if (hwndActive != 0) {
+                                       Event e = new Event();
+                                       if (hwndActive == hwndSearch) {
+                                               e.detail = SWT.ICON_SEARCH;
+                                       } else {
+                                               e.detail = SWT.ICON_CANCEL;
+                                               setText ("");
+                                       }
+                                       setFocus ();
+                                       selectAll ();
+                                       sendSelectionEvent (SWT.DefaultSelection, e, false);
+                               }
+                               break;
+                       }
+               }
+       }
+       long code = OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
+       switch (msg) {
+               case OS.WM_HSCROLL:
+               case OS.WM_VSCROLL: {
+                       if (redraw) {
+                               OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                               OS.InvalidateRect (handle, null, true);
+                       }
+                       break;
+               }
+       }
+       return code;
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       OS.SendMessage (handle, OS.EM_LIMITTEXT, 0, 0);
+       if ((style & SWT.READ_ONLY) != 0) {
+               if (applyThemeBackground () == 1) {
+                       state |= THEME_BACKGROUND;
+               }
+       }
+       if ((style & SWT.SEARCH) != 0) {
+               if (display.hIconSearch == 0) {
+                       long [] phicon = new long [1];
+                       int hresult = OS.LoadIconMetric (OS.GetLibraryHandle (), IDI_SEARCH, OS.LIM_SMALL, phicon);
+                       if (hresult != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+                       display.hIconSearch = phicon [0];
+                       hresult = OS.LoadIconMetric (OS.GetLibraryHandle (), IDI_CANCEL, OS.LIM_SMALL, phicon);
+                       if (hresult != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
+                       display.hIconCancel = phicon [0];
+               }
+               if ((style & SWT.ICON_SEARCH) != 0) {
+                       hwndSearch = OS.CreateWindowEx (0, Label.LabelClass, null,
+                                       OS.WS_CHILD | OS.WS_VISIBLE | OS.WS_CLIPSIBLINGS | OS.SS_OWNERDRAW,
+                                       0, 0, 0, 0, handle, 0, OS.GetModuleHandle (null), null);
+                       if (hwndSearch == 0) error (SWT.ERROR_NO_HANDLES);
+               }
+               if ((style & SWT.ICON_CANCEL) != 0) {
+                       state |= TRACK_MOUSE;
+                       hwndCancel = OS.CreateWindowEx (0, Label.LabelClass, null,
+                                       OS.WS_CHILD | OS.WS_CLIPSIBLINGS | OS.SS_OWNERDRAW,
+                                       0, 0, 0, 0, handle, 0, OS.GetModuleHandle (null), null);
+                       if (hwndCancel == 0) error (SWT.ERROR_NO_HANDLES);
+               }
+       }
+}
+
+@Override
+int applyThemeBackground () {
+       return (backgroundAlpha == 0 || (style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) ? 1 : 0;
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds a segment listener.
+ * <p>
+ * A <code>SegmentEvent</code> is sent whenever text content is being modified or
+ * a segment listener is added or removed. You can
+ * customize the appearance of text by indicating certain characters to be inserted
+ * at certain text offsets. This may be used for bidi purposes, e.g. 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>
+ * <p>
+ * <b>Warning</b>: This API is currently only implemented on Windows and GTK.
+ * <code>SegmentEvent</code>s won't be sent on Cocoa.
+ * </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 SegmentEvent
+ * @see SegmentListener
+ * @see #removeSegmentListener
+ *
+ * @since 3.8
+ */
+public void addSegmentListener (SegmentListener listener) {
+       checkWidget ();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       addListener (SWT.Segments, new TypedListener (listener));
+       clearSegments (true);
+       applySegments ();
+}
+
+/**
+ * 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.ICON_CANCEL</code> style
+ * and the user cancels the search, the event object detail field contains the value <code>SWT.ICON_CANCEL</code>.
+ * Likewise, if the receiver has the <code>SWT.ICON_SEARCH</code> style and the icon search is selected, the
+ * event object detail field contains the value <code>SWT.ICON_SEARCH</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 == 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 == 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 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>
+ */
+public void append (String string) {
+       checkWidget ();
+       if (string == 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 == null) return;
+       }
+       OS.SendMessage (handle, OS.EM_SETSEL, length, length);
+       clearSegments (true);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       /*
+       * 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);
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               super.updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+       applySegments ();
+}
+
+void applySegments () {
+       /*
+        * It is possible (but unlikely), that application code could have
+        * disposed the widget in the modify event. If this happens, return to
+        * cancel the operation.
+        */
+       if (isDisposed() || --clearSegmentsCount != 0) return;
+       if (!hooks (SWT.Segments) && !filters (SWT.Segments)) return;
+       int length = OS.GetWindowTextLength (handle);
+       char [] buffer = new char [length + 1];
+       if (length > 0) OS.GetWindowText (handle, buffer, length + 1);
+       String string = new String (buffer, 0, length);
+       /* Get segments text */
+       Event event = new Event ();
+       event.text = string;
+       event.segments = segments;
+       sendEvent (SWT.Segments, event);
+       segments = event.segments;
+       if (segments == null) return;
+       int nSegments = segments.length;
+       if (nSegments == 0) return;
+       length = string == null ? 0 : string.length ();
+
+       for (int i = 1; i < nSegments; i++) {
+               if (event.segments [i] < event.segments [i - 1] || event.segments [i] > length) {
+                       error (SWT.ERROR_INVALID_ARGUMENT);
+               }
+       }
+       char [] segmentsChars = event.segmentsChars;
+       char [] segmentsCharsCrLf = segmentsChars == null ? null : Display.withCrLf(segmentsChars);
+       if (segmentsChars != segmentsCharsCrLf) {
+               int [] segmentsCrLf = new int [nSegments + Math.min (nSegments, segmentsCharsCrLf.length - segmentsChars.length)];
+               for (int i = 0, c = 0; i < segmentsChars.length && i < nSegments; i++) {
+                       if (segmentsChars [i] == '\n' && segmentsCharsCrLf [i + c] == '\r') {
+                               segmentsCrLf [i + c++] = segments [i];
+                       }
+                       segmentsCrLf [i + c] = segments [i];
+               }
+               segments = segmentsCrLf;
+               nSegments = segments.length;
+               segmentsChars = segmentsCharsCrLf;
+       }
+
+       int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
+       OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min (nSegments, LIMIT - limit), 0);
+       length += nSegments;
+       char [] newChars = new char [length + 1];
+       int charCount = 0, segmentCount = 0;
+       char defaultSeparator = getOrientation () == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
+       while (charCount < length) {
+               if (segmentCount < nSegments && charCount - segmentCount == segments [segmentCount]) {
+                       char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
+                       newChars [charCount++] = separator;
+                       segmentCount++;
+               } else if (string != null) {
+                       newChars [charCount] = string.charAt (charCount++ - segmentCount);
+               }
+       }
+       while (segmentCount < nSegments) {
+               segments [segmentCount] = charCount - segmentCount;
+               char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
+               newChars [charCount++] = separator;
+               segmentCount++;
+       }
+       /* Get the current selection */
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify;
+       ignoreCharacter = ignoreModify = ignoreVerify = true;
+       /*
+        * SetWindowText empties the undo buffer and disables undo menu item.
+        * Sending OS.EM_REPLACESEL message instead.
+        */
+       newChars [length] = 0;
+       OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
+       long undo = OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0);
+       OS.SendMessage (handle, OS.EM_REPLACESEL, undo, newChars);
+       /* Restore selection */
+       start [0] = translateOffset (start [0]);
+       end [0] = translateOffset (end [0]);
+       OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+       ignoreCharacter = oldIgnoreCharacter;
+       ignoreModify = oldIgnoreModify;
+       ignoreVerify = oldIgnoreVerify;
+}
+
+static int checkStyle (int style) {
+       if ((style & SWT.SINGLE) != 0 && (style & SWT.MULTI) != 0) {
+               style &= ~SWT.MULTI;
+       }
+       style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+       /*
+        * NOTE: ICON_CANCEL and ICON_SEARCH have the same value as H_SCROLL and
+        * V_SCROLL. The meaning is determined by whether SWT.SEARCH is set.
+        */
+       if ((style & SWT.SEARCH) != 0) {
+               style |= SWT.SINGLE | SWT.BORDER;
+               style &= ~(SWT.PASSWORD | SWT.WRAP);
+       } else if ((style & SWT.SINGLE) != 0) {
+               style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
+       }
+       if ((style & SWT.WRAP) != 0) {
+               style |= SWT.MULTI;
+               style &= ~SWT.H_SCROLL;
+       }
+       if ((style & SWT.MULTI) != 0) style &= ~SWT.PASSWORD;
+       if ((style & (SWT.SINGLE | SWT.MULTI)) != 0) return style;
+       if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) return style | SWT.MULTI;
+       return style | SWT.SINGLE;
+}
+
+void clearSegments (boolean applyText) {
+       if (clearSegmentsCount++ != 0) return;
+       if (segments == null) return;
+       int nSegments = segments.length;
+       if (nSegments == 0) return;
+       int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
+       if (limit < LIMIT) {
+               OS.SendMessage (handle, OS.EM_SETLIMITTEXT, Math.max (1, limit - nSegments), 0);
+       }
+       if (!applyText) {
+               segments = null;
+               return;
+       }
+       boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify;
+       ignoreCharacter = ignoreModify = ignoreVerify = true;
+       int length = OS.GetWindowTextLength (handle);
+       int cp = getCodePage ();
+       TCHAR buffer = new TCHAR (cp, length + 1);
+       if (length > 0) OS.GetWindowText (handle, buffer, length + 1);
+       buffer = deprocessText (buffer, 0, -1, true);
+       /* Get the current selection */
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       start [0] = untranslateOffset (start [0]);
+       end [0] = untranslateOffset (end[0]);
+       segments = null;
+       /*
+        * SetWindowText empties the undo buffer and disables undo in the context
+        * menu. Sending OS.EM_REPLACESEL message instead.
+        */
+       OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
+       long undo = OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0);
+       OS.SendMessage (handle, OS.EM_REPLACESEL, undo, buffer);
+       OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+       ignoreCharacter = oldIgnoreCharacter;
+       ignoreModify = oldIgnoreModify;
+       ignoreVerify = oldIgnoreVerify;
+}
+
+/**
+ * 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 ();
+       OS.SendMessage (handle, OS.EM_SETSEL, -1, 0);
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       checkWidget ();
+       int height = 0, width = 0;
+       if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+               long newFont, oldFont = 0;
+               long hDC = OS.GetDC (handle);
+               newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               TEXTMETRIC tm = new TEXTMETRIC ();
+               OS.GetTextMetrics (hDC, tm);
+               int count = (style & SWT.SINGLE) != 0 ? 1 : (int)OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
+               height = count * tm.tmHeight;
+               RECT rect = new RECT ();
+               int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
+               boolean wrap = (style & SWT.MULTI) != 0 && (style & SWT.WRAP) != 0;
+               if (wrap && wHint != SWT.DEFAULT) {
+                       flags |= OS.DT_WORDBREAK;
+                       rect.right = wHint;
+               }
+               int length = OS.GetWindowTextLength (handle);
+               if (length != 0) {
+                       char [] buffer = new char [length + 1];
+                       OS.GetWindowText (handle, buffer, length + 1);
+                       OS.DrawText (hDC, buffer, length, rect, flags);
+                       Arrays.fill (buffer, '\0'); // erase sensitive data
+                       width = rect.right - rect.left;
+               }
+               if (wrap && hHint == SWT.DEFAULT) {
+                       int newHeight = rect.bottom - rect.top;
+                       if (newHeight != 0) height = newHeight;
+               }
+               if ((style & SWT.SINGLE) != 0 && message.length () > 0) {
+                       OS.SetRect (rect, 0, 0, 0, 0);
+                       char [] buffer = message.toCharArray ();
+                       OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+                       width = Math.max (width, rect.right - rect.left);
+               }
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       Rectangle trim = computeTrimInPixels (0, 0, width, height);
+       return new Point (trim.width, trim.height);
+}
+
+@Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       checkWidget ();
+       Rectangle rect = super.computeTrimInPixels (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.
+       */
+       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) != 0) rect.width++;
+       if ((style & SWT.BORDER) != 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) != 0) return;
+       OS.SendMessage (handle, OS.WM_CUT, 0, 0);
+}
+
+@Override
+int defaultBackground () {
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.ES_READONLY) != 0 || !OS.IsWindowEnabled (handle)) {
+               return OS.GetSysColor (OS.COLOR_3DFACE);
+       }
+       return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+TCHAR deprocessText (TCHAR text, int start, int end, boolean terminate) {
+       if (text == null) return null;
+       int length = text.length ();
+       char [] chars;
+       if (start < 0) start = 0;
+       chars = text.chars;
+       if (text.chars [length - 1] == 0) length--;
+       if (end == -1) end = length;
+       if (segments != null && end > segments [0]) {
+               int nSegments = segments.length;
+               if (nSegments > 0 && start <= segments [nSegments - 1]) {
+                       int nLeadSegments = 0;
+                       while (start - nLeadSegments > segments [nLeadSegments]) nLeadSegments++;
+                       int segmentCount = nLeadSegments;
+                       for (int i = start; i < end; i++) {
+                               if (segmentCount < nSegments && i - segmentCount == segments [segmentCount]) {
+                                       ++segmentCount;
+                               } else {
+                                       chars [i - segmentCount + nLeadSegments] = chars [i];
+                               }
+                       }
+                       length = end - start - segmentCount + nLeadSegments;
+               }
+       }
+       if (start != 0 || end != length) {
+               char [] newChars = new char [length];
+               System.arraycopy(chars, start, newChars, 0, length);
+               return new TCHAR (getCodePage (), newChars, terminate);
+       }
+       return text;
+}
+
+@Override
+boolean dragDetect (long hwnd, int x, int y, boolean filter, boolean [] detect, boolean [] consume) {
+       if (filter) {
+               int [] start = new int [1], end = new int [1];
+               OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+               if (start [0] != end [0]) {
+                       long lParam = OS.MAKELPARAM (x, y);
+                       int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
+                       if (start [0] <= position && position < end [0]) {
+                               if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
+                                       if (consume != 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) != 0) return;
+       int bits1 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+       int bits2 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((style & SWT.LEFT_TO_RIGHT) != 0) {
+               if ((style & SWT.RIGHT) != 0) {
+                       bits1 |= OS.WS_EX_RIGHT;
+                       bits2 |= OS.ES_RIGHT;
+               }
+               if ((style & SWT.LEFT) != 0) {
+                       bits1 &= ~OS.WS_EX_RIGHT;
+                       bits2 &= ~OS.ES_RIGHT;
+               }
+       } else {
+               if ((style & SWT.RIGHT) != 0) {
+                       bits1 &= ~OS.WS_EX_RIGHT;
+                       bits2 &= ~OS.ES_RIGHT;
+               }
+               if ((style & SWT.LEFT) != 0) {
+                       bits1 |= OS.WS_EX_RIGHT;
+                       bits2 |= OS.ES_RIGHT;
+               }
+       }
+       if ((style & SWT.CENTER) != 0) {
+               bits2 |= OS.ES_CENTER;
+       }
+       OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits1);
+       OS.SetWindowLong (handle, OS.GWL_STYLE, bits2);
+}
+
+@Override int getBorderWidthInPixels () {
+       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) != 0 && (style & SWT.FLAT) != 0) {
+//             return OS.GetSystemMetrics (OS.SM_CXBORDER);
+//     }
+       return super.getBorderWidthInPixels ();
+}
+
+/**
+ * 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 (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, -1, 0);
+}
+
+/**
+ * Returns a point describing the location of the caret relative
+ * to the receiver.
+ *
+ * @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 ();
+       return DPIUtil.autoScaleDown(getCaretLocationInPixels());
+}
+
+Point getCaretLocationInPixels () {
+       /*
+       * 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 = translateOffset (getCaretPosition ());
+       long caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
+       if (caretPos == -1) {
+               caretPos = 0;
+               if (position >= OS.GetWindowTextLength (handle)) {
+                       int [] start = new int [1], end = new int [1];
+                       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, new char [] {' ', '\0'});
+                       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, new char [] {'\0'});
+                       ignoreCharacter = ignoreModify = false;
+                       OS.SendMessage (handle, OS.EM_SETSEL, start [0], start [0]);
+                       OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+               }
+       }
+       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 = new int [1], end = new int [1];
+       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 [0];
+       if (start [0] != end [0]) {
+               int startLine = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, start [0], 0);
+               int endLine = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
+               if (startLine == endLine) {
+                       int idThread = OS.GetWindowThreadProcessId (handle, null);
+                       GUITHREADINFO lpgui = new GUITHREADINFO ();
+                       lpgui.cbSize = GUITHREADINFO.sizeof;
+                       if (OS.GetGUIThreadInfo (idThread, lpgui)) {
+                               if (lpgui.hwndCaret == handle || lpgui.hwndCaret == 0) {
+                                       POINT ptCurrentPos = new POINT ();
+                                       if (OS.GetCaretPos (ptCurrentPos)) {
+                                               long endPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, end [0], 0);
+                                               if (endPos == -1) {
+                                                       long startPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, start [0], 0);
+                                                       int startX = OS.GET_X_LPARAM (startPos);
+                                                       if (ptCurrentPos.x > startX) caret = end [0];
+                                               } else {
+                                                       int endX = OS.GET_X_LPARAM (endPos);
+                                                       if (ptCurrentPos.x >= endX) caret = end [0];
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       int caretPos = (int)OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
+                       int caretLine = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, caretPos, 0);
+                       if (caretLine == endLine) caret = end [0];
+               }
+       }
+       return untranslateOffset (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);
+       return untranslateOffset (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 boolean 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 ();
+       return (char) OS.SendMessage (handle, OS.EM_GETPASSWORDCHAR, 0, 0);
+}
+
+/**
+ * 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 boolean getEditable () {
+       checkWidget ();
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       return (bits & OS.ES_READONLY) == 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 (int)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 ();
+       return DPIUtil.autoScaleDown(getLineHeightInPixels ());
+}
+
+int getLineHeightInPixels () {
+       long newFont, oldFont = 0;
+       long hDC = OS.GetDC (handle);
+       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       TEXTMETRIC tm = new TEXTMETRIC ();
+       OS.GetTextMetrics (hDC, tm);
+       if (newFont != 0) 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
+ */
+@Override
+public int getOrientation () {
+       return super.getOrientation ();
+}
+
+/**
+ * Returns the widget message.  The message text is displayed
+ * as a hint for the user, indicating the purpose of the field.
+ * <p>
+ * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
+ * </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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       long lParam = OS.MAKELPARAM (point.x, point.y);
+       int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
+       return untranslateOffset (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 = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       return new Point (untranslateOffset (start [0]), untranslateOffset (end [0]));
+}
+
+/**
+ * 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 == 0) return "";
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       if (start [0] == end [0]) return "";
+       TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+       OS.GetWindowText (handle, buffer, length + 1);
+       if (segments != null) {
+               buffer = deprocessText (buffer, start [0], end [0], false);
+               return buffer.toString ();
+       }
+       return buffer.toString (start [0], end [0] - start [0]);
+}
+
+/**
+ * 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) {
+       long oldFont = 0;
+       RECT rect = new RECT ();
+       long hDC = OS.GetDC (handle);
+       long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+       OS.DrawText (hDC, new char [] {' '}, 1, rect, flags);
+       if (newFont != 0) 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 == 0) return "";
+       TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+       OS.GetWindowText (handle, buffer, length + 1);
+       if (segments != null) {
+               buffer = deprocessText (buffer, 0, -1, false);
+               return buffer.toString ();
+       }
+       return buffer.toString (0, length);
+}
+
+/**
+ * Returns the widget's text as a character array.
+ * <p>
+ * The text for a text widget is the characters in the widget, or
+ * a zero-length array if this has never been set.
+ * </p>
+ * <p>
+ * Note: Use this API to prevent the text from being written into a String
+ * object whose lifecycle is outside of your control. This can help protect
+ * the text, for example, when the widget is used as a password field.
+ * However, the text can't be protected if an {@link SWT#Segments} or
+ * {@link SWT#Verify} listener has been added to the widget.
+ * </p>
+ *
+ * @return a character array that contains the widget'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>
+ *
+ * @see #setTextChars(char[])
+ *
+ * @since 3.7
+ */
+public char[] getTextChars () {
+       checkWidget ();
+       int length = OS.GetWindowTextLength (handle);
+       if (length == 0) return new char[0];
+       TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+       OS.GetWindowText (handle, buffer, length + 1);
+       if (segments != null) buffer = deprocessText (buffer, 0, -1, false);
+       char [] chars = new char [length];
+       System.arraycopy (buffer.chars, 0, chars, 0, length);
+       buffer.clear ();
+       return chars;
+}
+
+/**
+ * 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);
+       end = Math.min (end, untranslateOffset (length) - 1);
+       if (start > end) return "";
+       start = Math.max (0, start);
+       /*
+       * 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 ();
+       int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+       if (segments != null && limit < LIMIT) limit = Math.max (1, limit - segments.length);
+       return limit;
+}
+
+/**
+ * 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) != 0) return 0;
+       return (int)OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
+}
+
+/**
+ * Returns the top SWT logical point.
+ * <p>
+ * The top point is the SWT logical point position of the line
+ * that is currently at the top of the widget.  On
+ * some platforms, a text widget can be scrolled by
+ * points instead of lines so that a partial line
+ * is displayed at the top of the widget.
+ * </p><p>
+ * The top SWT logical point changes when the widget is scrolled.
+ * The top SWT logical point does not include the widget trimming.
+ * </p>
+ *
+ * @return the SWT logical point 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 DPIUtil.autoScaleDown(getTopPixelInPixels());
+}
+
+int getTopPixelInPixels () {
+       /*
+       * 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 [] buffer = new int [2];
+       long code = OS.SendMessage (handle, OS.EM_GETSCROLLPOS, 0, buffer);
+       if (code == 1) return buffer [1];
+       return getTopIndex () * getLineHeightInPixels ();
+}
+
+/**
+ * Inserts a string.
+ * <p>
+ * The old selection is replaced with the new text.
+ * </p>
+ *
+ * @param string the string
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string 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 void insert (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       string = Display.withCrLf (string);
+       if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+               int [] start = new int [1], end = new int [1];
+               OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+               string = verifyText (string, start [0], end [0], null);
+               if (string == null) return;
+       }
+       clearSegments (true);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       /*
+       * 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;
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               super.updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+       applySegments ();
+}
+
+/**
+ * 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) != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * 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 SegmentEvent
+ * @see SegmentListener
+ * @see #addSegmentListener
+ *
+ * @since 3.8
+ */
+public void removeSegmentListener (SegmentListener listener) {
+       checkWidget ();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       eventTable.unhook (SWT.Segments, listener);
+       clearSegments (true);
+       applySegments ();
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Verify, listener);
+}
+
+@Override
+int resolveTextDirection() {
+       int textDirection = SWT.NONE;
+       int length = OS.GetWindowTextLength (handle);
+       if (length > 0) {
+               TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+               OS.GetWindowText (handle, buffer, length + 1);
+               if (segments != null) {
+                       buffer = deprocessText (buffer, 0, -1, false);
+                       textDirection = BidiUtil.resolveTextDirection(buffer.toString ());
+               } else {
+                       textDirection = BidiUtil.resolveTextDirection(buffer.toString (0, length));
+               }
+               if (textDirection == SWT.NONE) {
+                       /*
+                        * Force direction update also when there are no strong bidi chars.
+                       */
+                       textDirection = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+               }
+       }
+       return textDirection;
+}
+
+/**
+ * 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
+boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
+       if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+               return false;
+       }
+       if ((style & SWT.READ_ONLY) != 0) return true;
+       if (ignoreVerify) return true;
+       if (type != SWT.KeyDown) return true;
+       if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
+               return true;
+       }
+       if (event.character == 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 != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
+                       // FALL THROUGH
+               case OS.WM_KEYDOWN:
+                       if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
+                       break;
+       }
+
+       /*
+       * 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 == OS.GetCapture()) return true;
+       }
+
+       /* Verify the character */
+       String oldText = "";
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       switch (key) {
+               case 0x08:      /* Bs */
+                       if (start [0] == end [0]) {
+                               if (start [0] == 0) return true;
+                               int lineStart = (int)OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
+                               if (start [0] == lineStart) {
+                                       start [0] = start [0] - DELIMITER.length ();
+                               } else {
+                                       start [0] = start [0] - 1;
+                               }
+                               start [0] = Math.max (start [0], 0);
+                       }
+                       break;
+               case 0x7F:      /* Del */
+                       if (start [0] == end [0]) {
+                               int length = OS.GetWindowTextLength (handle);
+                               if (start [0] == length) return true;
+                               int line = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
+                               int lineStart = (int)OS.SendMessage (handle, OS.EM_LINEINDEX, line + 1, 0);
+                               if (end [0] == lineStart - DELIMITER.length ()) {
+                                       end [0] = end [0] + DELIMITER.length ();
+                               } else {
+                                       end [0] = end [0] + 1;
+                               }
+                               end [0] = Math.min (end [0], length);
+                       }
+                       break;
+               case '\r':      /* Return */
+                       if ((style & SWT.SINGLE) != 0) return true;
+                       oldText = DELIMITER;
+                       break;
+               default:        /* Tab and other characters */
+                       if (key != '\t' && key < 0x20) return true;
+                       oldText = new String (new char [] {key});
+                       break;
+       }
+       String newText = verifyText (oldText, start [0], end [0], event);
+       if (newText == null) return false;
+       if (newText == oldText) return true;
+       newText = Display.withCrLf (newText);
+       TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+       OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+       /*
+       * 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 setBackgroundImage (long hBitmap) {
+       int flags = OS.RDW_ERASE | OS.RDW_ALLCHILDREN | OS.RDW_INVALIDATE;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+@Override
+void setBackgroundPixel (int pixel) {
+       int flags = OS.RDW_ERASE | OS.RDW_ALLCHILDREN | OS.RDW_INVALIDATE;
+       OS.RedrawWindow (handle, null, 0, flags);
+}
+
+@Override
+void setBoundsInPixels (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) == 0 && width != 0) {
+               RECT rect = new RECT ();
+               OS.GetWindowRect (handle, rect);
+               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 = new int [1], end = new int [1];
+                       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+                       if (start [0] != 0 || end [0] != 0) {
+                               OS.SetWindowPos (handle, 0, x, y, width, height, flags);
+                               OS.SendMessage (handle, OS.EM_SETSEL, 0, 0);
+                               OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+                               return;
+                       }
+               }
+       }
+       super.setBoundsInPixels (x, y, width, height, flags);
+
+       /*
+       * Bug in Windows. If the client area height is smaller than
+       * the font height, then the multi-line text widget does not
+       * update the formatting rectangle when resized. The fix is to
+       * detect this case and explicitly set the formatting rectangle.
+       */
+       if ((flags & OS.SWP_NOSIZE) == 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.ES_MULTILINE) != 0) {
+                       long newFont, oldFont = 0;
+                       long hDC = OS.GetDC (handle);
+                       newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+                       TEXTMETRIC tm = new TEXTMETRIC ();
+                       OS.GetTextMetrics (hDC, tm);
+                       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+                       OS.ReleaseDC (handle, hDC);
+                       RECT rect = new RECT();
+                       OS.GetClientRect (handle, rect);
+                       if ((rect.bottom - rect.top) < tm.tmHeight) {
+                               long margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
+                               rect.left += OS.LOWORD (margins);
+                               rect.right -= OS.HIWORD (margins);
+                               rect.top = 0;
+                               rect.bottom = tm.tmHeight;
+                               OS.SendMessage (handle, OS.EM_SETRECT, 0, rect);
+                       }
+               }
+       }
+}
+
+@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 (boolean 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) != 0) return;
+       allowPasswordChar = true;
+       OS.SendMessage (handle, OS.EM_SETPASSWORDCHAR, echo, 0);
+       allowPasswordChar = false;
+       /*
+       * 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 (boolean 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 () {
+       if ((style & SWT.SEARCH) != 0) {
+               int flags = 0;
+               int fLeading = (style & SWT.LEFT_TO_RIGHT) != 0 ? OS.EC_LEFTMARGIN : OS.EC_RIGHTMARGIN;
+               int fTrailing = (style & SWT.LEFT_TO_RIGHT) != 0 ? OS.EC_RIGHTMARGIN : OS.EC_LEFTMARGIN;
+               if ((style & SWT.ICON_SEARCH) != 0) flags |= fLeading;
+               if ((style & SWT.ICON_CANCEL) != 0) flags |= fTrailing;
+               if (flags != 0) {
+                       int iconWidth = OS.GetSystemMetrics (OS.SM_CXSMICON);
+                       OS.SendMessage (handle, OS.EM_SETMARGINS, flags, OS.MAKELPARAM(iconWidth, iconWidth));
+               }
+       }
+}
+
+/**
+ * Sets the widget message. The message text is displayed
+ * as a hint for the user, indicating the purpose of the field.
+ * <p>
+ * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
+ * </p>
+ *
+ * @param message the new message
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the message 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 ();
+       if (message == null) error (SWT.ERROR_NULL_ARGUMENT);
+       this.message = message;
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.ES_MULTILINE) == 0) {
+               int length = message.length ();
+               char [] chars = new char [length + 1];
+               message.getChars(0, length, chars, 0);
+               OS.SendMessage (handle, OS.EM_SETCUEBANNER, 0, chars);
+       }
+}
+
+/**
+ * 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
+ */
+@Override
+public void setOrientation (int orientation) {
+       super.setOrientation (orientation);
+}
+
+/**
+ * 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 ();
+       start = translateOffset (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 ();
+       start = translateOffset (start);
+       end = translateOffset (end);
+       OS.SendMessage (handle, OS.EM_SETSEL, start, end);
+       OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+}
+
+@Override
+public void setRedraw (boolean 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 (!getDrawing ()) return;
+       int [] start = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       if (!redraw) {
+               oldStart = start [0];  oldEnd = end [0];
+       } else {
+               if (oldStart == start [0] && oldEnd == end [0]) 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 == 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
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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, new int [] {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.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param string the new text
+ *
+ * @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>
+ */
+public void setText (String string) {
+       checkWidget ();
+       if (string == 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 == null) return;
+       }
+       clearSegments (false);
+       int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+       if (string.length () > limit) string = string.substring (0, limit);
+       TCHAR buffer = new TCHAR (getCodePage (), string, true);
+       OS.SetWindowText (handle, buffer);
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               super.updateTextDirection(AUTO_TEXT_DIRECTION);
+       }
+       applySegments ();
+       /*
+       * 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) != 0) {
+               sendEvent (SWT.Modify);
+               // widget could be disposed at this point
+       }
+}
+
+/**
+ * Sets the contents of the receiver to the characters in the array. If the receiver
+ * has style <code>SWT.SINGLE</code> and the argument contains multiple lines of text
+ * then the result of this operation is undefined and may vary between platforms.
+ * <p>
+ * Note: Use this API to prevent the text from being written into a String
+ * object whose lifecycle is outside of your control. This can help protect
+ * the text, for example, when the widget is used as a password field.
+ * However, the text can't be protected if an {@link SWT#Segments} or
+ * {@link SWT#Verify} listener has been added to the widget.
+ * </p>
+ *
+ * @param text a character array that contains the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the 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>
+ *
+ * @see #getTextChars()
+ *
+ * @since 3.7
+ */
+public void setTextChars (char[] text) {
+       checkWidget ();
+       if (text == null) error (SWT.ERROR_NULL_ARGUMENT);
+       text = Display.withCrLf (text);
+       if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+               int length = OS.GetWindowTextLength (handle);
+               String string = verifyText (new String (text), 0, length, null);
+               if (string == null) return;
+               text = new char [string.length()];
+               string.getChars (0, text.length, text, 0);
+       }
+       clearSegments (false);
+       int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+       if (text.length > limit) {
+               char [] temp = new char [limit];
+               for (int i = 0; i < limit; i++) temp [i] = text [i];
+               text = temp;
+       }
+       TCHAR buffer = new TCHAR (getCodePage (), text, true);
+       OS.SetWindowText (handle, buffer);
+       buffer.clear ();
+       if ((state & HAS_AUTO_DIRECTION) != 0) {
+               super.updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+       applySegments ();
+       /*
+       * 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) != 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 == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+       if (segments != null && limit > 0) {
+               OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min (segments.length, LIMIT - limit), 0);
+       } else {
+               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) != 0) return;
+       int count = (int)OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
+       index = Math.min (Math.max (index, 0), count - 1);
+       int topIndex = (int)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);
+}
+
+int translateOffset (int offset) {
+       if (segments == null) return offset;
+       for (int i = 0, nSegments = segments.length; i < nSegments && offset - i >= segments [i]; i++) {
+               offset++;
+       }
+       return offset;
+}
+
+int untranslateOffset (int offset) {
+       if (segments == null) return offset;
+       for (int i = 0, nSegments = segments.length; i < nSegments && offset > segments [i]; i++) {
+               offset--;
+       }
+       return offset;
+}
+
+@Override
+void updateMenuLocation (Event event) {
+       Point point = display.mapInPixels (this, null, getCaretLocationInPixels ());
+       event.setLocationInPixels(point.x, point.y + getLineHeightInPixels ());
+}
+
+@Override
+void updateOrientation (){
+       int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+       if ((style & SWT.RIGHT_TO_LEFT) != 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 ();
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               clearSegments (true);
+               applySegments ();
+               return true;
+       }
+       return false;
+}
+
+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 != null) {
+               event.character = keyEvent.character;
+               event.keyCode = keyEvent.keyCode;
+               event.stateMask = keyEvent.stateMask;
+       }
+       event.start = untranslateOffset (event.start);
+       event.end = untranslateOffset (event.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;
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.ES_AUTOHSCROLL;
+       if ((style & SWT.PASSWORD) != 0) bits |= OS.ES_PASSWORD;
+       if ((style & SWT.CENTER) != 0) bits |= OS.ES_CENTER;
+       if ((style & SWT.RIGHT) != 0) bits |= OS.ES_RIGHT;
+       if ((style & SWT.READ_ONLY) != 0) bits |= OS.ES_READONLY;
+       if ((style & SWT.SEARCH) != 0) bits |= OS.WS_CLIPCHILDREN;
+       if ((style & SWT.SINGLE) != 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.
+               * Refer Bug438901:- ES_MULTILINE doesn't apply for:
+               * SWT.PASSWORD | SWT.READ_ONLY style combination.
+               */
+               if ((style & SWT.READ_ONLY) != 0) {
+                       if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.PASSWORD)) == 0) {
+                               if (OS.IsAppThemed ()) {
+                                       bits |= OS.ES_MULTILINE;
+                               }
+                       }
+               }
+               return bits;
+       }
+       bits |= OS.ES_MULTILINE | OS.ES_NOHIDESEL | OS.ES_AUTOVSCROLL;
+       if ((style & SWT.WRAP) != 0) bits &= ~(OS.WS_HSCROLL | OS.ES_AUTOHSCROLL);
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return EditClass;
+}
+
+@Override
+long windowProc () {
+       return EditProc;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       boolean processSegments = hooks (SWT.Segments) || filters (SWT.Segments), redraw = false, updateDirection = (state & HAS_AUTO_DIRECTION) != 0;
+       long code;
+       if (processSegments || updateDirection) {
+               switch (msg) {
+                       case OS.EM_CANUNDO:
+                               if (processSegments) return 0;
+                               updateDirection = false;
+                               break;
+                       case OS.EM_UNDO:
+                       case OS.WM_UNDO:
+                               if (processSegments) return 0;
+                               break;
+                       case OS.WM_KEYDOWN:
+                               if (wParam != OS.VK_DELETE) {
+                                       processSegments = updateDirection = false;
+                               }
+                               break;
+                       case OS.WM_COPY:
+                               processSegments = segments != null;
+                               updateDirection = false;
+                               break;
+                       case OS.WM_CHAR:
+                               if (ignoreCharacter || OS.GetKeyState (OS.VK_CONTROL) < 0 || OS.GetKeyState (OS.VK_MENU) < 0) {
+                                       processSegments = updateDirection = false;
+                               }
+                               break;
+                       case OS.WM_PASTE:
+                       case OS.WM_CUT:
+                       case OS.WM_CLEAR:
+                               break;
+                       default:
+                               processSegments = updateDirection = false;
+               }
+       }
+       if (processSegments) {
+               if (getDrawing () && OS.IsWindowVisible (handle)) {
+                       redraw = true;
+                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+               }
+               clearSegments (true);
+       }
+       if (msg == OS.EM_UNDO) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.ES_MULTILINE) == 0) {
+                       LRESULT result = wmClipboard (OS.EM_UNDO, wParam, lParam);
+                       if (result != null) return result.value;
+                       return callWindowProc (hwnd, OS.EM_UNDO, wParam, lParam);
+               }
+       }
+       if (msg == OS.EM_SETPASSWORDCHAR) {
+               if (!allowPasswordChar) {
+                       return 1;
+               }
+       }
+       if (msg == Display.SWT_RESTORECARET) {
+               callWindowProc (hwnd, OS.WM_KILLFOCUS, 0, 0);
+               callWindowProc (hwnd, OS.WM_SETFOCUS, 0, 0);
+               return 1;
+       }
+       code = super.windowProc (hwnd, msg, wParam, lParam);
+       if (updateDirection) {
+               super.updateTextDirection (AUTO_TEXT_DIRECTION);
+       }
+       if (processSegments) {
+               applySegments ();
+               if (redraw) {
+                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                       OS.InvalidateRect (handle, null, true);
+               }
+               OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+       }
+       return code;
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       if (ignoreCharacter) return null;
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != 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 ((int)wParam) {
+               case SWT.DEL:
+                       if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                               if ((style & SWT.READ_ONLY) != 0 || (style & SWT.PASSWORD) != 0) return LRESULT.ZERO;
+                               Point selection = getSelection ();
+                               int x = selection.x;
+                               int y = selection.y;
+                               if (x == y) {
+                                       String actText = getText (0, x - 1);
+                                       java.util.regex.Matcher m = CTRL_BS_PATTERN.matcher (actText);
+                                       if (m.find ()) {
+                                               x = m.start ();
+                                               y = m.end ();
+                                               OS.SendMessage (handle, OS.EM_SETSEL, x, y);
+                                       }
+                               }
+                               if (x < y) {
+                                       /*
+                                       * Instead of setting the new text directly we send the replace selection event to
+                                       * guarantee that the action is pushed to the undo buffer.
+                                       */
+                                       OS.SendMessage (handle, OS.EM_REPLACESEL, 1, 0);
+                               }
+                               return LRESULT.ZERO;
+                       }
+       }
+
+       /*
+       * 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) != 0) {
+               switch ((int)wParam) {
+                       case SWT.CR:
+                               sendSelectionEvent (SWT.DefaultSelection);
+                               // FALL THROUGH
+                       case SWT.TAB:
+                       case SWT.ESC: return LRESULT.ZERO;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_CLEAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CLEAR (wParam, lParam);
+       if (result != null) return result;
+       return wmClipboard (OS.WM_CLEAR, wParam, lParam);
+}
+
+@Override
+LRESULT WM_CUT (long wParam, long lParam) {
+       LRESULT result = super.WM_CUT (wParam, lParam);
+       if (result != null) return result;
+       return wmClipboard (OS.WM_CUT, wParam, lParam);
+}
+
+@Override
+LRESULT WM_DRAWITEM (long wParam, long lParam) {
+       DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+       OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+       RECT rect = new RECT ();
+       OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom);
+       POINT pt = new POINT ();
+       OS.MapWindowPoints (struct.hwndItem, handle, pt, 1);
+       drawBackground (struct.hDC, rect, -1, pt.x, pt.y);
+       if (struct.hwndItem == hwndCancel && struct.hwndItem == hwndActive && OS.IsAppThemed()) {
+               int state = OS.GetKeyState (OS.VK_LBUTTON) < 0 ? OS.PBS_PRESSED : OS.PBS_HOT;
+               OS.DrawThemeBackground (display.hButtonTheme (), struct.hDC, OS.BP_PUSHBUTTON, state, rect, null);
+       }
+       long hIcon = (struct.hwndItem == hwndSearch) ? display.hIconSearch : display.hIconCancel;
+       int y = (rect.bottom - rect.right) / 2;
+       OS.DrawIconEx (struct.hDC, 0, y, hIcon, 0, 0, 0, 0, OS.DI_NORMAL);
+       return LRESULT.ONE;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if ((style & SWT.READ_ONLY) != 0) {
+               if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.ES_MULTILINE) != 0) {
+                               Control control = findBackgroundControl ();
+                               if (control == null && background == -1) {
+                                       if ((state & THEME_BACKGROUND) != 0) {
+                                               if (OS.IsAppThemed ()) {
+                                                       control = findThemeControl ();
+                                                       if (control != null) {
+                                                               RECT rect = new RECT ();
+                                                               OS.GetClientRect (handle, rect);
+                                                               fillThemeBackground (wParam, control, rect);
+                                                               return LRESULT.ONE;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+       if (result != null) return result;
+
+       /*
+       * 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) != 0) {
+               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_GETOBJECT (long wParam, long lParam) {
+       /*
+       * Ensure that there is an accessible object created for this
+       * control because support for search text accessibility is
+       * implemented in the accessibility package.
+       */
+       if ((style & SWT.SEARCH) != 0) {
+               if (accessible == null) accessible = new_Accessible (this);
+       }
+       return super.WM_GETOBJECT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_IME_CHAR (long wParam, long lParam) {
+
+       /* Process a DBCS character */
+       Display display = this.display;
+       display.lastKey = 0;
+       display.lastAscii = (int)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;
+       long result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam);
+       MSG msg = new 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 (long wParam, long 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 () != 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 = new int [1], end = new int [1];
+       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+       if (start [0] == end [0]) {
+               int length = OS.GetWindowTextLength (handle);
+               if (length == start [0]) {
+                       int code = (int)OS.SendMessage (handle, OS.EM_LINELENGTH, length, 0);
+                       if (code == 0) return LRESULT.ZERO;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_PASTE (long wParam, long lParam) {
+       LRESULT result = super.WM_PASTE (wParam, lParam);
+       if (result != null) return result;
+       return wmClipboard (OS.WM_PASTE, wParam, lParam);
+}
+
+@Override
+LRESULT WM_SIZE(long wParam, long lParam) {
+       LRESULT result = super.WM_SIZE (wParam, lParam);
+       if (isDisposed ()) return result;
+       if ((style & SWT.SEARCH) != 0) {
+               /* NOTE: EDIT controls don't support mirrored layout. */
+               long hwndLeading = (style & SWT.LEFT_TO_RIGHT) != 0 ? hwndSearch : hwndCancel;
+               long hwndTrailing = (style & SWT.LEFT_TO_RIGHT) != 0 ? hwndCancel : hwndSearch;
+               int width = OS.LOWORD (lParam);
+               int height = OS.HIWORD (lParam);
+               int iconWidth = OS.GetSystemMetrics (OS.SM_CXSMICON);
+               int flags = OS.SWP_NOZORDER | OS.SWP_NOACTIVATE | OS.SWP_NOCOPYBITS;
+               if (hwndLeading != 0) OS.SetWindowPos (hwndLeading, 0, 0, 0, iconWidth, height, flags);
+               if (hwndTrailing != 0) OS.SetWindowPos (hwndTrailing, 0, width - iconWidth, 0, iconWidth, height, flags);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_UNDO (long wParam, long lParam) {
+       LRESULT result = super.WM_UNDO (wParam, lParam);
+       if (result != null) return result;
+       return wmClipboard (OS.WM_UNDO, wParam, lParam);
+}
+
+LRESULT wmClipboard (int msg, long wParam, long lParam) {
+       if ((style & SWT.READ_ONLY) != 0) return null;
+       if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+       boolean call = false;
+       int [] start = new int [1], end = new int [1];
+       String newText = null;
+       switch (msg) {
+               case OS.WM_CLEAR:
+               case OS.WM_CUT:
+                       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+                       if (start [0] != end [0]) {
+                               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) != 0) {
+                               ignoreModify = ignoreCharacter = true;
+                               callWindowProc (handle, msg, wParam, lParam);
+                               int length = OS.GetWindowTextLength (handle);
+                               int [] newStart = new int [1], newEnd = new int [1];
+                               OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
+                               if (length != 0 && newStart [0] != newEnd [0]) {
+                                       char [] buffer = new char [length + 1];
+                                       OS.GetWindowText (handle, buffer, length + 1);
+                                       newText = new String (buffer, newStart [0], newEnd [0] - newStart [0]);
+                               } else {
+                                       newText = "";
+                               }
+                               callWindowProc (handle, msg, wParam, lParam);
+                               OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+                               ignoreModify = ignoreCharacter = false;
+                       }
+                       break;
+       }
+       if (newText != null) {
+               String oldText = newText;
+               newText = verifyText (newText, start [0], end [0], null);
+               if (newText == null) return LRESULT.ZERO;
+               if (!newText.equals (oldText)) {
+                       if (call) {
+                               callWindowProc (handle, msg, wParam, lParam);
+                       }
+                       newText = Display.withCrLf (newText);
+                       TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+                       /*
+                       * 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 == OS.WM_UNDO) {
+               ignoreVerify = ignoreCharacter = true;
+               callWindowProc (handle, OS.WM_UNDO, wParam, lParam);
+               ignoreVerify = ignoreCharacter = false;
+               return LRESULT.ONE;
+       }
+       return null;
+}
+
+@Override
+LRESULT wmColorChild (long wParam, long lParam) {
+       if ((style & SWT.READ_ONLY) != 0) {
+               if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.ES_MULTILINE) != 0) {
+                               Control control = findBackgroundControl ();
+                               if (control == null && background == -1) {
+                                       if ((state & THEME_BACKGROUND) != 0) {
+                                               if (OS.IsAppThemed ()) {
+                                                       control = findThemeControl ();
+                                                       if (control != null) {
+                                                               OS.SetTextColor (wParam, getForegroundPixel ());
+                                                               OS.SetBkColor (wParam, getBackgroundPixel ());
+                                                               OS.SetBkMode (wParam, OS.TRANSPARENT);
+                                                               return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return super.wmColorChild (wParam, lParam);
+}
+
+@Override
+LRESULT wmCommandChild (long wParam, long lParam) {
+       int code = OS.HIWORD (wParam);
+       switch (code) {
+               case OS.EN_CHANGE:
+                       if (findImageControl () != null) {
+                               OS.InvalidateRect (handle, null, true);
+                       }
+                       if ((style & SWT.SEARCH) != 0 && hwndCancel != 0) {
+                               OS.ShowWindow (hwndCancel, OS.GetWindowTextLength (handle) != 0 ? OS.SW_SHOW : OS.SW_HIDE);
+                       }
+                       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:
+               case OS.EN_ALIGN_RTL_EC:
+                       /*
+                        * Ctrl + Shift to set explicit LTR or RTL text direction was
+                        * pressed, so auto direction should no longer be effective.
+                        */
+                       state &= ~HAS_AUTO_DIRECTION;
+                       int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+                       if ((bits & OS.WS_EX_RTLREADING) != 0) {
+                               style &= ~SWT.LEFT_TO_RIGHT;
+                               style |= SWT.RIGHT_TO_LEFT;
+                       } else {
+                               style &= ~SWT.RIGHT_TO_LEFT;
+                               style |= SWT.LEFT_TO_RIGHT;
+                       }
+                       Event event = new Event();
+                       event.doit = true;
+                       sendEvent(SWT.OrientationChange, event);
+                       if (!event.doit) {
+                               if (code == OS.EN_ALIGN_LTR_EC) {
+                                       bits |= (OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
+                                       style &= ~SWT.LEFT_TO_RIGHT;
+                                       style |= SWT.RIGHT_TO_LEFT;
+                               } else {
+                                       bits &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
+                                       style &= ~SWT.RIGHT_TO_LEFT;
+                                       style |= SWT.LEFT_TO_RIGHT;
+                               }
+                               OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+                       } else {
+                               clearSegments (true);
+                               applySegments ();
+                       }
+                       fixAlignment();
+                       break;
+       }
+       return super.wmCommandChild (wParam, lParam);
+}
+
+@Override
+LRESULT wmKeyDown (long hwnd, long wParam, long lParam) {
+       LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+       if (result != null) return result;
+
+       if (segments != null) {
+               switch ((int)wParam) {
+               case OS.VK_LEFT:
+               case OS.VK_UP:
+               case OS.VK_RIGHT:
+               case OS.VK_DOWN:
+                       long code = 0;
+                       int [] start = new int [1], end = new int [1], newStart = new int [1], newEnd = new int [1];
+                       OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+                       while (true) {
+                               code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                               OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
+                               if (newStart [0] != start [0]) {
+                                       if (untranslateOffset (newStart [0]) != untranslateOffset (start [0])) break;
+                               } else if (newEnd [0] != end [0]) {
+                                       if (untranslateOffset (newEnd [0]) != untranslateOffset (end [0]))  break;
+                               } else {
+                                       break;
+                               }
+                               start [0] = newStart [0];
+                               end [0] = newEnd [0];
+                       }
+                       result = code == 0 ? LRESULT.ZERO : new LRESULT (code);
+               }
+       }
+       return result;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolBar.java
new file mode 100644 (file)
index 0000000..aa76ab3
--- /dev/null
@@ -0,0 +1,1654 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * <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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ToolBar extends Composite {
+       int lastFocusId, lastArrowId, lastHotId;
+       ToolItem [] items;
+       ToolItem [] tabItemList;
+       boolean ignoreResize, ignoreMouse;
+       ImageList imageList, disabledImageList, hotImageList;
+       static final long ToolBarProc;
+       static final TCHAR ToolBarClass = new TCHAR (0, OS.TOOLBARCLASSNAME, true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, ToolBarClass, lpWndClass);
+               ToolBarProc = lpWndClass.lpfnWndProc;
+       }
+
+       /*
+       * 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 final int DEFAULT_WIDTH = 24;
+       static final 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 ToolBar (Composite parent, int style) {
+       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) != 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.IsAppThemed ()) {
+                       if ((style & SWT.RIGHT) != 0) bits |= OS.TBSTYLE_LIST;
+               }
+               OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.CCS_VERT);
+       } else {
+               this.style |= SWT.HORIZONTAL;
+       }
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) 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 == 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) == 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) != 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 ();
+       style |= SWT.DOUBLE_BUFFERED;
+}
+
+@Override
+protected void checkSubclass () {
+       if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       int width = 0, height = 0;
+       if ((style & SWT.VERTICAL) != 0) {
+               RECT rect = new RECT ();
+               TBBUTTON lpButton = new TBBUTTON ();
+               int count = (int)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) != 0) {
+                               TBBUTTONINFO info = new TBBUTTONINFO ();
+                               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 = new RECT ();
+               OS.GetWindowRect (handle, oldRect);
+               int oldWidth = oldRect.right - oldRect.left;
+               int oldHeight = oldRect.bottom - oldRect.top;
+               int border = getBorderWidthInPixels ();
+               int newWidth = wHint == SWT.DEFAULT ? 0x3FFF : wHint + border * 2;
+               int newHeight = hHint == SWT.DEFAULT ? 0x3FFF : hHint + border * 2;
+               boolean redraw = getDrawing () && OS.IsWindowVisible (handle);
+               ignoreResize = true;
+               if (redraw) OS.UpdateWindow (handle);
+               int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+               OS.SetWindowPos (handle, 0, 0, 0, newWidth, newHeight, flags);
+               int count = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+               if (count != 0) {
+                       RECT rect = new RECT ();
+                       OS.SendMessage (handle, OS.TB_GETITEMRECT, count - 1, rect);
+                       width = Math.max (width, rect.right);
+                       height = Math.max (height, rect.bottom);
+               }
+               OS.SetWindowPos (handle, 0, 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 == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       Rectangle trim = computeTrimInPixels (0, 0, width, height);
+       width = trim.width;  height = trim.height;
+       return new Point (width, height);
+}
+
+@Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
+       Rectangle trim = super.computeTrimInPixels (x, y, width, height);
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.CCS_NODIVIDER) == 0) trim.height += 2;
+       return trim;
+}
+
+@Override
+Widget computeTabGroup () {
+       ToolItem [] items = _getItems ();
+       if (tabItemList == null) {
+               int i = 0;
+               while (i < items.length && items [i].control == null) i++;
+               if (i == items.length) return super.computeTabGroup ();
+       }
+       int index = (int)OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
+       if (index == -1) index = lastHotId;
+       while (index >= 0) {
+               ToolItem item = items [index];
+               if (item.isTabGroup ()) return item;
+               index--;
+       }
+       return super.computeTabGroup ();
+}
+
+@Override
+Widget [] computeTabList () {
+       ToolItem [] items = _getItems ();
+       if (tabItemList == null) {
+               int i = 0;
+               while (i < items.length && items [i].control == null) i++;
+               if (i == items.length) return super.computeTabList ();
+       }
+       Widget result [] = {};
+       if (!isTabGroup () || !isEnabled () || !isVisible ()) return result;
+       ToolItem [] list = tabList != null ? _getTabItemList () : items;
+       for (int i=0; i<list.length; i++) {
+               ToolItem child = list [i];
+               Widget  [] childList = child.computeTabList ();
+               if (childList.length != 0) {
+                       Widget [] newResult = new Widget [result.length + childList.length];
+                       System.arraycopy (result, 0, newResult, 0, result.length);
+                       System.arraycopy (childList, 0, newResult, result.length, childList.length);
+                       result = newResult;
+               }
+       }
+       if (result.length == 0) result = new Widget [] {this};
+       return result;
+}
+
+@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) != 0) {
+               if (!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.
+       */
+//     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.
+       */
+       long 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 | OS.TBSTYLE_EX_DOUBLEBUFFER;
+       OS.SendMessage (handle, OS.TB_SETEXTENDEDSTYLE, 0, bits);
+}
+
+void createItem (ToolItem item, int index) {
+       int count = (int)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] != null) id++;
+       if (id == 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 = new TBBUTTON ();
+       lpButton.idCommand = id;
+       lpButton.fsStyle = (byte) bits;
+       lpButton.fsState = (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) == 0) lpButton.iBitmap = OS.I_IMAGENONE;
+       if (OS.SendMessage (handle, OS.TB_INSERTBUTTON, index, lpButton) == 0) {
+               error (SWT.ERROR_ITEM_NOT_ADDED);
+       }
+       items [item.id = id] = item;
+       if ((style & SWT.VERTICAL) != 0) setRowCount (count + 1);
+       layoutItems ();
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       items = new ToolItem [4];
+       lastFocusId = lastArrowId = lastHotId = -1;
+}
+
+@Override
+int applyThemeBackground () {
+       return -1; /* No Change */
+}
+
+void destroyItem (ToolItem item) {
+       TBBUTTONINFO info = new TBBUTTONINFO ();
+       info.cbSize = TBBUTTONINFO.sizeof;
+       info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
+       int index = (int)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) == 0 && info.iImage != OS.I_IMAGENONE) {
+               if (imageList != null) imageList.put (info.iImage, null);
+               if (hotImageList != null) hotImageList.put (info.iImage, null);
+               if (disabledImageList != null) disabledImageList.put (info.iImage, null);
+       }
+       OS.SendMessage (handle, OS.TB_DELETEBUTTON, index, 0);
+       if (item.id == lastFocusId) lastFocusId = -1;
+       if (item.id == lastArrowId) lastArrowId = -1;
+       if (item.id == lastHotId) lastHotId = -1;
+       items [item.id] = null;
+       item.id = -1;
+       int count = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+       if (count == 0) {
+               if (imageList != null) {
+                       OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
+                       display.releaseToolImageList (imageList);
+               }
+               if (hotImageList != null) {
+                       OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
+                       display.releaseToolHotImageList (hotImageList);
+               }
+               if (disabledImageList != null) {
+                       OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, 0);
+                       display.releaseToolDisabledImageList (disabledImageList);
+               }
+               imageList = hotImageList = disabledImageList = null;
+               items = new ToolItem [4];
+       }
+       if ((style & SWT.VERTICAL) != 0) setRowCount (count - 1);
+       layoutItems ();
+}
+
+@Override
+void enableWidget (boolean 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 != null) {
+                       if ((item.style & SWT.SEPARATOR) == 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 = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+       if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+       TBBUTTON lpButton = new TBBUTTON ();
+       long result = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
+       if (result == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       return getItemInPixels(DPIUtil.autoScaleUp(point));
+}
+
+ToolItem getItemInPixels (Point point) {
+       ToolItem [] items = getItems ();
+       for (int i=0; i<items.length; i++) {
+               Rectangle rect = items [i].getBoundsInPixels ();
+               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 (int)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 ();
+       return _getItems ();
+}
+
+ToolItem [] _getItems () {
+       int count = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+       TBBUTTON lpButton = new TBBUTTON ();
+       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) != 0) {
+               return (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+       }
+       return (int)OS.SendMessage (handle, OS.TB_GETROWS, 0, 0);
+}
+
+ToolItem [] _getTabItemList () {
+       if (tabItemList == null) return tabItemList;
+       int count = 0;
+       for (int i=0; i<tabItemList.length; i++) {
+               if (!tabItemList [i].isDisposed ()) count++;
+       }
+       if (count == tabItemList.length) return tabItemList;
+       ToolItem [] newList = new ToolItem [count];
+       int index = 0;
+       for (int i=0; i<tabItemList.length; i++) {
+               if (!tabItemList [i].isDisposed ()) {
+                       newList [index++] = tabItemList [i];
+               }
+       }
+       tabItemList = newList;
+       return tabItemList;
+}
+
+/**
+ * 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       return (int)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.IsAppThemed ()) {
+               if ((style & SWT.RIGHT) != 0 && (style & SWT.VERTICAL) == 0) {
+                       boolean hasText = false, hasImage = false;
+                       for (int i=0; i<items.length; i++) {
+                               ToolItem item = items [i];
+                               if (item != null) {
+                                       if (!hasText) hasText = item.text.length () != 0;
+                                       if (!hasImage) hasImage = item.image != 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 != 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.
+                               */
+                               long hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                               OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+                               setDropDownItems (true);
+                       }
+               }
+       }
+
+       if ((style & SWT.WRAP) != 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) != 0) {
+               int itemCount = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+               if (itemCount > 1) {
+                       TBBUTTONINFO info = new TBBUTTONINFO ();
+                       info.cbSize = TBBUTTONINFO.sizeof;
+                       info.dwMask = OS.TBIF_SIZE;
+                       long size = OS.SendMessage (handle, OS.TB_GETBUTTONSIZE, 0, 0);
+                       info.cx = (short) OS.LOWORD (size);
+                       int index = 0, extraPadding = 0;
+                       while (index < items.length) {
+                               ToolItem item = items [index];
+                               if (item != null && (item.style & SWT.DROP_DOWN) != 0) {
+                                       /*
+                                        * Specifying 1 pixel extra padding to avoid truncation
+                                        * of widest item in the tool-bar when a tool-bar has
+                                        * SWT.VERTICAL style and any of the items in the
+                                        * tool-bar has SWT.DROP_DOWN style, Refer bug#437206
+                                        */
+                                       extraPadding = 1;
+                                       break;
+                               }
+                               index++;
+                       }
+                       if (index < items.length) {
+                               long padding = OS.SendMessage (handle, OS.TB_GETPADDING, 0, 0);
+                               info.cx += OS.LOWORD (padding + extraPadding) * 2;
+                       }
+                       for (int i=0; i<items.length; i++) {
+                               ToolItem item = items [i];
+                               if (item != null && (item.style & SWT.SEPARATOR) == 0) {
+                                       OS.SendMessage (handle, OS.TB_SETBUTTONINFO, item.id, info);
+                               }
+                       }
+               }
+       }
+
+       /*
+       * Feature on Windows. When SWT.WRAP or SWT.VERTICAL are set
+       * the separator items with control are implemented using BTNS_BUTTON
+       * instead of BTNS_SEP. When that is the case and TBSTYLE_LIST is
+       * set, the layout of the ToolBar recalculates the width for all
+       * BTNS_BUTTON based on the text and bitmap of the item.
+       * This is not strictly wrong, but the user defined width for the
+       * separators has to be respected if set.
+       * The fix is to detect this case and reset the cx width for the item.
+       */
+       if ((style & (SWT.WRAP | SWT.VERTICAL)) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.TBSTYLE_LIST) != 0) {
+                       TBBUTTONINFO info = new TBBUTTONINFO ();
+                       info.cbSize = TBBUTTONINFO.sizeof;
+                       info.dwMask = OS.TBIF_SIZE;
+                       for (int i=0; i<items.length; i++) {
+                               ToolItem item = items [i];
+                               if (item != null && item.cx > 0) {
+                                       info.cx = item.cx;
+                                       OS.SendMessage (handle, OS.TB_SETBUTTONINFO, item.id, info);
+                               }
+                       }
+               }
+       }
+
+       for (int i=0; i<items.length; i++) {
+               ToolItem item = items [i];
+               if (item != null) item.resizeControl ();
+       }
+}
+
+@Override
+boolean mnemonicHit (char ch) {
+       int [] id = new int [1];
+       if (OS.SendMessage (handle, OS.TB_MAPACCELERATOR, ch, id) == 0) {
+               return false;
+       }
+       if ((style & SWT.FLAT) != 0 && !setTabGroupFocus ()) return false;
+       int index = (int)OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, id [0], 0);
+       if (index == -1) return false;
+       OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
+       items [id [0]].click (false);
+       return true;
+}
+
+@Override
+boolean mnemonicMatch (char ch) {
+       int [] id = new int [1];
+       if (OS.SendMessage (handle, OS.TB_MAPACCELERATOR, ch, id) == 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 = (int)OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, id [0], 0);
+       if (index == -1) return false;
+       return findMnemonic (items [id [0]].text) != '\0';
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       ToolItem item = items [i];
+                       if (item != null && !item.isDisposed ()) {
+                               item.release (false);
+                       }
+               }
+               items = null;
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (imageList != null) {
+               OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
+               display.releaseToolImageList (imageList);
+       }
+       if (hotImageList != null) {
+               OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
+               display.releaseToolHotImageList (hotImageList);
+       }
+       if (disabledImageList != 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 != null && item.control == control) {
+                       item.setControl (null);
+               }
+       }
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       ToolItem item = items [i];
+                       if (item != null) item.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+@Override
+void setBackgroundImage (long hBitmap) {
+       super.setBackgroundImage (hBitmap);
+       setBackgroundTransparent (hBitmap != 0);
+}
+
+@Override
+void setBackgroundPixel (int pixel) {
+       super.setBackgroundPixel (pixel);
+       setBackgroundTransparent (pixel != -1);
+}
+
+void setBackgroundTransparent (boolean 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) != 0) {
+               if (!OS.IsAppThemed ()) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if (!transparent && findBackgroundControl () == null) {
+                               bits &= ~OS.TBSTYLE_TRANSPARENT;
+                       } else {
+                               bits |= OS.TBSTYLE_TRANSPARENT;
+                       }
+                       OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+               }
+       }
+}
+
+@Override
+void setBoundsInPixels (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 != null) {
+               if (getDrawing () && OS.IsWindowVisible (handle)) {
+                       parent.setResizeChildren (false);
+                       parent.setResizeChildren (true);
+               }
+       }
+       super.setBoundsInPixels (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 (boolean 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
+       * only images.
+       */
+       if (OS.IsAppThemed ()) {
+               boolean hasText = false, hasImage = false;
+               for (int i=0; i<items.length; i++) {
+                       ToolItem item = items [i];
+                       if (item != null) {
+                               if (!hasText) hasText = item.text.length () != 0;
+                               if (!hasImage) hasImage = item.image != null;
+                               if (hasText && hasImage) break;
+                       }
+               }
+               if (hasImage && !hasText) {
+                       for (int i=0; i<items.length; i++) {
+                               ToolItem item = items [i];
+                               if (item != null && (item.style & SWT.DROP_DOWN) != 0) {
+                                       TBBUTTONINFO info = new TBBUTTONINFO ();
+                                       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 == imageList) return;
+       long hImageList = 0;
+       if ((disabledImageList = imageList) != 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 != null && (item.style & mask) != 0) break;
+               index++;
+       }
+       if (index == 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 == imageList) return;
+       long hImageList = 0;
+       if ((hotImageList = imageList) != null) {
+               hImageList = hotImageList.getHandle ();
+       }
+       setDropDownItems (false);
+       OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, hImageList);
+       setDropDownItems (true);
+}
+
+void setImageList (ImageList imageList) {
+       if (this.imageList == imageList) return;
+       long hImageList = 0;
+       if ((this.imageList = imageList) != null) {
+               hImageList = imageList.getHandle ();
+       }
+       setDropDownItems (false);
+       OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, hImageList);
+       setDropDownItems (true);
+}
+
+@Override
+public boolean setParent (Composite parent) {
+       checkWidget ();
+       if (!super.setParent (parent)) return false;
+       long hwndParent = parent.handle;
+       OS.SendMessage (handle, OS.TB_SETPARENT, hwndParent, 0);
+       /*
+       * Bug in Windows.  When a tool bar is reparented, the tooltip
+       * control that is automatically created for the item is not
+       * reparented to the new shell.  The fix is to move the tooltip
+       * over using SetWindowLongPtr().  Note that for some reason,
+       * SetParent() does not work.
+       */
+       long hwndShell = parent.getShell ().handle;
+       long hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
+       OS.SetWindowLongPtr (hwndToolTip, OS.GWLP_HWNDPARENT, hwndShell);
+       return true;
+}
+
+@Override
+public void setRedraw (boolean redraw) {
+       checkWidget ();
+       setDropDownItems (false);
+       super.setRedraw (redraw);
+       setDropDownItems (true);
+}
+
+void setRowCount (int count) {
+       if ((style & SWT.VERTICAL) != 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 = new RECT ();
+               OS.GetWindowRect (handle, rect);
+               OS.MapWindowPoints (0, parent.handle, 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;
+               OS.SetWindowPos (handle, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
+               ignoreResize = false;
+       }
+}
+
+/*public*/ void setTabItemList (ToolItem [] tabList) {
+       checkWidget ();
+       if (tabList != null) {
+               for (int i=0; i<tabList.length; i++) {
+                       ToolItem item = tabList [i];
+                       if (item == null) error (SWT.ERROR_INVALID_ARGUMENT);
+                       if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+                       if (item.parent != this) error (SWT.ERROR_INVALID_PARENT);
+               }
+               ToolItem [] newList = new ToolItem [tabList.length];
+               System.arraycopy (tabList, 0, newList, 0, tabList.length);
+               tabList = newList;
+       }
+       this.tabItemList = tabList;
+}
+
+@Override
+boolean setTabItemFocus () {
+       int index = 0;
+       while (index < items.length) {
+               ToolItem item = items [index];
+               if (item != null && (item.style & SWT.SEPARATOR) == 0) {
+                       if (item.getEnabled ()) break;
+               }
+               index++;
+       }
+       if (index == items.length) return false;
+       return super.setTabItemFocus ();
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       if (super.updateTextDirection(textDirection)) {
+               ToolItem [] items = _getItems ();
+               int i = items.length;
+               while (i-- > 0) {
+                       items[i].updateTextDirection(style & SWT.FLIP_TEXT_DIRECTION);
+               }
+               return true;
+       }
+       return false;
+}
+
+@Override
+String toolTipText (NMTTDISPINFO hdr) {
+       if ((hdr.uFlags & OS.TTF_IDISHWND) != 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 = (int)hdr.idFrom;
+       long hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
+       if (hwndToolTip == 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.
+               */
+               int flags = SWT.RIGHT_TO_LEFT | SWT.FLIP_TEXT_DIRECTION;
+               if ((style & flags) != 0 && (style & flags) != flags) {
+                       hdr.uFlags |= OS.TTF_RTLREADING;
+               } else {
+                       hdr.uFlags &= ~OS.TTF_RTLREADING;
+               }
+               if (toolTipText != null) return ""; //$NON-NLS-1$
+               if (0 <= index && index < items.length) {
+                       ToolItem item = items [index];
+                       if (item != null) {
+                               /*
+                               * Bug in Windows.  When the  arrow keys are used to change
+                               * the hot item, for some reason, Windows displays the tool
+                               * tip for the hot item in at (0, 0) on the screen rather
+                               * than next to the current hot item.  This fix is to disallow
+                               * tool tips while the user is traversing with the arrow keys.
+                               */
+                               if (lastArrowId != -1) return "";
+                               return item.toolTipText;
+                       }
+               }
+       }
+       return super.toolTipText (hdr);
+}
+
+@Override
+void updateOrientation () {
+       super.updateOrientation ();
+       if (imageList != null) {
+               Point size = imageList.getImageSize ();
+               ImageList newImageList = display.getImageListToolBar (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+               ImageList newHotImageList = display.getImageListToolBarHot (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+               ImageList newDisabledImageList = display.getImageListToolBarDisabled (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+               TBBUTTONINFO info = new TBBUTTONINFO ();
+               info.cbSize = TBBUTTONINFO.sizeof;
+               info.dwMask = OS.TBIF_IMAGE;
+               int count = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+               for (int i=0; i<count; i++) {
+                       ToolItem item = items [i];
+                       if ((item.style & SWT.SEPARATOR) != 0) continue;
+                       if (item.image == null) continue;
+                       OS.SendMessage (handle, OS.TB_GETBUTTONINFO, item.id, info);
+                       if (info.iImage != OS.I_IMAGENONE) {
+                               Image image = imageList.get(info.iImage);
+                               Image hot = hotImageList.get(info.iImage);
+                               Image disabled = disabledImageList.get(info.iImage);
+                               imageList.put(info.iImage, null);
+                               hotImageList.put(info.iImage, null);
+                               disabledImageList.put(info.iImage, null);
+                               info.iImage = newImageList.add(image);
+                               newHotImageList.add(hot);
+                               newDisabledImageList.add(disabled);
+                               OS.SendMessage (handle, OS.TB_SETBUTTONINFO, item.id, info);
+                       }
+               }
+               display.releaseToolImageList (imageList);
+               display.releaseToolHotImageList (hotImageList);
+               display.releaseToolDisabledImageList (disabledImageList);
+               OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, newImageList.getHandle ());
+               OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, newHotImageList.getHandle ());
+               OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, newDisabledImageList.getHandle ());
+               imageList = newImageList;
+               hotImageList = newHotImageList;
+               disabledImageList = newDisabledImageList;
+               OS.InvalidateRect (handle, null, true);
+       }
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.CCS_NORESIZE | OS.TBSTYLE_TOOLTIPS | OS.TBSTYLE_CUSTOMERASE;
+       if (OS.IsAppThemed ()) bits |= OS.TBSTYLE_TRANSPARENT;
+       if ((style & SWT.SHADOW_OUT) == 0) bits |= OS.CCS_NODIVIDER;
+       if ((style & SWT.WRAP) != 0) bits |= OS.TBSTYLE_WRAPABLE;
+       if ((style & SWT.FLAT) != 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.IsAppThemed ()) {
+               if ((style & SWT.RIGHT) != 0) bits |= OS.TBSTYLE_LIST;
+       }
+       return bits;
+}
+
+@Override
+TCHAR windowClass () {
+       return ToolBarClass;
+}
+
+@Override
+long windowProc () {
+       return ToolBarProc;
+}
+
+@Override
+LRESULT WM_CAPTURECHANGED (long wParam, long lParam) {
+       LRESULT result = super.WM_CAPTURECHANGED (wParam, lParam);
+       if (result != 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 != null) {
+                       int fsState = (int)OS.SendMessage (handle, OS.TB_GETSTATE, item.id, 0);
+                       if ((fsState & OS.TBSTATE_PRESSED) != 0) {
+                               fsState &= ~OS.TBSTATE_PRESSED;
+                               OS.SendMessage (handle, OS.TB_SETSTATE, item.id, fsState);
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               case ' ':
+                       int index = (int)OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
+                       if (index != -1) {
+                               TBBUTTON lpButton = new TBBUTTON ();
+                               long code = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
+                               if (code != 0) {
+                                       items [lpButton.idCommand].click (false);
+                                       return LRESULT.ZERO;
+                               }
+                       }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_COMMAND (long wParam, long 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 != null) return result;
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long 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 != null) return result;
+       return new LRESULT (OS.DLGC_BUTTON | OS.DLGC_WANTARROWS);
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)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;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long lParam) {
+       int index = (int)OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
+       TBBUTTON lpButton = new TBBUTTON ();
+       long code = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
+       if (code != 0) lastFocusId = lpButton.idCommand;
+       return super.WM_KILLFOCUS (wParam, lParam);
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       if (ignoreMouse) return null;
+       return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+@Override
+LRESULT WM_LBUTTONUP (long wParam, long lParam) {
+       if (ignoreMouse) return null;
+       return super.WM_LBUTTONUP (wParam, lParam);
+}
+
+@Override
+LRESULT WM_MOUSELEAVE (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSELEAVE (wParam, lParam);
+       if (result != 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.
+       */
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = TOOLINFO.sizeof;
+       long hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
+       if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+               if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) {
+                       OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
+                       OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEMOVE (long wParam, long lParam) {
+       if (OS.GetMessagePos () != display.lastMouse) lastArrowId = -1;
+       return super.WM_MOUSEMOVE (wParam, lParam);
+}
+
+@Override
+LRESULT WM_NOTIFY (long wParam, long 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 != null) return result;
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long lParam) {
+       LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+       if (lastFocusId != -1 && handle == OS.GetFocus ()) {
+               int index = (int)OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lastFocusId, 0);
+               OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       if (ignoreResize) {
+               long code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+               if (code == 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) != 0 && (style & SWT.WRAP) != 0) {
+               RECT windowRect = new RECT ();
+               OS.GetWindowRect (handle, windowRect);
+               int index = 0, border = getBorderWidthInPixels () * 2;
+               RECT rect = new RECT ();
+               int count = (int)OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+               while (index < count) {
+                       OS.SendMessage (handle, OS.TB_GETITEMRECT, index, rect);
+                       OS.MapWindowPoints (handle, 0, rect, 2);
+                       if (rect.right > windowRect.right - border * 2) break;
+                       index++;
+               }
+               int bits = (int)OS.SendMessage (handle, OS.TB_GETEXTENDEDSTYLE, 0, 0);
+               if (index == 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 (long wParam, long lParam) {
+       LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+       if (result != 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 (!getDrawing ()) return result;
+       if ((style & SWT.WRAP) == 0) return result;
+       if (!OS.IsWindowVisible (handle)) return result;
+       if (OS.SendMessage (handle, OS.TB_GETROWS, 0, 0) == 1) {
+               return result;
+       }
+       WINDOWPOS lpwp = new WINDOWPOS ();
+       OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+       if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) != 0) {
+               return result;
+       }
+       RECT oldRect = new RECT ();
+       OS.GetClientRect (handle, oldRect);
+       RECT newRect = new RECT ();
+       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 = new 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 (long wParam, long lParam) {
+       ToolItem child = items [OS.LOWORD (wParam)];
+       if (child == null) return null;
+       return child.wmCommandChild (wParam, lParam);
+}
+
+private boolean customDrawing() {
+       return hasCustomBackground() || (hasCustomForeground() && OS.IsWindowEnabled(handle));
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.TBN_DROPDOWN:
+                       NMTOOLBAR lpnmtb = new NMTOOLBAR ();
+                       OS.MoveMemory (lpnmtb, lParam, NMTOOLBAR.sizeof);
+                       ToolItem child = items [lpnmtb.iItem];
+                       if (child != null) {
+                               Event event = new Event ();
+                               event.detail = SWT.ARROW;
+                               int index = (int)OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lpnmtb.iItem, 0);
+                               RECT rect = new RECT ();
+                               OS.SendMessage (handle, OS.TB_GETITEMRECT, index, rect);
+                               event.setLocationInPixels(rect.left, rect.bottom);
+                               child.sendSelectionEvent (SWT.Selection, event, false);
+                       }
+                       break;
+               case OS.NM_CUSTOMDRAW:
+                       /*
+                       * 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.
+                       */
+                       NMTBCUSTOMDRAW nmcd = new NMTBCUSTOMDRAW ();
+                       OS.MoveMemory (nmcd, lParam, NMTBCUSTOMDRAW.sizeof);
+//                     if (drawCount != 0 || !OS.IsWindowVisible (handle)) {
+//                             if (OS.WindowFromDC (nmcd.hdc) == 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) == 0) {
+                                               drawBackground (nmcd.hdc);
+                                       } else {
+                                               RECT rect = new RECT ();
+                                               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                                               drawBackground (nmcd.hdc, rect);
+                                       }
+                                       return new LRESULT (OS.CDRF_SKIPDEFAULT);
+                               }
+                               case OS.CDDS_PREPAINT: {
+                                       return new LRESULT (customDrawing() ? OS.CDRF_NOTIFYITEMDRAW : OS.CDRF_DODEFAULT);
+                               }
+                               case OS.CDDS_ITEMPREPAINT: {
+                                       if (customDrawing()) {
+                                               nmcd.clrBtnFace = getBackgroundPixel();
+                                               nmcd.clrText = getForegroundPixel();
+                                               OS.MoveMemory(lParam, nmcd, NMTBCUSTOMDRAW.sizeof);
+                                               return new LRESULT(OS.TBCDRF_USECDCOLORS);
+                                       }
+                                       return new LRESULT (OS.CDRF_DODEFAULT);
+                               }
+                       }
+                       break;
+               case OS.TBN_HOTITEMCHANGE:
+                       NMTBHOTITEM lpnmhi = new NMTBHOTITEM ();
+                       OS.MoveMemory (lpnmhi, lParam, NMTBHOTITEM.sizeof);
+                       switch (lpnmhi.dwFlags) {
+                               case OS.HICF_MOUSE: {
+                                       /*
+                                       * Bug in Windows.  When the tool bar has focus, a mouse is
+                                       * in an item and hover help for that item is displayed and
+                                       * then the arrow keys are used to change the hot item,
+                                       * for some reason, Windows snaps the hot item back to the
+                                       * one that is under the mouse.  The fix is to disallow
+                                       * hot item changes when the user is traversing using the
+                                       * arrow keys.
+                                       */
+                                       if (lastArrowId != -1) return LRESULT.ONE;
+                                       break;
+                               }
+                               case OS.HICF_ARROWKEYS: {
+                                       RECT client = new RECT ();
+                                       OS.GetClientRect (handle, client);
+                                       int index = (int)OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lpnmhi.idNew, 0);
+                                       RECT rect = new RECT ();
+                                       OS.SendMessage (handle, OS.TB_GETITEMRECT, index, rect);
+                                       if (rect.right > client.right || rect.bottom > client.bottom) {
+                                               return LRESULT.ONE;
+                                       }
+                                       lastArrowId = lpnmhi.idNew;
+                                       break;
+                               }
+                               default:
+                                       lastArrowId = -1;
+                       }
+                       if ((lpnmhi.dwFlags & OS.HICF_LEAVING) == 0) {
+                               lastHotId = lpnmhi.idNew;
+                       }
+                       break;
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolItem.java
new file mode 100644 (file)
index 0000000..34e2926
--- /dev/null
@@ -0,0 +1,1095 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ToolItem extends Item {
+       ToolBar parent;
+       Control control;
+       String toolTipText;
+       Image disabledImage, hotImage;
+       Image disabledImage2;
+       int id;
+       short cx;
+
+/**
+ * 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 ToolItem (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 ToolItem (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>
+ * <p>
+ * When the <code>SWT.RADIO</code> style bit is set, the <code>widgetSelected</code> method is
+ * also called when the receiver loses selection because another item in the same radio group
+ * was selected by the user. During <code>widgetSelected</code> the application can use
+ * <code>getSelection()</code> to determine the current selected state of the receiver.
+ * </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 == 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 (boolean dropDown) {
+       long hwnd = parent.handle;
+       if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return;
+       int index = (int)OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+       RECT rect = new RECT ();
+       OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect);
+       int hotIndex = (int)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;
+       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 != -1) {
+               OS.SendMessage (hwnd, OS.TB_SETHOTITEM, hotIndex, 0);
+       }
+}
+
+Widget [] computeTabList () {
+       if (isTabGroup ()) {
+               if (getEnabled ()) {
+                       if ((style & SWT.SEPARATOR) != 0) {
+                               if (control != null) return control.computeTabList();
+                       } else {
+                               return new Widget [] {this};
+                       }
+               }
+       }
+       return new Widget [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();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels () {
+       long hwnd = parent.handle;
+       int index = (int)OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+       RECT rect = new 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 boolean getEnabled () {
+       checkWidget();
+       if ((style & SWT.SEPARATOR) != 0) {
+               return (state & DISABLED) == 0;
+       }
+       long hwnd = parent.handle;
+       long fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+       return (fsState & OS.TBSTATE_ENABLED) != 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 enabled image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's enabled 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>
+ */
+@Override
+public Image getImage () {
+       return super.getImage();
+}
+
+/**
+ * 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 boolean getSelection () {
+       checkWidget();
+       if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
+       long hwnd = parent.handle;
+       long fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+       return (fsState & OS.TBSTATE_CHECKED) != 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();
+       return DPIUtil.autoScaleDown(getWidthInPixels());
+}
+
+int getWidthInPixels () {
+       long hwnd = parent.handle;
+       int index = (int)OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+       RECT rect = new 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 boolean isEnabled () {
+       checkWidget();
+       return getEnabled () && parent.isEnabled ();
+}
+
+boolean isTabGroup () {
+       ToolItem [] tabList = parent._getTabItemList ();
+       if (tabList != null) {
+               for (int i=0; i<tabList.length; i++) {
+                       if (tabList [i] == this) return true;
+               }
+       }
+       if ((style & SWT.SEPARATOR) != 0) return true;
+       int index = parent.indexOf (this);
+       if (index == 0) return true;
+       ToolItem previous = parent.getItem (index - 1);
+       return (previous.getStyle () & SWT.SEPARATOR) != 0;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       releaseImages ();
+       control = null;
+       toolTipText = null;
+       disabledImage = hotImage = null;
+       if (disabledImage2 != null) disabledImage2.dispose ();
+       disabledImage2 = null;
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       parent = null;
+       id = -1;
+}
+
+void releaseImages () {
+       TBBUTTONINFO info = new TBBUTTONINFO ();
+       info.cbSize = TBBUTTONINFO.sizeof;
+       info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
+       long 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) == 0 && info.iImage != OS.I_IMAGENONE) {
+               ImageList imageList = parent.getImageList ();
+               ImageList hotImageList = parent.getHotImageList ();
+               ImageList disabledImageList = parent.getDisabledImageList();
+               if (imageList != null) imageList.put (info.iImage, null);
+               if (hotImageList != null) hotImageList.put (info.iImage, null);
+               if (disabledImageList != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Selection, listener);
+       eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+void resizeControl () {
+       if (control != 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] != 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 != null) {
+               if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+               if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+       }
+       if ((style & SWT.SEPARATOR) == 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)) != 0) {
+               boolean changed = false;
+               long hwnd = parent.handle;
+               TBBUTTONINFO info = new TBBUTTONINFO ();
+               info.cbSize = TBBUTTONINFO.sizeof;
+               info.dwMask = OS.TBIF_STYLE | OS.TBIF_STATE;
+               OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
+               if (control == null) {
+                       if ((info.fsStyle & OS.BTNS_SEP) == 0) {
+                               changed = true;
+                               info.fsStyle &= ~(OS.BTNS_BUTTON | OS.BTNS_SHOWTEXT);
+                               info.fsStyle |= OS.BTNS_SEP;
+                               if ((state & DISABLED) != 0) {
+                                       info.fsState &= ~OS.TBSTATE_ENABLED;
+                               } else {
+                                       info.fsState |= OS.TBSTATE_ENABLED;
+                               }
+                       }
+               } else {
+                       if ((info.fsStyle & OS.BTNS_SEP) != 0) {
+                               changed = true;
+                               info.fsStyle &= ~OS.BTNS_SEP;
+                               info.fsStyle |= OS.BTNS_BUTTON | OS.BTNS_SHOWTEXT;
+                               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 (boolean enabled) {
+       checkWidget();
+       long hwnd = parent.handle;
+       int fsState = (int)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) != 0) == 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) == 0) {
+               if (image != null) updateImages (enabled && parent.getEnabled ());
+       }
+       if (!enabled && parent.lastFocusId == id) {
+               parent.lastFocusId = -1;
+       }
+}
+
+/**
+ * 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) != 0) return;
+       if (image != 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) != 0) return;
+       if (image != 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) != 0) return;
+       if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       super.setImage (image);
+       updateImages (getEnabled () && parent.getEnabled ());
+}
+
+boolean setRadioSelection (boolean value) {
+       if ((style & SWT.RADIO) == 0) return false;
+       if (getSelection () != value) {
+               setSelection (value);
+               sendSelectionEvent (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 (boolean selected) {
+       checkWidget();
+       if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
+       long hwnd = parent.handle;
+       int fsState = (int)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) != 0) == 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)) != 0) {
+               if (!getEnabled () || !parent.getEnabled ()) {
+                       updateImages (false);
+               }
+       }
+}
+
+@Override
+boolean setTabItemFocus () {
+       if (parent.setTabItemFocus ()) {
+               long hwnd = parent.handle;
+               int index = (int)OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+               OS.SendMessage (hwnd, OS.TB_SETHOTITEM, index, 0);
+               return true;
+       }
+       return false;
+}
+
+void _setText (String string) {
+       long hwnd = parent.handle;
+       TBBUTTONINFO info = new TBBUTTONINFO ();
+       info.cbSize = TBBUTTONINFO.sizeof;
+       info.dwMask = OS.TBIF_TEXT | OS.TBIF_STYLE;
+       info.fsStyle = (byte) (widgetStyle () | OS.BTNS_AUTOSIZE);
+       long hHeap = OS.GetProcessHeap (), pszText = 0;
+       if (string.length () != 0) {
+               info.fsStyle |= OS.BTNS_SHOWTEXT;
+               TCHAR buffer;
+               if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) {
+                       int bits  = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                       if ((bits & OS.WS_EX_LAYOUTRTL) != 0) {
+                               buffer = new TCHAR (parent.getCodePage (), LRE + string, true);
+                       } else {
+                               buffer = new TCHAR (parent.getCodePage (), RLE + string, true);
+                       }
+               } else {
+                       buffer = new TCHAR(parent.getCodePage (), string, true);
+               }
+               int byteCount = buffer.length () * TCHAR.sizeof;
+               pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+               OS.MoveMemory (pszText, buffer, byteCount);
+               info.pszText = pszText;
+       }
+       OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
+       if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+}
+
+/**
+ * Sets the receiver's text. 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, 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>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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>
+ */
+@Override
+public void setText (String string) {
+       checkWidget();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if ((style & SWT.SEPARATOR) != 0) return;
+       if (string.equals (text)) return;
+       super.setText (string);
+       if ((state & HAS_AUTO_DIRECTION) == 0 || !updateTextDirection (AUTO_TEXT_DIRECTION)) {
+               _setText (string);
+       }
+       /*
+       * 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);
+       long hwnd = parent.handle;
+       long hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+       OS.SendMessage (hwnd, OS.WM_SETFONT, hFont, 0);
+       parent.setDropDownItems (true);
+       parent.layoutItems ();
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       /* AUTO is handled by super */
+       if (super.updateTextDirection(textDirection) && text.length() != 0) {
+               _setText (text);
+               return true;
+       }
+       return false;
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ *
+ * @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. If the new value is <code>SWT.DEFAULT</code>,
+ * the width is a fixed-width area whose amount is determined by the platform.
+ * If the new value is 0 a vertical or horizontal line will be drawn, depending
+ * on the setting of the corresponding style bit (<code>SWT.VERTICAL</code> or
+ * <code>SWT.HORIZONTAL</code>). If the new value is <code>SWT.SEPARATOR_FILL</code>
+ * a variable-width space is inserted that acts as a spring between the two adjoining
+ * items which will push them out to the extent of the containing ToolBar.
+ *
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the 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();
+       setWidthInPixels(DPIUtil.autoScaleUp(width));
+}
+
+void setWidthInPixels (int width) {
+       if ((style & SWT.SEPARATOR) == 0) return;
+       if (width < 0) return;
+       long hwnd = parent.handle;
+       TBBUTTONINFO info = new TBBUTTONINFO ();
+       info.cbSize = TBBUTTONINFO.sizeof;
+       info.dwMask = OS.TBIF_SIZE;
+       info.cx = cx = (short) width;
+       OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
+       parent.layoutItems ();
+}
+
+void updateImages (boolean enabled) {
+       if ((style & SWT.SEPARATOR) != 0) return;
+       long hwnd = parent.handle;
+       TBBUTTONINFO info = new TBBUTTONINFO ();
+       info.cbSize = TBBUTTONINFO.sizeof;
+       info.dwMask = OS.TBIF_IMAGE;
+       OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
+       if (info.iImage == OS.I_IMAGENONE && image == null) return;
+       ImageList imageList = parent.getImageList ();
+       ImageList hotImageList = parent.getHotImageList ();
+       ImageList disabledImageList = parent.getDisabledImageList();
+       if (info.iImage == OS.I_IMAGENONE) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               int listStyle = parent.style & SWT.RIGHT_TO_LEFT;
+               if (imageList == null) {
+                       imageList = display.getImageListToolBar (listStyle, bounds.width, bounds.height);
+               }
+               if (disabledImageList == null) {
+                       disabledImageList = display.getImageListToolBarDisabled (listStyle, bounds.width, bounds.height);
+               }
+               if (hotImageList == null) {
+                       hotImageList = display.getImageListToolBarHot (listStyle, bounds.width, bounds.height);
+               }
+               Image disabled = disabledImage;
+               if (disabledImage == null) {
+                       if (disabledImage2 != 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)) != 0) {
+                       if (!enabled) image2 = hot = disabled;
+               }
+               info.iImage = imageList.add (image2);
+               disabledImageList.add (disabled);
+               hotImageList.add (hot != null ? hot : image2);
+               parent.setImageList (imageList);
+               parent.setDisabledImageList (disabledImageList);
+               parent.setHotImageList (hotImageList);
+       } else {
+               Image disabled = null;
+               if (disabledImageList != null) {
+                       if (image != null) {
+                               if (disabledImage2 != null) disabledImage2.dispose ();
+                               disabledImage2 = null;
+                               disabled = disabledImage;
+                               if (disabledImage == 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)) != 0) {
+                       if (!enabled) image2 = hot = disabled;
+               }
+               if (imageList != null) imageList.put (info.iImage, image2);
+               if (hotImageList != null) {
+                       hotImageList.put (info.iImage, hot != null ? hot : image2);
+               }
+               if (image == 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);
+       long hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+       OS.SendMessage (hwnd, OS.WM_SETFONT, hFont, 0);
+       parent.layoutItems ();
+}
+
+int widgetStyle () {
+       if ((style & SWT.DROP_DOWN) != 0) return OS.BTNS_DROPDOWN;
+       if ((style & SWT.PUSH) != 0) return OS.BTNS_BUTTON;
+       if ((style & SWT.CHECK) != 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) != 0) return OS.BTNS_CHECKGROUP;
+       if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECK;
+       if ((style & SWT.SEPARATOR) != 0) return OS.BTNS_SEP;
+       return OS.BTNS_BUTTON;
+}
+
+LRESULT wmCommandChild (long wParam, long lParam) {
+       if ((style & SWT.RADIO) != 0) {
+               if ((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
+                       selectRadio ();
+               }
+       }
+       sendSelectionEvent (SWT.Selection);
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolTip.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/ToolTip.java
new file mode 100644 (file)
index 0000000..78c2a55
--- /dev/null
@@ -0,0 +1,582 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent popup windows that are used
+ * to inform or warn the user.
+ * <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>
+ * Note: Only one of the styles ICON_ERROR, ICON_INFORMATION,
+ * and ICON_WARNING 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/#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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ToolTip extends Widget {
+       Shell parent;
+       TrayItem item;
+       String text = "", message = "";
+       int id, x, y;
+       boolean autoHide = true, hasLocation, visible;
+       static final 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#BALLOON
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_WARNING
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ToolTip (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) == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener(listener);
+       addListener (SWT.Selection,typedListener);
+       addListener (SWT.DefaultSelection,typedListener);
+}
+
+@Override
+void destroyWidget () {
+       if (parent != 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 boolean 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 boolean getVisible () {
+       checkWidget();
+       if (item != null) return visible;
+       long hwndToolTip = hwndToolTip ();
+       if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = TOOLINFO.sizeof;
+               if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+                       return (lpti.uFlags & OS.TTF_IDISHWND) == 0 && lpti.uId == id;
+               }
+       }
+       return false;
+}
+
+int getWidth () {
+       long hwnd = parent.handle;
+       long hmonitor = OS.MonitorFromWindow (hwnd, OS.MONITOR_DEFAULTTONEAREST);
+       MONITORINFO lpmi = new MONITORINFO ();
+       lpmi.cbSize = MONITORINFO.sizeof;
+       OS.GetMonitorInfo (hmonitor, lpmi);
+       int maxWidth = lpmi.rcWork_right - lpmi.rcWork_left;
+       return maxWidth / 4;
+}
+
+long hwndToolTip () {
+       return (style & SWT.BALLOON) != 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 boolean isVisible () {
+       checkWidget ();
+       if (item != 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 == null) {
+               if (autoHide) {
+                       long hwndToolTip = hwndToolTip ();
+                       if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+                               TOOLINFO lpti = new TOOLINFO ();
+                               lpti.cbSize = TOOLINFO.sizeof;
+                               if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+                                       if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) {
+                                               if (lpti.uId == id) {
+                                                       OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 0, lpti);
+                                                       OS.SendMessage (hwndToolTip, OS.TTM_POP, 0, 0);
+                                                       OS.KillTimer (hwndToolTip, TIMER_ID);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       if (item != null && item.toolTip == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 (boolean 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 ();
+       setLocationInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+}
+
+void setLocationInPixels (int x, int y) {
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       location = DPIUtil.autoScaleUp(location);
+       setLocationInPixels(location.x, location.y);
+}
+
+/**
+ * Sets the receiver's message.
+ *
+ * @param string the new message
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setMessage (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       message = string;
+       updateMessage();
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       text = string;
+       //TODO - update when visible
+       //TODO - support text direction (?)
+}
+
+void updateMessage () {
+       long hwnd = hwndToolTip();
+       if (OS.SendMessage (hwnd, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = TOOLINFO.sizeof;
+               if (OS.SendMessage (hwnd, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+                       if (message != null && message.length() > 0) {
+                               long hHeap = OS.GetProcessHeap ();
+                               TCHAR buffer = new TCHAR (0, message, true);
+                               int byteCount = buffer.length () * TCHAR.sizeof;
+                               lpti.lpszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                               OS.MoveMemory (lpti.lpszText, buffer, byteCount);
+                               OS.SendMessage (hwnd, OS.TTM_UPDATETIPTEXT, 0, lpti);
+                               OS.HeapFree(hHeap, 0, lpti.lpszText);
+                       }
+                       else {
+                               /*
+                                * Bug 498895: When empty message string is set, then
+                                * underlying native tool-tip object goes into dirty state &
+                                * becomes unusable. Hence reset TOOLINFO#lpszText message
+                                * text field to -1 (which is the default initial value of
+                                * this field when fetch using TTM_GETCURRENTTOOL API call)
+                                * to set empty message string at native level successfully.
+                                */
+                               lpti.lpszText =  -1;
+                               OS.SendMessage (hwnd, OS.TTM_UPDATETIPTEXT, 0, lpti);
+                       }
+               }
+       }
+}
+
+/**
+ * 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 (boolean visible) {
+       checkWidget ();
+       if (visible == getVisible ()) return;
+       if (item == null) {
+               long hwnd = parent.handle;
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = TOOLINFO.sizeof;
+               lpti.uId = id;
+               lpti.hwnd = hwnd;
+               long hwndToolTip = hwndToolTip ();
+               Shell shell = parent.getShell ();
+               if (text.length () != 0) {
+                       int icon = OS.TTI_NONE;
+                       if ((style & SWT.ICON_INFORMATION) != 0) icon = OS.TTI_INFO;
+                       if ((style & SWT.ICON_WARNING) != 0) icon = OS.TTI_WARNING;
+                       if ((style & SWT.ICON_ERROR) != 0) icon = OS.TTI_ERROR;
+                       shell.setToolTipTitle (hwndToolTip, text, icon);
+               } else {
+                       shell.setToolTipTitle (hwndToolTip, null, 0);
+               }
+               OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, getWidth ());
+               if (visible) {
+                       int nX = x, nY = y;
+                       if (!hasLocation) {
+                               POINT pt = new POINT ();
+                               if (OS.GetCursorPos (pt)) {
+                                       nX = pt.x;
+                                       nY = pt.y;
+                               }
+                       }
+                       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 = new POINT ();
+                       OS.GetCursorPos (pt);
+                       RECT rect = new RECT ();
+                       OS.GetClientRect (hwnd, rect);
+                       OS.MapWindowPoints (hwnd, 0, rect, 2);
+                       if (!OS.PtInRect (rect, pt)) {
+                               long hCursor = OS.GetCursor ();
+                               OS.SetCursor (0);
+                               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 = (int)OS.SendMessage (hwndToolTip, OS.TTM_GETDELAYTIME, OS.TTDT_AUTOPOP, 0);
+                       OS.SetTimer (hwndToolTip, TIMER_ID, time, 0);
+                       updateMessage();
+               } 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 != null) {
+               if (visible) {
+                       NOTIFYICONDATA iconData = new NOTIFYICONDATA ();
+                       char [] szInfoTitle = iconData.szInfoTitle;
+                       int length1 = Math.min (szInfoTitle.length - 1, text.length ());
+                       text.getChars (0, length1, szInfoTitle, 0);
+                       char [] szInfo = iconData.szInfo;
+                       int length2 = Math.min (szInfo.length - 1, message.length ());
+                       message.getChars (0, length2, szInfo, 0);
+                       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) != 0) iconData.dwInfoFlags = OS.NIIF_INFO;
+                       if ((style & SWT.ICON_WARNING) != 0) iconData.dwInfoFlags = OS.NIIF_WARNING;
+                       if ((style & SWT.ICON_ERROR) != 0) iconData.dwInfoFlags = OS.NIIF_ERROR;
+                       sendEvent (SWT.Show);
+                       this.visible = OS.Shell_NotifyIcon (OS.NIM_MODIFY, iconData);
+               } else {
+                       //TODO - hide the tray item
+               }
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Touch.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Touch.java
new file mode 100644 (file)
index 0000000..f28d9a0
--- /dev/null
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+/**
+ * Instances of this class are created in response to a
+ * touch-based input device being touched. They are found
+ * in the <code>touches</code> field of an Event or TouchEvent.
+ *
+ * @see org.eclipse.swt.events.TouchEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.7
+ */
+public final class Touch {
+
+       /**
+        * The unique identity of the touch. Use this value to track changes to a touch
+        * during the touch's life. Two touches may have the same identity even if they
+        * come from different sources.
+        */
+       public long id;
+
+       /**
+        * The object representing the input source that generated the touch.
+        */
+       public TouchSource source;
+
+       /**
+        * The state of this touch at the time it was generated. If this field is 0
+        * then the finger is still touching the device but has not moved
+        * since the last <code>TouchEvent</code> was generated.
+        *
+        * @see org.eclipse.swt.SWT#TOUCHSTATE_DOWN
+        * @see org.eclipse.swt.SWT#TOUCHSTATE_MOVE
+        * @see org.eclipse.swt.SWT#TOUCHSTATE_UP
+        */
+       public int state;
+
+       /**
+        * A flag indicating that the touch is the first touch from a previous
+        * state of no touch points. Once designated as such, the touch remains
+        * the primary touch until all fingers are removed from the device.
+        */
+       public boolean primary;
+
+       /**
+        * The x location of the touch in TouchSource coordinates.
+        */
+       public int x;
+
+       /**
+        * The y location of the touch in TouchSource coordinates.
+        */
+       public int y;
+
+/**
+ * Constructs a new touch state from the given inputs.
+ *
+ * @param identity Identity of the touch
+ * @param source Object representing the device that generated the touch
+ * @param state One of the state constants representing the state of this touch
+ * @param primary Whether or not the touch is the primary touch
+ * @param x X location of the touch in screen coordinates
+ * @param y Y location of the touch in screen coordinates
+ */
+Touch (long identity, TouchSource source, int state, boolean primary, int x, int y) {
+       this.id = identity;
+       this.source = source;
+       this.state = state;
+       this.primary = primary;
+       this.x = x;
+       this.y = y;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+@Override
+public String toString() {
+       return "Touch {id=" + id
+       + " source=" + source
+       + " state=" + state
+       + " primary=" + primary
+       + " x=" + x
+       + " y=" + y
+       + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TouchSource.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TouchSource.java
new file mode 100644 (file)
index 0000000..d74cf17
--- /dev/null
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class represent sources of touch input that generate <code>Touch</code> objects.
+ * They also provide information about the input source, which is important for interpreting the
+ * information in the <code>Touch</code> object.
+ * <p>
+ * Instances of this class can be marked as direct or indirect:
+ * <ul>
+ * <li>When an instance is <em>direct</em>, the touch source is a touch-sensitive digitizer surface such
+ * as a tablet or a touch screen. There is a one-to-one mapping between a touch point and a location in
+ * a window.
+ * </li><li>
+ * When an instance is <em>indirect</em> (more precisely, not direct), the touch source is a track pad or
+ * other device that normally moves the cursor, but is also able to interpret multiple touches on its surface.
+ * In this case there is not a one-to-one mapping between the location of the touch on the device and a
+ * location on the display because the user can remove their finger or stylus and touch another part of
+ * the device and resume what they were doing.
+ * </li>
+ * </ul>
+ *
+ * @see Touch
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.7
+ */
+public final class TouchSource {
+       long handle;
+       boolean direct;
+       Rectangle bounds;
+
+/**
+ * Constructs a new touch source from the given inputs.
+ *
+ * @param direct Is the touch source direct or indirect?
+ * @param height height of the source in points.
+ * @param width width of the source in points.
+ */
+TouchSource (long handle, boolean direct, Rectangle bounds) {
+       this.handle = handle;
+       this.direct = direct;
+       this.bounds = bounds;
+}
+
+/**
+ * Returns the type of touch input this source generates, <code>true</code> for direct or <code>false</code> for indirect.
+ *
+ * @return <code>true</code> if the input source is direct, or <code>false</code> otherwise
+ */
+public boolean isDirect () {
+       return direct;
+}
+
+/**
+ * Returns the bounding rectangle of the device. For a direct source, this corresponds to the bounds of
+ * the display device in pixels. For an indirect source, this contains the size of the device in points.
+ * <p>
+ * Note that the x and y values may not necessarily be 0 if the TouchSource is a direct source.
+ *
+ * @return the bounding rectangle of the input source
+ */
+public Rectangle getBounds () {
+       return new Rectangle (bounds.x, bounds.y, bounds.width, bounds.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 "TouchSource {handle=" + handle + " direct=" + direct + " bounds=" + bounds + "}";
+}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tracker.java
new file mode 100644 (file)
index 0000000..ba256fe
--- /dev/null
@@ -0,0 +1,1246 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ *  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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Tracker extends Widget {
+       Control parent;
+       boolean tracking, cancelled, stippled;
+       Rectangle [] rectangles = new Rectangle [0], proportions = rectangles;
+       Rectangle bounds;
+       long resizeCursor;
+       Cursor clientCursor;
+       int cursorOrientation = SWT.NONE;
+       boolean inEvent = false;
+       boolean drawn;
+       long hwndTransparent, hwndOpaque, oldTransparentProc, oldOpaqueProc;
+       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 Tracker (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
+ * @see SWT#RESIZE
+ */
+public Tracker (Display display, int style) {
+       if (display == null) display = Display.getCurrent ();
+       if (display == null) display = Display.getDefault ();
+       if (!display.isValidThread ()) {
+               error (SWT.ERROR_THREAD_INVALID_ACCESS);
+       }
+       this.style = checkStyle (style);
+       this.display = display;
+       reskinWidget ();
+}
+
+/**
+ * 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 == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.KeyUp,typedListener);
+       addListener (SWT.KeyDown,typedListener);
+}
+
+Point adjustMoveCursor () {
+       if (bounds == null) return null;
+       int newX = bounds.x + bounds.width / 2;
+       int newY = bounds.y;
+       POINT pt = new POINT ();
+       pt.x = newX;  pt.y = newY;
+       /*
+        * Convert to screen coordinates iff needed
+        */
+       if (parent != null) {
+               OS.ClientToScreen (parent.handle, pt);
+       }
+       OS.SetCursorPos (pt.x, pt.y);
+       return new Point (pt.x, pt.y);
+}
+
+Point adjustResizeCursor () {
+       if (bounds == null) return null;
+       int newX, newY;
+
+       if ((cursorOrientation & SWT.LEFT) != 0) {
+               newX = bounds.x;
+       } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+               newX = bounds.x + bounds.width;
+       } else {
+               newX = bounds.x + bounds.width / 2;
+       }
+
+       if ((cursorOrientation & SWT.UP) != 0) {
+               newY = bounds.y;
+       } else if ((cursorOrientation & SWT.DOWN) != 0) {
+               newY = bounds.y + bounds.height;
+       } else {
+               newY = bounds.y + bounds.height / 2;
+       }
+
+       POINT pt = new POINT ();
+       pt.x = newX;  pt.y = newY;
+       /*
+        * Convert to screen coordinates iff needed
+        */
+       if (parent != 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 == null) {
+               long newCursor = 0;
+               switch (cursorOrientation) {
+                       case SWT.UP:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZENS);
+                               break;
+                       case SWT.DOWN:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZENS);
+                               break;
+                       case SWT.LEFT:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZEWE);
+                               break;
+                       case SWT.RIGHT:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZEWE);
+                               break;
+                       case SWT.LEFT | SWT.UP:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZENWSE);
+                               break;
+                       case SWT.RIGHT | SWT.DOWN:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZENWSE);
+                               break;
+                       case SWT.LEFT | SWT.DOWN:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZENESW);
+                               break;
+                       case SWT.RIGHT | SWT.UP:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZENESW);
+                               break;
+                       default:
+                               newCursor = OS.LoadCursor (0, OS.IDC_SIZEALL);
+                               break;
+               }
+               OS.SetCursor (newCursor);
+               if (resizeCursor != 0) {
+                       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)) == 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 == 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 != null) {
+               for (int i = 0; i < rects.length; i++) {
+                       int x = 0, y = 0, width = 0, height = 0;
+                       if (bounds.width != 0) {
+                               x = (rects [i].x - bounds.x) * 100 / bounds.width;
+                               width = rects [i].width * 100 / bounds.width;
+                       } else {
+                               width = 100;
+                       }
+                       if (bounds.height != 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, boolean stippled) {
+       if (hwndOpaque != 0) {
+               RECT rect1 = new RECT();
+               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.MapWindowPoints (0, hwndOpaque, rect1, 2);
+                       OS.RedrawWindow (hwndOpaque, rect1, 0, OS.RDW_INVALIDATE);
+               }
+               return;
+       }
+       int bandWidth = 1;
+       long hwndTrack = parent == null ? OS.GetDesktopWindow () : parent.handle;
+       long hDC = OS.GetDCEx (hwndTrack, 0, OS.DCX_CACHE);
+       long hBitmap = 0, hBrush = 0, oldBrush = 0;
+       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);
+               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 = getRectanglesInPixels();
+       for (int i = 0; i < result.length; i++) {
+               result[i] = DPIUtil.autoScaleDown(result[i]);
+       }
+       return result;
+}
+
+Rectangle [] getRectanglesInPixels () {
+       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 boolean getStippled () {
+       checkWidget ();
+       return stippled;
+}
+
+void moveRectangles (int xChange, int yChange) {
+       if (bounds == null) return;
+       if (xChange < 0 && ((style & SWT.LEFT) == 0)) xChange = 0;
+       if (xChange > 0 && ((style & SWT.RIGHT) == 0)) xChange = 0;
+       if (yChange < 0 && ((style & SWT.UP) == 0)) yChange = 0;
+       if (yChange > 0 && ((style & SWT.DOWN) == 0)) yChange = 0;
+       if (xChange == 0 && yChange == 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 boolean 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 == SWT.UP || vStyle == SWT.DOWN) {
+               cursorOrientation |= vStyle;
+       }
+       int hStyle = style & (SWT.LEFT | SWT.RIGHT);
+       if (hStyle == SWT.LEFT || hStyle == SWT.RIGHT) {
+               cursorOrientation |= hStyle;
+       }
+
+       Callback newProc = null;
+       boolean mouseDown = OS.GetKeyState(OS.VK_LBUTTON) < 0;
+       /*
+       * Bug in Vista. Drawing directly to the screen with XOR does not
+       * perform well. The fix is to draw on layered window instead.
+       *
+       * Note that one window (almost opaque) is used for catching all events and a
+       * second window is used for drawing the rectangles.
+       */
+       if (parent == null) {
+               Rectangle bounds = display.getBoundsInPixels();
+               hwndTransparent = OS.CreateWindowEx (
+                       OS.WS_EX_LAYERED | OS.WS_EX_NOACTIVATE | OS.WS_EX_TOOLWINDOW,
+                       display.windowClass,
+                       null,
+                       OS.WS_POPUP,
+                       bounds.x, bounds.y,
+                       bounds.width, bounds.height,
+                       0,
+                       0,
+                       OS.GetModuleHandle (null),
+                       null);
+               OS.SetLayeredWindowAttributes (hwndTransparent, 0, (byte)0x01, OS.LWA_ALPHA);
+               hwndOpaque = OS.CreateWindowEx (
+                       OS.WS_EX_LAYERED | OS.WS_EX_NOACTIVATE | OS.WS_EX_TOOLWINDOW,
+                       display.windowClass,
+                       null,
+                       OS.WS_POPUP,
+                       bounds.x, bounds.y,
+                       bounds.width, bounds.height,
+                       hwndTransparent,
+                       0,
+                       OS.GetModuleHandle (null),
+                       null);
+               OS.SetLayeredWindowAttributes (hwndOpaque, 0xFFFFFF, (byte)0, OS.LWA_COLORKEY | OS.LWA_ALPHA);
+               drawn = false;
+               newProc = new Callback (this, "transparentProc", 4); //$NON-NLS-1$
+               long newProcAddress = newProc.getAddress ();
+               if (newProcAddress == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+               oldTransparentProc = OS.GetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC);
+               OS.SetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC, newProcAddress);
+               oldOpaqueProc = OS.GetWindowLongPtr (hwndOpaque, OS.GWLP_WNDPROC);
+               OS.SetWindowLongPtr (hwndOpaque, OS.GWLP_WNDPROC, newProcAddress);
+               OS.ShowWindow (hwndTransparent, OS.SW_SHOWNOACTIVATE);
+               OS.ShowWindow (hwndOpaque, OS.SW_SHOWNOACTIVATE);
+       } else {
+               /*
+               * 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).
+               */
+               if (!mouseDown) {
+                       Rectangle bounds = display.getBoundsInPixels();
+                       hwndTransparent = OS.CreateWindowEx (
+                               OS.WS_EX_TRANSPARENT,
+                               display.windowClass,
+                               null,
+                               OS.WS_POPUP,
+                               bounds.x, bounds.y,
+                               bounds.width, bounds.height,
+                               0,
+                               0,
+                               OS.GetModuleHandle (null),
+                               null);
+                       newProc = new Callback (this, "transparentProc", 4); //$NON-NLS-1$
+                       long newProcAddress = newProc.getAddress ();
+                       if (newProcAddress == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+                       oldTransparentProc = OS.GetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC);
+                       OS.SetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC, newProcAddress);
+                       OS.ShowWindow (hwndTransparent, OS.SW_SHOWNOACTIVATE);
+               }
+       }
+
+       update ();
+       drawRectangles (rectangles, stippled);
+       Point cursorPos = null;
+       if (mouseDown) {
+               POINT pt = new POINT ();
+               OS.GetCursorPos (pt);
+               cursorPos = new Point (pt.x, pt.y);
+       } else {
+               if ((style & SWT.RESIZE) != 0) {
+                       cursorPos = adjustResizeCursor ();
+               } else {
+                       cursorPos = adjustMoveCursor ();
+               }
+       }
+       if (cursorPos != null) {
+               oldX = cursorPos.x;
+               oldY = cursorPos.y;
+       }
+
+       Display display = this.display;
+       try {
+               /* Tracker behaves like a Dialog with its own OS event loop. */
+               MSG msg = new MSG ();
+               while (tracking && !cancelled) {
+                       if (parent != null && parent.isDisposed ()) break;
+                       display.runSkin ();
+                       display.runDeferredLayouts ();
+                       display.sendPreExternalEventDispatchEvent ();
+                       OS.GetMessage (msg, 0, 0, 0);
+                       display.sendPostExternalEventDispatchEvent ();
+                       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;
+                       }
+                       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 (hwndOpaque == 0) {
+                               if (msg.message == OS.WM_PAINT) {
+                                       update ();
+                                       drawRectangles (rectangles, stippled);
+                               }
+                       }
+                       OS.DispatchMessage (msg);
+                       if (hwndOpaque == 0) {
+                               if (msg.message == OS.WM_PAINT) {
+                                       drawRectangles (rectangles, stippled);
+                               }
+                       }
+                       display.runAsyncMessages (false);
+               }
+               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 != 0) {
+                       OS.DestroyWindow (hwndTransparent);
+                       hwndTransparent = 0;
+               }
+               hwndOpaque = 0;
+               if (newProc != null) {
+                       newProc.dispose ();
+                       oldTransparentProc = oldOpaqueProc = 0;
+               }
+               /*
+               * Cleanup: If this tracker was resizing then the last cursor that it created
+               * needs to be destroyed.
+               */
+               if (resizeCursor != 0) {
+                       OS.DestroyCursor (resizeCursor);
+                       resizeCursor = 0;
+               }
+       }
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.KeyUp, listener);
+       eventTable.unhook (SWT.KeyDown, listener);
+}
+
+void resizeRectangles (int xChange, int yChange) {
+       if (bounds == 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) != 0) && ((cursorOrientation & SWT.RIGHT) == 0)) {
+               cursorOrientation |= SWT.LEFT;
+       }
+       if (xChange > 0 && ((style & SWT.RIGHT) != 0) && ((cursorOrientation & SWT.LEFT) == 0)) {
+               cursorOrientation |= SWT.RIGHT;
+       }
+       if (yChange < 0 && ((style & SWT.UP) != 0) && ((cursorOrientation & SWT.DOWN) == 0)) {
+               cursorOrientation |= SWT.UP;
+       }
+       if (yChange > 0 && ((style & SWT.DOWN) != 0) && ((cursorOrientation & SWT.UP) == 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) != 0) {
+               if (xChange > bounds.width) {
+                       if ((style & SWT.RIGHT) == 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) != 0) {
+               if (bounds.width < -xChange) {
+                       if ((style & SWT.LEFT) == 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) != 0) {
+               if (yChange > bounds.height) {
+                       if ((style & SWT.DOWN) == 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) != 0) {
+               if (bounds.height < -yChange) {
+                       if ((style & SWT.UP) == 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) != 0) {
+               bounds.x += xChange;
+               bounds.width -= xChange;
+       } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+               bounds.width += xChange;
+       }
+       if ((cursorOrientation & SWT.UP) != 0) {
+               bounds.y += yChange;
+               bounds.height -= yChange;
+       } else if ((cursorOrientation & SWT.DOWN) != 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 != 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 is null or 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 ();
+       if (rectangles == null) error (SWT.ERROR_NULL_ARGUMENT);
+       Rectangle [] rectanglesInPixels = new Rectangle [rectangles.length];
+       for (int i = 0; i < rectangles.length; i++) {
+               rectanglesInPixels [i] = DPIUtil.autoScaleUp (rectangles [i]);
+       }
+       setRectanglesInPixels (rectanglesInPixels);
+}
+
+void setRectanglesInPixels (Rectangle [] rectangles) {
+       this.rectangles = new Rectangle [rectangles.length];
+       for (int i = 0; i < rectangles.length; i++) {
+               Rectangle current = rectangles [i];
+               if (current == 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 (boolean stippled) {
+       checkWidget ();
+       this.stippled = stippled;
+}
+
+long transparentProc (long hwnd, long msg, long wParam, long lParam) {
+       switch ((int)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 != null) {
+                               OS.SetCursor (clientCursor.handle);
+                               return 1;
+                       }
+                       if (resizeCursor != 0) {
+                               OS.SetCursor (resizeCursor);
+                               return 1;
+                       }
+                       break;
+               case OS.WM_PAINT:
+                       if (hwndOpaque == hwnd) {
+                               PAINTSTRUCT ps = new PAINTSTRUCT();
+                               long hDC = OS.BeginPaint (hwnd, ps);
+                               long hBitmap = 0, hBrush = 0, oldBrush = 0;
+                               long transparentBrush = OS.CreateSolidBrush(0xFFFFFF);
+                               oldBrush = OS.SelectObject (hDC, transparentBrush);
+                               OS.PatBlt (hDC, ps.left, ps.top, ps.right - ps.left, ps.bottom - ps.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);
+                                       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;
+                               RECT rect1 = new RECT ();
+                               for (int i=0; i<rects.length; i++) {
+                                       Rectangle rect = rects [i];
+                                       rect1.left = rect.x;
+                                       rect1.top  = rect.y;
+                                       rect1.right = rect.x + rect.width;
+                                       rect1.bottom = rect.y + rect.height;
+                                       OS.MapWindowPoints (0, hwndOpaque, rect1, 2);
+                                       int width = rect1.right - rect1.left;
+                                       int height = rect1.bottom - rect1.top;
+                                       OS.PatBlt (hDC, rect1.left, rect1.top, width, bandWidth, OS.PATCOPY);
+                                       OS.PatBlt (hDC, rect1.left, rect1.top + bandWidth, bandWidth, height - (bandWidth * 2), OS.PATCOPY);
+                                       OS.PatBlt (hDC, rect1.right - bandWidth, rect1.top + bandWidth, bandWidth, height - (bandWidth * 2), OS.PATCOPY);
+                                       OS.PatBlt (hDC, rect1.left, rect1.bottom - bandWidth, width, bandWidth, OS.PATCOPY);
+                               }
+                               OS.SelectObject (hDC, oldBrush);
+                               if (stippled) {
+                                       OS.DeleteObject (hBrush);
+                                       OS.DeleteObject (hBitmap);
+                               }
+                               OS.EndPaint (hwnd, ps);
+                               if (!drawn) {
+                                       OS.SetLayeredWindowAttributes (hwndOpaque, 0xFFFFFF, (byte)0xFF, OS.LWA_COLORKEY | OS.LWA_ALPHA);
+                                       drawn = true;
+                               }
+                               return 0;
+                       }
+       }
+       return OS.CallWindowProc (hwnd == hwndTransparent ? oldTransparentProc : oldOpaqueProc, hwnd, (int)msg, wParam, lParam);
+}
+
+void update () {
+       if (hwndOpaque != 0) return;
+       if (parent != null) {
+               if (parent.isDisposed ()) return;
+               Shell shell = parent.getShell ();
+               shell.update (true);
+       } else {
+               display.update ();
+       }
+}
+
+@Override
+LRESULT wmKeyDown (long hwnd, long wParam, long lParam) {
+       LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+       if (result != null) return result;
+       boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0;
+       int stepSize = OS.GetKeyState (OS.VK_CONTROL) < 0 ? STEPSIZE_SMALL : STEPSIZE_LARGE;
+       int xChange = 0, yChange = 0;
+       switch ((int)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;
+       }
+       if (xChange != 0 || yChange != 0) {
+               Rectangle [] oldRectangles = rectangles;
+               boolean 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.setLocationInPixels(oldX + xChange, oldY + yChange);
+               Point cursorPos;
+               if ((style & SWT.RESIZE) != 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;
+                       }
+                       boolean 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 != oldRectangles) {
+                               int length = rectangles.length;
+                               if (length != rectsToErase.length) {
+                                       draw = true;
+                               } else {
+                                       for (int i = 0; i < length; i++) {
+                                               if (!rectangles [i].equals (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;
+                       }
+                       boolean 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 != oldRectangles) {
+                               int length = rectangles.length;
+                               if (length != rectsToErase.length) {
+                                       draw = true;
+                               } else {
+                                       for (int i = 0; i < length; i++) {
+                                               if (!rectangles [i].equals (rectsToErase [i])) {
+                                                       draw = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       } else {
+                               draw = true;
+                       }
+                       if (draw) {
+                               drawRectangles (rectsToErase, oldStippled);
+                               update ();
+                               drawRectangles (rectangles, stippled);
+                       }
+                       cursorPos = adjustMoveCursor ();
+               }
+               if (cursorPos != null) {
+                       oldX = cursorPos.x;
+                       oldY = cursorPos.y;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT wmSysKeyDown (long hwnd, long wParam, long lParam) {
+       LRESULT result = super.wmSysKeyDown (hwnd, wParam, lParam);
+       if (result != null) return result;
+       cancelled = true;
+       tracking = false;
+       return result;
+}
+
+LRESULT wmMouse (int message, long wParam, long lParam) {
+       boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0;
+       int newPos = OS.GetMessagePos ();
+       int newX = OS.GET_X_LPARAM (newPos);
+       int newY = OS.GET_Y_LPARAM (newPos);
+       if (newX != oldX || newY != oldY) {
+               Rectangle [] oldRectangles = rectangles;
+               boolean 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.setLocationInPixels(newX, newY);
+               if ((style & SWT.RESIZE) != 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;
+                       }
+                       boolean 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 != oldRectangles) {
+                               int length = rectangles.length;
+                               if (length != rectsToErase.length) {
+                                       draw = true;
+                               } else {
+                                       for (int i = 0; i < length; i++) {
+                                               if (!rectangles [i].equals (rectsToErase [i])) {
+                                                       draw = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       else {
+                               draw = true;
+                       }
+                       if (draw) {
+                               drawRectangles (rectsToErase, oldStippled);
+                               update ();
+                               drawRectangles (rectangles, stippled);
+                       }
+                       Point cursorPos = adjustResizeCursor ();
+                       if (cursorPos != 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;
+                       }
+                       boolean 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 != oldRectangles) {
+                               int length = rectangles.length;
+                               if (length != rectsToErase.length) {
+                                       draw = true;
+                               } else {
+                                       for (int i = 0; i < length; i++) {
+                                               if (!rectangles [i].equals (rectsToErase [i])) {
+                                                       draw = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       } else {
+                               draw = true;
+                       }
+                       if (draw) {
+                               drawRectangles (rectsToErase, oldStippled);
+                               update ();
+                               drawRectangles (rectangles, stippled);
+                       }
+               }
+               oldX = newX;
+               oldY = newY;
+       }
+       tracking = message != OS.WM_LBUTTONUP;
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tray.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tray.java
new file mode 100644 (file)
index 0000000..a0f34b4
--- /dev/null
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+
+/**
+ * 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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Tray extends Widget {
+       int itemCount;
+       TrayItem [] items = new TrayItem [4];
+
+Tray (Display display, int style) {
+       this.display = display;
+       reskinWidget ();
+}
+
+void createItem (TrayItem item, int index) {
+       if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+       if (itemCount == 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] == item) break;
+               index++;
+       }
+       if (index == 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 (boolean destroy) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       TrayItem item = items [i];
+                       if (item != null && !item.isDisposed ()) {
+                               item.release (false);
+                       }
+               }
+               items = null;
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (display.tray == this) display.tray = null;
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       TrayItem item = items [i];
+                       if (item != null) item.reskin (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TrayItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TrayItem.java
new file mode 100644 (file)
index 0000000..ea39f26
--- /dev/null
@@ -0,0 +1,581 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent icons that can be placed on the
+ * system tray or task bar status area.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, MenuDetect, 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/#tray">Tray, TrayItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TrayItem extends Item {
+       Tray parent;
+       int id;
+       Image image2, highlightImage;
+       ToolTip toolTip;
+       String toolTipText;
+       boolean 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 TrayItem (Tray parent, int style) {
+       super (parent, style);
+       this.parent = parent;
+       parent.createItem (this, parent.getItemCount ());
+       createUpdateWidget (true);
+}
+
+/**
+ * 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 == 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 == 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 createUpdateWidget (boolean newIcon) {
+       NOTIFYICONDATA iconData = new NOTIFYICONDATA ();
+       iconData.cbSize = NOTIFYICONDATA.sizeof;
+       /*
+        * As per MSDN article iconData.uID is unique for every TrayItem
+        * instance(https://msdn.microsoft.com/en-us/library/windows/desktop/
+        * bb762159%28v=vs.85%29.aspx) and this uID value should be specified
+        * during TrayItem instance creation & should be cached and used in
+        * subsequent calls to Shell_NotifyIcon to perform later actions on the
+        * TrayItem instance refer Win10 bug 488739.
+        */
+       iconData.uID = id = (newIcon ? display.nextTrayId++ : id);
+       iconData.hWnd = display.hwndMessage;
+       iconData.uFlags = OS.NIF_MESSAGE;
+       iconData.uCallbackMessage = Display.SWT_TRAYICONMSG;
+       /*
+        * OS.NIM_ADD message should be called only once in a TrayItem instance
+        * life-cycle i.e. in the TrayItem instance creation step only, else
+        * will lead to multiple TrayIcons entries on Win10 refer bug 488739.
+        */
+       OS.Shell_NotifyIcon ((newIcon ? OS.NIM_ADD : OS.NIM_MODIFY), iconData);
+}
+
+@Override
+void destroyWidget () {
+       parent.destroyItem (this);
+       releaseHandle ();
+}
+
+/**
+ * Returns the receiver's highlight image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's highlight 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.8
+ */
+public Image getHighlightImage () {
+       checkWidget ();
+       return highlightImage;
+}
+
+/**
+ * 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 boolean getVisible () {
+       checkWidget ();
+       return visible;
+}
+
+long messageProc (long hwnd, int msg, long wParam, long 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 ((int)lParam) {
+               case OS.WM_LBUTTONDOWN:
+                       if (hooks (SWT.Selection)) {
+                               OS.SetForegroundWindow (hwnd);
+                               sendSelectionEvent (SWT.Selection);
+                       }
+                       break;
+               case OS.WM_LBUTTONDBLCLK:
+               case OS.WM_RBUTTONDBLCLK:
+                       if (hooks (SWT.DefaultSelection)) {
+                               OS.SetForegroundWindow (hwnd);
+                               sendSelectionEvent (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 != 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 != 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 == OS.NIN_BALLOONUSERCLICK) {
+                                       if (toolTip.hooks (SWT.Selection)) {
+                                               OS.SetForegroundWindow (hwnd);
+                                               toolTip.sendSelectionEvent (SWT.Selection);
+                                               // widget could be disposed at this point
+                                               if (isDisposed()) return 0;
+                                       }
+                               }
+                       }
+                       break;
+       }
+       display.wakeThread ();
+       return 0;
+}
+
+void recreate () {
+       createUpdateWidget (false);
+       if (!visible) setVisible (false);
+       if (text.length () != 0) setText (text);
+       if (image != null) setImage (image);
+       if (toolTipText != null) setToolTipText (toolTipText);
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       parent = null;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if (toolTip != null) toolTip.item = null;
+       toolTip = null;
+       if (image2 != null) image2.dispose ();
+       image2 = null;
+       highlightImage = null;
+       toolTipText = null;
+       NOTIFYICONDATA iconData = new NOTIFYICONDATA ();
+       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.MenuDetect, listener);
+}
+
+/**
+ * Sets the receiver's highlight image.
+ *
+ * @param image the new highlight 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.8
+ */
+public void setHighlightImage (Image image) {
+       checkWidget ();
+       if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       highlightImage = image;
+}
+
+/**
+ * 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 != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       super.setImage (image);
+       if (image2 != null) image2.dispose ();
+       image2 = null;
+       long hIcon = 0;
+       Image icon = image;
+       if (icon != null) {
+               switch (icon.type) {
+                       case SWT.BITMAP:
+                               image2 = Display.createIcon (image);
+                               hIcon = image2.handle;
+                               break;
+                       case SWT.ICON:
+                               hIcon = icon.handle;
+                               break;
+               }
+       }
+       NOTIFYICONDATA iconData = new NOTIFYICONDATA ();
+       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 != null) oldTip.item = null;
+       this.toolTip = newTip;
+       if (newTip != null) newTip.item = this;
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ *
+ * @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;
+       NOTIFYICONDATA iconData = new NOTIFYICONDATA ();
+       if (string != null) {
+               char [] szTip = iconData.szTip;
+               int length = Math.min (szTip.length - 1, string.length ());
+               string.getChars (0, length, szTip, 0);
+       }
+       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 (boolean visible) {
+       checkWidget ();
+       if (this.visible == 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 = new NOTIFYICONDATA ();
+       iconData.cbSize = NOTIFYICONDATA.sizeof;
+       iconData.uID = id;
+       iconData.hWnd = display.hwndMessage;
+       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);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Tree.java
new file mode 100644 (file)
index 0000000..456e338
--- /dev/null
@@ -0,0 +1,8095 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>:</p>
+ * <pre><code>
+ *  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 == null) {
+ *              text = "node " + tree.indexOf(item);
+ *          } else {
+ *              text = parentItem.getText() + " - " + parentItem.indexOf(item);
+ *          }
+ *          item.setText(text);
+ *          System.out.println(text);
+ *          item.setItemCount(10);
+ *      }
+ *  });
+ * </code></pre>
+ * <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>
+ * <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>
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class Tree extends Composite {
+       TreeItem [] items;
+       TreeColumn [] columns;
+       int columnCount;
+       ImageList imageList, headerImageList;
+       TreeItem currentItem;
+       TreeColumn sortColumn;
+       RECT focusRect;
+       long hwndParent, hwndHeader, hAnchor, hInsert, hSelect;
+       int lastID;
+       long hFirstIndexOf, hLastIndexOf;
+       int lastIndexOf, itemCount, sortDirection;
+       boolean dragStarted, gestureCompleted, insertAfter, shrink, ignoreShrink;
+       boolean ignoreSelect, ignoreExpand, ignoreDeselect, ignoreResize;
+       boolean lockSelection, oldSelected, newSelected, ignoreColumnMove;
+       boolean linesVisible, customDraw, painted, ignoreItemHeight;
+       boolean ignoreCustomDraw, ignoreDrawForeground, ignoreDrawBackground, ignoreDrawFocus;
+       boolean ignoreDrawSelection, ignoreDrawHot, ignoreFullSelection, explorerTheme;
+       boolean createdAsRTL;
+       boolean headerItemDragging;
+       int scrollWidth, selectionForeground;
+       long headerToolTipHandle, itemToolTipHandle;
+       long lastTimerID = -1;
+       int lastTimerCount;
+       int headerBackground = -1;
+       int headerForeground = -1;
+       static final boolean ENABLE_TVS_EX_FADEINOUTEXPANDOS = System.getProperty("org.eclipse.swt.internal.win32.enableFadeInOutExpandos") != null;
+       static final int TIMER_MAX_COUNT = 8;
+       static final int INSET = 3;
+       static final int GRID_WIDTH = 1;
+       static final int SORT_WIDTH = 10;
+       static final int HEADER_MARGIN = 12;
+       static final int HEADER_EXTRA = 3;
+       static final int INCREMENT = 5;
+       static final int EXPLORER_EXTRA = 2;
+       static final int DRAG_IMAGE_SIZE = 301;
+       static final long TreeProc;
+       static final TCHAR TreeClass = new TCHAR (0, OS.WC_TREEVIEW, true);
+       static final long HeaderProc;
+       static final TCHAR HeaderClass = new TCHAR (0, OS.WC_HEADER, true);
+       static {
+               WNDCLASS lpWndClass = new WNDCLASS ();
+               OS.GetClassInfo (0, TreeClass, lpWndClass);
+               TreeProc = lpWndClass.lpfnWndProc;
+               OS.GetClassInfo (0, HeaderClass, lpWndClass);
+               HeaderProc = lpWndClass.lpfnWndProc;
+       }
+
+/**
+ * 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 Tree (Composite parent, int style) {
+       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) == 0) {
+               style |= SWT.H_SCROLL | SWT.V_SCROLL;
+       }
+       /*
+       * Note: Windows only supports TVS_NOSCROLL and TVS_NOHSCROLL.
+       */
+       if ((style & SWT.H_SCROLL) != 0 && (style & SWT.V_SCROLL) == 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) != 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 == SWT.MeasureItem) {
+                               /*
+                               * This code is intentionally commented.
+                               */
+//                             if (explorerTheme) {
+//                                     int bits1 = (int)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) != 0) {
+                               if (eventType != SWT.MeasureItem) {
+                                       if (!explorerTheme) bits &= ~OS.TVS_FULLROWSELECT;
+                               }
+                       }
+                       if (bits != 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 = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+                               if (count != 0 && (bits & OS.TVS_NOHSCROLL) != 0) {
+                                       OS.ShowScrollBar (handle, OS.SB_HORZ, false);
+                               }
+                       }
+                       break;
+               }
+       }
+}
+
+TreeItem _getItem (long hItem) {
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       tvItem.hItem = hItem;
+       if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) != 0) {
+               return _getItem (tvItem.hItem, (int)tvItem.lParam);
+       }
+       return null;
+}
+
+TreeItem _getItem (long hItem, int id) {
+       if ((style & SWT.VIRTUAL) == 0) return items [id];
+       return id != -1 ? items [id] : new TreeItem (this, SWT.NONE, -1, -1, hItem);
+}
+
+@Override
+void _removeListener (int eventType, Listener listener) {
+       super._removeListener (eventType, listener);
+       switch (eventType) {
+               case SWT.MeasureItem: {
+                       /**
+                        * If H_SCROLL is set, reverting the TVS_NOHSCROLL settings which
+                        * was applied while adding SWT.MeasureItem event Listener.
+                        */
+                       if ((style & SWT.H_SCROLL) != 0 && (state & DISPOSE_SENT) == 0) {
+                               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                               bits &= ~OS.TVS_NOHSCROLL;
+                               OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+                               OS.InvalidateRect (handle, null, true);
+                       }
+                       break;
+               }
+       }
+}
+
+void _setBackgroundPixel (int newPixel) {
+       int oldPixel = (int)OS.SendMessage (handle, OS.TVM_GETBKCOLOR, 0, 0);
+       if (oldPixel != 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 != -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 && ENABLE_TVS_EX_FADEINOUTEXPANDOS) {
+                       int bits2 = (int)OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+                       if (newPixel == -1 && findImageControl () == 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) != 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 == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Expand, typedListener);
+       addListener (SWT.Collapse, typedListener);
+}
+
+@Override
+long borderHandle () {
+       return hwndParent != 0 ? hwndParent : handle;
+}
+
+LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) {
+       if (ignoreCustomDraw) return null;
+       if (nmcd.left == nmcd.right) return new LRESULT (OS.CDRF_DODEFAULT);
+       long hDC = 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 == 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.left >= nmcd.right || nmcd.top >= nmcd.bottom) return null;
+       if (!OS.IsWindowVisible (handle)) return null;
+       if ((style & SWT.FULL_SELECTION) != 0 || findImageControl () != null || ignoreDrawSelection || explorerTheme) {
+               OS.SetBkMode (hDC, OS.TRANSPARENT);
+       }
+       boolean selected = isItemSelected (nmcd);
+       boolean hot = explorerTheme && (nmcd.uItemState & OS.CDIS_HOT) != 0;
+       if (OS.IsWindowEnabled (handle)) {
+               if (explorerTheme) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.TVS_TRACKSELECT) != 0) {
+                               if ((style & SWT.FULL_SELECTION) != 0 && (selected || hot)) {
+                                       OS.SetTextColor (hDC, OS.GetSysColor (OS.COLOR_WINDOWTEXT));
+                               } else {
+                                       OS.SetTextColor (hDC, getForegroundPixel ());
+                               }
+                       }
+               }
+       }
+       int [] order = null;
+       RECT clientRect = new RECT ();
+       OS.GetClientRect (scrolledHandle (), clientRect);
+       if (hwndHeader != 0) {
+               OS.MapWindowPoints (hwndParent, handle, clientRect, 2);
+               if (columnCount != 0) {
+                       order = new int [columnCount];
+                       OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order);
+               }
+       }
+       int sortIndex = -1, clrSortBk = -1;
+       if (OS.IsAppThemed ()) {
+               if (sortColumn != null && sortDirection != SWT.NONE) {
+                       if (findImageControl () == 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 == null ? i : order [i], width = nmcd.right - nmcd.left;
+               if (columnCount > 0 && hwndHeader != 0) {
+                       HDITEM hdItem = new HDITEM ();
+                       hdItem.mask = OS.HDI_WIDTH;
+                       OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+                       width = hdItem.cxy;
+               }
+               if (i == 0) {
+                       if ((style & SWT.FULL_SELECTION) != 0) {
+                               boolean clear = !explorerTheme && !ignoreDrawSelection && findImageControl () == null;
+                               if (clear || (selected && !ignoreDrawSelection) || (hot && !ignoreDrawHot)) {
+                                       boolean draw = true;
+                                       RECT pClipRect = new RECT ();
+                                       OS.SetRect (pClipRect, width, nmcd.top, nmcd.right, nmcd.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 != 0) {
+                                                               HDITEM hdItem = new HDITEM ();
+                                                               hdItem.mask = OS.HDI_WIDTH;
+                                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+                                                               pClipRect.right = Math.min (pClipRect.right, nmcd.left + hdItem.cxy);
+                                                       }
+                                               }
+                                               RECT pRect = new RECT ();
+                                               OS.SetRect (pRect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                                               if (columnCount > 0 && hwndHeader != 0) {
+                                                       int totalWidth = 0;
+                                                       HDITEM hdItem = new 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;
+                                               long hTheme = OS.OpenThemeData (handle, Display.TREEVIEW);
+                                               int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
+                                               if (OS.GetFocus () != 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;
+                       boolean drawItem = true, drawText = true, drawImage = true, drawBackground = false;
+                       if (i == 0) {
+                               drawItem = drawImage = drawText = false;
+                               if (findImageControl () != null) {
+                                       if (explorerTheme) {
+                                               if (OS.IsWindowEnabled (handle) && !hooks (SWT.EraseItem)) {
+                                                       Image image = null;
+                                                       if (index == 0) {
+                                                               image = item.image;
+                                                       } else {
+                                                               Image [] images  = item.images;
+                                                               if (images != null) image = images [index];
+                                                       }
+                                                       if (image != null) {
+                                                               Rectangle bounds = image.getBounds (); // Points
+                                                               if (size == null) size = DPIUtil.autoScaleDown (getImageSize ()); // To Points
+                                                               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); // Pixels
+                                                                       gc.setClipping (DPIUtil.autoScaleDown(new Rectangle(iconRect.left, iconRect.top, iconRect.right - iconRect.left, iconRect.bottom - iconRect.top)));
+                                                                       gc.drawImage (image, 0, 0, bounds.width, bounds.height, DPIUtil.autoScaleDown(iconRect.left), DPIUtil.autoScaleDown(iconRect.top), size.x, size.y);
+                                                                       OS.SelectClipRgn (hDC, 0);
+                                                                       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) != 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.top, x + width, nmcd.bottom);
+                               backgroundRect = rect;
+                       }
+                       int clrText = -1, clrTextBk = -1;
+                       long hFont = item.fontHandle (index);
+                       if (selectionForeground != -1) clrText = selectionForeground;
+                       if (OS.IsWindowEnabled (handle)) {
+                               boolean drawForeground = false;
+                               if (selected) {
+                                       if (i != 0 && (style & SWT.FULL_SELECTION) == 0) {
+                                               OS.SetTextColor (hDC, getForegroundPixel ());
+                                               OS.SetBkColor (hDC, getBackgroundPixel ());
+                                               drawForeground = drawBackground = true;
+                                       }
+                               } else {
+                                       drawForeground = drawBackground = true;
+                               }
+                               if (drawForeground) {
+                                       clrText = item.cellForeground != null ? item.cellForeground [index] : -1;
+                                       if (clrText == -1) clrText = item.foreground;
+                               }
+                               if (drawBackground) {
+                                       clrTextBk = item.cellBackground != null ? item.cellBackground [index] : -1;
+                                       if (clrTextBk == -1) clrTextBk = item.background;
+                                       if (clrTextBk == -1 && index == sortIndex) clrTextBk = clrSortBk;
+                               }
+                       } else {
+                               if (clrTextBk == -1 && index == sortIndex) {
+                                       drawBackground = true;
+                                       clrTextBk = clrSortBk;
+                               }
+                       }
+                       if (explorerTheme) {
+                               if (selected || (nmcd.uItemState & OS.CDIS_HOT) != 0) {
+                                       if ((style & SWT.FULL_SELECTION) != 0) {
+                                               drawBackground = false;
+                                       } else {
+                                               if (i == 0) {
+                                                       drawBackground = false;
+                                                       if (!hooks (SWT.EraseItem)) drawText = false;
+                                               }
+                                       }
+                               }
+                       }
+                       if (drawItem) {
+                               if (i != 0) {
+                                       if (hooks (SWT.MeasureItem)) {
+                                               sendMeasureItemEvent (item, index, hDC, selected ? SWT.SELECTED : 0);
+                                               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) == 0) {
+                                                       if (clrText != -1) data.foreground = clrText;
+                                                       if (clrTextBk != -1) data.background = clrTextBk;
+                                               }
+                                               data.font = item.getFont (index);
+                                               data.uiState = (int)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 != -1) event.detail |= SWT.BACKGROUND;
+                                               if ((style & SWT.FULL_SELECTION) != 0) {
+                                                       if (hot) event.detail |= SWT.HOT;
+                                                       if (selected) event.detail |= SWT.SELECTED;
+                                                       if (!explorerTheme) {
+                                                               //if ((nmcd.uItemState & OS.CDIS_FOCUS) != 0) {
+                                                               if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) == nmcd.dwItemSpec) {
+                                                                       if (handle == OS.GetFocus ()) {
+                                                                               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                                                                               if ((uiState & OS.UISF_HIDEFOCUS) == 0) event.detail |= SWT.FOCUSED;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               Rectangle boundsInPixels = new Rectangle (cellRect.left, cellRect.top, cellRect.right - cellRect.left, cellRect.bottom - cellRect.top);
+                                               event.setBoundsInPixels (boundsInPixels);
+                                               gc.setClipping (DPIUtil.autoScaleDown (boundsInPixels));
+                                               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) == 0;
+                                                       ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0;
+                                                       if ((style & SWT.FULL_SELECTION) != 0) {
+                                                               ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0;
+                                                               ignoreDrawFocus = (event.detail & SWT.FOCUSED) == 0;
+                                                               ignoreDrawHot = (event.detail & SWT.HOT) == 0;
+                                                       }
+                                               } else {
+                                                       ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = true;
+                                               }
+                                               if (selected && ignoreDrawSelection) ignoreDrawHot = true;
+                                               if ((style & SWT.FULL_SELECTION) != 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 == OS.GetFocus () || display.getHighContrast ()) && OS.IsWindowEnabled (handle)) {
+                                                                                       clrTextBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+                                                                               } else {
+                                                                                       clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE);
+                                                                               }
+                                                                               if (!ignoreFullSelection && index == columnCount - 1) {
+                                                                                       RECT selectionRect = new RECT ();
+                                                                                       OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.right, backgroundRect.bottom);
+                                                                                       backgroundRect = selectionRect;
+                                                                               }
+                                                                       } else {
+                                                                               RECT pRect = new RECT ();
+                                                                               OS.SetRect (pRect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                                                                               if (columnCount > 0 && hwndHeader != 0) {
+                                                                                       int totalWidth = 0;
+                                                                                       HDITEM hdItem = new 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 == columnCount - 1) {
+                                                                                               RECT selectionRect = new RECT ();
+                                                                                               OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, pRect.right, backgroundRect.bottom);
+                                                                                               backgroundRect = selectionRect;
+                                                                                       }
+                                                                               }
+                                                                               long hTheme = OS.OpenThemeData (handle, Display.TREEVIEW);
+                                                                               int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
+                                                                               if (OS.GetFocus () != 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 == -1 && OS.IsWindowEnabled (handle)) {
+                                                                                       Control control = findBackgroundControl ();
+                                                                                       if (control == null) control = this;
+                                                                                       clrTextBk = control.getBackgroundPixel ();
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       if (selectionForeground != -1) clrText = selectionForeground;
+                               }
+                               if (!ignoreDrawBackground) {
+                                       if (clrTextBk != -1) {
+                                               if (drawBackground) fillBackground (hDC, clrTextBk, backgroundRect);
+                                       } else {
+                                               Control control = findImageControl ();
+                                               if (control != null) {
+                                                       if (i == 0) {
+                                                               int right = Math.min (rect.right, width);
+                                                               OS.SetRect (rect, rect.left, rect.top, right, rect.bottom);
+                                                               if (drawBackground) fillImageBackground (hDC, control, rect, 0, 0);
+                                                       } else {
+                                                               if (drawBackground) fillImageBackground (hDC, control, rect, 0, 0);
+                                                       }
+                                               }
+                                       }
+                               }
+                               rect.left += INSET - 1;
+                               if (drawImage) {
+                                       Image image = null;
+                                       if (index == 0) {
+                                               image = item.image;
+                                       } else {
+                                               Image [] images  = item.images;
+                                               if (images != null) image = images [index];
+                                       }
+                                       int inset = i != 0 ? INSET : 0;
+                                       int offset = i != 0 ? INSET : INSET + 2;
+                                       if (image != null) {
+                                               Rectangle bounds = image.getBounds (); // Points
+                                               if (size == null) size = DPIUtil.autoScaleDown (getImageSize ()); // To Points
+                                               if (!ignoreDrawForeground) {
+                                                       //int y1 = rect.top + (index == 0 ? (getItemHeight () - size.y) / 2 : 0);
+                                                       int y1 = rect.top + DPIUtil.autoScaleUp((getItemHeight () - size.y) / 2);
+                                                       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 (DPIUtil.autoScaleDown(new Rectangle(x1, rect.top, rect.right - x1, rect.bottom - rect.top)));
+                                                       gc.drawImage (image, 0, 0, bounds.width, bounds.height, DPIUtil.autoScaleDown(x1), DPIUtil.autoScaleDown(y1), size.x, size.y);
+                                                       OS.SelectClipRgn (hDC, 0);
+                                                       gc.dispose ();
+                                               }
+                                               OS.SetRect (rect, rect.left + DPIUtil.autoScaleUp(size.x) + offset, rect.top, rect.right - inset, rect.bottom);
+                                       } else {
+                                               if (i == 0) {
+                                                       if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) != 0) {
+                                                               if (size == 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 == 0) {
+                                                       string = item.text;
+                                               } else {
+                                                       String [] strings  = item.strings;
+                                                       if (strings != null) string = strings [index];
+                                               }
+                                               if (string != null) {
+                                                       if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                                                       if (clrText != -1) clrText = OS.SetTextColor (hDC, clrText);
+                                                       if (clrTextBk != -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
+                                                       int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                                       if (i != 0) flags |= OS.DT_ENDELLIPSIS;
+                                                       TreeColumn column = columns != null ? columns [index] : null;
+                                                       if (column != null) {
+                                                               if ((column.style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+                                                               if ((column.style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+                                                       }
+                                                       if ((string != null) && (string.length() > Item.TEXT_LIMIT)) {
+                                                               string = string.substring(0, Item.TEXT_LIMIT - Item.ELLIPSIS.length()) + Item.ELLIPSIS;
+                                                       }
+                                                       char [] buffer = string.toCharArray ();
+                                                       if (!ignoreDrawForeground) OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+                                                       OS.DrawText (hDC, buffer, buffer.length, rect, flags | OS.DT_CALCRECT);
+                                                       if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                                                       if (clrText != -1) clrText = OS.SetTextColor (hDC, clrText);
+                                                       if (clrTextBk != -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
+                                               }
+                                       }
+                               }
+                       }
+                       if (selectionForeground != -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) != 0) {
+                                       if (selectionForeground != -1) data.foreground = selectionForeground;
+                               } else {
+                                       if (clrText != -1) data.foreground = clrText;
+                                       if (clrTextBk != -1) data.background = clrTextBk;
+                               }
+                               data.uiState = (int)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 != -1) event.detail |= SWT.BACKGROUND;
+                               if (hot) event.detail |= SWT.HOT;
+                               if (selected && (i == 0 /*nmcd.iSubItem == 0*/ || (style & SWT.FULL_SELECTION) != 0)) {
+                                       event.detail |= SWT.SELECTED;
+                               }
+                               if (!explorerTheme) {
+                                       //if ((nmcd.uItemState & OS.CDIS_FOCUS) != 0) {
+                                       if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) == nmcd.dwItemSpec) {
+                                               if (i == 0 /*nmcd.iSubItem == 0*/ || (style & SWT.FULL_SELECTION) != 0) {
+                                                       if (handle == OS.GetFocus ()) {
+                                                               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                                                               if ((uiState & OS.UISF_HIDEFOCUS) == 0) event.detail |= SWT.FOCUSED;
+                                                       }
+                                               }
+                                       }
+                               }
+                               event.setBoundsInPixels(new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, 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 (DPIUtil.autoScaleDown(new Rectangle(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) != 0) {
+                       if (columnCount != 0) {
+                               HDITEM hdItem = new HDITEM ();
+                               hdItem.mask = OS.HDI_WIDTH;
+                               OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, hdItem);
+                               RECT rect = new RECT ();
+                               OS.SetRect (rect, nmcd.left + hdItem.cxy, nmcd.top, nmcd.right, nmcd.bottom);
+                               OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+                       }
+               }
+               RECT rect = new RECT ();
+               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+               OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+       }
+       if (!ignoreDrawFocus && focusRect != null) {
+               OS.DrawFocusRect (hDC, focusRect);
+               focusRect = null;
+       } else {
+               if (!explorerTheme) {
+                       if (handle == OS.GetFocus ()) {
+                               int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((uiState & OS.UISF_HIDEFOCUS) == 0) {
+                                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                                       if (hItem == item.handle) {
+                                               if (!ignoreDrawFocus && findImageControl () != null) {
+                                                       if ((style & SWT.FULL_SELECTION) != 0) {
+                                                               RECT focusRect = new RECT ();
+                                                               OS.SetRect (focusRect, 0, nmcd.top, clientRect.right + 1, nmcd.bottom);
+                                                               OS.DrawFocusRect (hDC, focusRect);
+                                                       } else {
+                                                               int index = (int)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, 0);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return new LRESULT (OS.CDRF_DODEFAULT);
+}
+
+LRESULT CDDS_ITEMPREPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long 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 == null) return null;
+       long hDC = nmcd.hdc;
+       int index = hwndHeader != 0 ? (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) : 0;
+       long hFont = item.fontHandle (index);
+       if (hFont != -1) OS.SelectObject (hDC, hFont);
+       if (ignoreCustomDraw || nmcd.left == nmcd.right) {
+               return new LRESULT (hFont == -1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT);
+       }
+       RECT clipRect = null;
+       if (columnCount != 0) {
+               clipRect = new RECT ();
+               HDITEM hdItem = new HDITEM ();
+               hdItem.mask = OS.HDI_WIDTH;
+               OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+               OS.SetRect (clipRect, nmcd.left, nmcd.top, nmcd.left + hdItem.cxy, nmcd.bottom);
+       }
+       int clrText = -1, clrTextBk = -1;
+       if (OS.IsWindowEnabled (handle)) {
+               clrText = item.cellForeground != null ? item.cellForeground [index] : -1;
+               if (clrText == -1) clrText = item.foreground;
+               clrTextBk = item.cellBackground != null ? item.cellBackground [index] : -1;
+               if (clrTextBk == -1) clrTextBk = item.background;
+       }
+       int clrSortBk = -1;
+       if (OS.IsAppThemed ()) {
+               if (sortColumn != null && sortDirection != SWT.NONE) {
+                       if (findImageControl () == null) {
+                               if (indexOf (sortColumn) == index) {
+                                       clrSortBk = getSortColumnPixel ();
+                                       if (clrTextBk == -1) clrTextBk = clrSortBk;
+                               }
+                       }
+               }
+       }
+       boolean selected = isItemSelected (nmcd);
+       boolean hot = explorerTheme && (nmcd.uItemState & OS.CDIS_HOT) != 0;
+       boolean focused = explorerTheme && (nmcd.uItemState & OS.CDIS_FOCUS) != 0;
+       if (OS.IsWindowVisible (handle) && nmcd.left < nmcd.right && nmcd.top < nmcd.bottom) {
+               if (hFont != -1) OS.SelectObject (hDC, hFont);
+               if (linesVisible) {
+                       RECT rect = new RECT ();
+                       OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.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;
+               Rectangle boundsInPixels = null;
+               if (hooks (SWT.MeasureItem)) {
+                       measureEvent = sendMeasureItemEvent (item, index, hDC, selected ? SWT.SELECTED : 0);
+                       boundsInPixels = measureEvent.getBoundsInPixels ();
+                       if (isDisposed () || item.isDisposed ()) return null;
+               }
+               selectionForeground = -1;
+               ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false;
+               if (hooks (SWT.EraseItem)) {
+                       RECT rect = new RECT ();
+                       OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                       RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
+                       if (clrSortBk != -1) {
+                               drawBackground (hDC, cellRect, clrSortBk, 0, 0);
+                       } else {
+                               if (OS.IsWindowEnabled (handle) || findImageControl () != 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 != -1) data.foreground = clrText;
+                               if (clrTextBk != -1) data.background = clrTextBk;
+                       }
+                       data.uiState = (int)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 != -1) event.detail |= SWT.BACKGROUND;
+                       if (hot) event.detail |= SWT.HOT;
+                       if (selected) event.detail |= SWT.SELECTED;
+                       //if ((nmcd.uItemState & OS.CDIS_FOCUS) != 0) {
+                       if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) == nmcd.dwItemSpec) {
+                               if (handle == OS.GetFocus ()) {
+                                       int uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                                       if ((uiState & OS.UISF_HIDEFOCUS) == 0) {
+                                               if (!explorerTheme || !selected) {
+                                                       focused = true;
+                                                       event.detail |= SWT.FOCUSED;
+                                               }
+                                       }
+                               }
+                       }
+                       Rectangle boundsInPixels2 = new Rectangle (cellRect.left, cellRect.top, cellRect.right - cellRect.left, cellRect.bottom - cellRect.top);
+                       event.setBoundsInPixels (boundsInPixels2);
+                       gc.setClipping (DPIUtil.autoScaleDown (boundsInPixels2));
+                       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) == 0;
+                               ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0;
+                               ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0;
+                               ignoreDrawFocus = (event.detail & SWT.FOCUSED) == 0;
+                               ignoreDrawHot = (event.detail & SWT.HOT) == 0;
+                       } else {
+                               ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = true;
+                       }
+                       if (selected && ignoreDrawSelection) ignoreDrawHot = true;
+                       if (!ignoreDrawBackground && clrTextBk != -1) {
+                               boolean draw = !selected && !hot;
+                               if (!explorerTheme && selected) draw = !ignoreDrawSelection;
+                               if (draw) {
+                                       if (columnCount == 0) {
+                                               if ((style & SWT.FULL_SELECTION) != 0) {
+                                                       fillBackground (hDC, clrTextBk, rect);
+                                               } else {
+                                                       RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
+                                                       if (measureEvent != null) {
+                                                               textRect.right = Math.min (cellRect.right, boundsInPixels.x + boundsInPixels.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) == 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 != null) {
+                                                       pRect.right = Math.min (pClipRect.right, boundsInPixels.x + boundsInPixels.width);
+                                               } else {
+                                                       pRect.right += EXPLORER_EXTRA;
+                                                       pClipRect.right += EXPLORER_EXTRA;
+                                               }
+                                               pRect.left -= EXPLORER_EXTRA;
+                                               pClipRect.left -= EXPLORER_EXTRA;
+                                               long hTheme = OS.OpenThemeData (handle, Display.TREEVIEW);
+                                               int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
+                                               if (OS.GetFocus () != 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) != 0) {
+                                               if ((style & SWT.FULL_SELECTION) != 0 && columnCount == 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 != null) {
+                                                       textRect.right = Math.min (cellRect.right, boundsInPixels.x + boundsInPixels.width);
+                                               }
+                                               fillBackground (hDC, OS.GetBkColor (hDC), textRect);
+                                       }
+                               }
+                       } else {
+                               if (selected || hot) {
+                                       selectionForeground = clrText = newTextClr;
+                                       ignoreDrawSelection = ignoreDrawHot = true;
+                               }
+                               if (explorerTheme) {
+                                       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 == -1 ? getForegroundPixel () : clrText;
+                                       if (nmcd.clrText == newColor) {
+                                               nmcd.clrText |= 0x20000000;
+                                               if (nmcd.clrText == newColor) nmcd.clrText &= ~0x20000000;
+                                       } else {
+                                               nmcd.clrText = newColor;
+                                       }
+                                       OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                               }
+                       }
+                       if (focused && !ignoreDrawFocus && (style & SWT.FULL_SELECTION) == 0) {
+                               RECT textRect = item.getBounds (index, true, explorerTheme, false, false, true, hDC);
+                               if (measureEvent != null) {
+                                       textRect.right = Math.min (cellRect.right, boundsInPixels.x + boundsInPixels.width);
+                               }
+                               nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                               OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                               focusRect = textRect;
+                       }
+                       if (explorerTheme) {
+                               if (selected || (hot && ignoreDrawHot)) nmcd.uItemState &= ~OS.CDIS_HOT;
+                               OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                       }
+                       RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+                       OS.SaveDC (hDC);
+                       OS.SelectClipRgn (hDC, 0);
+                       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 != 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) != 0) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.TVS_FULLROWSELECT) == 0) {
+                               RECT rect = new RECT ();
+                               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                               if (selected) {
+                                       fillBackground (hDC, OS.GetBkColor (hDC), rect);
+                               } else {
+                                       if (OS.IsWindowEnabled (handle)) drawBackground (hDC, rect);
+                               }
+                               nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                               OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                       }
+               }
+       }
+       LRESULT result = null;
+       if (clrText == -1 && clrTextBk == -1 && hFont == -1) {
+               result = new LRESULT (OS.CDRF_DODEFAULT | OS.CDRF_NOTIFYPOSTPAINT);
+       } else {
+               result = new LRESULT (OS.CDRF_NEWFONT | OS.CDRF_NOTIFYPOSTPAINT);
+               if (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 != -1) {
+                               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                               if ((bits & OS.TVS_FULLROWSELECT) == 0) {
+                                       if (columnCount != 0 && hwndHeader != 0) {
+                                               RECT rect = new RECT ();
+                                               HDITEM hdItem = new HDITEM ();
+                                               hdItem.mask = OS.HDI_WIDTH;
+                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+                                               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.left + hdItem.cxy, nmcd.bottom);
+                                               if (!OS.IsAppThemed ()) {
+                                                       RECT itemRect = new RECT ();
+                                                       if (OS.TreeView_GetItemRect (handle, item.handle, itemRect, true)) {
+                                                               rect.left = Math.min (itemRect.left, rect.right);
+                                                       }
+                                               }
+                                               if ((style & SWT.FULL_SELECTION) != 0) {
+                                                       if (!selected) fillBackground (hDC, clrTextBk, rect);
+                                               } else {
+                                                       fillBackground (hDC, clrTextBk, rect);
+                                               }
+                                       } else {
+                                               if ((style & SWT.FULL_SELECTION) != 0) {
+                                                       RECT rect = new RECT ();
+                                                       OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                                                       if (!selected) fillBackground (hDC, clrTextBk, rect);
+                                               }
+                                       }
+                               }
+                       }
+                       if (!selected) {
+                               nmcd.clrText = clrText == -1 ? getForegroundPixel () : clrText;
+                               nmcd.clrTextBk = clrTextBk == -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 () !=  null) {
+                               if (!selected && (nmcd.uItemState & (OS.CDIS_HOT | OS.CDIS_SELECTED)) == 0) {
+                                       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 == -1 ? getForegroundPixel () : clrText;
+                                       if (nmcd.clrText == newColor) {
+                                               nmcd.clrText |= 0x20000000;
+                                               if (nmcd.clrText == newColor) nmcd.clrText &= ~0x20000000;
+                                       } else {
+                                               nmcd.clrText = newColor;
+                                       }
+                                       OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                                       if (clrTextBk != -1) {
+                                               if ((style & SWT.FULL_SELECTION) != 0) {
+                                                       RECT rect = new RECT ();
+                                                       if (columnCount != 0) {
+                                                               HDITEM hdItem = new HDITEM ();
+                                                               hdItem.mask = OS.HDI_WIDTH;
+                                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+                                                               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.left + hdItem.cxy, nmcd.bottom);
+                                                       } else {
+                                                               OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.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 != -1) {
+                       RECT rect = new RECT ();
+                       HDITEM hdItem = new HDITEM ();
+                       hdItem.mask = OS.HDI_WIDTH;
+                       OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+                       OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.left + hdItem.cxy, nmcd.bottom);
+                       fillBackground (hDC, clrSortBk, rect);
+               }
+       }
+       OS.SaveDC (hDC);
+       if (clipRect != null) {
+               long hRgn = OS.CreateRectRgn (clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+               POINT lpPoint = new POINT ();
+               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, long wParam, long lParam) {
+       if (ignoreCustomDraw) return null;
+       if (OS.IsWindowVisible (handle)) {
+               if (OS.IsAppThemed ()) {
+                       if (sortColumn != null && sortDirection != SWT.NONE) {
+                               if (findImageControl () == null) {
+                                       int index = indexOf (sortColumn);
+                                       if (index != -1) {
+                                               int top = nmcd.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.
+                                               */
+                                               long hItem = 0;
+                                               if (OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                                                       hItem = getBottomItem ();
+                                               } else {
+                                                       hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+                                               }
+                                               if (hItem != 0) {
+                                                       RECT rect = new RECT ();
+                                                       if (OS.TreeView_GetItemRect (handle, hItem, rect, false)) {
+                                                               top = rect.bottom;
+                                                       }
+                                               }
+                                               RECT rect = new RECT ();
+                                               OS.SetRect (rect, nmcd.left, top, nmcd.right, nmcd.bottom);
+                                               RECT headerRect = new RECT ();
+                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+                                               rect.left = headerRect.left;
+                                               rect.right = headerRect.right;
+                                               fillBackground (nmcd.hdc, getSortColumnPixel (), rect);
+                                       }
+                               }
+                       }
+               }
+               if (linesVisible) {
+                       long hDC = nmcd.hdc;
+                       if (hwndHeader != 0) {
+                               int x = 0;
+                               RECT rect = new RECT ();
+                               HDITEM hdItem = new HDITEM ();
+                               hdItem.mask = OS.HDI_WIDTH;
+                               for (int i=0; i<columnCount; i++) {
+                                       int index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, i, 0);
+                                       OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+                                       OS.SetRect (rect, x, nmcd.top, x + hdItem.cxy, nmcd.bottom);
+                                       OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_RIGHT);
+                                       x += hdItem.cxy;
+                               }
+                       }
+                       int height = 0;
+                       RECT rect = new 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.
+                       */
+                       long hItem = 0;
+                       if (OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                               hItem = getBottomItem ();
+                       } else {
+                               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+                       }
+                       if (hItem != 0) {
+                               if (OS.TreeView_GetItemRect (handle, hItem, rect, false)) {
+                                       height = rect.bottom - rect.top;
+                               }
+                       }
+                       if (height == 0) {
+                               height = (int)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);
+                       }
+                       if (height != 0) {
+                               while (rect.bottom < nmcd.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, long wParam, long lParam) {
+       if (explorerTheme) {
+               if ((OS.IsWindowEnabled (handle) && hooks (SWT.EraseItem)) || hasCustomBackground() || findImageControl () != null) {
+                       RECT rect = new RECT ();
+                       OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                       drawBackground (nmcd.hdc, rect);
+               }
+       }
+       return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+}
+
+@Override
+long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (handle == 0) return 0;
+       if (hwndParent != 0 && hwnd == hwndParent) {
+               return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+       }
+       if (hwndHeader != 0 && hwnd == 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) != 0) break;
+                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                       if (hItem == 0) {
+                               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                               if (hItem != 0) {
+                                       TVITEM tvItem = new TVITEM ();
+                                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                                       tvItem.hItem = 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 = 0;
+                                       if ((tvItem.state & OS.TVIS_SELECTED) == 0) {
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                       }
+                               }
+                       }
+                       break;
+               }
+       }
+       long hItem = 0;
+       boolean redraw = false;
+       switch (msg) {
+               /* Keyboard messages */
+               case OS.WM_KEYDOWN:
+                       if (wParam == OS.VK_CONTROL || wParam == 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 () != null && getDrawing () && 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 () != null) {
+                               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                       }
+
+                       break;
+               }
+       }
+       long code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
+       switch (msg) {
+               /* Keyboard messages */
+               case OS.WM_KEYDOWN:
+                       if (wParam == OS.VK_CONTROL || wParam == 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 != 0) 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 () != null) {
+                               if (hItem != OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0)) {
+                                       OS.InvalidateRect (handle, null, true);
+                               }
+                       }
+                       updateScrollBar ();
+                       break;
+               }
+
+               case OS.WM_PAINT:
+                       painted = true;
+                       break;
+       }
+       return code;
+}
+
+@Override
+void checkBuffered () {
+       super.checkBuffered ();
+       if ((style & SWT.VIRTUAL) != 0) {
+               style |= SWT.DOUBLE_BUFFERED;
+               OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
+       }
+       if (OS.IsAppThemed ()) {
+               int exStyle = (int)OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+               if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) != 0) style |= SWT.DOUBLE_BUFFERED;
+       }
+}
+
+boolean checkData (TreeItem item, boolean redraw) {
+       if ((style & SWT.VIRTUAL) == 0) return true;
+       if (!item.cached) {
+               TreeItem parentItem = item.getParentItem ();
+               return checkData (item, parentItem == null ? indexOf (item) : parentItem.indexOf (item), redraw);
+       }
+       return true;
+}
+
+boolean checkData (TreeItem item, int index, boolean redraw) {
+       if ((style & SWT.VIRTUAL) == 0) return true;
+       if (!item.cached) {
+               item.cached = true;
+               Event event = new Event ();
+               event.item = item;
+               event.index = index;
+               TreeItem oldItem = currentItem;
+               currentItem = item;
+               /*
+               * Bug in Windows.  If the tree scrolls during WM_NOTIFY
+               * with TVN_GETDISPINFO, pixel corruption occurs.  The fix
+               * is to detect that the top item has changed and redraw
+               * the entire tree.
+               */
+               long hTopItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+               sendEvent (SWT.SetData, event);
+               //widget could be disposed at this point
+               currentItem = oldItem;
+               if (isDisposed () || item.isDisposed ()) return false;
+               if (redraw) item.redraw ();
+               if (hTopItem != OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0)) {
+                       OS.InvalidateRect (handle, null, true);
+               }
+       }
+       return true;
+}
+
+@Override
+boolean checkHandle (long hwnd) {
+       return hwnd == handle || (hwndParent != 0 && hwnd == hwndParent) || (hwndHeader != 0 && hwnd == hwndHeader);
+}
+
+boolean checkScroll (long 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 (getDrawing ()) return false;
+       long hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       long hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+       while (hParent != hRoot && hParent != 0) {
+               hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hParent);
+       }
+       return hParent == 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, boolean all) {
+       checkWidget ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+       hItem = findItem (hItem, index);
+       if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       clear (hItem, tvItem);
+       if (all) {
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+               clearAll (hItem, tvItem, all);
+       }
+}
+
+void clear (long hItem, TVITEM tvItem) {
+       tvItem.hItem = hItem;
+       TreeItem item = null;
+       if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) != 0) {
+               item = tvItem.lParam != -1 ? items [(int)tvItem.lParam] : null;
+       }
+       if (item != null) {
+               if ((style & SWT.VIRTUAL) != 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 (boolean all) {
+       checkWidget ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       if (hItem == 0) return;
+       if (all) {
+               boolean redraw = false;
+               for (int i=0; i<items.length; i++) {
+                       TreeItem item = items [i];
+                       if (item != null && item != currentItem) {
+                               item.clear ();
+                               redraw = true;
+                       }
+               }
+               if (redraw) OS.InvalidateRect (handle, null, true);
+       } else {
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+               clearAll (hItem, tvItem, all);
+       }
+}
+
+void clearAll (long hItem, TVITEM tvItem, boolean all) {
+       while (hItem != 0) {
+               clear (hItem, tvItem);
+               if (all) {
+                       long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+                       clearAll (hFirstItem, tvItem, all);
+               }
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+       }
+}
+
+long CompareFunc (long lParam1, long lParam2, long lParamSort) {
+       TreeItem item1 = items [(int)lParam1], item2 = items [(int)lParam2];
+       String text1 = item1.getText ((int)lParamSort), text2 = item2.getText ((int)lParamSort);
+       return sortDirection == SWT.UP ? text1.compareTo (text2) : text2.compareTo (text1);
+}
+
+@Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       int width = 0, height = 0;
+       if (hwndHeader != 0) {
+               HDITEM hdItem = new 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 = new RECT ();
+               OS.GetWindowRect (hwndHeader, rect);
+               height += rect.bottom - rect.top;
+       }
+       RECT rect = new RECT ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       while (hItem != 0) {
+               if ((style & SWT.VIRTUAL) == 0 && !painted) {
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+                       tvItem.hItem = hItem;
+                       tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                       ignoreCustomDraw = true;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                       ignoreCustomDraw = false;
+               }
+               if (OS.TreeView_GetItemRect (handle, hItem, rect, true)) {
+                       width = Math.max (width, rect.right);
+                       height += rect.bottom - rect.top;
+               }
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+       }
+       if (width == 0) width = DEFAULT_WIDTH;
+       if (height == 0) height = DEFAULT_HEIGHT;
+       if (wHint != SWT.DEFAULT) width = wHint;
+       if (hHint != SWT.DEFAULT) height = hHint;
+       int border = getBorderWidthInPixels ();
+       width += border * 2;
+       height += border * 2;
+       if ((style & SWT.V_SCROLL) != 0) {
+               width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+       }
+       if ((style & SWT.H_SCROLL) != 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 (OS.IsAppThemed ()) {
+               explorerTheme = true;
+               OS.SetWindowTheme (handle, Display.EXPLORER, null);
+               int bits = OS.TVS_EX_DOUBLEBUFFER | OS.TVS_EX_RICHTOOLTIP;
+               if (ENABLE_TVS_EX_FADEINOUTEXPANDOS) bits |= OS.TVS_EX_FADEINOUTEXPANDOS;
+               /*
+               * This code is intentionally commented.
+               */
+//             if ((style & SWT.FULL_SELECTION) == 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);
+       }
+
+       /* Set the checkbox image list */
+       if ((style & SWT.CHECK) != 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.
+       */
+       long hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+       OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+
+       /*
+        * Bug in Windows. When image list is not set, tree glyph
+        * size is tied to tree indent. Indent doesn't automatically
+        * scale with DPI resulting in distorted glyph image
+        * at higher DPI settings.
+        */
+       int indent = DPIUtil.autoScaleUpUsingNativeDPI(16);
+       OS.SendMessage(handle, OS.TVM_SETINDENT, indent, 0);
+
+       createdAsRTL = (style & SWT.RIGHT_TO_LEFT) != 0;
+}
+
+void createHeaderToolTips () {
+       if (headerToolTipHandle != 0) return;
+       int bits = 0;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL;
+       headerToolTipHandle = OS.CreateWindowEx (
+               bits,
+               new TCHAR (0, OS.TOOLTIPS_CLASS, true),
+               null,
+               OS.TTS_NOPREFIX,
+               OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+               handle,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (headerToolTipHandle == 0) 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 == 0) createParent ();
+       if (!(0 <= index && index <= columnCount)) error (SWT.ERROR_INVALID_RANGE);
+       if (columnCount == 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 != null) {
+                       String [] strings = item.strings;
+                       if (strings != 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 != 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 == 0) {
+                               if (columnCount != 0) {
+                                       if (strings == null) {
+                                               item.strings = new String [columnCount + 1];
+                                               item.strings [1] = item.text;
+                                       }
+                                       item.text = "";
+                                       if (images == null) {
+                                               item.images = new Image [columnCount + 1];
+                                               item.images [1] = item.image;
+                                       }
+                                       item.image = null;
+                               }
+                       }
+                       if (item.cellBackground != 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 != 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 != 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.
+       */
+       long hHeap = OS.GetProcessHeap ();
+       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+       HDITEM hdItem = new HDITEM ();
+       hdItem.mask = OS.HDI_TEXT | OS.HDI_FORMAT;
+       hdItem.pszText = pszText;
+       if ((column.style & SWT.LEFT) == SWT.LEFT) hdItem.fmt = OS.HDF_LEFT;
+       if ((column.style & SWT.CENTER) == SWT.CENTER) hdItem.fmt = OS.HDF_CENTER;
+       if ((column.style & SWT.RIGHT) == SWT.RIGHT) hdItem.fmt = OS.HDF_RIGHT;
+       OS.SendMessage (hwndHeader, OS.HDM_INSERTITEM, index, hdItem);
+       if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+
+       /* When the first column is created, hide the horizontal scroll bar */
+       if (columnCount == 1) {
+               scrollWidth = 0;
+               if ((style & SWT.H_SCROLL) != 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 = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+               if (count != 0) {
+                       OS.ShowScrollBar (handle, OS.SB_HORZ, false);
+               }
+               createItemToolTips ();
+               if (itemToolTipHandle != 0) {
+                       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 == 1 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) != 0) {
+               OS.InvalidateRect (handle, null, true);
+       }
+
+       /* Add the tool tip item for the header */
+       if (headerToolTipHandle != 0) {
+               RECT rect = new RECT ();
+               if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, rect) != 0) {
+                       TOOLINFO lpti = new TOOLINFO ();
+                       lpti.cbSize = TOOLINFO.sizeof;
+                       lpti.uFlags = OS.TTF_SUBCLASS;
+                       lpti.hwnd = hwndHeader;
+                       lpti.uId = column.id = display.nextToolTipId++;
+                       lpti.left = rect.left;
+                       lpti.top = rect.top;
+                       lpti.right = rect.right;
+                       lpti.bottom = rect.bottom;
+                       lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+                       OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+}
+
+// For fast bulk insert, see comments for TreeItem#TreeItem(TreeItem,int,int)
+void createItem (TreeItem item, long hParent, long hInsertAfter, long hItem) {
+       int id = -1;
+       if (item != null) {
+               id = lastID < items.length ? lastID : 0;
+               while (id < items.length && items [id] != null) id++;
+               if (id == 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 (getDrawing () && 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;
+       }
+       long hNewItem = 0;
+       long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent);
+       boolean fixParent = hFirstItem == 0;
+       if (hItem == 0) {
+               TVINSERTSTRUCT tvInsert = new TVINSERTSTRUCT ();
+               tvInsert.hParent = hParent;
+               tvInsert.hInsertAfter = hInsertAfter;
+               tvInsert.lParam = id;
+               tvInsert.pszText = OS.LPSTR_TEXTCALLBACK;
+               tvInsert.iImage = tvInsert.iSelectedImage = OS.I_IMAGECALLBACK;
+               tvInsert.mask = OS.TVIF_TEXT | OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE | OS.TVIF_HANDLE | OS.TVIF_PARAM;
+               if ((style & SWT.CHECK) != 0) {
+                       tvInsert.mask = tvInsert.mask | OS.TVIF_STATE;
+                       tvInsert.state = 1 << 12;
+                       tvInsert.stateMask = OS.TVIS_STATEIMAGEMASK;
+               }
+               ignoreCustomDraw = true;
+               hNewItem = OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, tvInsert);
+               ignoreCustomDraw = false;
+               if (hNewItem == 0) error (SWT.ERROR_ITEM_NOT_ADDED);
+               /*
+               * This code is intentionally commented.
+               */
+//             if (hParent != 0) {
+//                     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//                     bits |= OS.TVS_LINESATROOT;
+//                     OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+//             }
+       } else {
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+               tvItem.hItem = hNewItem = hItem;
+               tvItem.lParam = id;
+               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+       }
+       if (item != null) {
+               item.handle = hNewItem;
+               items [id] = item;
+       }
+       if (hFirstItem == 0) {
+               if (hInsertAfter == OS.TVI_FIRST || hInsertAfter == OS.TVI_LAST) {
+                       hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
+                       itemCount = lastIndexOf = 0;
+               }
+       }
+       if (hFirstItem == hFirstIndexOf && itemCount != -1) itemCount++;
+       if (hItem == 0) {
+               /*
+               * 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 (getDrawing () && OS.IsWindowVisible (handle)) {
+                               RECT rect = new RECT ();
+                               if (OS.TreeView_GetItemRect (handle, 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) != 0) {
+                       if (currentItem != null) {
+                               RECT rect = new RECT ();
+                               if (OS.TreeView_GetItemRect (handle, hNewItem, rect, false)) {
+                                       RECT damageRect = new RECT ();
+                                       boolean damaged = OS.GetUpdateRect (handle, damageRect, true);
+                                       if (damaged && damageRect.top < rect.bottom) {
+                                               long rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                                               int result = OS.GetUpdateRgn (handle, rgn, true);
+                                               if (result != OS.NULLREGION) {
+                                                       OS.OffsetRgn (rgn, 0, rect.bottom - rect.top);
+                                                       OS.InvalidateRgn (handle, rgn, true);
+                                               }
+                                               OS.DeleteObject (rgn);
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                Note: Don't update scrollbars when drawing is disabled.
+                This gives significant improvement for bulk insert scenarios.
+                Later, setRedraw(true) will update scrollbars once.
+                */
+               if (getDrawing ()) updateScrollBar ();
+       }
+}
+
+void createItemToolTips () {
+       if (itemToolTipHandle != 0) return;
+       int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       bits1 |= OS.TVS_NOTOOLTIPS;
+       OS.SetWindowLong (handle, OS.GWL_STYLE, bits1);
+       int bits2 = 0;
+       if ((style & SWT.RIGHT_TO_LEFT) != 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.
+       */
+       bits2 |= OS.WS_EX_TRANSPARENT;
+       itemToolTipHandle = OS.CreateWindowEx (
+               bits2,
+               new TCHAR (0, OS.TOOLTIPS_CLASS, true),
+               null,
+               OS.TTS_NOPREFIX | OS.TTS_NOANIMATE | OS.TTS_NOFADE,
+               OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+               handle,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (itemToolTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
+       OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 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.
+       */
+       OS.SendMessage (itemToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = TOOLINFO.sizeof;
+       lpti.hwnd = handle;
+       lpti.uId = 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 = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       OS.MapWindowPoints (0, parent.handle, rect, 2);
+       int oldStyle = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       int newStyle = super.widgetStyle () & ~OS.WS_VISIBLE;
+       if ((oldStyle & OS.WS_DISABLED) != 0) newStyle |= OS.WS_DISABLED;
+//     if ((oldStyle & OS.WS_VISIBLE) != 0) newStyle |= OS.WS_VISIBLE;
+       hwndParent = OS.CreateWindowEx (
+               super.widgetExtStyle (),
+               super.windowClass (),
+               null,
+               newStyle,
+               rect.left,
+               rect.top,
+               rect.right - rect.left,
+               rect.bottom - rect.top,
+               parent.handle,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (hwndParent == 0) error (SWT.ERROR_NO_HANDLES);
+       OS.SetWindowLongPtr (hwndParent, OS.GWLP_ID, hwndParent);
+       int bits = OS.WS_EX_NOINHERITLAYOUT;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL;
+       hwndHeader = OS.CreateWindowEx (
+               bits,
+               HeaderClass,
+               null,
+               OS.HDS_BUTTONS | OS.HDS_FULLDRAG | OS.HDS_DRAGDROP | OS.HDS_HIDDEN | OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
+               0, 0, 0, 0,
+               hwndParent,
+               0,
+               OS.GetModuleHandle (null),
+               null);
+       if (hwndHeader == 0) error (SWT.ERROR_NO_HANDLES);
+       OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, hwndHeader);
+       if (OS.IsDBLocale) {
+               long 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) != 0) {
+//                     int oldExStyle = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+//                     oldExStyle &= ~OS.WS_EX_CLIENTEDGE;
+//                     OS.SetWindowLong (handle, OS.GWL_EXSTYLE, oldExStyle);
+//             }
+//     }
+       long hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (hFont != 0) OS.SendMessage (hwndHeader, OS.WM_SETFONT, hFont, 0);
+       long hwndInsertAfter = OS.GetWindow (handle, OS.GW_HWNDPREV);
+       int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+       OS.SetWindowPos (hwndParent, hwndInsertAfter, 0, 0, 0, 0, flags);
+       SCROLLINFO info = new SCROLLINFO ();
+       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) != 0) {
+               OS.ShowWindow (hwndParent, OS.SW_SHOW);
+       }
+       long hwndFocus = OS.GetFocus ();
+       if (hwndFocus == handle) OS.SetFocus (hwndParent);
+       OS.SetParent (handle, hwndParent);
+       if (hwndFocus == handle) OS.SetFocus (handle);
+       register ();
+       subclass ();
+}
+
+@Override
+void createWidget () {
+       super.createWidget ();
+       items = new TreeItem [4];
+       columns = new TreeColumn [4];
+       itemCount = -1;
+}
+
+private boolean customHeaderDrawing() {
+       return headerBackground != -1 || headerForeground != -1;
+}
+
+@Override
+int defaultBackground () {
+       return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+@Override
+void deregister () {
+       super.deregister ();
+       if (hwndParent != 0) display.removeControl (hwndParent);
+       if (hwndHeader != 0) display.removeControl (hwndHeader);
+}
+
+void deselect (long hItem, TVITEM tvItem, long hIgnoreItem) {
+       while (hItem != 0) {
+               if (hItem != hIgnoreItem) {
+                       tvItem.hItem = hItem;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+               }
+               long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+               deselect (hFirstItem, tvItem, hIgnoreItem);
+               hItem = 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_SELECTED;
+       tvItem.hItem = item.handle;
+       OS.SendMessage (handle, OS.TVM_SETITEM, 0, 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 = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_SELECTED;
+       if ((style & SWT.SINGLE) != 0) {
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (hItem != 0) {
+                       tvItem.hItem = hItem;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+               }
+       } else {
+               long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+               if ((style & SWT.VIRTUAL) != 0) {
+                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+                       deselect (hItem, tvItem, 0);
+               } else {
+                       for (int i=0; i<items.length; i++) {
+                               TreeItem item = items [i];
+                               if (item != null) {
+                                       tvItem.hItem = item.handle;
+                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                               }
+                       }
+               }
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+       }
+}
+
+void destroyItem (TreeColumn column) {
+       if (hwndHeader == 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+       int index = 0;
+       while (index < columnCount) {
+               if (columns [index] == column) break;
+               index++;
+       }
+       int [] oldOrder = new int [columnCount];
+       OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder);
+       int orderIndex = 0;
+       while (orderIndex < columnCount) {
+               if (oldOrder [orderIndex] == index) break;
+               orderIndex++;
+       }
+       RECT headerRect = new RECT ();
+       OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+       if (OS.SendMessage (hwndHeader, OS.HDM_DELETEITEM, index, 0) == 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 != null) {
+                       if (columnCount == 0) {
+                               item.strings = null;
+                               item.images = null;
+                               item.cellBackground = null;
+                               item.cellForeground = null;
+                               item.cellFont = null;
+                       } else {
+                               if (item.strings != null) {
+                                       String [] strings = item.strings;
+                                       if (index == 0) {
+                                               item.text = strings [1] != 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 == 0) item.text = "";
+                               }
+                               if (item.images != null) {
+                                       Image [] images = item.images;
+                                       if (index == 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 == 0) item.image = null;
+                               }
+                               if (item.cellBackground != 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 != 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 != 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 == 0) {
+               scrollWidth = 0;
+               if (!hooks (SWT.MeasureItem)) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((style & SWT.H_SCROLL) != 0) bits &= ~OS.TVS_NOHSCROLL;
+                       OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+                       OS.InvalidateRect (handle, null, true);
+               }
+               if (itemToolTipHandle != 0) {
+                       OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
+               }
+       } else {
+               if (index == 0) {
+                       columns [0].style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+                       columns [0].style |= SWT.LEFT;
+                       HDITEM hdItem = new 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 = new RECT ();
+               OS.GetClientRect (handle, rect);
+               rect.left = headerRect.left;
+               OS.InvalidateRect (handle, rect, true);
+       }
+       setScrollWidth ();
+       updateImageList ();
+       updateScrollBar ();
+       if (columnCount != 0) {
+               int [] newOrder = new int [columnCount];
+               OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, newOrder);
+               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 != 0) {
+               TOOLINFO lpti = new TOOLINFO ();
+               lpti.cbSize = TOOLINFO.sizeof;
+               lpti.uId = column.id;
+               lpti.hwnd = hwndHeader;
+               OS.SendMessage (headerToolTipHandle, OS.TTM_DELTOOL, 0, lpti);
+       }
+}
+
+void destroyItem (TreeItem item, long hItem) {
+       hFirstIndexOf = hLastIndexOf = 0;
+       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.
+       */
+       long hParent = 0;
+       boolean fixRedraw = false;
+       if ((style & SWT.DOUBLE_BUFFERED) == 0) {
+               if (getDrawing () && OS.IsWindowVisible (handle)) {
+                       RECT rect = new RECT ();
+                       fixRedraw = !OS.TreeView_GetItemRect (handle, hItem, rect, false);
+               }
+       }
+       if (fixRedraw) {
+               hParent = 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);
+       }
+       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.
+       */
+       long hwndToolTip = OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0);
+       if (hwndToolTip != 0) OS.SendMessage (hwndToolTip, OS.TTM_POP, 0 ,0);
+
+       shrink = ignoreShrink = true;
+       OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, hItem);
+       ignoreShrink = false;
+       /*
+        * Bug 546333: When TVGN_CARET item is deleted, Windows automatically
+        * sets selection to some other item. We do not want that.
+        */
+       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) == 0) {
+                       RECT rect = new RECT ();
+                       if (OS.TreeView_GetItemRect (handle, hParent, rect, false)) {
+                               OS.InvalidateRect (handle, rect, true);
+                       }
+               }
+       }
+       int count = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+       if (count == 0) {
+               if (imageList != null) {
+                       OS.SendMessage (handle, OS.TVM_SETIMAGELIST, 0, 0);
+                       display.releaseImageList (imageList);
+               }
+               imageList = null;
+               if (hwndParent == 0 && !linesVisible) {
+                       if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                               customDraw = false;
+                       }
+               }
+               items = new TreeItem [4];
+               scrollWidth = 0;
+               setScrollWidth ();
+       }
+
+       /*
+        Note: Don't update scrollbars when drawing is disabled.
+        This gives significant improvement for bulk remove scenarios.
+        Later, setRedraw(true) will update scrollbars once.
+        */
+       if (getDrawing ()) 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)) == 0) {
+               bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+               bits |= OS.TVS_NOSCROLL;
+       } else {
+               if ((style & SWT.H_SCROLL) == 0) {
+                       bits &= ~OS.WS_HSCROLL;
+                       bits |= OS.TVS_NOHSCROLL;
+               }
+       }
+       OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+}
+
+@Override
+void enableDrag (boolean 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 (boolean enabled) {
+       super.enableWidget (enabled);
+       /*
+       * 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.
+       */
+       Control control = findBackgroundControl ();
+       if (control == null) control = this;
+       if (control.backgroundImage == null) {
+               _setBackgroundPixel (hasCustomBackground() ? control.getBackgroundPixel () : -1);
+       }
+       if (hwndParent != 0) 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 there is
+       * as sort column.
+       */
+       updateFullSelection ();
+}
+
+boolean findCell (int x, int y, TreeItem [] item, int [] index, RECT [] cellRect, RECT [] itemRect) {
+       boolean found = false;
+       TVHITTESTINFO lpht = new TVHITTESTINFO ();
+       lpht.x = x;
+       lpht.y = y;
+       OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+       if (lpht.hItem != 0) {
+               item [0] = _getItem (lpht.hItem);
+               POINT pt = new POINT ();
+               pt.x = x;
+               pt.y = y;
+               long hDC = OS.GetDC (handle);
+               long oldFont = 0, newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+               if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+               RECT rect = new RECT ();
+               if (hwndParent != 0) {
+                       OS.GetClientRect (hwndParent, rect);
+                       OS.MapWindowPoints (hwndParent, handle, rect, 2);
+               } else {
+                       OS.GetClientRect (handle, rect);
+               }
+               int count = Math.max (1, columnCount);
+               int [] order = new int [count];
+               if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order);
+               index [0] = 0;
+               boolean quit = false;
+               while (index [0] < count && !quit) {
+                       long hFont = item [0].fontHandle (order [index [0]]);
+                       if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                       cellRect [0] = item [0].getBounds (order [index [0]], true, false, true, false, true, hDC);
+                       if (cellRect [0].left > rect.right) {
+                               quit = true;
+                       } else {
+                               cellRect [0].right = Math.min (cellRect [0].right, rect.right);
+                               if (OS.PtInRect (cellRect [0], pt)) {
+                                       if (isCustomToolTip ()) {
+                                               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, lpht.hItem, OS.TVIS_SELECTED);
+                                               int detail = (state & OS.TVIS_SELECTED) != 0 ? SWT.SELECTED : 0;
+                                               Event event = sendMeasureItemEvent (item [0], order [index [0]], hDC, detail);
+                                               if (isDisposed () || item [0].isDisposed ()) break;
+                                               Rectangle boundsInPixels = event.getBoundsInPixels();
+                                               itemRect [0] = new RECT ();
+                                               itemRect [0].left = boundsInPixels.x;
+                                               itemRect [0].right = boundsInPixels.x + boundsInPixels.width;
+                                               itemRect [0].top = boundsInPixels.y;
+                                               itemRect [0].bottom = boundsInPixels.y + boundsInPixels.height;
+                                       } else {
+                                               itemRect [0] = item [0].getBounds (order [index [0]], true, false, false, false, false, hDC);
+                                       }
+                                       if (itemRect [0].right > cellRect [0].right) found = true;
+                                       quit = true;
+                               }
+                       }
+                       if (hFont != -1) OS.SelectObject (hDC, hFont);
+                       if (!found) index [0]++;
+               }
+               if (newFont != 0) OS.SelectObject (hDC, oldFont);
+               OS.ReleaseDC (handle, hDC);
+       }
+       return found;
+}
+
+int findIndex (long hFirstItem, long hItem) {
+       if (hFirstItem == 0) return -1;
+       if (hFirstItem == hFirstIndexOf) {
+               if (hFirstIndexOf == hItem) {
+                       hLastIndexOf = hFirstIndexOf;
+                       return lastIndexOf = 0;
+               }
+               if (hLastIndexOf == hItem) return lastIndexOf;
+               long hPrevItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hLastIndexOf);
+               if (hPrevItem == hItem) {
+                       hLastIndexOf = hPrevItem;
+                       return --lastIndexOf;
+               }
+               long hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hLastIndexOf);
+               if (hNextItem == hItem) {
+                       hLastIndexOf = hNextItem;
+                       return ++lastIndexOf;
+               }
+               int previousIndex = lastIndexOf - 1;
+               while (hPrevItem != 0 && hPrevItem != hItem) {
+                       hPrevItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hPrevItem);
+                       --previousIndex;
+               }
+               if (hPrevItem == hItem) {
+                       hLastIndexOf = hPrevItem;
+                       return lastIndexOf = previousIndex;
+               }
+               int nextIndex = lastIndexOf + 1;
+               while (hNextItem != 0 && hNextItem != hItem) {
+                       hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+                       nextIndex++;
+               }
+               if (hNextItem == hItem) {
+                       hLastIndexOf = hNextItem;
+                       return lastIndexOf = nextIndex;
+               }
+               return -1;
+       }
+       int index = 0;
+       long hNextItem = hFirstItem;
+       while (hNextItem != 0 && hNextItem != hItem) {
+               hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+               index++;
+       }
+       if (hNextItem == hItem) {
+               itemCount = -1;
+               hFirstIndexOf = hFirstItem;
+               hLastIndexOf = hNextItem;
+               return lastIndexOf = index;
+       }
+       return -1;
+}
+
+@Override
+Widget findItem (long hItem) {
+       return _getItem (hItem);
+}
+
+long findItem (long hFirstItem, int index) {
+       if (hFirstItem == 0) return 0;
+       if (hFirstItem == hFirstIndexOf) {
+               if (index == 0) {
+                       lastIndexOf = 0;
+                       return hLastIndexOf = hFirstIndexOf;
+               }
+               if (lastIndexOf == index) return hLastIndexOf;
+               if (lastIndexOf - 1 == index) {
+                       --lastIndexOf;
+                       return hLastIndexOf = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hLastIndexOf);
+               }
+               if (lastIndexOf + 1 == index) {
+                       lastIndexOf++;
+                       return hLastIndexOf = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hLastIndexOf);
+               }
+               if (index < lastIndexOf) {
+                       int previousIndex = lastIndexOf - 1;
+                       long hPrevItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hLastIndexOf);
+                       while (hPrevItem != 0 && index < previousIndex) {
+                               hPrevItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hPrevItem);
+                               --previousIndex;
+                       }
+                       if (index == previousIndex) {
+                               lastIndexOf = previousIndex;
+                               return hLastIndexOf = hPrevItem;
+                       }
+               } else {
+                       int nextIndex = lastIndexOf + 1;
+                       long hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hLastIndexOf);
+                       while (hNextItem != 0 && nextIndex < index) {
+                               hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+                               nextIndex++;
+                       }
+                       if (index == nextIndex) {
+                               lastIndexOf = nextIndex;
+                               return hLastIndexOf = hNextItem;
+                       }
+               }
+               return 0;
+       }
+       int nextIndex = 0;
+       long hNextItem = hFirstItem;
+       while (hNextItem != 0 && nextIndex < index) {
+               hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+               nextIndex++;
+       }
+       if (index == nextIndex) {
+               itemCount = -1;
+               lastIndexOf = nextIndex;
+               hFirstIndexOf = hFirstItem;
+               return hLastIndexOf = hNextItem;
+       }
+       return 0;
+}
+
+TreeItem getFocusItem () {
+//     checkWidget ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+       return hItem != 0 ? _getItem (hItem) : null;
+}
+
+/**
+ * Returns the width in points of a grid line.
+ *
+ * @return the width of a grid line in points
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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 DPIUtil.autoScaleDown(getGridLineWidthInPixels ());
+}
+
+int getGridLineWidthInPixels () {
+       return GRID_WIDTH;
+}
+
+/**
+ * Returns the header background color.
+ *
+ * @return the receiver's header 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.106
+ */
+public Color getHeaderBackground () {
+       checkWidget ();
+       return Color.win32_new (display, getHeaderBackgroundPixel());
+}
+
+private int getHeaderBackgroundPixel() {
+       return headerBackground != -1 ? headerBackground : defaultBackground();
+}
+
+/**
+ * Returns the header foreground color.
+ *
+ * @return the receiver's header 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.106
+ */
+public Color getHeaderForeground () {
+       checkWidget ();
+       return Color.win32_new (display, getHeaderForegroundPixel());
+}
+
+private int getHeaderForegroundPixel() {
+       return headerForeground != -1 ? headerForeground : defaultForeground();
+}
+
+/**
+ * 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 ();
+       return DPIUtil.autoScaleDown(getHeaderHeightInPixels ());
+}
+
+int getHeaderHeightInPixels () {
+       if (hwndHeader == 0) return 0;
+       RECT rect = new 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 boolean getHeaderVisible () {
+       checkWidget ();
+       if (hwndHeader == 0) return false;
+       int bits = OS.GetWindowLong (hwndHeader, OS.GWL_STYLE);
+       return (bits & OS.WS_VISIBLE) != 0;
+}
+
+Point getImageSize () {
+       if (imageList != null) return imageList.getImageSize ();
+       return new Point (0, getItemHeightInPixels ());
+}
+
+long getBottomItem () {
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+       if (hItem == 0) return 0;
+       int index = 0, count = (int)OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0);
+       while (index <= count) {
+               long hNextItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+               if (hNextItem == 0) 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(boolean)
+ * @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(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public int[] getColumnOrder () {
+       checkWidget ();
+       if (columnCount == 0) return new int [0];
+       int [] order = new int [columnCount];
+       OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order);
+       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(boolean)
+ * @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);
+       long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       if (hFirstItem == 0) error (SWT.ERROR_INVALID_RANGE);
+       long hItem = findItem (hFirstItem, index);
+       if (hItem == 0) 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 = (int)nmcd.lItemlParam;
+       if ((style & SWT.VIRTUAL) != 0) {
+               if (id == -1) {
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+                       tvItem.hItem = nmcd.dwItemSpec;
+                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                       id = (int)tvItem.lParam;
+               }
+       }
+       return _getItem (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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       return getItemInPixels(DPIUtil.autoScaleUp(point));
+}
+
+TreeItem getItemInPixels (Point point) {
+       TVHITTESTINFO lpht = new TVHITTESTINFO ();
+       lpht.x = point.x;
+       lpht.y = point.y;
+       OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+       if (lpht.hItem != 0) {
+               int flags = OS.TVHT_ONITEM;
+               if ((style & SWT.FULL_SELECTION) != 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.x, lpht.y)) {
+                                       lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                               }
+                       }
+               }
+               if ((lpht.flags & flags) != 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 ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       if (hItem == 0) return 0;
+       return getItemCount (hItem);
+}
+
+int getItemCount (long hItem) {
+       int count = 0;
+       long hFirstItem = hItem;
+       if (hItem == hFirstIndexOf) {
+               if (itemCount != -1) return itemCount;
+               hFirstItem = hLastIndexOf;
+               count = lastIndexOf;
+       }
+       while (hFirstItem != 0) {
+               hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hFirstItem);
+               count++;
+       }
+       if (hItem == 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 DPIUtil.autoScaleDown(getItemHeightInPixels());
+}
+
+int getItemHeightInPixels () {
+       return (int)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 ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       if (hItem == 0) return new TreeItem [0];
+       return getItems (hItem);
+}
+
+TreeItem [] getItems (long hTreeItem) {
+       int count = 0;
+       long hItem = hTreeItem;
+       while (hItem != 0) {
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+               count++;
+       }
+       int index = 0;
+       TreeItem [] result = new TreeItem [count];
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       tvItem.hItem = 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 != 0) {
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+               TreeItem item = _getItem (tvItem.hItem, (int)tvItem.lParam);
+               if (item != null) result [index++] = item;
+               tvItem.hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, tvItem.hItem);
+       }
+       if (index != 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. Note that some platforms draw
+ * grid lines while others may draw alternating row colors.
+ * <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 boolean getLinesVisible () {
+       checkWidget ();
+       return linesVisible;
+}
+
+long getNextSelection (long hItem) {
+       while (hItem != 0) {
+               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+               if ((state & OS.TVIS_SELECTED) != 0) return hItem;
+               long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+               long hSelected = getNextSelection (hFirstItem);
+               if (hSelected != 0) return hSelected;
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+       }
+       return 0;
+}
+
+/**
+ * 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 (long hItem, TVITEM tvItem, TreeItem [] selection, int index, int count, boolean bigSelection, boolean all) {
+       while (hItem != 0) {
+               boolean expanded = true;
+               if (bigSelection) {
+                       tvItem.hItem = hItem;
+                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                       if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+                               if (selection != null && index < selection.length) {
+                                       TreeItem item = _getItem (hItem, (int)tvItem.lParam);
+                                       if (item != null) {
+                                               selection [index] = item;
+                                       } else {
+                                               index--;
+                                       }
+                               }
+                               index++;
+                       }
+                       expanded = (tvItem.state & OS.TVIS_EXPANDED) != 0;
+               } else {
+                       int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED | OS.TVIS_EXPANDED);
+                       if ((state & OS.TVIS_SELECTED) != 0) {
+                               if (tvItem != null && selection != null && index < selection.length) {
+                                       tvItem.hItem = hItem;
+                                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                       TreeItem item = _getItem (hItem, (int)tvItem.lParam);
+                                       if (item != null) {
+                                               selection [index] = item;
+                                       } else {
+                                               index--;
+                                       }
+                               }
+                               index++;
+                       }
+                       expanded = (state & OS.TVIS_EXPANDED) != 0;
+               }
+               if (index == count) break;
+               if (all) {
+                       if (expanded) {
+                               long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+                               if ((index = getSelection (hFirstItem, tvItem, selection, index, count, bigSelection, all)) == count) {
+                                       break;
+                               }
+                       }
+                       hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+               } else {
+                       hItem = 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) != 0) {
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (hItem == 0) return new TreeItem [0];
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+               tvItem.hItem = hItem;
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+               if ((tvItem.state & OS.TVIS_SELECTED) == 0) return new TreeItem [0];
+               TreeItem item = _getItem (tvItem.hItem, (int)tvItem.lParam);
+               if (item == null) return new TreeItem [0];
+               return new TreeItem [] {item};
+       }
+       int count = 0;
+       TreeItem [] guess = new TreeItem [(style & SWT.VIRTUAL) != 0 ? 8 : 1];
+       long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+       if ((style & SWT.VIRTUAL) != 0) {
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+               count = getSelection (hItem, tvItem, guess, 0, -1, false, true);
+       } else {
+               for (int i=0; i<items.length; i++) {
+                       TreeItem item = items [i];
+                       if (item != null) {
+                               long hItem = item.handle;
+                               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+                               if ((state & OS.TVIS_SELECTED) != 0) {
+                                       if (count < guess.length) guess [count] = item;
+                                       count++;
+                               }
+                       }
+               }
+       }
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+       if (count == 0) return new TreeItem [0];
+       if (count == 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, TreeProc);
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       int itemCount = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+       boolean bigSelection = result.length > itemCount / 2;
+       if (count != getSelection (hItem, tvItem, result, 0, count, bigSelection, false)) {
+               count = getSelection (hItem, tvItem, result, 0, count, bigSelection, true);
+       }
+       if (count != result.length) {
+               TreeItem[] newResult = new TreeItem[count];
+               System.arraycopy (result, 0, newResult, 0, count);
+               result = newResult;
+       }
+       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) != 0) {
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (hItem == 0) return 0;
+               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+               return (state & OS.TVIS_SELECTED) == 0 ? 0 : 1;
+       }
+       int count = 0;
+       long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+       if ((style & SWT.VIRTUAL) != 0) {
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+               count = getSelection (hItem, null, null, 0, -1, false, true);
+       } else {
+               for (int i=0; i<items.length; i++) {
+                       TreeItem item = items [i];
+                       if (item != null) {
+                               long hItem = item.handle;
+                               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+                               if ((state & OS.TVIS_SELECTED) != 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) || hasCustomBackground() ? getBackgroundPixel () : OS.GetSysColor (OS.COLOR_3DFACE);
+       return getSlightlyDifferentBackgroundColor(pixel);
+}
+
+/**
+ * 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 ();
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+       return hItem != 0 ? _getItem (hItem) : null;
+}
+
+boolean hitTestSelection (long hItem, int x, int y) {
+       if (hItem == 0) return false;
+       TreeItem item = _getItem (hItem);
+       if (item == null) return false;
+       if (!hooks (SWT.MeasureItem)) return false;
+       boolean result = false;
+
+       //BUG? - moved columns, only hittest first column
+       //BUG? - check drag detect
+       int [] order = new int [1], index = new int [1];
+
+       long hDC = OS.GetDC (handle);
+       long oldFont = 0, newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       long hFont = item.fontHandle (order [index [0]]);
+       if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+       int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+       int detail = (state & OS.TVIS_SELECTED) != 0 ? SWT.SELECTED : 0;
+       Event event = sendMeasureItemEvent (item, order [index [0]], hDC, detail);
+       if (event.getBoundsInPixels ().contains (x, y)) result = true;
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (handle, hDC);
+//     if (isDisposed () || item.isDisposed ()) return false;
+       return result;
+}
+
+int imageIndex (Image image, int index) {
+       if (image == null) return OS.I_IMAGENONE;
+       if (imageList == null) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+       }
+       int imageIndex = imageList.indexOf (image);
+       if (imageIndex == -1) imageIndex = imageList.add (image);
+       if (hwndHeader == 0 || OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) == 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.
+               */
+               long hImageList = imageList.getHandle ();
+               long hOldImageList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+               if (hOldImageList != hImageList) {
+                       OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
+                       updateScrollBar ();
+               }
+       }
+       return imageIndex;
+}
+
+int imageIndexHeader (Image image) {
+       if (image == null) return OS.I_IMAGENONE;
+       if (headerImageList == null) {
+               Rectangle bounds = image.getBoundsInPixels ();
+               headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+               int index = headerImageList.indexOf (image);
+               if (index == -1) index = headerImageList.add (image);
+               long hImageList = headerImageList.getHandle ();
+               if (hwndHeader != 0) {
+                       OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageList);
+               }
+               updateScrollBar ();
+               return index;
+       }
+       int index = headerImageList.indexOf (image);
+       if (index != -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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       for (int i=0; i<columnCount; i++) {
+               if (columns [i] == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       return hItem == 0 ? -1 : findIndex (hItem, item.handle);
+}
+
+boolean isCustomToolTip () {
+       return hooks (SWT.MeasureItem);
+}
+
+boolean isItemSelected (NMTVCUSTOMDRAW nmcd) {
+       boolean selected = false;
+       if (OS.IsWindowEnabled (handle)) {
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+               tvItem.hItem = nmcd.dwItemSpec;
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+               if ((tvItem.state & (OS.TVIS_SELECTED | OS.TVIS_DROPHILITED)) != 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 == OS.GetFocus ()) {
+                               if (OS.GetTextColor (nmcd.hdc) != OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT)) {
+                                       selected = false;
+                               } else {
+                                       if (OS.GetBkColor (nmcd.hdc) != OS.GetSysColor (OS.COLOR_HIGHLIGHT)) {
+                                               selected = false;
+                                       }
+                               }
+                       }
+               } else {
+                       if (nmcd.dwDrawStage == 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.hdc) == OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT)) {
+                                       if (OS.GetBkColor (nmcd.hdc) == OS.GetSysColor (OS.COLOR_HIGHLIGHT)) {
+                                               selected = true;
+                                       }
+                               }
+                       }
+               }
+       }
+       return selected;
+}
+
+void redrawSelection () {
+       if ((style & SWT.SINGLE) != 0) {
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (hItem != 0) {
+                       RECT rect = new RECT ();
+                       if (OS.TreeView_GetItemRect (handle, hItem, rect, false)) {
+                               OS.InvalidateRect (handle, rect, true);
+                       }
+               }
+       } else {
+               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+               if (hItem != 0) {
+                       RECT rect = new RECT ();
+                       int index = 0, count = (int)OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0);
+                       while (index <= count && hItem != 0) {
+                               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+                               if ((state & OS.TVIS_SELECTED) != 0) {
+                                       if (OS.TreeView_GetItemRect (handle, hItem, rect, false)) {
+                                               OS.InvalidateRect (handle, rect, true);
+                                       }
+                               }
+                               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                               index++;
+                       }
+               }
+       }
+}
+
+@Override
+void register () {
+       super.register ();
+       if (hwndParent != 0) display.addControl (hwndParent, this);
+       if (hwndHeader != 0) display.addControl (hwndHeader, this);
+}
+
+void releaseItem (long hItem, TVITEM tvItem, boolean release) {
+       if (hItem == hAnchor) hAnchor = 0;
+       if (hItem == hInsert) hInsert = 0;
+       tvItem.hItem = hItem;
+       if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) != 0) {
+               if (tvItem.lParam != -1) {
+                       if (tvItem.lParam < lastID) lastID = (int)tvItem.lParam;
+                       if (release) {
+                               TreeItem item = items [(int)tvItem.lParam];
+                               if (item != null) item.release (false);
+                       }
+                       items [(int)tvItem.lParam] = null;
+               }
+       }
+}
+
+void releaseItems (long hItem, TVITEM tvItem) {
+       hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+       while (hItem != 0) {
+               releaseItems (hItem, tvItem);
+               releaseItem (hItem, tvItem, true);
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+       }
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       hwndParent = hwndHeader = 0;
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       TreeItem item = items [i];
+                       if (item != null && !item.isDisposed ()) {
+                               item.release (false);
+                       }
+               }
+               items = null;
+       }
+       if (columns != null) {
+               for (int i=0; i<columns.length; i++) {
+                       TreeColumn column = columns [i];
+                       if (column != 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 != null) {
+               OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, 0);
+               display.releaseImageList (imageList);
+       }
+       if (headerImageList != null) {
+               if (hwndHeader != 0) {
+                       OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, 0);
+               }
+               display.releaseImageList (headerImageList);
+       }
+       imageList = headerImageList = null;
+       long hStateList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_STATE, 0);
+       OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, 0);
+       if (hStateList != 0) OS.ImageList_Destroy (hStateList);
+       if (itemToolTipHandle != 0) OS.DestroyWindow (itemToolTipHandle);
+       if (headerToolTipHandle != 0) OS.DestroyWindow (headerToolTipHandle);
+       itemToolTipHandle = headerToolTipHandle = 0;
+}
+
+/**
+ * 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 = 0;
+       itemCount = -1;
+       for (int i=0; i<items.length; i++) {
+               TreeItem item = items [i];
+               if (item != null && !item.isDisposed ()) {
+                       item.release (false);
+               }
+       }
+       ignoreDeselect = ignoreSelect = true;
+       boolean redraw = getDrawing () && OS.IsWindowVisible (handle);
+       if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+       shrink = ignoreShrink = true;
+       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 == 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+       if (imageList != null) {
+               OS.SendMessage (handle, OS.TVM_SETIMAGELIST, 0, 0);
+               display.releaseImageList (imageList);
+       }
+       imageList = null;
+       if (hwndParent == 0 && !linesVisible) {
+               if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                       customDraw = false;
+               }
+       }
+       hAnchor = hInsert = hFirstIndexOf = hLastIndexOf = 0;
+       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 == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Expand, listener);
+       eventTable.unhook (SWT.Collapse, listener);
+}
+
+@Override
+void reskinChildren (int flags) {
+       if (items != null) {
+               for (int i=0; i<items.length; i++) {
+                       TreeItem item = items [i];
+                       if (item != null) item.reskinChildren (flags);
+               }
+       }
+       if (columns != null) {
+               for (int i=0; i<columns.length; i++) {
+                       TreeColumn column = columns [i];
+                       if (column != null) column.reskinChildren (flags);
+               }
+       }
+       super.reskinChildren (flags);
+}
+
+
+/**
+ * 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, boolean before) {
+       checkWidget ();
+       long hItem = 0;
+       if (item != 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);
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       setItemCount (count, OS.TVGN_ROOT, hItem);
+}
+
+void setItemCount (int count, long hParent, long hItem) {
+       boolean redraw = false;
+       if (OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) == 0) {
+               redraw = getDrawing () && OS.IsWindowVisible (handle);
+               if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+       }
+       int itemCount = 0;
+       while (hItem != 0 && itemCount < count) {
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+               itemCount++;
+       }
+       boolean expanded = false;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       if (!redraw && (style & SWT.VIRTUAL) != 0) {
+               /*
+               * 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 = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hParent, OS.TVIS_EXPANDED);
+               expanded = (state & OS.TVIS_EXPANDED) != 0;
+       }
+       while (hItem != 0) {
+               tvItem.hItem = hItem;
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+               TreeItem item = tvItem.lParam != -1 ? items [(int)tvItem.lParam] : null;
+               if (item != null && !item.isDisposed ()) {
+                       item.dispose ();
+               } else {
+                       releaseItem (tvItem.hItem, tvItem, false);
+                       destroyItem (null, tvItem.hItem);
+               }
+       }
+       if ((style & SWT.VIRTUAL) != 0) {
+               for (int i=itemCount; i<count; i++) {
+                       if (expanded) ignoreShrink = true;
+                       createItem (null, hParent, OS.TVI_LAST, 0);
+                       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, OS.TVI_LAST, 0);
+               }
+       }
+       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. Note that some platforms draw
+ * grid lines while others may draw alternating row colors.
+ * <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 (boolean show) {
+       checkWidget ();
+       if (linesVisible == show) return;
+       linesVisible = show;
+       if (hwndParent == 0 && linesVisible) customDraw = true;
+       OS.InvalidateRect (handle, null, true);
+       if (hwndHeader != 0) OS.InvalidateRect (hwndHeader, null, true);
+}
+
+@Override
+long scrolledHandle () {
+       if (hwndHeader == 0) return handle;
+       return columnCount == 0 && scrollWidth == 0 ? handle : hwndParent;
+}
+
+void select (long hItem, TVITEM tvItem) {
+       while (hItem != 0) {
+               tvItem.hItem = hItem;
+               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_EXPANDED);
+               if ((state & OS.TVIS_EXPANDED) != 0) {
+                       long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+                       select (hFirstItem, tvItem);
+               }
+
+               hItem = 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if ((style & SWT.SINGLE) != 0) {
+               long hItem = item.handle;
+               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+               if ((state & OS.TVIS_SELECTED) != 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)) == 0) {
+                       hInfo = new SCROLLINFO ();
+                       hInfo.cbSize = SCROLLINFO.sizeof;
+                       hInfo.fMask = OS.SIF_ALL;
+                       OS.GetScrollInfo (handle, OS.SB_HORZ, hInfo);
+               }
+               SCROLLINFO vInfo = new SCROLLINFO ();
+               vInfo.cbSize = SCROLLINFO.sizeof;
+               vInfo.fMask = OS.SIF_ALL;
+               OS.GetScrollInfo (handle, OS.SB_VERT, vInfo);
+               boolean redraw = getDrawing () && OS.IsWindowVisible (handle);
+               if (redraw) {
+                       OS.UpdateWindow (handle);
+                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+               }
+               setSelection (item);
+               if (hInfo != null) {
+                       long hThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, hInfo.nPos);
+                       OS.SendMessage (handle, OS.WM_HSCROLL, hThumb, 0);
+               }
+               /*
+               * Feature in Windows.  It seems that Vista does not
+               * use wParam to get the new position when WM_VSCROLL
+               * is sent with SB_THUMBPOSITION.  The fix is to use
+               * SetScrollInfo() to move the scroll bar thumb before
+               * calling WM_VSCROLL.
+               *
+               * NOTE: This code is only necessary on Windows Vista.
+               */
+               OS.SetScrollInfo (handle, OS.SB_VERT, vInfo, true);
+               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) == 0) {
+                               int oldStyle = style;
+                               style |= SWT.DOUBLE_BUFFERED;
+                               OS.UpdateWindow (handle);
+                               style = oldStyle;
+                       }
+               }
+               return;
+       }
+       expandToItem(item);
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_SELECTED;
+       tvItem.state = OS.TVIS_SELECTED;
+       tvItem.hItem = item.handle;
+       OS.SendMessage (handle, OS.TVM_SETITEM, 0, 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) != 0) return;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.state = OS.TVIS_SELECTED;
+       tvItem.stateMask = OS.TVIS_SELECTED;
+       long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       select (hItem, tvItem);
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+}
+
+Event sendEraseItemEvent (TreeItem item, NMTTCUSTOMDRAW nmcd, int column, RECT cellRect) {
+       int nSavedDC = OS.SaveDC (nmcd.hdc);
+       RECT insetRect = toolTipInset (cellRect);
+       OS.SetWindowOrgEx (nmcd.hdc, insetRect.left, insetRect.top, null);
+       GCData data = new GCData ();
+       data.device = display;
+       data.foreground = OS.GetTextColor (nmcd.hdc);
+       data.background = OS.GetBkColor (nmcd.hdc);
+       data.font = item.getFont (column);
+       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+       GC gc = GC.win32_new (nmcd.hdc, data);
+       Event event = new Event ();
+       event.item = item;
+       event.index = column;
+       event.gc = gc;
+       event.detail |= SWT.FOREGROUND;
+       event.setBoundsInPixels(new Rectangle(cellRect.left, cellRect.top, cellRect.right - cellRect.left, 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.hdc, nSavedDC);
+       return event;
+}
+
+Event sendMeasureItemEvent (TreeItem item, int index, long hDC, int detail) {
+       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.setBoundsInPixels(new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top));
+       event.detail = detail;
+       sendEvent (SWT.MeasureItem, event);
+       event.gc = null;
+       gc.dispose ();
+       OS.RestoreDC (hDC, nSavedDC);
+       if (isDisposed () || item.isDisposed ()) return null;
+       Rectangle rect = event.getBoundsInPixels ();
+       if (hwndHeader != 0) {
+               if (columnCount == 0) {
+                       if (rect.x + rect.width > scrollWidth) {
+                               setScrollWidth (scrollWidth = rect.x + rect.width);
+                       }
+               }
+       }
+       if (rect.height > getItemHeightInPixels ()) setItemHeight (rect.height);
+       return event;
+}
+
+Event sendPaintItemEvent (TreeItem item, NMTTCUSTOMDRAW nmcd, int column, RECT itemRect) {
+       int nSavedDC = OS.SaveDC (nmcd.hdc);
+       RECT insetRect = toolTipInset (itemRect);
+       OS.SetWindowOrgEx (nmcd.hdc, insetRect.left, insetRect.top, null);
+       GCData data = new GCData ();
+       data.device = display;
+       data.font = item.getFont (column);
+       data.foreground = OS.GetTextColor (nmcd.hdc);
+       data.background = OS.GetBkColor (nmcd.hdc);
+       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+       GC gc = GC.win32_new (nmcd.hdc, data);
+       Event event = new Event ();
+       event.item = item;
+       event.index = column;
+       event.gc = gc;
+       event.detail |= SWT.FOREGROUND;
+       event.setBoundsInPixels(new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top));
+       //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+       sendEvent (SWT.PaintItem, event);
+       event.gc = null;
+       gc.dispose ();
+       OS.RestoreDC (nmcd.hdc, nSavedDC);
+       return event;
+}
+
+@Override
+void setBackgroundImage (long hBitmap) {
+       super.setBackgroundImage (hBitmap);
+       if (hBitmap != 0) {
+               /*
+               * 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) == -1) {
+                       OS.SendMessage (handle, OS.TVM_SETBKCOLOR, 0, -1);
+               }
+               _setBackgroundPixel (-1);
+       } else {
+               Control control = findBackgroundControl ();
+               if (control == null) control = this;
+               if (control.backgroundImage == 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 != null) {
+               setBackgroundImage (control.backgroundImage);
+               return;
+       }
+       _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 ();
+       long hCursor = cursor == null ? OS.LoadCursor (0, 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_NULL_ARGUMENT - if the item order is null</li>
+ *    <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(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setColumnOrder (int [] order) {
+       checkWidget ();
+       if (order == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (columnCount == 0) {
+               if (order.length != 0) error (SWT.ERROR_INVALID_ARGUMENT);
+               return;
+       }
+       if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+       int [] oldOrder = new int [columnCount];
+       OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder);
+       boolean reorder = false;
+       boolean [] seen = new boolean [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 != 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);
+               OS.InvalidateRect (handle, null, true);
+               updateImageList ();
+               TreeColumn [] newColumns = new TreeColumn [columnCount];
+               System.arraycopy (columns, 0, newColumns, 0, columnCount);
+               RECT newRect = new RECT ();
+               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 != oldRects [i].left) {
+                                       column.updateToolTip (i);
+                                       column.sendEvent (SWT.Move);
+                               }
+                       }
+               }
+       }
+}
+
+void setCheckboxImageList () {
+       if ((style & SWT.CHECK) == 0) return;
+       int count = 5, flags = OS.ILC_COLOR32;
+       if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.ILC_MIRROR;
+       if (!OS.IsAppThemed ()) flags |= OS.ILC_MASK;
+       int height = (int)OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0), width = height;
+       long hStateList = OS.ImageList_Create (width, height, flags, count, count);
+       long hDC = OS.GetDC (handle);
+       long memDC = OS.CreateCompatibleDC (hDC);
+       long hBitmap = OS.CreateCompatibleBitmap (hDC, width * count, height);
+       long hOldBitmap = OS.SelectObject (memDC, hBitmap);
+       RECT rect = new 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.IsAppThemed ()) {
+               Control control = findBackgroundControl ();
+               if (control == null) control = this;
+               clrBackground = control.getBackgroundPixel ();
+       } else {
+               clrBackground = 0x020000FF;
+               if ((clrBackground & 0xFFFFFF) == OS.GetSysColor (OS.COLOR_WINDOW)) {
+                       clrBackground = 0x0200FF00;
+               }
+       }
+       long hBrush = OS.CreateSolidBrush (clrBackground);
+       OS.FillRect (memDC, rect, hBrush);
+       OS.DeleteObject (hBrush);
+       long oldFont = OS.SelectObject (hDC, defaultFont ());
+       TEXTMETRIC tm = new TEXTMETRIC ();
+       OS.GetTextMetrics (hDC, tm);
+       OS.SelectObject (hDC, oldFont);
+       int itemWidth = Math.min (tm.tmHeight, width);
+       int itemHeight = Math.min (tm.tmHeight, height);
+       if (OS.IsAppThemed()) {
+               /*
+                * Feature in Windows. DrawThemeBackground stretches the checkbox
+                * bitmap to fill the provided rectangle. To avoid stretching
+                * artifacts, limit the rectangle to actual checkbox bitmap size.
+                */
+               SIZE size = new SIZE();
+               OS.GetThemePartSize(display.hButtonTheme(), memDC, OS.BP_CHECKBOX, 0, null, OS.TS_TRUE, size);
+               itemWidth = Math.min (size.cx, itemWidth);
+               itemHeight = Math.min (size.cy, itemHeight);
+       }
+       int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2 + 1;
+       OS.SetRect (rect, left + width, top, left + width + itemWidth, top + itemHeight);
+       if (OS.IsAppThemed ()) {
+               long 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.IsAppThemed ()) {
+               OS.ImageList_Add (hStateList, hBitmap, 0);
+       } else {
+               OS.ImageList_AddMasked (hStateList, hBitmap, clrBackground);
+       }
+       OS.DeleteObject (hBitmap);
+       long hOldStateList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_STATE, 0);
+       OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, hStateList);
+       if (hOldStateList != 0) OS.ImageList_Destroy (hOldStateList);
+}
+
+@Override
+public void setFont (Font font) {
+       checkWidget ();
+       super.setFont (font);
+       if ((style & SWT.CHECK) != 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 == -1) pixel = defaultForeground ();
+       }
+       OS.SendMessage (handle, OS.TVM_SETTEXTCOLOR, 0, pixel);
+}
+
+/**
+ * Sets the header background color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </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 3.106
+ */
+public void setHeaderBackground (Color color) {
+       checkWidget ();
+       int pixel = -1;
+       if (color != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == headerBackground) return;
+       headerBackground = pixel;
+       if (getHeaderVisible()) {
+               OS.InvalidateRect (hwndHeader, null, true);
+       }
+}
+
+/**
+ * Sets the header foreground color to the color specified
+ * by the argument, or to the default system color if the argument is null.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not supported on all platforms. If
+ * the native header has a 3D look and feel (e.g. Windows 7), this method
+ * will cause the header to look FLAT irrespective of the state of the tree style.
+ * </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 3.106
+ */
+public void setHeaderForeground (Color color) {
+       checkWidget ();
+       int pixel = -1;
+       if (color != null) {
+               if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+               pixel = color.handle;
+       }
+       if (pixel == headerForeground) return;
+       headerForeground = pixel;
+       if (getHeaderVisible()) {
+               OS.InvalidateRect (hwndHeader, 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>
+ *
+ * @since 3.1
+ */
+public void setHeaderVisible (boolean show) {
+       checkWidget ();
+       if (hwndHeader == 0) {
+               if (!show) return;
+               createParent ();
+       }
+       int bits = OS.GetWindowLong (hwndHeader, OS.GWL_STYLE);
+       if (show) {
+               if ((bits & OS.HDS_HIDDEN) == 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) != 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 (boolean 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.
+       */
+       long hItem = 0;
+       boolean willEnableDraw = redraw && (drawCount == 1);
+       if (willEnableDraw) {
+               int count = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+               if (count == 0) {
+                       TVINSERTSTRUCT tvInsert = new TVINSERTSTRUCT ();
+                       tvInsert.hInsertAfter = OS.TVI_FIRST;
+                       hItem = OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, tvInsert);
+               }
+               OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+               updateScrollBar ();
+       }
+
+       super.setRedraw (redraw);
+
+       boolean haveDisabledDraw = !redraw && (drawCount == 1);
+       if (haveDisabledDraw) {
+               OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+       }
+       if (hItem != 0) {
+               ignoreShrink = true;
+               OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, hItem);
+               ignoreShrink = false;
+       }
+}
+
+void setScrollWidth () {
+       if (hwndHeader == 0 || hwndParent == 0) return;
+       int width = 0;
+       HDITEM hdItem = new 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 == 0 || hwndParent == 0) return;
+       //TEMPORARY CODE
+       //scrollWidth = width;
+       int left = 0;
+       RECT rect = new RECT ();
+       SCROLLINFO info = new SCROLLINFO ();
+       info.cbSize = SCROLLINFO.sizeof;
+       info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+       if (columnCount == 0 && width == 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) != 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 != null) {
+               horizontalBar.setIncrement (INCREMENT);
+               horizontalBar.setPageIncrement (info.nPage);
+       }
+       OS.GetClientRect (hwndParent, rect);
+       long hHeap = OS.GetProcessHeap ();
+       HDLAYOUT playout = new HDLAYOUT ();
+       playout.prc = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, RECT.sizeof);
+       playout.pwpos = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, WINDOWPOS.sizeof);
+       OS.MoveMemory (playout.prc, rect, RECT.sizeof);
+       OS.SendMessage (hwndHeader, OS.HDM_LAYOUT, 0, playout);
+       WINDOWPOS pos = new WINDOWPOS ();
+       OS.MoveMemory (pos, playout.pwpos, WINDOWPOS.sizeof);
+       if (playout.prc != 0) OS.HeapFree (hHeap, 0, playout.prc);
+       if (playout.pwpos != 0) OS.HeapFree (hHeap, 0, playout.pwpos);
+       OS.SetWindowPos (hwndHeader, 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) != 0 ? OS.GetSystemMetrics (OS.SM_CXEDGE) : 0;
+       int w = pos.cx + (columnCount == 0 && width == 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL));
+       int h = rect.bottom - rect.top - pos.cy;
+       boolean oldIgnore = ignoreResize;
+       ignoreResize = true;
+       OS.SetWindowPos (handle, 0, 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 (long hItem, TVITEM tvItem, TreeItem [] selection) {
+       while (hItem != 0) {
+               int index = 0;
+               while (index < selection.length) {
+                       TreeItem item = selection [index];
+                       if (item != null && item.handle == hItem) break;
+                       index++;
+               }
+               tvItem.hItem = hItem;
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+               if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+                       if (index == selection.length) {
+                               tvItem.state = 0;
+                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                       }
+               } else {
+                       if (index != selection.length) {
+                               expandToItem(_getItem(hItem));
+                               tvItem.state = OS.TVIS_SELECTED;
+                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                       }
+               }
+               long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+               setSelection (hFirstItem, tvItem, selection);
+               hItem = 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,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       setSelection (new TreeItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected,
+ * and if necessary the receiver is scrolled to make the new selection visible.
+ * <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_NULL_ARGUMENT - if the array of items is null</li>
+ *    <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 ();
+       if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int length = items.length;
+       if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) {
+               deselectAll();
+               return;
+       }
+
+       /* Select/deselect the first item */
+       TreeItem item = items [0];
+       if (item != null) {
+               if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+               long hOldItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               long 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.
+               */
+               boolean 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) == 0) {
+                       OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hNewItem);
+                       long hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem);
+                       if (hParent == 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 == hNewItem) {
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                       tvItem.state = OS.TVIS_SELECTED;
+                       tvItem.stateMask = OS.TVIS_SELECTED;
+                       tvItem.hItem = hNewItem;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                       showItem (hNewItem);
+               }
+       }
+       if ((style & SWT.SINGLE) != 0) return;
+
+       /* Select/deselect the rest of the items */
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_SELECTED;
+       long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+       if ((style & SWT.VIRTUAL) != 0) {
+               long hItem = 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 != null) {
+                               int index = 0;
+                               while (index < length) {
+                                       if (items [index] == item) break;
+                                       index++;
+                               }
+                               tvItem.hItem = item.handle;
+                               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                               if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+                                       if (index == length) {
+                                               tvItem.state = 0;
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                       }
+                               } else {
+                                       if (index != length) {
+                                               expandToItem(item);
+                                               tvItem.state = OS.TVIS_SELECTED;
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                       }
+                               }
+                       }
+               }
+       }
+       OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+}
+
+void expandToItem(TreeItem item) {
+       TreeItem parentItem = item.getParentItem();
+       if (parentItem != null && !parentItem.getExpanded()) {
+               expandToItem(parentItem);
+               parentItem.setExpanded(true);
+               Event event = new Event ();
+               event.item = parentItem;
+               sendEvent (SWT.Expand, event);
+       }
+}
+
+/**
+ * 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 != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       if (sortColumn != null && !sortColumn.isDisposed ()) {
+               sortColumn.setSortDirection (SWT.NONE);
+       }
+       sortColumn = column;
+       if (sortColumn != null && sortDirection != 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)) == 0 && direction != SWT.NONE) return;
+       sortDirection = direction;
+       if (sortColumn != 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       long hItem = item.handle;
+       long hTopItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+       if (hItem == hTopItem) return;
+       boolean 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 = getDrawing () && OS.IsWindowVisible (handle);
+               if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+       }
+       SCROLLINFO hInfo = null;
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       long hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+       if (hParent != 0 && (bits & (OS.TVS_NOHSCROLL | OS.TVS_NOSCROLL)) == 0) {
+               hInfo = new SCROLLINFO ();
+               hInfo.cbSize = SCROLLINFO.sizeof;
+               hInfo.fMask = OS.SIF_ALL;
+               OS.GetScrollInfo (handle, OS.SB_HORZ, hInfo);
+       }
+       OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hItem);
+       if (hParent != 0) {
+               if (hInfo != null) {
+                       long hThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, hInfo.nPos);
+                       OS.SendMessage (handle, OS.WM_HSCROLL, hThumb, 0);
+               }
+       } else {
+               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 (long 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) == 0) {
+               boolean 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 == 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 {
+               boolean scroll = true;
+               RECT itemRect = new RECT ();
+               if (OS.TreeView_GetItemRect (handle, hItem, itemRect, true)) {
+                       forceResize ();
+                       RECT rect = new RECT ();
+                       OS.GetClientRect (handle, rect);
+                       POINT pt = new POINT ();
+                       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) {
+                       boolean 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 != 0) {
+               RECT itemRect = new RECT ();
+               if (OS.TreeView_GetItemRect (handle, hItem, itemRect, true)) {
+                       forceResize ();
+                       RECT rect = new RECT ();
+                       OS.GetClientRect (hwndParent, rect);
+                       OS.MapWindowPoints (hwndParent, handle, rect, 2);
+                       POINT pt = new POINT ();
+                       pt.x = itemRect.left;
+                       pt.y = itemRect.top;
+                       if (!OS.PtInRect (rect, pt)) {
+                               pt.y = itemRect.bottom;
+                               if (!OS.PtInRect (rect, pt)) {
+                                       SCROLLINFO info = new SCROLLINFO ();
+                                       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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (column.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+       if (column.parent != this) return;
+       int index = indexOf (column);
+       if (index == -1) return;
+       if (0 <= index && index < columnCount) {
+               forceResize ();
+               RECT rect = new RECT ();
+               OS.GetClientRect (hwndParent, rect);
+               OS.MapWindowPoints (hwndParent, handle, rect, 2);
+               RECT headerRect = new RECT ();
+               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+               boolean 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 = new SCROLLINFO ();
+                       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 == 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 ();
+       long hItem = 0;
+       if ((style & SWT.SINGLE) != 0) {
+               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (hItem == 0) return;
+               int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+               if ((state & OS.TVIS_SELECTED) == 0) return;
+       } else {
+               long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+               if ((style & SWT.VIRTUAL) != 0) {
+                       long hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+                       hItem = getNextSelection (hRoot);
+               } else {
+                       //FIXME - this code expands first selected item it finds
+                       int index = 0;
+                       while (index <items.length) {
+                               TreeItem item = items [index];
+                               if (item != null) {
+                                       int state = (int)OS.SendMessage (handle, OS.TVM_GETITEMSTATE, item.handle, OS.TVIS_SELECTED);
+                                       if ((state & OS.TVIS_SELECTED) != 0) {
+                                               hItem = item.handle;
+                                               break;
+                                       }
+                               }
+                               index++;
+                       }
+               }
+               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+       }
+       if (hItem != 0) showItem (hItem);
+}
+
+/*public*/ void sort () {
+       checkWidget ();
+       if ((style & SWT.VIRTUAL) != 0) return;
+       sort (OS.TVI_ROOT, false);
+}
+
+void sort (long hParent, boolean all) {
+       int itemCount = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+       if (itemCount == 0 || itemCount == 1) return;
+       hFirstIndexOf = hLastIndexOf = 0;
+       itemCount = -1;
+       if (sortDirection == SWT.UP || sortDirection == SWT.NONE) {
+               OS.SendMessage (handle, OS.TVM_SORTCHILDREN, all ? 1 : 0, hParent);
+       } else {
+               Callback compareCallback = new Callback (this, "CompareFunc", 3);
+               long lpfnCompare = compareCallback.getAddress ();
+               TVSORTCB psort = new TVSORTCB ();
+               psort.hParent = hParent;
+               psort.lpfnCompare = lpfnCompare;
+               psort.lParam = sortColumn == null ? 0 : indexOf (sortColumn);
+               OS.SendMessage (handle, OS.TVM_SORTCHILDRENCB, all ? 1 : 0, psort);
+               compareCallback.dispose ();
+       }
+}
+
+@Override
+void subclass () {
+       super.subclass ();
+       if (hwndHeader != 0) {
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc);
+       }
+}
+
+RECT toolTipInset (RECT rect) {
+       RECT insetRect = new RECT ();
+       OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+       return insetRect;
+}
+
+RECT toolTipRect (RECT rect) {
+       RECT toolRect = new RECT ();
+       OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+       return toolRect;
+}
+
+@Override
+String toolTipText (NMTTDISPINFO hdr) {
+       long hwndToolTip = OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0);
+       if (hwndToolTip == hdr.hwndFrom && toolTipText != null) return ""; //$NON-NLS-1$
+       if (headerToolTipHandle == hdr.hwndFrom) {
+               for (int i=0; i<columnCount; i++) {
+                       TreeColumn column = columns [i];
+                       if (column.id == hdr.idFrom) return column.toolTipText;
+               }
+               return super.toolTipText (hdr);
+       }
+       if (itemToolTipHandle == hdr.hwndFrom) {
+               if (toolTipText != null) return "";
+               int pos = OS.GetMessagePos ();
+               POINT pt = new POINT();
+               OS.POINTSTOPOINT (pt, pos);
+               OS.ScreenToClient (handle, pt);
+               int [] index = new int [1];
+               TreeItem [] item = new TreeItem [1];
+               RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
+               if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                       String text = null;
+                       if (index [0] == 0) {
+                               text = item [0].text;
+                       } else {
+                               String[] strings = item [0].strings;
+                               if (strings != null) text = strings [index [0]];
+                       }
+                       //TEMPORARY CODE
+                       if (isCustomToolTip ()) text = " ";
+                       if (text != null) return text;
+               }
+       }
+       return super.toolTipText (hdr);
+}
+
+@Override
+long topHandle () {
+       return hwndParent != 0 ? hwndParent : handle;
+}
+
+void updateFullSelection () {
+       if ((style & SWT.FULL_SELECTION) != 0) {
+               int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+               if ((newBits & OS.TVS_FULLROWSELECT) != 0) {
+                       if (!OS.IsWindowEnabled (handle) || findImageControl () != null) {
+                               if (!explorerTheme) newBits &= ~OS.TVS_FULLROWSELECT;
+                       }
+               } else {
+                       if (OS.IsWindowEnabled (handle) && findImageControl () == null) {
+                               if (!hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                                       newBits |= OS.TVS_FULLROWSELECT;
+                               }
+                       }
+               }
+               if (newBits != oldBits) {
+                       OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+                       OS.InvalidateRect (handle, null, true);
+               }
+       }
+}
+
+void updateHeaderToolTips () {
+       if (headerToolTipHandle == 0) return;
+       RECT rect = new RECT ();
+       TOOLINFO lpti = new TOOLINFO ();
+       lpti.cbSize = 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) != 0) {
+                       lpti.uId = column.id = display.nextToolTipId++;
+                       lpti.left = rect.left;
+                       lpti.top = rect.top;
+                       lpti.right = rect.right;
+                       lpti.bottom = rect.bottom;
+                       OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
+               }
+       }
+}
+
+void updateImageList () {
+       if (imageList == null) return;
+       if (hwndHeader == 0) return;
+       int i = 0, index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+       while (i < items.length) {
+               TreeItem item = items [i];
+               if (item != null) {
+                       Image image = null;
+                       if (index == 0) {
+                               image = item.image;
+                       } else {
+                               Image [] images = item.images;
+                               if (images != null) image = images [index];
+                       }
+                       if (image != 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.
+       */
+       long hImageList = i == items.length ? 0 : imageList.getHandle ();
+       long hOldImageList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+       if (hImageList != hOldImageList) {
+               OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
+       }
+}
+
+@Override
+void updateMenuLocation (Event event) {
+       Rectangle clientArea = getClientAreaInPixels ();
+       int x = clientArea.x, y = clientArea.y;
+       TreeItem focusItem = getFocusItem ();
+       if (focusItem != null) {
+               Rectangle bounds = focusItem.getBoundsInPixels (0);
+               if (focusItem.text != null && focusItem.text.length () != 0) {
+                       bounds = focusItem.getBoundsInPixels ();
+               }
+               x = Math.max (x, bounds.x + bounds.width / 2);
+               x = Math.min (x, clientArea.x + clientArea.width);
+               y = Math.max (y, bounds.y + bounds.height);
+               y = Math.min (y, clientArea.y + clientArea.height);
+       }
+       Point pt = toDisplayInPixels (x, y);
+       event.setLocationInPixels(pt.x, pt.y);
+}
+
+@Override
+void updateOrientation () {
+       super.updateOrientation ();
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       int width = rect.right - rect.left, height = rect.bottom - rect.top;
+       OS.SetWindowPos (handle, 0, 0, 0, width - 1, height - 1, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       OS.SetWindowPos (handle, 0, 0, 0, width, height, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       if (hwndParent != 0) {
+               int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+               if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                       bits |= OS.WS_EX_LAYOUTRTL;
+               } else {
+                       bits &= ~OS.WS_EX_LAYOUTRTL;
+               }
+               bits &= ~OS.WS_EX_RTLREADING;
+               OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
+               rect = new RECT ();
+               OS.GetWindowRect (hwndParent, rect);
+               width = rect.right - rect.left; height = rect.bottom - rect.top;
+               OS.SetWindowPos (hwndParent, 0, 0, 0, width - 1, height - 1, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+               OS.SetWindowPos (hwndParent, 0, 0, 0, width, height, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
+       }
+       if (hwndHeader != 0) {
+               int bits = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE);
+               if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+                       bits |= OS.WS_EX_LAYOUTRTL;
+               } else {
+                       bits &= ~OS.WS_EX_LAYOUTRTL;
+               }
+               OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits);
+               OS.InvalidateRect (hwndHeader, null, true);
+       }
+       if ((style & SWT.CHECK) != 0) setCheckboxImageList ();
+       if (imageList != null) {
+               Point size = imageList.getImageSize ();
+               display.releaseImageList (imageList);
+               imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+               for (int i = 0; i < items.length; i++) {
+                       TreeItem item = items[i];
+                       if (item != null) {
+                               Image image = item.image;
+                               if (image != null) {
+                                       int index = imageList.indexOf (image);
+                                       if (index == -1) imageList.add (image);
+                               }
+                       }
+               }
+               long hImageList = imageList.getHandle ();
+               OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
+       }
+       if (hwndHeader != 0) {
+               if (headerImageList != null) {
+                       Point size = headerImageList.getImageSize ();
+                       display.releaseImageList (headerImageList);
+                       headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, size.x, size.y);
+                       if (columns != null) {
+                               for (int i = 0; i < columns.length; i++) {
+                                       TreeColumn column = columns[i];
+                                       if (column != null) {
+                                               Image image = column.image;
+                                               if (image != null) {
+                                                       HDITEM hdItem = new HDITEM ();
+                                                       hdItem.mask = OS.HDI_FORMAT;
+                                                       OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, hdItem);
+                                                       if ((hdItem.fmt & OS.HDF_IMAGE)!= 0) {
+                                                               int index = headerImageList.indexOf (image);
+                                                               if (index == -1) index = headerImageList.add (image);
+                                                               hdItem.mask = OS.HDI_IMAGE;
+                                                               hdItem.iImage = index;
+                                                               OS.SendMessage (hwndHeader, OS.HDM_SETITEM, i, hdItem);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       long hImageListHeader = headerImageList.getHandle ();
+                       OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageListHeader);
+               }
+       }
+}
+
+/**
+ * Copies Tree's scrollbar state to intermediate parent.
+ *
+ * If Tree has a header, then (Tree+header) get wrapped into intermediate
+ * parent. This parent also has scrollbar, and it is configured to
+ * obscure the Tree's scrollbar - I think this is due to aesthetic
+ * reasons where the new scrollbar also extends over header. Since it
+ * obscures the true scrollbar, it always needs to be in sync with the
+ * true scrollbar.
+ */
+void updateScrollBar () {
+       if (hwndParent != 0) {
+               if (columnCount != 0 || scrollWidth != 0) {
+                       SCROLLINFO info = new SCROLLINFO ();
+                       info.cbSize = SCROLLINFO.sizeof;
+                       info.fMask = OS.SIF_ALL;
+                       int itemCount = (int)OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+                       if (itemCount == 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 (info.nPage == 0) {
+                                       SCROLLBARINFO psbi = new SCROLLBARINFO ();
+                                       psbi.cbSize = SCROLLBARINFO.sizeof;
+                                       OS.GetScrollBarInfo (handle, OS.OBJID_VSCROLL, psbi);
+                                       if ((psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) != 0) {
+                                               info.nPage = info.nMax + 1;
+                                       }
+                               }
+                               OS.SetScrollInfo (hwndParent, OS.SB_VERT, info, true);
+                       }
+               }
+       }
+}
+
+@Override
+void unsubclass () {
+       super.unsubclass ();
+       if (hwndHeader != 0) {
+               OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, HeaderProc);
+       }
+}
+
+@Override
+int widgetStyle () {
+       int bits = super.widgetStyle () | OS.TVS_SHOWSELALWAYS | OS.TVS_LINESATROOT | OS.TVS_HASBUTTONS | OS.TVS_NONEVENHEIGHT;
+       if (OS.IsAppThemed ()) {
+               bits |= OS.TVS_TRACKSELECT;
+               if ((style & SWT.FULL_SELECTION) != 0) bits |= OS.TVS_FULLROWSELECT;
+       } else {
+               if ((style & SWT.FULL_SELECTION) != 0) {
+                       bits |= OS.TVS_FULLROWSELECT;
+               } else {
+                       bits |= OS.TVS_HASLINES;
+               }
+       }
+       if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
+               bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+               bits |= OS.TVS_NOSCROLL;
+       } else {
+               if ((style & SWT.H_SCROLL) == 0) {
+                       bits &= ~OS.WS_HSCROLL;
+                       bits |= OS.TVS_NOHSCROLL;
+               }
+       }
+//     bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP;
+       return bits | OS.TVS_DISABLEDRAGDROP;
+}
+
+@Override
+TCHAR windowClass () {
+       return TreeClass;
+}
+
+@Override
+long windowProc () {
+       return TreeProc;
+}
+
+@Override
+long windowProc (long hwnd, int msg, long wParam, long lParam) {
+       if (hwndHeader != 0 && hwnd == hwndHeader) {
+               switch (msg) {
+                       case OS.WM_CONTEXTMENU: {
+                               LRESULT result = wmContextMenu (hwnd, wParam, lParam);
+                               if (result != null) return result.value;
+                               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.
+                               */
+                               updateHeaderToolTips ();
+                               updateHeaderToolTips ();
+                               break;
+                       }
+                       case OS.WM_NOTIFY: {
+                               NMHDR hdr = new NMHDR ();
+                               OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+                               switch (hdr.code) {
+                                       case OS.TTN_SHOW:
+                                       case OS.TTN_POP:
+                                       case OS.TTN_GETDISPINFO:
+                                               return OS.SendMessage (handle, msg, wParam, lParam);
+                               }
+                               break;
+                       }
+                       case OS.WM_SETCURSOR: {
+                               if (wParam == hwnd) {
+                                       int hitTest = (short) OS.LOWORD (lParam);
+                                       if (hitTest == OS.HTCLIENT) {
+                                               HDHITTESTINFO pinfo = new HDHITTESTINFO ();
+                                               int pos = OS.GetMessagePos ();
+                                               POINT pt = new POINT ();
+                                               OS.POINTSTOPOINT (pt, pos);
+                                               OS.ScreenToClient (hwnd, pt);
+                                               pinfo.x = pt.x;
+                                               pinfo.y = pt.y;
+                                               int index = (int)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)) != 0) {
+                                                               OS.SetCursor (OS.LoadCursor (0, OS.IDC_ARROW));
+                                                               return 1;
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+                       }
+               }
+               return callWindowProc (hwnd, msg, wParam, lParam);
+       }
+       if (hwndParent != 0 && hwnd == hwndParent) {
+               switch (msg) {
+                       case OS.WM_MOVE: {
+                               sendEvent (SWT.Move);
+                               return 0;
+                       }
+                       case OS.WM_SIZE: {
+                               setScrollWidth ();
+                               if (ignoreResize) return 0;
+                               setResizeChildren (false);
+                               long code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
+                               sendEvent (SWT.Resize);
+                               if (isDisposed ()) return 0;
+                               if (layout != null) {
+                                       markLayout (false, false);
+                                       updateLayout (false, false);
+                               }
+                               setResizeChildren (true);
+                               updateScrollBar ();
+                               return code;
+                       }
+                       case OS.WM_NCPAINT: {
+                               LRESULT result = wmNCPaint (hwnd, wParam, lParam);
+                               if (result != null) return result.value;
+                               break;
+                       }
+                       case OS.WM_PRINT: {
+                               LRESULT result = wmPrint (hwnd, wParam, lParam);
+                               if (result != 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 != null && (lParam == 0 || lParam == hwndParent)) {
+                                       wmScroll (horizontalBar, true, hwndParent, OS.WM_HSCROLL, wParam, lParam);
+                               }
+                               setScrollWidth ();
+                               break;
+                       }
+                       case OS.WM_VSCROLL: {
+                               SCROLLINFO info = new SCROLLINFO ();
+                               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.LOWORD (wParam) == OS.SB_THUMBTRACK) {
+                                       info.nPos = info.nTrackPos;
+                               }
+                               OS.SetScrollInfo (handle, OS.SB_VERT, info, true);
+                               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;
+                       }
+               }
+               return callWindowProc (hwnd, msg, wParam, lParam);
+       }
+       if (msg == 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) != 0 || hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                       TreeItem [] items = new TreeItem [10];
+                       TVITEM tvItem = new TVITEM ();
+                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+                       int count = getSelection (hItem, tvItem, items, 0, 10, false, true);
+                       if (count == 0) return 0;
+                       POINT mousePos = new POINT ();
+                       OS.POINTSTOPOINT (mousePos, OS.GetMessagePos ());
+                       OS.MapWindowPoints (0, handle, mousePos, 1);
+                       RECT clientRect = new RECT ();
+                       OS.GetClientRect(handle, clientRect);
+                       RECT rect = items [0].getBounds (0, true, true, false);
+                       if ((style & SWT.FULL_SELECTION) != 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);
+                               }
+                       } else {
+                               rect.left = Math.max (rect.left, clientRect.left);
+                               rect.right = Math.min (rect.right, clientRect.right);
+                       }
+                       long 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) != 0) {
+                                       itemRect.left = rect.left;
+                                       itemRect.right = rect.right;
+                               } else {
+                                       itemRect.left = Math.max (itemRect.left, clientRect.left);
+                                       itemRect.right = Math.min (itemRect.right, clientRect.right);
+                               }
+                               long 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 */
+                       long hdc = OS.GetDC (handle);
+                       long memHdc = OS.CreateCompatibleDC (hdc);
+                       BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
+                       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, bmiHeader, BITMAPINFOHEADER.sizeof);
+                       long [] pBits = new long [1];
+                       long memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+                       if (memDib == 0) error (SWT.ERROR_NO_HANDLES);
+                       long oldMemBitmap = OS.SelectObject (memHdc, memDib);
+                       int colorKey = 0x0000FD;
+                       POINT pt = new POINT ();
+                       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 (0, hdc);
+                       OS.DeleteObject (hRgn);
+
+                       SHDRAGIMAGE shdi = new SHDRAGIMAGE ();
+                       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) != 0) {
+                               shdi.ptOffset.x = shdi.sizeDragImage.cx - shdi.ptOffset.x;
+                       }
+                       OS.MoveMemory (lParam, shdi, SHDRAGIMAGE.sizeof);
+                       return 1;
+               }
+       }
+       return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+@Override
+LRESULT WM_CHAR (long wParam, long lParam) {
+       LRESULT result = super.WM_CHAR (wParam, lParam);
+       if (result != 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 ((int)wParam) {
+               case ' ': {
+                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                       if (hItem != 0) {
+                               hAnchor = hItem;
+                               OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem);
+                               TVITEM tvItem = new TVITEM ();
+                               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE | OS.TVIF_PARAM;
+                               tvItem.hItem = hItem;
+                               if ((style & SWT.CHECK) != 0) {
+                                       tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+                                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                       int state = tvItem.state >> 12;
+                                       if ((state & 0x1) != 0) {
+                                               state++;
+                                       } else  {
+                                               --state;
+                                       }
+                                       tvItem.state = state << 12;
+                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                       long id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, hItem, 0);
+                                       OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, (int)id);
+                               }
+                               tvItem.stateMask = OS.TVIS_SELECTED;
+                               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                               if ((style & SWT.MULTI) != 0 && OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                                       if ((tvItem.state & OS.TVIS_SELECTED) != 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, (int)tvItem.lParam);
+                               Event event = new Event ();
+                               event.item = item;
+                               sendSelectionEvent (SWT.Selection, event, false);
+                               if ((style & SWT.CHECK) != 0) {
+                                       event = new Event ();
+                                       event.item = item;
+                                       event.detail = SWT.CHECK;
+                                       sendSelectionEvent (SWT.Selection, event, false);
+                               }
+                       }
+                       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 ();
+                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                       if (hItem != 0) event.item = _getItem (hItem);
+                       sendSelectionEvent (SWT.DefaultSelection, event, false);
+                       return LRESULT.ZERO;
+               }
+               case SWT.ESC:
+                       return LRESULT.ZERO;
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if ((style & SWT.DOUBLE_BUFFERED) != 0) return LRESULT.ONE;
+       if (findImageControl () != null) return LRESULT.ONE;
+       return result;
+}
+
+@Override
+LRESULT WM_GETOBJECT (long wParam, long 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) != 0 || hwndParent != 0) {
+               if (accessible == null) accessible = new_Accessible (this);
+       }
+       return super.WM_GETOBJECT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_HSCROLL (long wParam, long lParam) {
+       boolean fixScroll = false;
+       if ((style & SWT.DOUBLE_BUFFERED) != 0) {
+               fixScroll = (style & SWT.VIRTUAL) != 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 != null) return result;
+       return result;
+}
+
+@Override
+LRESULT WM_KEYDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+       if (result != null) return result;
+       switch ((int)wParam) {
+               case OS.VK_LEFT:
+               case OS.VK_RIGHT:
+                       /*
+                       * Bug in Windows. The behavior for the left and right keys is not
+                       * changed if the orientation changes after the control was created.
+                       * The fix is to replace VK_LEFT by VK_RIGHT and VK_RIGHT by VK_LEFT
+                       * when the current orientation differs from the orientation used to
+                       * create the control.
+                       */
+                       boolean isRTL = (style & SWT.RIGHT_TO_LEFT) != 0;
+                       if (isRTL != createdAsRTL) {
+                               long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam == OS.VK_RIGHT ? OS.VK_LEFT : OS.VK_RIGHT, lParam);
+                               return new LRESULT (code);
+                       }
+                       break;
+               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 != 0) {
+                                       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 (itemToolTipHandle != 0) OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+                       if ((style & SWT.SINGLE) != 0) break;
+                       if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
+                               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                               if (hItem != 0) {
+                                       if (hAnchor == 0) hAnchor = hItem;
+                                       ignoreSelect = ignoreDeselect = true;
+                                       long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                                       ignoreSelect = ignoreDeselect = false;
+                                       long hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                                       TVITEM tvItem = new TVITEM ();
+                                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                                       tvItem.stateMask = OS.TVIS_SELECTED;
+                                       long hDeselectItem = hItem;
+                                       RECT rect1 = new RECT ();
+                                       if (!OS.TreeView_GetItemRect (handle, hAnchor, rect1, false)) {
+                                               hAnchor = hItem;
+                                               OS.TreeView_GetItemRect (handle, hAnchor, rect1, false);
+                                       }
+                                       RECT rect2 = new RECT ();
+                                       OS.TreeView_GetItemRect (handle, hDeselectItem, rect2, false);
+                                       int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
+                                       while (hDeselectItem != hAnchor) {
+                                               tvItem.hItem = hDeselectItem;
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                               hDeselectItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem);
+                                       }
+                                       long hSelectItem = hAnchor;
+                                       OS.TreeView_GetItemRect (handle, hNewItem, rect1, false);
+                                       OS.TreeView_GetItemRect (handle, hSelectItem, rect2, false);
+                                       tvItem.state = OS.TVIS_SELECTED;
+                                       flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
+                                       while (hSelectItem != hNewItem) {
+                                               tvItem.hItem = hSelectItem;
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                               hSelectItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hSelectItem);
+                                       }
+                                       tvItem.hItem = hNewItem;
+                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+                                       tvItem.hItem = hNewItem;
+                                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                       Event event = new Event ();
+                                       event.item = _getItem (hNewItem, (int)tvItem.lParam);
+                                       sendSelectionEvent (SWT.Selection, event, false);
+                                       return new LRESULT (code);
+                               }
+                       }
+                       if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                               long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                               if (hItem != 0) {
+                                       TVITEM tvItem = new TVITEM ();
+                                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                                       tvItem.stateMask = OS.TVIS_SELECTED;
+                                       tvItem.hItem = hItem;
+                                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                       boolean oldSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+                                       long hNewItem = 0;
+                                       switch ((int)wParam) {
+                                               case OS.VK_UP:
+                                                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUSVISIBLE, hItem);
+                                                       break;
+                                               case OS.VK_DOWN:
+                                                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                                                       break;
+                                               case OS.VK_HOME:
+                                                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+                                                       break;
+                                               case OS.VK_PRIOR:
+                                                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                                                       if (hNewItem == hItem) {
+                                                               OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEUP, 0);
+                                                               hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                                                       }
+                                                       break;
+                                               case OS.VK_NEXT:
+                                                       RECT rect = new RECT (), clientRect = new RECT ();
+                                                       OS.GetClientRect (handle, clientRect);
+                                                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                                                       do {
+                                                               long hVisible = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem);
+                                                               if (hVisible == 0) break;
+                                                               if (!OS.TreeView_GetItemRect (handle, hVisible, rect, false)) break;
+                                                               if (rect.bottom > clientRect.bottom) break;
+                                                               if ((hNewItem = hVisible) == hItem) {
+                                                                       OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0);
+                                                               }
+                                                       } while (hNewItem != 0);
+                                                       break;
+                                               case OS.VK_END:
+                                                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+                                                       break;
+                                       }
+                                       if (hNewItem != 0) {
+                                               OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hNewItem);
+                                               tvItem.hItem = hNewItem;
+                                               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                               boolean newSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+                                               boolean redraw = !newSelected && getDrawing () && 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 = 0;
+                                               if (oldSelected) {
+                                                       tvItem.state = OS.TVIS_SELECTED;
+                                                       tvItem.hItem = hItem;
+                                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                               }
+                                               if (!newSelected) {
+                                                       tvItem.state = 0;
+                                                       tvItem.hItem = hNewItem;
+                                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                               }
+                                               if (redraw) {
+                                                       RECT rect1 = new RECT (), rect2 = new RECT ();
+                                                       OS.TreeView_GetItemRect (handle, hItem, rect1, false);
+                                                       OS.TreeView_GetItemRect (handle, hNewItem, rect2, false);
+                                                       OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                                                       OS.InvalidateRect (handle, rect1, true);
+                                                       OS.InvalidateRect (handle, rect2, true);
+                                                       OS.UpdateWindow (handle);
+                                               }
+                                               return LRESULT.ZERO;
+                                       }
+                               }
+                       }
+                       long code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                       hAnchor = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                       return new LRESULT (code);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_KILLFOCUS (long wParam, long 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.
+       */
+       boolean redraw = (style & SWT.MULTI) != 0;
+       if (!redraw && imageList != null) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.TVS_FULLROWSELECT) == 0) {
+                       redraw = true;
+               }
+       }
+       if (redraw) redrawSelection ();
+       return super.WM_KILLFOCUS (wParam, lParam);
+}
+
+@Override
+LRESULT WM_LBUTTONDBLCLK (long wParam, long lParam) {
+       TVHITTESTINFO lpht = new TVHITTESTINFO ();
+       lpht.x = OS.GET_X_LPARAM (lParam);
+       lpht.y = OS.GET_Y_LPARAM (lParam);
+       OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+       if (lpht.hItem != 0) {
+               if ((style & SWT.CHECK) != 0) {
+                       if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) != 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 () != handle) OS.SetCapture (handle);
+                                       }
+                                       return LRESULT.ZERO;
+                               }
+                               if (!display.captureChanged && !isDisposed ()) {
+                                       if (OS.GetCapture () != handle) OS.SetCapture (handle);
+                               }
+                               OS.SetFocus (handle);
+                               TVITEM tvItem = new 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) != 0) {
+                                       state++;
+                               } else  {
+                                       --state;
+                               }
+                               tvItem.state = state << 12;
+                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                               long id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0);
+                               OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, (int)id);
+                               Event event = new Event ();
+                               event.item = _getItem (tvItem.hItem, (int)tvItem.lParam);
+                               event.detail = SWT.CHECK;
+                               sendSelectionEvent (SWT.Selection, event, false);
+                               return LRESULT.ZERO;
+                       }
+               }
+       }
+       LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+       if (lpht.hItem != 0) {
+               int flags = OS.TVHT_ONITEM;
+               if ((style & SWT.FULL_SELECTION) != 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.x, lpht.y)) {
+                                       lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                               }
+                       }
+               }
+               if ((lpht.flags & flags) != 0) {
+                       Event event = new Event ();
+                       event.item = _getItem (lpht.hItem);
+                       sendSelectionEvent (SWT.DefaultSelection, event, false);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long 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 = new TVHITTESTINFO ();
+       lpht.x = OS.GET_X_LPARAM (lParam);
+       lpht.y = OS.GET_Y_LPARAM (lParam);
+       OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+       if (lpht.hItem == 0 || (lpht.flags & OS.TVHT_ONITEMBUTTON) != 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 () != handle) OS.SetCapture (handle);
+                       }
+                       return LRESULT.ZERO;
+               }
+               boolean fixSelection = false, deselected = false;
+               long hOldSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (lpht.hItem != 0 && (style & SWT.MULTI) != 0) {
+                       if (hOldSelection != 0) {
+                               TVITEM tvItem = new 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) != 0) {
+                                       fixSelection = true;
+                                       tvItem.stateMask = OS.TVIS_SELECTED;
+                                       long hNext = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem);
+                                       while (hNext != 0) {
+                                               if (hNext == hAnchor) hAnchor = 0;
+                                               tvItem.hItem = hNext;
+                                               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                               if ((tvItem.state & OS.TVIS_SELECTED) != 0) deselected = true;
+                                               tvItem.state = 0;
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                               long hItem = hNext = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNext);
+                                               while (hItem != 0 && hItem != lpht.hItem) {
+                                                       hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+                                               }
+                                               if (hItem == 0) break;
+                                       }
+                               }
+                       }
+               }
+               dragStarted = gestureCompleted = false;
+               if (fixSelection) {
+                       hSelect = lpht.hItem;
+                       ignoreDeselect = ignoreSelect = lockSelection = true;
+               }
+               long code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+               /* Bug 225404 */
+               if (OS.GetFocus () != handle) OS.SetFocus (handle);
+               if (fixSelection) {
+                       hSelect = 0;
+                       ignoreDeselect = ignoreSelect = lockSelection = false;
+               }
+               long hNewSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               if (hOldSelection != hNewSelection) hAnchor = hNewSelection;
+               if (dragStarted) {
+                       if (!display.captureChanged && !isDisposed ()) {
+                               if (OS.GetCapture () != 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) != 0) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.TVS_FULLROWSELECT) == 0) {
+                               if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) == 0) {
+                                       long hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                                       if (hItem != 0) {
+                                               RECT rect = new RECT ();
+                                               if (OS.TreeView_GetItemRect (handle, hItem, rect, false)) {
+                                                       OS.InvalidateRect (handle, rect, true);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               if (deselected) {
+                       Event event = new Event ();
+                       event.item = _getItem (lpht.hItem);
+                       sendSelectionEvent (SWT.Selection, event, false);
+               }
+               return new LRESULT (code);
+       }
+
+       /* Look for check/uncheck */
+       if ((style & SWT.CHECK) != 0) {
+               if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) != 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 () != handle) OS.SetCapture (handle);
+                               }
+                               return LRESULT.ZERO;
+                       }
+                       if (!display.captureChanged && !isDisposed ()) {
+                               if (OS.GetCapture () != handle) OS.SetCapture (handle);
+                       }
+                       OS.SetFocus (handle);
+                       TVITEM tvItem = new 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) != 0) {
+                               state++;
+                       } else  {
+                               --state;
+                       }
+                       tvItem.state = state << 12;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                       long id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0);
+                       OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, (int)id);
+                       Event event = new Event ();
+                       event.item = _getItem (tvItem.hItem, (int)tvItem.lParam);
+                       event.detail = SWT.CHECK;
+                       sendSelectionEvent (SWT.Selection, event, false);
+                       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.
+       */
+       boolean selected = false;
+       boolean fakeSelection = false;
+       if (lpht.hItem != 0) {
+               if ((style & SWT.FULL_SELECTION) != 0) {
+                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                       if ((bits & OS.TVS_FULLROWSELECT) == 0) fakeSelection = true;
+               } else {
+                       if (hooks (SWT.MeasureItem)) {
+                               selected = hitTestSelection (lpht.hItem, lpht.x, lpht.y);
+                               if (selected) {
+                                       if ((lpht.flags & OS.TVHT_ONITEM) == 0) fakeSelection = true;
+                               }
+                       }
+               }
+       }
+
+       /* Process the mouse when an item is not selected */
+       if (!selected && (style & SWT.FULL_SELECTION) == 0) {
+               if ((lpht.flags & OS.TVHT_ONITEM) == 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 () != handle) OS.SetCapture (handle);
+                               }
+                               return LRESULT.ZERO;
+                       }
+                       long code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+                       /* Bug 225404 */
+                       if (OS.GetFocus () != handle) OS.SetFocus (handle);
+                       if (!display.captureChanged && !isDisposed ()) {
+                               if (OS.GetCapture () != handle) OS.SetCapture (handle);
+                       }
+                       return new LRESULT (code);
+               }
+       }
+
+       /* Get the selected state of the item under the mouse */
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_SELECTED;
+       boolean hittestSelected = false;
+       if ((style & SWT.MULTI) != 0) {
+               tvItem.hItem = lpht.hItem;
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+               hittestSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+       }
+
+       /* Get the selected state of the last selected item */
+       long hOldItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+       if ((style & SWT.MULTI) != 0) {
+               tvItem.hItem = hOldItem;
+               OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+
+               /* Check for CONTROL or drag selection */
+               if (hittestSelected || (wParam & OS.MK_CONTROL) != 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 = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                       if ((uiState & OS.UISF_HIDEFOCUS) != 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 () != handle) OS.SetCapture (handle);
+               }
+               return LRESULT.ZERO;
+       }
+       hSelect = lpht.hItem;
+       dragStarted = gestureCompleted = false;
+       ignoreDeselect = ignoreSelect = true;
+       long code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+       /* Bug 225404 */
+       if (OS.GetFocus () != handle) OS.SetFocus (handle);
+       long hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+       if (fakeSelection) {
+               if (hOldItem == 0 || (hNewItem == hOldItem && lpht.hItem != hOldItem)) {
+                       OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
+                       hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+               }
+               if (!dragStarted && (state & DRAG_DETECT) != 0 && hooks (SWT.DragDetect)) {
+                       dragStarted = dragDetect (handle, lpht.x, lpht.y, false, null, null);
+               }
+       }
+       ignoreDeselect = ignoreSelect = false;
+       hSelect = 0;
+       if (dragStarted) {
+               if (!display.captureChanged && !isDisposed ()) {
+                       if (OS.GetCapture () != 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) != 0) {
+               if (hOldItem == hNewItem) {
+                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                       tvItem.state = OS.TVIS_SELECTED;
+                       tvItem.stateMask = OS.TVIS_SELECTED;
+                       tvItem.hItem = hNewItem;
+                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+               }
+       }
+
+       /* Reselect the last item that was unselected */
+       if ((style & SWT.MULTI) != 0) {
+
+               /* Check for CONTROL and reselect the last item */
+               if (hittestSelected || (wParam & OS.MK_CONTROL) != 0) {
+                       if (hOldItem == hNewItem && hOldItem == lpht.hItem) {
+                               if ((wParam & OS.MK_CONTROL) != 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) != 0) {
+                                       tvItem.state = OS.TVIS_SELECTED;
+                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                               }
+                               if ((wParam & OS.MK_CONTROL) != 0 && !dragStarted) {
+                                       if (hittestSelected) {
+                                               tvItem.state = 0;
+                                               tvItem.hItem = lpht.hItem;
+                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                       }
+                               }
+                       }
+                       RECT rect1 = new RECT (), rect2 = new RECT ();
+                       OS.TreeView_GetItemRect (handle, hOldItem, rect1, false);
+                       OS.TreeView_GetItemRect (handle, hNewItem, rect2, false);
+                       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) == 0) {
+                       if (!hittestSelected || !dragStarted) {
+                               tvItem.state = 0;
+                               long oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+                               OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, TreeProc);
+                               if ((style & SWT.VIRTUAL) != 0) {
+                                       long hItem = 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 != null && item.handle != hNewItem) {
+                                                       tvItem.hItem = item.handle;
+                                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                               }
+                                       }
+                               }
+                               tvItem.hItem = 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) != 0) {
+                                       RECT rect1 = new RECT ();
+                                       if (hAnchor == 0) hAnchor = hNewItem;
+                                       if (OS.TreeView_GetItemRect (handle, hAnchor, rect1, false)) {
+                                               RECT rect2 = new RECT ();
+                                               if (OS.TreeView_GetItemRect (handle, hNewItem, rect2, false)) {
+                                                       int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
+                                                       tvItem.state = OS.TVIS_SELECTED;
+                                                       long hItem = tvItem.hItem = hAnchor;
+                                                       OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                                       while (hItem != hNewItem) {
+                                                               tvItem.hItem = hItem;
+                                                               OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+                                                               hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       if ((wParam & OS.MK_SHIFT) == 0) hAnchor = hNewItem;
+
+       /* Issue notification */
+       if (!gestureCompleted) {
+               tvItem.hItem = 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, (int)tvItem.lParam);
+               sendSelectionEvent (SWT.Selection, event, false);
+       }
+       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) == 0) {
+                       sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam);
+               }
+       }
+       dragStarted = false;
+       return new LRESULT (code);
+}
+
+@Override
+LRESULT WM_MOUSEMOVE (long wParam, long lParam) {
+       Display display = this.display;
+       LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+       if (result != null) return result;
+       if (itemToolTipHandle != 0) {
+               /*
+               * 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) == 0) {
+                       int x = OS.GET_X_LPARAM (lParam);
+                       int y = OS.GET_Y_LPARAM (lParam);
+                       int [] index = new int [1];
+                       TreeItem [] item = new TreeItem [1];
+                       RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
+                       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) == 0) {
+                                       if (OS.IsWindowVisible (itemToolTipHandle)) {
+                                               OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+                                       }
+                               }
+                               TOOLINFO lpti = new TOOLINFO ();
+                               lpti.cbSize = TOOLINFO.sizeof;
+                               lpti.hwnd = handle;
+                               lpti.uId = handle;
+                               lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
+                               lpti.left = cellRect [0].left;
+                               lpti.top = cellRect [0].top;
+                               lpti.right = cellRect [0].right;
+                               lpti.bottom = cellRect [0].bottom;
+                               OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, lpti);
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_MOUSEWHEEL (long wParam, long lParam) {
+       LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam);
+       if (itemToolTipHandle != 0) OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+       return result;
+}
+
+@Override
+LRESULT WM_MOVE (long wParam, long lParam) {
+       if (itemToolTipHandle != 0) OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+       if (ignoreResize) return null;
+       return super.WM_MOVE (wParam, lParam);
+}
+
+@Override
+LRESULT WM_RBUTTONDOWN (long wParam, long 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 () != handle) OS.SetCapture (handle);
+               }
+               return LRESULT.ZERO;
+       }
+       /*
+       * This code is intentionally commented.
+       */
+//     if (OS.GetCapture () != handle) OS.SetCapture (handle);
+       /* Bug 225404 */
+       if (OS.GetFocus () != 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 = new TVHITTESTINFO ();
+       lpht.x = OS.GET_X_LPARAM (lParam);
+       lpht.y = OS.GET_Y_LPARAM (lParam);
+       OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+       if (lpht.hItem != 0) {
+               boolean fakeSelection = (style & SWT.FULL_SELECTION) != 0;
+               if (!fakeSelection) {
+                       if (hooks (SWT.MeasureItem)) {
+                               fakeSelection = hitTestSelection (lpht.hItem, lpht.x, lpht.y);
+                       } else {
+                               int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                               fakeSelection = (lpht.flags & flags) != 0;
+                       }
+               }
+               if (fakeSelection) {
+                       if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) == 0) {
+                               TVITEM tvItem = new 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) == 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 (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+
+       if (shrink && !ignoreShrink && items != null) {
+               /* Resize the item array to fit the last item */
+               int count = items.length - 1;
+               while (count >= 0) {
+                       if (items [count] != 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) != 0 || findImageControl () != null) {
+               boolean doubleBuffer = true;
+               if (explorerTheme) {
+                       int exStyle = (int)OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+                       if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) != 0) doubleBuffer = false;
+               }
+               if (doubleBuffer) {
+                       GC gc = null;
+                       long paintDC = 0;
+                       PAINTSTRUCT ps = new PAINTSTRUCT ();
+                       boolean hooksPaint = hooks (SWT.Paint) || filters (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.right - ps.left;
+                       int height = ps.bottom - ps.top;
+                       if (width != 0 && height != 0) {
+                               long hDC = OS.CreateCompatibleDC (paintDC);
+                               POINT lpPoint1 = new POINT (), lpPoint2 = new POINT ();
+                               OS.SetWindowOrgEx (hDC, ps.left, ps.top, lpPoint1);
+                               OS.SetBrushOrgEx (hDC, ps.left, ps.top, lpPoint2);
+                               long hBitmap = OS.CreateCompatibleBitmap (paintDC, width, height);
+                               long hOldBitmap = OS.SelectObject (hDC, hBitmap);
+                               RECT rect = new RECT ();
+                               OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                               drawBackground (hDC, rect);
+                               callWindowProc (handle, OS.WM_PAINT, hDC, 0);
+                               OS.SetWindowOrgEx (hDC, lpPoint1.x, lpPoint1.y, null);
+                               OS.SetBrushOrgEx (hDC, lpPoint2.x, lpPoint2.y, null);
+                               OS.BitBlt (paintDC, ps.left, ps.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.setBoundsInPixels(new Rectangle(ps.left, ps.top, ps.right - ps.left, ps.bottom - ps.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_SETCURSOR (long wParam, long lParam) {
+       LRESULT result = super.WM_SETCURSOR (wParam, lParam);
+       if (result != null) return result;
+
+       /*
+       * Feature in Windows. On Windows 7, the tree control show the
+       * hand cursor when the mouse is over an item.  This is the
+       * correct Windows 7 behavior but not correct for SWT. The fix
+       * is to always ensure a cursor is set.
+       */
+       if (OS.WIN32_VERSION >= OS.VERSION (6, 1)) {
+               if (wParam == handle) {
+                       int hitTest = (short) OS.LOWORD (lParam);
+                       if (hitTest == OS.HTCLIENT) {
+                               OS.SetCursor (OS.LoadCursor (0, OS.IDC_ARROW));
+                               return LRESULT.ONE;
+                       }
+               }
+       }
+       return null;
+}
+
+@Override
+LRESULT WM_SETFOCUS (long wParam, long 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.
+       */
+       boolean redraw = (style & SWT.MULTI) != 0;
+       if (!redraw && imageList != null) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+               if ((bits & OS.TVS_FULLROWSELECT) == 0) {
+                       redraw = true;
+               }
+       }
+       if (redraw) redrawSelection ();
+       return super.WM_SETFOCUS (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SETFONT (long wParam, long lParam) {
+       LRESULT result = super.WM_SETFONT (wParam, lParam);
+       if (result != null) return result;
+       if (hwndHeader != 0) {
+               /*
+               * 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 != 0) {
+               OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+               OS.SendMessage (itemToolTipHandle, OS.WM_SETFONT, wParam, lParam);
+       }
+       if (headerToolTipHandle != 0) {
+               OS.SendMessage (headerToolTipHandle, OS.WM_SETFONT, wParam, lParam);
+               updateHeaderToolTips ();
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETREDRAW (long wParam, long lParam) {
+       LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+       if (result != null) return result;
+       if (itemToolTipHandle != 0) OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+       /*
+       * 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.
+       */
+       long code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+       return code == 0 ? LRESULT.ZERO : new LRESULT (code);
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       if (itemToolTipHandle != 0) OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+       /*
+       * 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) != 0) {
+               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) != 0) {
+               OS.InvalidateRect (handle, null, false);
+       }
+       if (ignoreResize) return null;
+       return super.WM_SIZE (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+       if (result != 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 == -1) setForegroundPixel (-1);
+       }
+       if ((style & SWT.CHECK) != 0) setCheckboxImageList ();
+       return result;
+}
+
+@Override
+LRESULT WM_VSCROLL (long wParam, long lParam) {
+       boolean fixScroll = false;
+       if ((style & SWT.DOUBLE_BUFFERED) != 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) != 0 || hooks (SWT.EraseItem) || hooks (SWT.PaintItem);
+                               break;
+               }
+       }
+       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 != null) return result;
+       return result;
+}
+
+@Override
+LRESULT WM_TIMER (long wParam, long lParam) {
+       LRESULT result = super.WM_TIMER (wParam, lParam);
+       if (result != null) return result;
+
+       /* Bug in Windows. When the expandos are visible (or in process of fading away)
+        * and the tree control is hidden the animation timer does not stop calling the
+        * window proc till the tree is visible again. This can cause performance problems
+        * specially in cases there the application has several tree controls in this state.
+        * The fix is to detect a timer that repeats itself several times when the control
+        * is not visible and stop it. The timer is stopped by sending a fake mouse move event.
+        *
+        * Note: Just killing the timer could cause some internal clean up task related to the
+        * animation not to run.
+        */
+       long bits = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+       if ((bits & OS.TVS_EX_FADEINOUTEXPANDOS) != 0) {
+               if (!OS.IsWindowVisible (handle)) {
+                       if (lastTimerID == wParam) {
+                               lastTimerCount++;
+                       } else {
+                               lastTimerCount = 0;
+                       }
+                       lastTimerID = wParam;
+                       if (lastTimerCount >= TIMER_MAX_COUNT) {
+                               OS.CallWindowProc (TreeProc, handle, OS.WM_MOUSEMOVE, 0, 0);
+                               lastTimerID = -1;
+                               lastTimerCount = 0;
+                       }
+               } else {
+                       lastTimerID = -1;
+                       lastTimerCount = 0;
+               }
+       }
+       return result;
+};
+
+@Override
+LRESULT wmColorChild (long wParam, long lParam) {
+       if (findImageControl () != null) {
+               return new LRESULT (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, long wParam, long lParam) {
+       if (hdr.hwndFrom == itemToolTipHandle) {
+               LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
+               if (result != null) return result;
+       }
+       if (hdr.hwndFrom == hwndHeader) {
+               LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
+               if (result != null) return result;
+       }
+       return super.wmNotify (hdr, wParam, lParam);
+}
+
+@Override
+LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.TVN_GETDISPINFO: {
+                       NMTVDISPINFO lptvdi = new NMTVDISPINFO ();
+                       OS.MoveMemory (lptvdi, lParam, NMTVDISPINFO.sizeof);
+                       if ((style & SWT.VIRTUAL) != 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.
+                               */
+                               boolean 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 != null && lptvdi.lParam != -1) {
+                                               if (items [(int)lptvdi.lParam] != null && items [(int)lptvdi.lParam].cached) {
+                                                       checkVisible = false;
+                                               }
+                                       }
+                               }
+                               if (checkVisible) {
+                                       if (!getDrawing () || !OS.IsWindowVisible (handle)) break;
+                                       RECT itemRect = new RECT ();
+                                       if (!OS.TreeView_GetItemRect (handle, lptvdi.hItem, itemRect, false)) {
+                                               break;
+                                       }
+                                       RECT rect = new RECT ();
+                                       OS.GetClientRect (handle, rect);
+                                       if (!OS.IntersectRect (rect, rect, itemRect)) break;
+                                       if (ignoreShrink) {
+                                               OS.InvalidateRect (handle, rect, true);
+                                               break;
+                                       }
+                               }
+                       }
+                       if (items == 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 = (int)lptvdi.lParam;
+                       if ((style & SWT.VIRTUAL) != 0) {
+                               if (id == -1) {
+                                       TVITEM tvItem = new TVITEM ();
+                                       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+                                       tvItem.hItem = lptvdi.hItem;
+                                       OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                                       id = (int)tvItem.lParam;
+                               }
+                       }
+                       TreeItem item = _getItem (lptvdi.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 == null) break;
+                       if (item.isDisposed ()) break;
+                       if (!item.cached) {
+                               if ((style & SWT.VIRTUAL) != 0) {
+                                       if (!checkData (item, false)) break;
+                               }
+                               if (painted) item.cached = true;
+                       }
+                       int index = 0;
+                       if (hwndHeader != 0) {
+                               index = (int)OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+                       }
+                       if ((lptvdi.mask & OS.TVIF_TEXT) != 0) {
+                               String string = null;
+                               if (index == 0) {
+                                       string = item.text;
+                               } else {
+                                       String [] strings  = item.strings;
+                                       if (strings != null) string = strings [index];
+                               }
+                               if (string != null) {
+                                       int length = Math.min (string.length() + 1, lptvdi.cchTextMax);
+                                       char [] buffer = new char [length];
+                                       string.getChars(0, length - 1, buffer, 0);
+                                       OS.MoveMemory (lptvdi.pszText, buffer, length * TCHAR.sizeof);
+                                       lptvdi.cchTextMax = length;
+                               }
+                       }
+                       if ((lptvdi.mask & (OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE)) != 0) {
+                               Image image = null;
+                               if (index == 0) {
+                                       image = item.image;
+                               } else {
+                                       Image [] images  = item.images;
+                                       if (images != null) image = images [index];
+                               }
+                               lptvdi.iImage = lptvdi.iSelectedImage = OS.I_IMAGENONE;
+                               if (image != null) {
+                                       lptvdi.iImage = lptvdi.iSelectedImage = imageIndex (image, index);
+                               }
+                               if (explorerTheme && OS.IsWindowEnabled (handle)) {
+                                       if (findImageControl () != null) {
+                                               lptvdi.iImage = lptvdi.iSelectedImage = OS.I_IMAGENONE;
+                                       }
+                               }
+                       }
+                       OS.MoveMemory (lParam, lptvdi, NMTVDISPINFO.sizeof);
+                       break;
+               }
+               case OS.NM_CUSTOMDRAW: {
+                       if (hdr.hwndFrom == hwndHeader) break;
+                       if (hooks (SWT.MeasureItem)) {
+                               if (hwndHeader == 0) createParent ();
+                       }
+                       if (!customDraw && findImageControl () == null) {
+                               if (OS.IsAppThemed ()) {
+                                       if (sortColumn == null || sortDirection == SWT.NONE) {
+                                               break;
+                                       }
+                               }
+                       }
+                       NMTVCUSTOMDRAW nmcd = new NMTVCUSTOMDRAW ();
+                       OS.MoveMemory (nmcd, lParam, NMTVCUSTOMDRAW.sizeof);
+                       switch (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);
+                       }
+                       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 = new POINT ();
+                               int pos = OS.GetMessagePos ();
+                               OS.POINTSTOPOINT (pt, pos);
+                               OS.ScreenToClient (handle, pt);
+                               TVHITTESTINFO lpht = new TVHITTESTINFO ();
+                               lpht.x = pt.x;
+                               lpht.y = pt.y;
+                               OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+                               if (lpht.hItem != 0 && (lpht.flags & OS.TVHT_ONITEM) != 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_ITEMCHANGING: {
+                       if ((style & SWT.MULTI) != 0) {
+                               if (hSelect != 0) {
+                                       NMTVITEMCHANGE pnm = new NMTVITEMCHANGE ();
+                                       OS.MoveMemory (pnm, lParam, NMTVITEMCHANGE.sizeof);
+                                       if (hSelect == pnm.hItem) break;
+                                       return LRESULT.ONE;
+                               }
+                       }
+                       break;
+               }
+               case OS.TVN_SELCHANGING: {
+                       if ((style & SWT.MULTI) != 0) {
+                               if (lockSelection) {
+                                       /* Save the old selection state for both items */
+                                       NMTREEVIEW treeView = new NMTREEVIEW ();
+                                       OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                                       TVITEM tvItem = treeView.itemOld;
+                                       oldSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+                                       tvItem = treeView.itemNew;
+                                       newSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+                               }
+                       }
+                       if (!ignoreSelect && !ignoreDeselect) {
+                               hAnchor = 0;
+                               if ((style & SWT.MULTI) != 0) deselectAll ();
+                       }
+                       break;
+               }
+               case OS.TVN_SELCHANGED: {
+                       NMTREEVIEW treeView = null;
+                       if ((style & SWT.MULTI) != 0) {
+                               if (lockSelection) {
+                                       /* Restore the old selection state of both items */
+                                       if (oldSelected) {
+                                               if (treeView == null) {
+                                                       treeView = new NMTREEVIEW ();
+                                                       OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                                               }
+                                               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 == null) {
+                                                       treeView = new NMTREEVIEW ();
+                                                       OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                                               }
+                                               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 == null) {
+                                       treeView = new NMTREEVIEW ();
+                                       OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                               }
+                               TVITEM tvItem = treeView.itemNew;
+                               hAnchor = tvItem.hItem;
+                               Event event = new Event ();
+                               event.item = _getItem (tvItem.hItem, (int)tvItem.lParam);
+                               sendSelectionEvent (SWT.Selection, event, false);
+                       }
+                       updateScrollBar ();
+                       break;
+               }
+               case OS.TVN_ITEMEXPANDING: {
+                       if (itemToolTipHandle != 0) OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
+                       boolean runExpanded = false;
+                       if ((style & SWT.VIRTUAL) != 0) style &= ~SWT.DOUBLE_BUFFERED;
+                       if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) style &= ~SWT.DOUBLE_BUFFERED;
+                       if (findImageControl () != null && getDrawing () && 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 != 0) {
+                               OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0);
+                       }
+                       if (!ignoreExpand) {
+                               NMTREEVIEW treeView = new NMTREEVIEW ();
+                               OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                               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 == null) break;
+                               TreeItem item = _getItem (tvItem.hItem, (int)tvItem.lParam);
+                               if (item == 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) == 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;
+                               }
+                               /*
+                               * 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.
+                               */
+                               long hFirstItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, tvItem.hItem);
+                               runExpanded = hFirstItem == 0;
+                       }
+                       if (!runExpanded) break;
+                       //FALL THROUGH
+               }
+               case OS.TVN_ITEMEXPANDED: {
+                       if ((style & SWT.VIRTUAL) != 0) style |= SWT.DOUBLE_BUFFERED;
+                       if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) style |= SWT.DOUBLE_BUFFERED;
+                       if (findImageControl () != null && getDrawing () /*&& 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 != 0) {
+                               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 (imageList != null) {
+                               NMTREEVIEW treeView = new NMTREEVIEW ();
+                               OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                               TVITEM tvItem = treeView.itemNew;
+                               if (tvItem.hItem != 0) {
+                                       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                                       if ((bits & OS.TVS_FULLROWSELECT) == 0) {
+                                               RECT rect = new RECT ();
+                                               if (OS.TreeView_GetItemRect (handle, tvItem.hItem, rect, false)) {
+                                                       OS.InvalidateRect (handle, rect, true);
+                                               }
+                                       }
+                               }
+                       }
+                       updateScrollBar ();
+                       break;
+               }
+               case OS.TVN_BEGINDRAG:
+                       if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) break;
+                       //FALL THROUGH
+               case OS.TVN_BEGINRDRAG: {
+                       dragStarted = true;
+                       NMTREEVIEW treeView = new NMTREEVIEW ();
+                       OS.MoveMemory (treeView, lParam, NMTREEVIEW.sizeof);
+                       TVITEM tvItem = treeView.itemNew;
+                       if (tvItem.hItem != 0 && (tvItem.state & OS.TVIS_SELECTED) == 0) {
+                               hSelect = tvItem.hItem;
+                               ignoreSelect = ignoreDeselect = true;
+                               OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, tvItem.hItem);
+                               ignoreSelect = ignoreDeselect = false;
+                               hSelect = 0;
+                       }
+                       break;
+               }
+       }
+       return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+LRESULT wmNotifyHeader (NMHDR hdr, long wParam, 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_BEGINTRACK:
+               case OS.HDN_DIVIDERDBLCLICK: {
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       TreeColumn column = columns [phdn.iItem];
+                       if (column != null && !column.getResizable ()) {
+                               return LRESULT.ONE;
+                       }
+                       ignoreColumnMove = true;
+                       if (hdr.code == OS.HDN_DIVIDERDBLCLICK) {
+                               if (column != null) column.pack ();
+                       }
+                       break;
+               }
+               case OS.NM_CUSTOMDRAW: {
+                       NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW();
+                       OS.MoveMemory(nmcd, lParam, NMCUSTOMDRAW.sizeof);
+                       switch (nmcd.dwDrawStage) {
+                               case OS.CDDS_PREPAINT: {
+                                       /* Drawing here will be deleted by further drawing steps, even with OS.CDRF_SKIPDEFAULT.
+                                          Changing the TextColor and returning OS.CDRF_NEWFONT has no effect. */
+                                       return new LRESULT (customHeaderDrawing() ? OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT : OS.CDRF_DODEFAULT);
+                               }
+                               case OS.CDDS_ITEMPREPAINT: {
+                                       // draw background
+                                       RECT rect = new RECT();
+                                       OS.SetRect(rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+                                       int pixel = getHeaderBackgroundPixel();
+                                       if ((nmcd.uItemState & OS.CDIS_SELECTED) != 0) {
+                                               pixel = getDifferentColor(pixel);
+                                       } else if (columns[(int) nmcd.dwItemSpec] == sortColumn && sortDirection != SWT.NONE) {
+                                               pixel = getSlightlyDifferentColor(pixel);
+                                       }
+                                       long brush = OS.CreateSolidBrush(pixel);
+                                       OS.FillRect(nmcd.hdc, rect, brush);
+                                       OS.DeleteObject(brush);
+
+                                       return new LRESULT(OS.CDRF_SKIPDEFAULT); // if we got here, we will paint everything ourself
+                               }
+                               case OS.CDDS_POSTPAINT: {
+                                       // get the cursor position
+                                       POINT cursorPos = new POINT();
+                                       OS.GetCursorPos(cursorPos);
+                                       OS.MapWindowPoints(0, hwndHeader, cursorPos, 1);
+
+                                       // drawing all cells
+                                       int highlightedHeaderDividerX = -1;
+                                       int lastColumnRight = -1;
+                                       RECT [] rects = new RECT [columnCount];
+                                       for (int i=0; i<columnCount; i++) {
+                                               rects [i] = new RECT ();
+                                               OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, rects [i]);
+                                               if (rects[i].right > lastColumnRight) {
+                                                       lastColumnRight = rects[i].right;
+                                               }
+
+                                               if (columns[i] == sortColumn && sortDirection != SWT.NONE) {
+                                                       // the display.getSortImage looks terrible after scaling up.
+                                                       long pen = OS.CreatePen (OS.PS_SOLID, 1, getHeaderForegroundPixel());
+                                                       long oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                                       int center = rects[i].left + (rects[i].right - rects[i].left) / 2;
+                                                       /*
+                                                        * Sort indicator size needs to scale as per the Native Windows OS DPI level
+                                                        * when header is custom drawn. For more details refer bug 537097.
+                                                        */
+                                                       int leg = DPIUtil.autoScaleUpUsingNativeDPI(3);
+                                                       if (sortDirection == SWT.UP) {
+                                                               OS.Polyline(nmcd.hdc, new int[] {center-leg, 1+leg, center+1, 0}, 2);
+                                                               OS.Polyline(nmcd.hdc, new int[] {center+leg, 1+leg, center-1, 0}, 2);
+                                                       } else if (sortDirection == SWT.DOWN) {
+                                                               OS.Polyline(nmcd.hdc, new int[] {center-leg, 1, center+1, 1+leg+1}, 2);
+                                                               OS.Polyline(nmcd.hdc, new int[] {center+leg, 1, center-1, 1+leg+1}, 2);
+                                                       }
+                                                       OS.SelectObject (nmcd.hdc, oldPen);
+                                                       OS.DeleteObject (pen);
+                                               }
+
+                                               /* Windows 7 and 10 always draw a nearly invisible vertical line between the columns, even if lines are disabled.
+                                                  This line uses no fixed color constant, but calculates it from the background color.
+                                                  The method getSlightlyDifferentColor gives us a color, that is near enough to the windows algorithm. */
+                                               long pen = OS.CreatePen (OS.PS_SOLID, getGridLineWidthInPixels(), getSlightlyDifferentColor(getHeaderBackgroundPixel()));
+                                               long oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                               OS.Polyline(nmcd.hdc, new int[] {rects[i].right-1, rects[i].top, rects[i].right-1, rects[i].bottom}, 2);
+                                               OS.SelectObject (nmcd.hdc, oldPen);
+                                               OS.DeleteObject (pen);
+
+                                               pen = OS.CreatePen (OS.PS_SOLID, getGridLineWidthInPixels(), OS.GetSysColor(OS.COLOR_3DFACE));
+                                               oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                               /* To differentiate headers, always draw header column separator. */
+                                               OS.Polyline(nmcd.hdc, new int[] {rects[i].right-1, rects[i].top, rects[i].right-1, rects[i].bottom}, 2);
+                                               /* To differentiate header & content area, always draw the line separator between header & first row. */
+                                               if (i == 0) OS.Polyline(nmcd.hdc, new int[] {nmcd.left, nmcd.bottom-1, nmcd.right, nmcd.bottom-1}, 2);
+                                               OS.SelectObject (nmcd.hdc, oldPen);
+                                               OS.DeleteObject (pen);
+
+                                               if (headerItemDragging && highlightedHeaderDividerX == -1) {
+                                                       int distanceToLeftBorder = cursorPos.x - rects[i].left;
+                                                       int distanceToRightBorder = rects[i].right - cursorPos.x;
+                                                       if (distanceToLeftBorder >= 0 && distanceToRightBorder >= 0) {
+                                                               // the cursor is in the current rectangle
+                                                               highlightedHeaderDividerX = distanceToLeftBorder <= distanceToRightBorder ? rects[i].left-1 : rects[i].right;
+                                                       }
+                                               }
+
+                                               int x = rects[i].left + INSET + 2;
+                                               if (columns[i].image != null) {
+                                                       GCData data = new GCData();
+                                                       data.device = display;
+                                                       GC gc = GC.win32_new (nmcd.hdc, data);
+                                                       int y = Math.max (0, (nmcd.bottom - columns[i].image.getBoundsInPixels().height) / 2);
+                                                       gc.drawImage (columns[i].image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y));
+                                                       x += columns[i].image.getBoundsInPixels().width + 12;
+                                                       gc.dispose ();
+                                               }
+
+                                               if (columns[i].text != null) {
+                                                       int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                                       if ((columns[i].style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+                                                       if ((columns[i].style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+                                                       char [] buffer = columns[i].text.toCharArray ();
+                                                       OS.SetBkMode(nmcd.hdc, OS.TRANSPARENT);
+                                                       OS.SetTextColor(nmcd.hdc, getHeaderForegroundPixel());
+                                                       RECT textRect = new RECT();
+                                                       textRect.left = x;
+                                                       textRect.top = rects[i].top;
+                                                       textRect.right = rects[i].right;
+                                                       textRect.bottom = rects[i].bottom;
+                                                       OS.DrawText (nmcd.hdc, buffer, buffer.length, textRect, flags);
+                                               }
+                                       }
+
+                                       if (lastColumnRight < nmcd.right) {
+                                               // draw background of the 'no column' area
+                                               RECT rect = new RECT();
+                                               OS.SetRect(rect, lastColumnRight, nmcd.top, nmcd.right, nmcd.bottom-1);
+                                               long brush = OS.CreateSolidBrush(getHeaderBackgroundPixel());
+                                               OS.FillRect(nmcd.hdc, rect, brush);
+                                               OS.DeleteObject(brush);
+                                       }
+
+                                       // always draw the highlighted border at the end, to avoid overdrawing by other borders.
+                                       if (highlightedHeaderDividerX != -1) {
+                                               long pen = OS.CreatePen (OS.PS_SOLID, 4, OS.GetSysColor(OS.COLOR_HIGHLIGHT));
+                                               long oldPen = OS.SelectObject (nmcd.hdc, pen);
+                                               OS.Polyline(nmcd.hdc, new int[] {highlightedHeaderDividerX, nmcd.top, highlightedHeaderDividerX, nmcd.bottom}, 2);
+                                               OS.SelectObject (nmcd.hdc, oldPen);
+                                               OS.DeleteObject (pen);
+                                       }
+
+                                       return new LRESULT(OS.CDRF_DODEFAULT);
+                               }
+                       }
+                       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 = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       if (phdn.iItem != -1) {
+                               TreeColumn column = columns [phdn.iItem];
+                               if (column != null && !column.getMoveable ()) {
+                                       ignoreColumnMove = true;
+                                       return LRESULT.ONE;
+                               }
+                               headerItemDragging = true;
+                       }
+                       break;
+               }
+               case OS.HDN_ENDDRAG: {
+                       headerItemDragging = false;
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       if (phdn.iItem != -1 && phdn.pitem != 0) {
+                               HDITEM pitem = new HDITEM ();
+                               OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
+                               if ((pitem.mask & OS.HDI_ORDER) != 0 && pitem.iOrder != -1) {
+                                       int [] order = new int [columnCount];
+                                       OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order);
+                                       int index = 0;
+                                       while (index < order.length) {
+                                               if (order [index] == phdn.iItem) break;
+                                               index++;
+                                       }
+                                       if (index == order.length) index = 0;
+                                       if (index == pitem.iOrder) break;
+                                       int start = Math.min (index, pitem.iOrder);
+                                       int end = Math.max (index, pitem.iOrder);
+                                       RECT rect = new RECT (), headerRect = new RECT ();
+                                       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_ITEMCHANGING: {
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       if (phdn.pitem != 0) {
+                               HDITEM newItem = new HDITEM ();
+                               OS.MoveMemory (newItem, phdn.pitem, HDITEM.sizeof);
+                               if ((newItem.mask & OS.HDI_WIDTH) != 0) {
+                                       RECT rect = new RECT ();
+                                       OS.GetClientRect (handle, rect);
+                                       HDITEM oldItem = new HDITEM ();
+                                       oldItem.mask = OS.HDI_WIDTH;
+                                       OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, oldItem);
+                                       int deltaX = newItem.cxy - oldItem.cxy;
+                                       RECT headerRect = new RECT ();
+                                       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 () != 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, 0, null, flags);
+                                       }
+                                       if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) != 0) {
+                                               rect.left = headerRect.left;
+                                               rect.right = newX;
+                                               OS.InvalidateRect (handle, rect, true);
+                                       }
+                                       setScrollWidth ();
+                               }
+                       }
+                       break;
+               }
+               case OS.HDN_ITEMCHANGED: {
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       if (phdn.pitem != 0) {
+                               HDITEM pitem = new HDITEM ();
+                               OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
+                               if ((pitem.mask & OS.HDI_WIDTH) != 0) {
+                                       if (ignoreColumnMove) {
+                                               int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+                                               OS.RedrawWindow (handle, null, 0, flags);
+                                       }
+                                       TreeColumn column = columns [phdn.iItem];
+                                       if (column != 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);
+                                               boolean 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 == column) moved = true;
+                                               }
+                                       }
+                               }
+                               setScrollWidth ();
+                       }
+                       break;
+               }
+               case OS.HDN_ITEMCLICK: {
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       TreeColumn column = columns [phdn.iItem];
+                       if (column != null) {
+                               column.sendSelectionEvent (SWT.Selection);
+                       }
+                       break;
+               }
+               case OS.HDN_ITEMDBLCLICK: {
+                       NMHEADER phdn = new NMHEADER ();
+                       OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+                       TreeColumn column = columns [phdn.iItem];
+                       if (column != null) {
+                               column.sendSelectionEvent (SWT.DefaultSelection);
+                       }
+                       break;
+               }
+       }
+       return null;
+}
+
+LRESULT wmNotifyToolTip (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               case OS.NM_CUSTOMDRAW: {
+                       NMTTCUSTOMDRAW nmcd = new NMTTCUSTOMDRAW ();
+                       OS.MoveMemory (nmcd, lParam, NMTTCUSTOMDRAW.sizeof);
+                       return wmNotifyToolTip (nmcd, lParam);
+               }
+               case OS.TTN_SHOW: {
+                       LRESULT result = super.wmNotify (hdr, wParam, lParam);
+                       if (result != null) return result;
+                       int pos = OS.GetMessagePos ();
+                       POINT pt = new POINT();
+                       OS.POINTSTOPOINT (pt, pos);
+                       OS.ScreenToClient (handle, pt);
+                       int [] index = new int [1];
+                       TreeItem [] item = new TreeItem [1];
+                       RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
+                       if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                               RECT toolRect = toolTipRect (itemRect [0]);
+                               OS.MapWindowPoints (handle, 0, 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;
+                               OS.SetWindowPos (itemToolTipHandle, 0, toolRect.left, toolRect.top, width, height, flags);
+                               return LRESULT.ONE;
+                       }
+                       return result;
+               }
+       }
+       return null;
+}
+
+LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW nmcd, long lParam) {
+       switch (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: {
+                       if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+                               TOOLINFO lpti = new TOOLINFO ();
+                               lpti.cbSize = TOOLINFO.sizeof;
+                               if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+                                       int [] index = new int [1];
+                                       TreeItem [] item = new TreeItem [1];
+                                       RECT [] cellRect = new RECT [1], itemRect = new RECT [1];
+                                       int pos = OS.GetMessagePos ();
+                                       POINT pt = new POINT();
+                                       OS.POINTSTOPOINT (pt, pos);
+                                       OS.ScreenToClient (handle, pt);
+                                       if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                                               long hDC = OS.GetDC (handle);
+                                               long hFont = item [0].fontHandle (index [0]);
+                                               if (hFont == -1) hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                                               long oldFont = OS.SelectObject (hDC, hFont);
+                                               boolean drawForeground = true;
+                                               cellRect [0] = item [0].getBounds (index [0], true, true, false, false, false, hDC);
+                                               if (hooks (SWT.EraseItem)) {
+                                                       Event event = sendEraseItemEvent (item [0], nmcd, index [0], cellRect [0]);
+                                                       if (isDisposed () || item [0].isDisposed ()) break;
+                                                       if (event.doit) {
+                                                               drawForeground = (event.detail & SWT.FOREGROUND) != 0;
+                                                       } else {
+                                                               drawForeground = false;
+                                                       }
+                                               }
+                                               if (drawForeground) {
+                                                       int nSavedDC = OS.SaveDC (nmcd.hdc);
+                                                       int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0;
+                                                       RECT insetRect = toolTipInset (cellRect [0]);
+                                                       OS.SetWindowOrgEx (nmcd.hdc, insetRect.left, insetRect.top, null);
+                                                       GCData data = new GCData ();
+                                                       data.device = display;
+                                                       data.foreground = OS.GetTextColor (nmcd.hdc);
+                                                       data.background = OS.GetBkColor (nmcd.hdc);
+                                                       data.font = Font.win32_new (display, hFont);
+                                                       GC gc = GC.win32_new (nmcd.hdc, data);
+                                                       int x = cellRect [0].left + INSET;
+                                                       if (index [0] != 0) x -= gridWidth;
+                                                       Image image = item [0].getImage (index [0]);
+                                                       if (image != null || index [0] == 0) {
+                                                               Point size = getImageSize ();
+                                                               RECT imageRect = item [0].getBounds (index [0], false, true, false, false, false, hDC);
+                                                               if (imageList == null) size.x = imageRect.right - imageRect.left;
+                                                               if (image != null) {
+                                                                       Rectangle rect = image.getBounds (); // Points
+                                                                       gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(imageRect.top), DPIUtil.autoScaleDown(size.x), DPIUtil.autoScaleDown(size.y));
+                                                                       x += INSET + (index [0] == 0 ? 1 : 0);
+                                                               }
+                                                               x += size.x;
+                                                       } else {
+                                                               x += INSET;
+                                                       }
+                                                       String string = item [0].getText (index [0]);
+                                                       if (string != null) {
+                                                               int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                                               TreeColumn column = columns != null ? columns [index [0]] : null;
+                                                               if (column != null) {
+                                                                       if ((column.style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+                                                                       if ((column.style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+                                                               }
+                                                               char [] buffer = string.toCharArray ();
+                                                               RECT textRect = new RECT ();
+                                                               OS.SetRect (textRect, x, cellRect [0].top, cellRect [0].right, cellRect [0].bottom);
+                                                               OS.DrawText (nmcd.hdc, buffer, buffer.length, textRect, flags);
+                                                       }
+                                                       gc.dispose ();
+                                                       OS.RestoreDC (nmcd.hdc, nSavedDC);
+                                               }
+                                               if (hooks (SWT.PaintItem)) {
+                                                       itemRect [0] = item [0].getBounds (index [0], true, true, false, false, false, hDC);
+                                                       sendPaintItemEvent (item [0], nmcd, index[0], itemRect [0]);
+                                               }
+                                               OS.SelectObject (hDC, oldFont);
+                                               OS.ReleaseDC (handle, hDC);
+                                       }
+                                       break;
+                               }
+                       }
+                       break;
+               }
+       }
+       return null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TreeColumn.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TreeColumn.java
new file mode 100644 (file)
index 0000000..495b10a
--- /dev/null
@@ -0,0 +1,767 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * Instances of this class represent a column in a tree widget.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd> Move, Resize, Selection</dd>
+ * </dl>
+ * <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
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TreeColumn extends Item {
+       Tree parent;
+       boolean 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 TreeColumn (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 TreeColumn (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 == 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 == 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) != 0) return SWT.LEFT;
+       if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+       if ((style & SWT.RIGHT) != 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(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public boolean 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 boolean 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 ();
+       return DPIUtil.autoScaleDown(getWidthInPixels());
+}
+
+int getWidthInPixels () {
+       int index = parent.indexOf (this);
+       if (index == -1) return 0;
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader == 0) return 0;
+       HDITEM hdItem = new 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 == -1) return;
+       int columnWidth = 0;
+       long hwnd = parent.handle, hwndHeader = parent.hwndHeader;
+       RECT headerRect = new RECT ();
+       OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+       long hDC = OS.GetDC (hwnd);
+       long oldFont = 0, newFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+       if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+       tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       while (tvItem.hItem != 0) {
+               OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+               TreeItem item = tvItem.lParam != -1 ? parent.items [(int)tvItem.lParam] : null;
+               if (item != null) {
+                       int itemRight = 0;
+                       if (parent.hooks (SWT.MeasureItem)) {
+                               int detail = (tvItem.state & OS.TVIS_SELECTED) != 0 ? SWT.SELECTED : 0;
+                               Event event = parent.sendMeasureItemEvent (item, index, hDC, detail);
+                               if (isDisposed () || parent.isDisposed ()) break;
+                               Rectangle bounds = event.getBoundsInPixels();
+                               itemRight = bounds.x + bounds.width;
+                       } else {
+                               long hFont = item.fontHandle (index);
+                               if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
+                               RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+                               if (hFont != -1) OS.SelectObject (hDC, hFont);
+                               itemRight = itemRect.right;
+                       }
+                       columnWidth = Math.max (columnWidth, itemRight - headerRect.left);
+               }
+               tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, tvItem.hItem);
+       }
+       RECT rect = new RECT ();
+       int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+       char [] buffer = text.toCharArray ();
+       OS.DrawText (hDC, buffer, buffer.length, rect, flags);
+       int headerWidth = rect.right - rect.left + Tree.HEADER_MARGIN;
+       if (OS.IsAppThemed ()) headerWidth += Tree.HEADER_EXTRA;
+       if (image != null || parent.sortColumn == this) {
+               Image headerImage = null;
+               if (parent.sortColumn == this && parent.sortDirection != SWT.NONE) {
+                       headerWidth += Tree.SORT_WIDTH;
+               } else {
+                       headerImage = image;
+               }
+               if (headerImage != null) {
+                       Rectangle bounds = headerImage.getBoundsInPixels ();
+                       headerWidth += bounds.width;
+               }
+               int margin = 0;
+               if (hwndHeader != 0) {
+                       margin = (int)OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
+               } else {
+                       margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3;
+               }
+               headerWidth += margin * 2;
+       }
+       if (newFont != 0) OS.SelectObject (hDC, oldFont);
+       OS.ReleaseDC (hwnd, hDC);
+       int gridWidth = parent.linesVisible ? Tree.GRID_WIDTH : 0;
+       setWidthInPixels (Math.max (headerWidth, columnWidth + gridWidth));
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       parent = null;
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if (parent.sortColumn == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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)) == 0) return;
+       int index = parent.indexOf (this);
+       if (index == -1 || index == 0) return;
+       style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+       style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader == 0) return;
+       HDITEM hdItem = new HDITEM ();
+       hdItem.mask = OS.HDI_FORMAT;
+       OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
+       hdItem.fmt &= ~OS.HDF_JUSTIFYMASK;
+       if ((style & SWT.LEFT) == SWT.LEFT) hdItem.fmt |= OS.HDF_LEFT;
+       if ((style & SWT.CENTER) == SWT.CENTER) hdItem.fmt |= OS.HDF_CENTER;
+       if ((style & SWT.RIGHT) == SWT.RIGHT) hdItem.fmt |= OS.HDF_RIGHT;
+       OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, hdItem);
+       if (index != 0) {
+               long hwnd = parent.handle;
+               parent.forceResize ();
+               RECT rect = new RECT (), headerRect = new RECT ();
+               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 != null && image.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       super.setImage (image);
+       if (parent.sortColumn != this || parent.sortDirection != SWT.NONE) {
+               setImage (image, false, false);
+       }
+}
+
+void setImage (Image image, boolean sort, boolean right) {
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader == 0) return;
+       HDITEM hdItem = new 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 != 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 (boolean 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 (boolean resizable) {
+       checkWidget ();
+       this.resizable = resizable;
+}
+
+void setSortDirection (int direction) {
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader != 0) {
+               int index = parent.indexOf (this);
+               if (index == -1) return;
+               HDITEM hdItem = new 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 == 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 == null) hdItem.mask &= ~OS.HDI_IMAGE;
+                               break;
+                       case SWT.NONE:
+                               hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
+                               if (image != null) {
+                                       hdItem.fmt |= OS.HDF_IMAGE;
+                                       hdItem.iImage = parent.imageIndexHeader (image);
+                               } else {
+                                       hdItem.fmt &= ~OS.HDF_IMAGE;
+                                       hdItem.mask &= ~OS.HDI_IMAGE;
+                               }
+                               break;
+               }
+               OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, hdItem);
+               if (OS.IsAppThemed ()) {
+                       long hwnd = parent.handle;
+                       parent.forceResize ();
+                       RECT rect = new RECT (), headerRect = new RECT ();
+                       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 setText (String string) {
+       checkWidget ();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (string.equals (text)) return;
+       int index = parent.indexOf (this);
+       if (index == -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.
+       */
+       long hHeap = OS.GetProcessHeap ();
+       char [] buffer = fixMnemonic (string);
+       int byteCount = buffer.length * TCHAR.sizeof;
+       long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+       OS.MoveMemory (pszText, buffer, byteCount);
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader == 0) return;
+       HDITEM hdItem = new HDITEM ();
+       hdItem.mask = OS.HDI_TEXT;
+       hdItem.pszText = pszText;
+       long result = OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, hdItem);
+       if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
+       if (result == 0) error (SWT.ERROR_CANNOT_SET_TEXT);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that the default tool tip for the
+ * control will be shown. For a control that has a default
+ * tool tip, such as the Tree control on Windows, setting
+ * the tool tip text to an empty string replaces the default,
+ * causing no tool tip text to be shown.
+ * <p>
+ * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
+ * To display a single '&amp;' in the tool tip, the character '&amp;' can be
+ * escaped by doubling it in the string.
+ * </p>
+ * <p>
+ * NOTE: This operation is a hint and behavior is platform specific, on Windows
+ * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
+ * are not shown in tooltip.
+ * </p>
+ *
+ * @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;
+       long hwndHeaderToolTip = parent.headerToolTipHandle;
+       if (hwndHeaderToolTip == 0) {
+               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 ();
+       setWidthInPixels(DPIUtil.autoScaleUp(width));
+}
+
+void setWidthInPixels (int width) {
+       if (width < 0) return;
+       int index = parent.indexOf (this);
+       if (index == -1) return;
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader == 0) return;
+       HDITEM hdItem = new HDITEM ();
+       hdItem.mask = OS.HDI_WIDTH;
+       hdItem.cxy = width;
+       OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, hdItem);
+       RECT headerRect = new RECT ();
+       OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
+       parent.forceResize ();
+       long hwnd = parent.handle;
+       RECT rect = new RECT ();
+       OS.GetClientRect (hwnd, rect);
+       rect.left = headerRect.left;
+       OS.InvalidateRect (hwnd, rect, true);
+       parent.setScrollWidth ();
+}
+
+void updateToolTip (int index) {
+       long hwndHeaderToolTip = parent.headerToolTipHandle;
+       if (hwndHeaderToolTip != 0) {
+               long hwndHeader = parent.hwndHeader;
+               RECT rect = new RECT ();
+               if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, rect) != 0) {
+                       TOOLINFO lpti = new TOOLINFO ();
+                       lpti.cbSize = TOOLINFO.sizeof;
+                       lpti.hwnd = hwndHeader;
+                       lpti.uId = id;
+                       lpti.left = rect.left;
+                       lpti.top = rect.top;
+                       lpti.right = rect.right;
+                       lpti.bottom = rect.bottom;
+                       OS.SendMessage (hwndHeaderToolTip, OS.TTM_NEWTOOLRECT, 0, lpti);
+               }
+       }
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TreeItem.java
new file mode 100644 (file)
index 0000000..35e7f5e
--- /dev/null
@@ -0,0 +1,1805 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TreeItem extends 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>
+        *
+        * @noreference This field is not intended to be referenced by clients.
+        */
+       public long handle;
+       Tree parent;
+       String [] strings;
+       Image [] images;
+       Font font;
+       Font [] cellFont;
+       boolean cached;
+       int background = -1, foreground = -1;
+       int [] cellBackground, cellForeground;
+
+/**
+ * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
+ * Item is inserted as last direct child of the tree.
+ * <p>
+ * For bulk insert scenarios, see TreeItem#TreeItem(Tree,int,int)
+ *
+ * @param parent a tree control which will be the parent of the new instance (cannot be null)
+ * @param style no styles are currently supported, pass SWT.NONE
+ *
+ * @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 TreeItem (Tree parent, int style) {
+       this (parent, style, OS.TVGN_ROOT, OS.TVI_LAST, 0);
+}
+
+/**
+ * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
+ * Item is inserted as <code>index</code> direct child of the tree.
+ * <p>
+ * The fastest way to insert many items is:
+ * <ol>
+ * <li>Use {@link Tree#setRedraw} to disable drawing during bulk insert</li>
+ * <li>Insert every item at index 0 (insert them in reverse to get the same result)</li>
+ * </ol>
+ *
+ * @param parent a tree control which will be the parent of the new instance (cannot be null)
+ * @param style no styles are currently supported, pass SWT.NONE
+ * @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
+ * @see Tree#setRedraw
+ */
+public TreeItem (Tree parent, int style, int index) {
+       this (parent, style, OS.TVGN_ROOT, findPrevious (parent, index), 0);
+}
+
+/**
+ * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
+ * Item is inserted as last direct child of the specified <code>TreeItem</code>.
+ * <p>
+ * For bulk insert scenarios, see TreeItem#TreeItem(TreeItem,int,int)
+ *
+ * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
+ * @param style no styles are currently supported, pass SWT.NONE
+ *
+ * @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 TreeItem (TreeItem parentItem, int style) {
+       this (checkNull (parentItem).parent, style, parentItem.handle, OS.TVI_LAST, 0);
+}
+
+/**
+ * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
+ * Item is inserted as <code>index</code> direct child of the specified <code>TreeItem</code>.
+ * <p>
+ * The fastest way to insert many items is:
+ * <ol>
+ * <li>Use {@link Tree#setRedraw} to disable drawing during bulk insert</li>
+ * <li>Insert child items while parent item is collapsed</li>
+ * <li>Insert every item at index 0 (insert them in reverse to get the same result)</li>
+ * </ol>
+ *
+ * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
+ * @param style no styles are currently supported, pass SWT.NONE
+ * @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
+ * @see Tree#setRedraw
+ */
+public TreeItem (TreeItem parentItem, int style, int index) {
+       this (checkNull (parentItem).parent, style, parentItem.handle, findPrevious (parentItem, index), 0);
+}
+
+TreeItem (Tree parent, int style, long hParent, long hInsertAfter, long hItem) {
+       super (parent, style);
+       this.parent = parent;
+       parent.createItem (this, hParent, hInsertAfter, hItem);
+}
+
+static TreeItem checkNull (TreeItem item) {
+       if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+       return item;
+}
+
+static long findPrevious (Tree parent, int index) {
+       if (parent == null) return 0;
+       if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
+       if (index == 0) return OS.TVI_FIRST;
+       long hwnd = parent.handle;
+       long hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+       long hItem = parent.findItem (hFirstItem, index - 1);
+       if (hItem == 0) SWT.error (SWT.ERROR_INVALID_RANGE);
+       return hItem;
+}
+
+static long findPrevious (TreeItem parentItem, int index) {
+       if (parentItem == null) return 0;
+       if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
+       if (index == 0) return OS.TVI_FIRST;
+       Tree parent = parentItem.parent;
+       long hwnd = parent.handle, hParent = parentItem.handle;
+       long hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent);
+       long hItem = parent.findItem (hFirstItem, index - 1);
+       if (hItem == 0) 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) != 0) {
+               long hwnd = parent.handle;
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+               tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+               tvItem.state = 1 << 12;
+               tvItem.hItem = handle;
+               OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
+       }
+       background = foreground = -1;
+       font = null;
+       cellBackground = cellForeground = null;
+       cellFont = null;
+       if ((parent.style & SWT.VIRTUAL) != 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, boolean all) {
+       checkWidget ();
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+       hItem = parent.findItem (hItem, index);
+       if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       parent.clear (hItem, tvItem);
+       if (all) {
+               hItem = 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 (boolean all) {
+       checkWidget ();
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       if (hItem == 0) return;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       parent.clearAll (hItem, tvItem, all);
+}
+
+@Override
+void destroyWidget () {
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       parent.releaseItem (handle, tvItem, false);
+       parent.destroyItem (this, handle);
+       releaseHandle ();
+}
+
+long fontHandle (int index) {
+       if (cellFont != null && cellFont [index] != null) return cellFont [index].handle;
+       if (font != null) return font.handle;
+       return -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 == -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 != null ? cellBackground [index] : -1;
+       return pixel == -1 ? getBackground () : Color.win32_new (display, pixel);
+}
+
+/**
+ * Returns a rectangle describing the size and location of the receiver's
+ * text relative to its parent.
+ *
+ * @return the bounding rectangle of 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 Rectangle getBounds () {
+       checkWidget ();
+       return DPIUtil.autoScaleDown(getBoundsInPixels());
+}
+
+Rectangle getBoundsInPixels () {
+       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();
+       return DPIUtil.autoScaleDown(getBoundsInPixels(index));
+}
+
+Rectangle getBoundsInPixels (int index) {
+       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, boolean getText, boolean getImage, boolean fullText) {
+       return getBounds (index, getText, getImage, fullText, false, true, 0);
+}
+
+//TODO - take into account grid (add boolean arg) to damage less during redraw
+RECT getBounds (int index, boolean getText, boolean getImage, boolean fullText, boolean fullImage, boolean clip, long hDC) {
+       if (!getText && !getImage) return new RECT ();
+       long hwnd = parent.handle;
+       if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+               tvItem.hItem = handle;
+               tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+               parent.ignoreCustomDraw = true;
+               OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
+               parent.ignoreCustomDraw = false;
+       }
+       boolean firstColumn = index == 0;
+       int columnCount = 0;
+       long hwndHeader = parent.hwndHeader;
+       if (hwndHeader != 0) {
+               columnCount = parent.columnCount;
+               firstColumn = index == OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+       }
+       RECT rect = new RECT ();
+       if (firstColumn) {
+               boolean full = columnCount == 0 && getText && getImage && fullText && fullImage;
+               if (!OS.TreeView_GetItemRect (hwnd, handle, rect, !full)) {
+                       return new RECT ();
+               }
+               if (getImage && !fullImage) {
+                       if (OS.SendMessage (hwnd, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) != 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 != 0) {
+                               RECT headerRect = new RECT ();
+                               if (columnCount != 0) {
+                                       if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect) == 0) {
+                                               return new RECT ();
+                                       }
+                               } else {
+                                       headerRect.right = parent.scrollWidth;
+                                       if (headerRect.right == 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, headerRect) == 0) {
+                       return new RECT ();
+               }
+               if (!OS.TreeView_GetItemRect (hwnd, 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 == 0) {
+                               image = this.image;
+                       } else {
+                               if (images != null) image = images [index];
+                       }
+                       if (image != 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 == 0 ? text : strings != null ? strings [index] : null;
+                                       if (string != null) {
+                                               RECT textRect = new RECT ();
+                                               char [] buffer = string.toCharArray ();
+                                               int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
+                                               long hNewDC = hDC, hFont = 0;
+                                               if (hDC == 0) {
+                                                       hNewDC = OS.GetDC (hwnd);
+                                                       hFont = fontHandle (index);
+                                                       if (hFont == -1) hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+                                                       hFont = OS.SelectObject (hNewDC, hFont);
+                                               }
+                                               OS.DrawText (hNewDC, buffer, buffer.length, textRect, flags);
+                                               if (hDC == 0) {
+                                                       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 != 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</code> style, return false.
+ *
+ * @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 boolean getChecked () {
+       checkWidget ();
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       if ((parent.style & SWT.CHECK) == 0) return false;
+       long hwnd = parent.handle;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+       tvItem.hItem = handle;
+       long result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+       return (result != 0) && (((tvItem.state >> 12) & 1) == 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 boolean getExpanded () {
+       checkWidget ();
+       long hwnd = parent.handle;
+       /*
+       * 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 = (int)OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
+       return (state & OS.TVIS_EXPANDED) != 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 != 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 == null || cellFont [index] == 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 == -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 != null ? cellForeground [index] : -1;
+       return pixel == -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 boolean getGrayed () {
+       checkWidget ();
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       if ((parent.style & SWT.CHECK) == 0) return false;
+       long hwnd = parent.handle;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+       tvItem.hItem = handle;
+       long result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+       return (result != 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);
+       long hwnd = parent.handle;
+       long hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       if (hFirstItem == 0) error (SWT.ERROR_INVALID_RANGE);
+       long hItem = parent.findItem (hFirstItem, index);
+       if (hItem == 0) 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);
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       if (hItem == 0) 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);
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       if (hItem == 0) return new TreeItem [0];
+       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 == 0) return getImage ();
+       if (images != 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();
+       return DPIUtil.autoScaleDown(getImageBoundsInPixels(index));
+}
+
+Rectangle getImageBoundsInPixels (int index) {
+       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 ();
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, handle);
+       return hItem != 0 ? 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 == 0) return getText ();
+       if (strings != null) {
+               if (0 <= index && index < strings.length) {
+                       String string = strings [index];
+                       return string != 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();
+       return DPIUtil.autoScaleDown(getTextBoundsInPixels(index));
+}
+
+Rectangle getTextBoundsInPixels (int index) {
+       if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+       RECT rect = getBounds (index, true, false, true);
+       if (index == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       return hItem == 0 ? -1 : parent.findIndex (hItem, item.handle);
+}
+
+void redraw () {
+       if (parent.currentItem == this || !parent.getDrawing ()) return;
+       long 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.
+       */
+       boolean full = (parent.style & (SWT.FULL_SELECTION | SWT.VIRTUAL)) != 0;
+       if (!full) {
+               full = parent.columnCount != 0;
+               if (!full) {
+                       if (parent.hooks (SWT.EraseItem) || parent.hooks (SWT.PaintItem)) {
+                               full = true;
+                       }
+               }
+       }
+       RECT rect = new RECT ();
+       if (OS.TreeView_GetItemRect (hwnd, handle, rect, !full)) {
+               OS.InvalidateRect (hwnd, rect, true);
+       }
+}
+
+void redraw (int column, boolean drawText, boolean drawImage) {
+       if (parent.currentItem == this || !parent.getDrawing ()) return;
+       long hwnd = parent.handle;
+       if (!OS.IsWindowVisible (hwnd)) return;
+       boolean fullImage = column == 0 && drawText && drawImage;
+       RECT rect = getBounds (column, drawText, drawImage, true, fullImage, true, 0);
+       OS.InvalidateRect (hwnd, rect, true);
+}
+
+@Override
+void releaseChildren (boolean destroy) {
+       if (destroy) {
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+               parent.releaseItems (handle, tvItem);
+       }
+       super.releaseChildren (destroy);
+}
+
+@Override
+void releaseHandle () {
+       super.releaseHandle ();
+       handle = 0;
+       parent = null;
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       strings = null;
+       images = null;
+       cellBackground = cellForeground = null;
+       cellFont = 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>
+ *
+ * @since 3.1
+ */
+public void removeAll () {
+       checkWidget ();
+       long hwnd = parent.handle;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+       tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       while (tvItem.hItem != 0) {
+               OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+               TreeItem item = tvItem.lParam != -1 ? parent.items [(int)tvItem.lParam] : null;
+               if (item != null && !item.isDisposed ()) {
+                       item.dispose ();
+               } else {
+                       parent.releaseItem (tvItem.hItem, tvItem, false);
+                       parent.destroyItem (null, tvItem.hItem);
+               }
+               tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, 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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int pixel = -1;
+       if (color != null) {
+               parent.customDraw = true;
+               pixel = color.handle;
+       }
+       if (background == pixel) return;
+       background = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       int pixel = -1;
+       if (color != null) {
+               parent.customDraw = true;
+               pixel = color.handle;
+       }
+       if (cellBackground == null) {
+               cellBackground = new int [count];
+               for (int i = 0; i < count; i++) {
+                       cellBackground [i] = -1;
+               }
+       }
+       if (cellBackground [index] == pixel) return;
+       cellBackground [index] = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 (boolean checked) {
+       checkWidget ();
+       if ((parent.style & SWT.CHECK) == 0) return;
+       long hwnd = parent.handle;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+       tvItem.hItem = handle;
+       OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+       int state = tvItem.state >> 12;
+       if (checked) {
+               if ((state & 0x1) != 0) state++;
+       } else {
+               if ((state & 0x1) == 0) --state;
+       }
+       state <<= 12;
+       if (tvItem.state == state) return;
+       if ((parent.style & SWT.VIRTUAL) != 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) != 0) {
+               if (parent.currentItem == this && OS.IsWindowVisible (hwnd)) {
+                       RECT rect = new RECT ();
+                       if (OS.TreeView_GetItemRect (hwnd, 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 (boolean expanded) {
+       checkWidget ();
+
+       /* Do nothing when the item is a leaf or already expanded */
+       long hwnd = parent.handle;
+       if (OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle) == 0) {
+               return;
+       }
+       /*
+       * 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 = (int)OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
+       if (((state & OS.TVIS_EXPANDED) != 0) == 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 = null;
+       RECT [] rects = null;
+       SCROLLINFO oldInfo = null;
+       int count = 0;
+       long hBottomItem = 0;
+       boolean redraw = false, noScroll = true;
+       long hTopItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+       if (noScroll && hTopItem != 0) {
+               oldInfo = new SCROLLINFO ();
+               oldInfo.cbSize = SCROLLINFO.sizeof;
+               oldInfo.fMask = OS.SIF_ALL;
+               if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, oldInfo)) {
+                       oldInfo = null;
+               }
+               if (parent.getDrawing () && OS.IsWindowVisible (hwnd)) {
+                       boolean noAnimate = true;
+                       count = (int)OS.SendMessage (hwnd, OS.TVM_GETVISIBLECOUNT, 0, 0);
+                       rects = new RECT [count + 1];
+                       long hItem = hTopItem;
+                       int index = 0;
+                       while (hItem != 0 && (noAnimate || hItem != handle) && index < count) {
+                               RECT rect = new RECT ();
+                               if (OS.TreeView_GetItemRect (hwnd, hItem, rect, true)) {
+                                       rects [index++] = rect;
+                               }
+                               hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                       }
+                       if (noAnimate || hItem != handle) {
+                               redraw = true;
+                               count = index;
+                               hBottomItem = hItem;
+                               oldRect = new RECT ();
+                               OS.GetClientRect (hwnd, oldRect);
+                               long topHandle = parent.topHandle ();
+                               OS.UpdateWindow (topHandle);
+                               OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0);
+                               if (hwnd != 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.
+       */
+       long hOldItem = 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 != 0) {
+               boolean collapsed = false;
+               if (!expanded) {
+                       RECT rect = new RECT ();
+                       while (hTopItem != 0 && !OS.TreeView_GetItemRect (hwnd, hTopItem, rect, false)) {
+                               hTopItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem);
+                               collapsed = true;
+                       }
+               }
+               boolean scrolled = true;
+               if (hTopItem != 0) {
+                       OS.SendMessage (hwnd, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hTopItem);
+                       scrolled = hTopItem != OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+               }
+               if (!collapsed && !scrolled && oldInfo != null) {
+                       SCROLLINFO newInfo = new SCROLLINFO ();
+                       newInfo.cbSize = SCROLLINFO.sizeof;
+                       newInfo.fMask = OS.SIF_ALL;
+                       if (OS.GetScrollInfo (hwnd, OS.SB_HORZ, newInfo)) {
+                               if (oldInfo.nPos != newInfo.nPos) {
+                                       long lParam = OS.MAKELPARAM (OS.SB_THUMBPOSITION, oldInfo.nPos);
+                                       OS.SendMessage (hwnd, OS.WM_HSCROLL, lParam, 0);
+                               }
+                       }
+               }
+               if (redraw) {
+                       boolean fixScroll = false;
+                       if (!collapsed && !scrolled) {
+                               RECT newRect = new RECT ();
+                               OS.GetClientRect (hwnd, newRect);
+                               if (OS.EqualRect (oldRect, newRect)) {
+                                       long hItem = hTopItem;
+                                       int index = 0;
+                                       while (hItem != 0 && index < count) {
+                                               RECT rect = new RECT ();
+                                               if (OS.TreeView_GetItemRect (hwnd, hItem, rect, true)) {
+                                                       if (!OS.EqualRect (rect, rects [index])) {
+                                                               break;
+                                                       }
+                                               }
+                                               hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                                               index++;
+                                       }
+                                       fixScroll = index == count && hItem == hBottomItem;
+                               }
+                       }
+                       long topHandle = parent.topHandle ();
+                       OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 1, 0);
+                       if (hwnd != 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 = new SCROLLINFO ();
+                               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 == hBottomItem) {
+                                       RECT rect = new RECT ();
+                                       if (OS.TreeView_GetItemRect (hwnd, hBottomItem, rect, false)) {
+                                               OS.InvalidateRect (hwnd, rect, true);
+                                       }
+                               }
+                       } else {
+                               int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                               OS.RedrawWindow (topHandle, null, 0, flags);
+                       }
+               }
+       }
+
+       /* Check for a selection event */
+       long hNewItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+       if (hNewItem != hOldItem) {
+               Event event = new Event ();
+               if (hNewItem != 0) {
+                       event.item = parent._getItem (hNewItem);
+                       parent.hAnchor = hNewItem;
+               }
+               parent.sendSelectionEvent (SWT.Selection, event, 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 != null && font.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       Font oldFont = this.font;
+       if (oldFont == font) return;
+       this.font = font;
+       if (oldFont != null && oldFont.equals (font)) return;
+       if (font != null) parent.customDraw = true;
+       if ((parent.style & SWT.VIRTUAL) != 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) == 0 && !cached && !parent.painted) {
+               return;
+       }
+       long hwnd = parent.handle;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+       tvItem.hItem = 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 != null && font.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       if (cellFont == null) {
+               if (font == null) return;
+               cellFont = new Font [count];
+       }
+       Font oldFont = cellFont [index];
+       if (oldFont == font) return;
+       cellFont [index] = font;
+       if (oldFont != null && oldFont.equals (font)) return;
+       if (font != null) parent.customDraw = true;
+       if ((parent.style & SWT.VIRTUAL) != 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 == 0) {
+               if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
+                       return;
+               }
+               long hwnd = parent.handle;
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+               tvItem.hItem = 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)
+ *
+ * @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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int pixel = -1;
+       if (color != null) {
+               parent.customDraw = true;
+               pixel = color.handle;
+       }
+       if (foreground == pixel) return;
+       foreground = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 != null && color.isDisposed ()) {
+               error (SWT.ERROR_INVALID_ARGUMENT);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       int pixel = -1;
+       if (color != null) {
+               parent.customDraw = true;
+               pixel = color.handle;
+       }
+       if (cellForeground == null) {
+               cellForeground = new int [count];
+               for (int i = 0; i < count; i++) {
+                       cellForeground [i] = -1;
+               }
+       }
+       if (cellForeground [index] == pixel) return;
+       cellForeground [index] = pixel;
+       if ((parent.style & SWT.VIRTUAL) != 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 (boolean grayed) {
+       checkWidget ();
+       if ((parent.style & SWT.CHECK) == 0) return;
+       long hwnd = parent.handle;
+       TVITEM tvItem = new TVITEM ();
+       tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+       tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+       tvItem.hItem = 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 == state) return;
+       if ((parent.style & SWT.VIRTUAL) != 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) != 0) {
+               if (parent.currentItem == this && OS.IsWindowVisible (hwnd)) {
+                       RECT rect = new RECT ();
+                       if (OS.TreeView_GetItemRect (hwnd, 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_NULL_ARGUMENT - if the array of images is null</li>
+ *    <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();
+       if (images == 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 != null && image.isDisposed ()) {
+               error(SWT.ERROR_INVALID_ARGUMENT);
+       }
+       Image oldImage = null;
+       if (index == 0) {
+               if (image != null && image.type == SWT.ICON) {
+                       if (image.equals (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 == null && index != 0) {
+               images = new Image [count];
+               images [0] = image;
+       }
+       if (images != null) {
+               if (image != null && image.type == SWT.ICON) {
+                       if (image.equals (images [index])) return;
+               }
+               oldImage = images [index];
+               images [index] = image;
+       }
+       if ((parent.style & SWT.VIRTUAL) != 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 == 0) {
+               if ((parent.style & SWT.VIRTUAL) == 0 &&!cached && !parent.painted) {
+                       return;
+               }
+               long hwnd = parent.handle;
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE;
+               tvItem.hItem = 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 {
+               boolean drawText = (image == null && oldImage != null) || (image != null && oldImage == 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);
+       long hwnd = parent.handle;
+       long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+       parent.setItemCount (count, handle, hItem);
+}
+
+/**
+ * Sets the text for multiple columns in the tree.
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param strings the array of new strings
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (String [] strings) {
+       checkWidget();
+       if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
+       for (int i=0; i<strings.length; i++) {
+               String string = strings [i];
+               if (string != null) setText (i, string);
+       }
+}
+
+/**
+ * Sets the receiver's text at a column
+ * <p>
+ * Note: If control characters like '\n', '\t' etc. are used
+ * in the string, then the behavior is platform dependent.
+ * </p>
+ * @param index the column index
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (int index, String string) {
+       checkWidget();
+       if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (index == 0) {
+               if (string.equals (text)) return;
+               super.setText (string);
+       }
+       int count = Math.max (1, parent.getColumnCount ());
+       if (0 > index || index > count - 1) return;
+       if (strings == null && index != 0) {
+               strings = new String [count];
+               strings [0] = text;
+       }
+       if (strings != null) {
+               if (string.equals (strings [index])) return;
+               strings [index] = string;
+       }
+       if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+       if (index == 0) {
+               if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
+                       return;
+               }
+               long hwnd = parent.handle;
+               TVITEM tvItem = new TVITEM ();
+               tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+               tvItem.hItem = 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) != 0) return;
+       parent.sort (handle, false);
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TypedListener.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TypedListener.java
new file mode 100644 (file)
index 0000000..aa0d78b
--- /dev/null
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * 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 implements 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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public TypedListener (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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void handleEvent (Event e) {
+       switch (e.type) {
+               case SWT.Activate: {
+                       ((ShellListener) eventListener).shellActivated(new ShellEvent(e));
+                       break;
+               }
+               case SWT.Arm: {
+                       ((ArmListener) eventListener).widgetArmed (new ArmEvent (e));
+                       break;
+               }
+               case SWT.Close: {
+                       /* Fields set by Decorations */
+                       ShellEvent event = new ShellEvent (e);
+                       ((ShellListener) eventListener).shellClosed(event);
+                       e.doit = event.doit;
+                       break;
+               }
+               case SWT.Collapse: {
+                       if (eventListener instanceof TreeListener) {
+                               ((TreeListener) eventListener).treeCollapsed(new TreeEvent(e));
+                       } else {
+                               ((ExpandListener) eventListener).itemCollapsed(new ExpandEvent(e));
+                       }
+                       break;
+               }
+               case SWT.Deactivate: {
+                       ((ShellListener) eventListener).shellDeactivated(new ShellEvent(e));
+                       break;
+               }
+               case SWT.Deiconify: {
+                       ((ShellListener) eventListener).shellDeiconified(new ShellEvent(e));
+                       break;
+               }
+               case SWT.DefaultSelection: {
+                       ((SelectionListener)eventListener).widgetDefaultSelected(new SelectionEvent(e));
+                       break;
+               }
+               case SWT.Dispose: {
+                       ((DisposeListener) eventListener).widgetDisposed(new DisposeEvent(e));
+                       break;
+               }
+               case SWT.DragDetect: {
+                       ((DragDetectListener) eventListener).dragDetected(new DragDetectEvent(e));
+                       break;
+               }
+               case SWT.Expand: {
+                       if (eventListener instanceof TreeListener) {
+                               ((TreeListener) eventListener).treeExpanded(new TreeEvent(e));
+                       } else {
+                               ((ExpandListener) eventListener).itemExpanded(new ExpandEvent(e));
+                       }
+                       break;
+               }
+               case SWT.FocusIn: {
+                       ((FocusListener) eventListener).focusGained(new FocusEvent(e));
+                       break;
+               }
+               case SWT.FocusOut: {
+                       ((FocusListener) eventListener).focusLost(new FocusEvent(e));
+                       break;
+               }
+               case SWT.Gesture: {
+                       GestureEvent event = new GestureEvent(e);
+                       ((GestureListener)eventListener).gesture(event);
+                       e.doit = event.doit;
+                       break;
+               }
+               case SWT.Help: {
+                       ((HelpListener) eventListener).helpRequested (new HelpEvent (e));
+                       break;
+               }
+               case SWT.Hide: {
+                       ((MenuListener) eventListener).menuHidden(new MenuEvent(e));
+                       break;
+               }
+               case SWT.Iconify: {
+                       ((ShellListener) eventListener).shellIconified(new ShellEvent(e));
+                       break;
+               }
+               case SWT.KeyDown: {
+                       /* Fields set by Control */
+                       KeyEvent event = new KeyEvent(e);
+                       ((KeyListener) eventListener).keyPressed(event);
+                       e.doit = event.doit;
+                       break;
+               }
+               case SWT.KeyUp: {
+                       /* Fields set by Control */
+                       KeyEvent event = new KeyEvent(e);
+                       ((KeyListener) eventListener).keyReleased(event);
+                       e.doit = event.doit;
+                       break;
+               }
+               case SWT.Modify: {
+                       ((ModifyListener) eventListener).modifyText(new ModifyEvent(e));
+                       break;
+               }
+               case SWT.MenuDetect: {
+                       MenuDetectEvent event = new MenuDetectEvent(e);
+                       ((MenuDetectListener) eventListener).menuDetected(event);
+                       e.x = event.x;
+                       e.y = event.y;
+                       e.doit = event.doit;
+                       e.detail = event.detail;
+                       break;
+               }
+               case SWT.MouseDown: {
+                       ((MouseListener) eventListener).mouseDown(new MouseEvent(e));
+                       break;
+               }
+               case SWT.MouseDoubleClick: {
+                       ((MouseListener) eventListener).mouseDoubleClick(new MouseEvent(e));
+                       break;
+               }
+               case SWT.MouseEnter: {
+                       ((MouseTrackListener) eventListener).mouseEnter (new MouseEvent (e));
+                       break;
+               }
+               case SWT.MouseExit: {
+                       ((MouseTrackListener) eventListener).mouseExit (new MouseEvent (e));
+                       break;
+               }
+               case SWT.MouseHover: {
+                       ((MouseTrackListener) eventListener).mouseHover (new MouseEvent (e));
+                       break;
+               }
+               case SWT.MouseMove: {
+                       ((MouseMoveListener) eventListener).mouseMove(new MouseEvent(e));
+                       return;
+               }
+               case SWT.MouseWheel: {
+                       ((MouseWheelListener) eventListener).mouseScrolled(new MouseEvent(e));
+                       return;
+               }
+               case SWT.MouseUp: {
+                       ((MouseListener) eventListener).mouseUp(new MouseEvent(e));
+                       break;
+               }
+               case SWT.Move: {
+                       ((ControlListener) eventListener).controlMoved(new ControlEvent(e));
+                       break;
+               }
+               case SWT.Paint: {
+                       /* Fields set by Control */
+                       PaintEvent event = new PaintEvent (e);
+                       ((PaintListener) eventListener).paintControl (event);
+                       e.gc = event.gc;
+                       break;
+               }
+               case SWT.Resize: {
+                       ((ControlListener) eventListener).controlResized(new ControlEvent(e));
+                       break;
+               }
+               case SWT.Segments: {
+                       SegmentEvent event = new SegmentEvent(e);
+                       ((SegmentListener) eventListener).getSegments(event);
+                       e.segments = event.segments;
+                       e.segmentsChars = event.segmentsChars;
+                       break;
+               }
+               case SWT.Selection: {
+                       /* Fields set by Sash */
+                       SelectionEvent event = new SelectionEvent (e);
+                       ((SelectionListener) eventListener).widgetSelected (event);
+                       e.x = event.x;
+                       e.y = event.y;
+                       e.doit = event.doit;
+                       break;
+               }
+               case SWT.Show: {
+                       ((MenuListener) eventListener).menuShown(new MenuEvent(e));
+                       break;
+               }
+               case SWT.Touch: {
+                       ((TouchListener)eventListener).touch(new TouchEvent(e));
+                       break;
+               }
+               case SWT.Traverse: {
+                       /* Fields set by Control */
+                       TraverseEvent event = new TraverseEvent (e);
+                       ((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);
+                       ((VerifyListener) eventListener).verifyText (event);
+                       e.text = event.text;
+                       e.doit = event.doit;
+                       break;
+               }
+       }
+}
+
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Widget.java
new file mode 100644 (file)
index 0000000..ad1f538
--- /dev/null
@@ -0,0 +1,2455 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Pierre-Yves B., pyvesdev@gmail.com - Bug 219750: [styled text] Typing ~~ inserts Ã©~~
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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;
+
+       /* Global state flags */
+       static final int DISPOSED               = 1<<0;
+       static final int CANVAS                 = 1<<1;
+       static final int KEYED_DATA             = 1<<2;
+       static final int DISABLED               = 1<<3;
+       static final int HIDDEN                 = 1<<4;
+
+       /* A layout was requested on this widget */
+       static final int LAYOUT_NEEDED  = 1<<5;
+
+       /* The preferred size of a child has changed */
+       static final int LAYOUT_CHANGED = 1<<6;
+
+       /* A layout was requested in this widget hierarchy */
+       static final int LAYOUT_CHILD = 1<<7;
+
+       /* Background flags */
+       static final int THEME_BACKGROUND = 1<<8;
+       static final int DRAW_BACKGROUND = 1<<9;
+       static final int PARENT_BACKGROUND = 1<<10;
+
+       /* Dispose and release flags */
+       static final int RELEASED               = 1<<11;
+       static final int DISPOSE_SENT   = 1<<12;
+
+       /* More global widget state flags */
+       static final int TRACK_MOUSE    = 1<<13;
+       static final int FOREIGN_HANDLE = 1<<14;
+       static final 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;
+
+       /* Notify of the opportunity to skin this widget */
+       static final int SKIN_NEEDED = 1<<21;
+
+       /* Bidi "auto" text direction */
+       static final int HAS_AUTO_DIRECTION = 1<<22;
+
+       /* Default size for widgets */
+       static final int DEFAULT_WIDTH  = 64;
+       static final int DEFAULT_HEIGHT = 64;
+
+       /* Bidi UCC to enforce text direction */
+       static final char LRE = '\u202a';
+       static final char RLE = '\u202b';
+
+       /* Bidi flag and for auto text direction */
+       static final int AUTO_TEXT_DIRECTION = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+
+       /* Initialize the Common Controls DLL */
+       static {
+               OS.InitCommonControls ();
+       }
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Widget () {
+}
+
+/**
+ * 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 Widget (Widget parent, int style) {
+       checkSubclass ();
+       checkParent (parent);
+       this.style = style;
+       display = parent.display;
+       reskinWidget ();
+}
+
+void _addListener (int eventType, Listener listener) {
+       if (eventTable == null) eventTable = new EventTable ();
+       eventTable.hook (eventType, listener);
+}
+
+void _removeListener (int eventType, Listener listener) {
+       if (eventTable == null) return;
+       eventTable.unhook (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 == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       TypedListener typedListener = new TypedListener (listener);
+       addListener (SWT.Dispose, typedListener);
+}
+
+long callWindowProc (long hwnd, int msg, long wParam, long 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) == 0) style |= int0;
+       if ((style & int0) != 0) style = (style & ~mask) | int0;
+       if ((style & int1) != 0) style = (style & ~mask) | int1;
+       if ((style & int2) != 0) style = (style & ~mask) | int2;
+       if ((style & int3) != 0) style = (style & ~mask) | int3;
+       if ((style & int4) != 0) style = (style & ~mask) | int4;
+       if ((style & int5) != 0) style = (style & ~mask) | int5;
+       return style;
+}
+
+void checkOrientation (Widget parent) {
+       style &= ~SWT.MIRRORED;
+       if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
+               if (parent != null) {
+                       if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT;
+                       if ((parent.style & SWT.RIGHT_TO_LEFT) != 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 == 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>
+ */
+protected void checkWidget () {
+       Display display = this.display;
+       if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
+       if (display.thread != Thread.currentThread ()) {
+               /*
+               * 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 != OS.GetCurrentThreadId ()) {
+                       error (SWT.ERROR_THREAD_INVALID_ACCESS);
+               }
+       }
+       if ((state & DISPOSED) != 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 ();
+}
+
+/**
+ * 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.
+ * This method does nothing if the widget is already disposed.
+ * <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);
+}
+
+boolean dragDetect (long hwnd, int x, int y, boolean filter, boolean [] detect, boolean [] consume) {
+       if (consume != null) consume [0] = false;
+       if (detect != null) detect [0] = true;
+       POINT pt = new POINT ();
+       pt.x = x;
+       pt.y = y;
+       OS.ClientToScreen (hwnd, pt);
+       return 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);
+}
+
+boolean filters (int eventType) {
+       return display.filters (eventType);
+}
+
+Widget findItem (long id) {
+       return null;
+}
+
+char [] fixMnemonic (String string) {
+       return fixMnemonic (string, false, false);
+}
+
+char [] fixMnemonic (String string, boolean spaces) {
+       return fixMnemonic (string, spaces, false);
+}
+
+char [] fixMnemonic (String string, boolean spaces, boolean removeAppended) {
+       // fixMnemonic must return a null-terminated array
+       char [] buffer = new char [string.length () + 1];
+       string.getChars (0, string.length (), buffer, 0);
+       int i = 0, j = 0;
+       while (i < buffer.length) {
+               if (buffer [i] == '&') {
+                       if (i + 1 < buffer.length && buffer [i + 1] == '&') {
+                               buffer [j++] = spaces ? ' ' : buffer [i];
+                               i++;
+                       }
+                       i++;
+               } else if (buffer [i] == '(' && removeAppended && i + 4 == string.length () && buffer [i + 1] == '&' && buffer [i + 3] == ')') {
+                       if (spaces) buffer [j++] = ' ';
+                       i += 4;
+               } 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) != 0 ? ((Object []) data) [0] : data;
+}
+
+/**
+ * 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the key 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 #setData(String, Object)
+ */
+public Object getData (String key) {
+       checkWidget();
+       if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if ((state & KEYED_DATA) != 0) {
+               Object [] table = (Object []) data;
+               for (int i=1; i<table.length; i+=2) {
+                       if (key.equals (table [i])) return table [i+1];
+               }
+       }
+       return null;
+}
+
+/**
+ * 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 == 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 == 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 string = getClass ().getName ();
+       int index = string.lastIndexOf ('.');
+       if (index == -1) return string;
+       return string.substring (index + 1, string.length ());
+}
+
+/*
+ * 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
+ */
+boolean hooks (int eventType) {
+       if (eventTable == null) return false;
+       return eventTable.hooks (eventType);
+}
+
+/**
+ * Returns <code>true</code> if the widget has auto text direction,
+ * and <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when the widget has auto direction and <code>false</code> otherwise
+ *
+ * @see SWT#AUTO_TEXT_DIRECTION
+ *
+ * @since 3.105
+ */
+public boolean isAutoDirection () {
+       return (state & HAS_AUTO_DIRECTION) != 0;
+}
+
+/**
+ * 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 (except {@link #dispose()}) using the widget.
+ * </p>
+ *
+ * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+       return (state & DISPOSED) != 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 boolean 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
+ */
+boolean isValidSubclass () {
+       return 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
+ */
+boolean isValidThread () {
+       return getDisplay ().isValidThread ();
+}
+
+void mapEvent (long 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 == 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 (boolean destroy) {
+       if ((state & DISPOSE_SENT) == 0) {
+               state |= DISPOSE_SENT;
+               sendEvent (SWT.Dispose);
+       }
+       if ((state & DISPOSED) == 0) {
+               releaseChildren (destroy);
+       }
+       if ((state & RELEASED) == 0) {
+               state |= RELEASED;
+               if (destroy) {
+                       releaseParent ();
+                       releaseWidget ();
+                       destroyWidget ();
+               } else {
+                       releaseWidget ();
+                       releaseHandle ();
+               }
+       }
+}
+
+void releaseChildren (boolean 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       _removeListener (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
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ */
+protected void removeListener (int eventType, SWTEventListener listener) {
+       checkWidget();
+       if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == 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 == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (eventTable == null) return;
+       eventTable.unhook (SWT.Dispose, listener);
+}
+
+/**
+ * Marks the widget to be skinned.
+ * <p>
+ * The skin event is sent to the receiver's display when appropriate (usually before the next event
+ * is handled). Widgets are automatically marked for skinning upon creation as well as when its skin
+ * id or class changes. The skin id and/or class can be changed by calling {@link Display#setData(String, Object)}
+ * with the keys {@link SWT#SKIN_ID} and/or {@link SWT#SKIN_CLASS}. Once the skin event is sent to a widget, it
+ * will not be sent again unless <code>reskin(int)</code> is called on the widget or on an ancestor
+ * while specifying the <code>SWT.ALL</code> flag.
+ * </p>
+ * <p>
+ * The parameter <code>flags</code> may be either:
+ * </p>
+ * <dl>
+ * <dt><b>{@link SWT#ALL}</b></dt>
+ * <dd>all children in the receiver's widget tree should be skinned</dd>
+ * <dt><b>{@link SWT#NONE}</b></dt>
+ * <dd>only the receiver should be skinned</dd>
+ * </dl>
+ * @param flags the flags specifying how to reskin
+ *
+ * @exception SWTException
+ * <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - 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.6
+ */
+public void reskin (int flags) {
+       checkWidget ();
+       reskinWidget ();
+       if ((flags & SWT.ALL) != 0) reskinChildren (flags);
+}
+
+void reskinChildren (int flags) {
+}
+
+void reskinWidget() {
+       if ((state & SKIN_NEEDED) != SKIN_NEEDED) {
+               this.state |= SKIN_NEEDED;
+               display.addSkinnableWidget(this);
+       }
+}
+
+boolean sendDragEvent (int button, int x, int y) {
+       Event event = new Event ();
+       event.button = button;
+       event.setLocationInPixels(x, y); // In Pixels
+       setInputState (event, SWT.DragDetect);
+       postEvent (SWT.DragDetect, event);
+       if (isDisposed ()) return false;
+       return event.doit;
+}
+
+boolean sendDragEvent (int button, int stateMask, int x, int y) {
+       Event event = new Event ();
+       event.button = button;
+       event.setLocationInPixels(x, 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 != null) display.sendEvent(eventTable, 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, boolean send) {
+       if (eventTable == null && !display.filters (eventType)) {
+               return;
+       }
+       if (event == null) event = new Event ();
+       event.type = eventType;
+       event.display = display;
+       event.widget = this;
+       if (event.time == 0) {
+               event.time = display.getLastEventTime ();
+       }
+       if (send) {
+               sendEvent (event);
+       } else {
+               display.postEvent (event);
+       }
+}
+
+
+void sendSelectionEvent (int type) {
+       sendSelectionEvent (type, null, false);
+}
+
+void sendSelectionEvent (int type, Event event, boolean send) {
+       if (eventTable == null && !display.filters (type)) {
+               return;
+       }
+       if (event == null) event = new Event ();
+       setInputState (event, type);
+       sendEvent (type, event, send);
+}
+
+boolean sendKeyEvent (int type, int msg, long wParam, long lParam) {
+       Event event = new Event ();
+       if (!setKeyState (event, type, wParam, lParam)) return true;
+       return sendKeyEvent (type, msg, wParam, lParam, event);
+}
+
+boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
+       sendEvent (type, event);
+       if (isDisposed ()) return false;
+       return event.doit;
+}
+
+boolean sendMouseEvent (int type, int button, long hwnd, int msg, long wParam, long lParam) {
+       return sendMouseEvent (type, button, display.getClickCount (type, button, hwnd, lParam), 0, false, hwnd, msg, wParam, lParam);
+}
+
+boolean sendMouseEvent (int type, int button, int count, int detail, boolean send, long hwnd, int msg, long wParam, long lParam) {
+       if (!hooks (type) && !filters (type)) return true;
+       Event event = new Event ();
+       event.button = button;
+       event.detail = detail;
+       event.count = count;
+       event.setLocationInPixels(OS.GET_X_LPARAM (lParam), 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;
+}
+
+boolean sendMouseWheelEvent (int type, long hwnd, long wParam, long lParam) {
+       int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam);
+       int detail = 0;
+       if (type == SWT.MouseWheel) {
+               int [] linesToScroll = new int [1];
+               OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, linesToScroll, 0);
+               if (linesToScroll [0] == OS.WHEEL_PAGESCROLL) {
+                       detail = SWT.SCROLL_PAGE;
+               } else {
+                       detail = SWT.SCROLL_LINE;
+                       delta *= linesToScroll [0];
+               }
+               /* 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;
+       } else {
+               /* Check if the delta and the remainder have the same direction (sign) */
+               if ((delta ^ display.scrollHRemainder) >= 0) delta += display.scrollHRemainder;
+               display.scrollHRemainder = delta % OS.WHEEL_DELTA;
+
+               delta = -delta;
+       }
+
+       if (!hooks (type) && !filters (type)) return true;
+       int count = delta / OS.WHEEL_DELTA;
+       POINT pt = new POINT ();
+       OS.POINTSTOPOINT (pt, lParam);
+       OS.ScreenToClient (hwnd, pt);
+       lParam = OS.MAKELPARAM (pt.x, pt.y);
+       return sendMouseEvent (type, 0, count, detail, true, hwnd, OS.WM_MOUSEWHEEL, wParam, lParam);
+}
+
+/**
+ * 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) != 0) {
+               ((Object []) this.data) [0] = data;
+       } else {
+               this.data = 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 IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the key 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 #getData(String)
+ */
+public void setData (String key, Object value) {
+       checkWidget();
+       if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+       int index = 1;
+       Object [] table = null;
+       if ((state & KEYED_DATA) != 0) {
+               table = (Object []) data;
+               while (index < table.length) {
+                       if (key.equals (table [index])) break;
+                       index += 2;
+               }
+       }
+       if (value != null) {
+               if ((state & KEYED_DATA) != 0) {
+                       if (index == table.length) {
+                               Object [] newTable = new Object [table.length + 2];
+                               System.arraycopy (table, 0, newTable, 0, table.length);
+                               data = table = newTable;
+                       }
+               } else {
+                       table = new Object [3];
+                       table [0] = data;
+                       data = table;
+                       state |= KEYED_DATA;
+               }
+               table [index] = key;
+               table [index + 1] = value;
+       } else {
+               if ((state & KEYED_DATA) != 0) {
+                       if (index != table.length) {
+                               int length = table.length - 2;
+                               if (length == 1) {
+                                       data = table [0];
+                                       state &= ~KEYED_DATA;
+                               } else {
+                                       Object [] newTable = new Object [length];
+                                       System.arraycopy (table, 0, newTable, 0, index);
+                                       System.arraycopy (table, index + 2, newTable, index, length - index);
+                                       data = newTable;
+                               }
+                       }
+               }
+       }
+       if (key.equals(SWT.SKIN_CLASS) || key.equals(SWT.SKIN_ID)) this.reskin(SWT.ALL);
+}
+
+boolean sendFocusEvent (int type) {
+       sendEvent (type);
+       // widget could be disposed at this point
+       return true;
+}
+
+boolean 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;
+       /*
+       * 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.
+       */
+       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 == 1) event.stateMask &= ~SWT.BUTTON1;
+                       if (event.button == 2) event.stateMask &= ~SWT.BUTTON2;
+                       if (event.button == 3) event.stateMask &= ~SWT.BUTTON3;
+                       if (event.button == 4) event.stateMask &= ~SWT.BUTTON4;
+                       if (event.button == 5) event.stateMask &= ~SWT.BUTTON5;
+                       break;
+               case SWT.MouseUp:
+                       if (event.button == 1) event.stateMask |= SWT.BUTTON1;
+                       if (event.button == 2) event.stateMask |= SWT.BUTTON2;
+                       if (event.button == 3) event.stateMask |= SWT.BUTTON3;
+                       if (event.button == 4) event.stateMask |= SWT.BUTTON4;
+                       if (event.button == 5) event.stateMask |= SWT.BUTTON5;
+                       break;
+               case SWT.KeyDown:
+               case SWT.Traverse:
+                       if (event.keyCode == SWT.ALT) event.stateMask &= ~SWT.ALT;
+                       if (event.keyCode == SWT.SHIFT) event.stateMask &= ~SWT.SHIFT;
+                       if (event.keyCode == SWT.CONTROL) event.stateMask &= ~SWT.CONTROL;
+                       break;
+               case SWT.KeyUp:
+                       if (event.keyCode == SWT.ALT) event.stateMask |= SWT.ALT;
+                       if (event.keyCode == SWT.SHIFT) event.stateMask |= SWT.SHIFT;
+                       if (event.keyCode == SWT.CONTROL) event.stateMask |= SWT.CONTROL;
+                       break;
+       }
+       return true;
+}
+
+boolean setKeyState (Event event, int type, long wParam, 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 == SWT.BS) display.lastAscii = SWT.BS;
+                       break;
+               case SWT.LF:
+                       if (display.lastKey == SWT.CR) display.lastAscii = SWT.CR;
+                       break;
+       }
+
+       /*
+       * 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 == SWT.CR && display.lastAscii == SWT.CR) {
+               if ((lParam & 0x1000000) != 0) display.lastKey = SWT.KEYPAD_CR;
+       }
+
+       setLocationMask(event, type, wParam, lParam);
+
+       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 == 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 == OS.VK_CANCEL) display.lastAscii = 0x0;
+
+               event.keyCode = Display.translateKey (display.lastKey);
+       } else {
+               event.keyCode = display.lastKey;
+       }
+       if (display.lastAscii != 0 || display.lastNull) {
+               event.character = (char) display.lastAscii;
+       }
+       if (event.keyCode == 0 && event.character == 0) {
+               if (!display.lastNull) return false;
+       }
+       return setInputState (event, type);
+}
+
+int setLocationMask (Event event, int type, long wParam, long lParam) {
+       int location = SWT.NONE;
+       if (display.lastVirtual) {
+               switch (display.lastKey) {
+                       case OS.VK_SHIFT:
+                               if (OS.GetKeyState(OS.VK_LSHIFT) < 0) location = SWT.LEFT;
+                               if (OS.GetKeyState(OS.VK_RSHIFT) < 0) location = SWT.RIGHT;
+                               break;
+                       case OS.VK_NUMLOCK:
+                               location = SWT.KEYPAD;
+                               break;
+                       case OS.VK_CONTROL:
+                       case OS.VK_MENU:
+                               location = (lParam & 0x1000000) == 0 ? SWT.LEFT : SWT.RIGHT;
+                               break;
+                       case OS.VK_INSERT:
+                       case OS.VK_DELETE:
+                       case OS.VK_HOME:
+                       case OS.VK_END:
+                       case OS.VK_PRIOR:
+                       case OS.VK_NEXT:
+                       case OS.VK_UP:
+                       case OS.VK_DOWN:
+                       case OS.VK_LEFT:
+                       case OS.VK_RIGHT:
+                               if ((lParam & 0x1000000) == 0) {
+                                       location = SWT.KEYPAD;
+                               }
+                               break;
+               }
+               if (display.numpadKey(display.lastKey) != 0) {
+                       location = SWT.KEYPAD;
+               }
+       } else {
+               if (display.lastKey == SWT.KEYPAD_CR) {
+                       location = SWT.KEYPAD;
+               }
+       }
+       event.keyLocation = location;
+       return location;
+}
+
+boolean setTabGroupFocus () {
+       return setTabItemFocus ();
+}
+
+boolean setTabItemFocus () {
+       return false;
+}
+
+boolean showMenu (int x, int y) {
+       return showMenu (x, y, SWT.MENU_MOUSE);
+}
+
+boolean showMenu (int x, int y, int detail) {
+       Event event = new Event ();
+       event.setLocationInPixels(x, y);
+       event.detail = detail;
+       if (event.detail == SWT.MENU_KEYBOARD) {
+               updateMenuLocation (event);
+       }
+       sendEvent (SWT.MenuDetect, event);
+       // widget could be disposed at this point
+       if (isDisposed ()) return false;
+       if (!event.doit) return true;
+       Menu menu = getMenu ();
+       if (menu != null && !menu.isDisposed ()) {
+               Point loc = event.getLocationInPixels(); // In Pixels
+               if (x != loc.x || y != loc.y) {
+                       menu.setLocation (event.getLocation());
+               }
+               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 getName () + " {" + string + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+void updateMenuLocation (Event event) {
+       /* Do nothing */
+}
+
+LRESULT wmCaptureChanged (long hwnd, long wParam, long lParam) {
+       display.captureChanged = true;
+       return null;
+}
+
+LRESULT wmChar (long hwnd, long wParam, long lParam) {
+       display.lastAscii = (int)wParam;
+       display.lastNull = wParam == 0;
+       if (!sendKeyEvent (SWT.KeyDown, OS.WM_CHAR, wParam, lParam)) {
+               return LRESULT.ONE;
+       }
+       // widget could be disposed at this point
+       return null;
+}
+
+LRESULT wmContextMenu (long hwnd, long wParam, long lParam) {
+       if (wParam != hwnd) 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, detail = 0;
+       if (lParam != -1) {
+               POINT pt = new POINT ();
+               OS.POINTSTOPOINT (pt, lParam);
+               x = pt.x;
+               y = pt.y;
+               detail = SWT.MENU_MOUSE;
+               OS.ScreenToClient (hwnd, pt);
+               RECT rect = new 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);
+               detail = SWT.MENU_KEYBOARD;
+       }
+
+       /* Show the menu */
+       return showMenu (x, y, detail) ? LRESULT.ZERO : null;
+}
+
+LRESULT wmIMEChar (long hwnd, long wParam, long lParam) {
+       Display display = this.display;
+       display.lastKey = 0;
+       display.lastAscii = (int)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 (long hwnd, long wParam, long lParam) {
+
+       /* Ignore repeating modifier keys by testing key down state */
+       switch ((int)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) != 0) return null;
+       }
+
+       boolean lastDead = display.lastDead;
+       /* 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;
+
+       /* Map the virtual key */
+       int mapKey = OS.MapVirtualKey ((int)wParam, 2);
+       /*
+       * Feature in Windows.  For Devanagari and Bengali numbers,
+       * MapVirtualKey() returns the localized number instead of
+       * the ASCII equivalent.  For example, MapVirtualKey()
+       * maps VK_1 on the numbers keyboard to \u0967, which is
+       * the Devanagari digit '1', but not ASCII.
+       * The fix is to test for Devanagari and Bengali digits and
+       * map these explicitly.
+       *
+       * NOTE: VK_0 to VK_9 are the same as ASCII.
+       */
+       if (('\u09e6' <= mapKey && mapKey <= '\u09ef') || ('\u0966' <= mapKey && mapKey <= '\u096f')) {
+               mapKey = (int)wParam;
+       }
+
+       /*
+       * 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().
+       *
+       * 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 ((mapKey & 0x80000000) != 0) return null;
+
+       MSG msg = new 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 == 0;
+               display.lastKey = display.lastVirtual ? (int)wParam : mapKey;
+               return null;
+       }
+
+       /*
+        * When hitting accent keys twice in a row, PeekMessage only returns
+        * a WM_DEADCHAR for the first WM_KEYDOWN. Ignore the second
+        * WM_KEYDOWN and issue the key down event from inside WM_CHAR.
+        */
+       if (lastDead) {
+               display.lastVirtual = mapKey == 0;
+               display.lastKey = display.lastVirtual ? (int)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 == 0 || display.numpadKey ((int)wParam) != 0;
+       if (display.lastVirtual) {
+               display.lastKey = (int)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 == 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) != 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 = (int)OS.CharLower ((short) 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 == 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.
+               */
+               int asciiKey = display.asciiKey ((int)wParam);
+               if (asciiKey != 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 == ' ') return null;
+                       if (asciiKey != (int)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 == 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 ((int)wParam);
+                       if (display.lastAscii == 0) display.lastAscii = mapKey;
+               } else {
+                       display.lastAscii = (int)OS.CharLower ((short) mapKey);
+               }
+
+               /* Note that Ctrl+'@' is ASCII NUL and is delivered in WM_CHAR */
+               if (display.lastAscii == '@') 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 (long hwnd, long wParam, long lParam) {
+       Display display = this.display;
+
+       /*
+       * 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. */
+       int mapKey = OS.MapVirtualKey ((int)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 ().
+       */
+       if ((mapKey & 0x80000000) != 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 == 0 || display.numpadKey ((int)wParam) != 0;
+       if (display.lastVirtual) {
+               display.lastKey = (int)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 == OS.VK_CANCEL) display.lastVirtual = true;
+               if (display.lastKey == 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 (long hwnd, long wParam, long lParam) {
+       display.scrollRemainder = display.scrollHRemainder = 0;
+       long 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 == 0) return LRESULT.ZERO;
+       return new LRESULT (code);
+}
+
+LRESULT wmLButtonDblClk (long hwnd, long wParam, long 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmLButtonDown (long hwnd, long wParam, long lParam) {
+       Display display = this.display;
+       LRESULT result = null;
+       int x = OS.GET_X_LPARAM (lParam);
+       int y = OS.GET_Y_LPARAM (lParam);
+       boolean [] consume = null, detect = null;
+       boolean dragging = false, mouseDown = true;
+       int count = display.getClickCount (SWT.MouseDown, 1, hwnd, lParam);
+       if (count == 1 && (state & DRAG_DETECT) != 0 && hooks (SWT.DragDetect)) {
+               /*
+               * 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 boolean [1];
+               consume = new boolean [1];
+               dragging = dragDetect (hwnd, x, y, true, detect, consume);
+               if (isDisposed ()) return LRESULT.ZERO;
+               mouseDown = OS.GetKeyState (OS.VK_LBUTTON) < 0;
+       }
+       display.captureChanged = false;
+       boolean dispatch = sendMouseEvent (SWT.MouseDown, 1, count, 0, false, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam);
+       if (dispatch && (consume == null || !consume [0])) {
+               result = new LRESULT (callWindowProc (hwnd, OS.WM_LBUTTONDOWN, wParam, lParam));
+       } else {
+               result = LRESULT.ZERO;
+       }
+       if (mouseDown) {
+               if (!display.captureChanged && !isDisposed ()) {
+                       if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+               }
+       }
+       if (dragging) {
+               sendDragEvent (1, x, y);
+       } else {
+               if (detect != 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 (long hwnd, long wParam, long 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) == 0) {
+               if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+       }
+       return result;
+}
+
+LRESULT wmMButtonDblClk (long hwnd, long wParam, long 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmMButtonDown (long hwnd, long wParam, long 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmMButtonUp (long hwnd, long wParam, long 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) == 0) {
+               if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+       }
+       return result;
+}
+
+LRESULT wmMouseHover (long hwnd, long wParam, long lParam) {
+       if (!sendMouseEvent (SWT.MouseHover, 0, hwnd, OS.WM_MOUSEHOVER, wParam, lParam)) {
+               return LRESULT.ZERO;
+       }
+       return null;
+}
+
+LRESULT wmMouseLeave (long hwnd, long wParam, long lParam) {
+       if (!hooks (SWT.MouseExit) && !filters (SWT.MouseExit)) return null;
+       int pos = OS.GetMessagePos ();
+       POINT pt = new POINT ();
+       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 (long hwnd, long wParam, long lParam) {
+       LRESULT result = null;
+       Display display = this.display;
+       int pos = OS.GetMessagePos ();
+       if (pos != display.lastMouse || display.captureChanged) {
+               boolean trackMouse = (state & TRACK_MOUSE) != 0;
+               boolean mouseEnter = hooks (SWT.MouseEnter) || display.filters (SWT.MouseEnter);
+               boolean mouseExit = hooks (SWT.MouseExit) || display.filters (SWT.MouseExit);
+               boolean mouseHover = hooks (SWT.MouseHover) || display.filters (SWT.MouseHover);
+               if (trackMouse || mouseEnter || mouseExit || mouseHover) {
+                       TRACKMOUSEEVENT lpEventTrack = new TRACKMOUSEEVENT ();
+                       lpEventTrack.cbSize = TRACKMOUSEEVENT.sizeof;
+                       lpEventTrack.dwFlags = OS.TME_QUERY;
+                       lpEventTrack.hwndTrack = hwnd;
+                       OS.TrackMouseEvent (lpEventTrack);
+                       if (lpEventTrack.dwFlags == 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 = new MSG ();
+                                       int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+                                       while (OS.PeekMessage (msg, 0, 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 != 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 (long hwnd, long wParam, long lParam) {
+       return sendMouseWheelEvent(SWT.MouseWheel, hwnd, wParam, lParam) ? null : LRESULT.ZERO;
+}
+
+LRESULT wmMouseHWheel (long hwnd, long wParam, long lParam) {
+       return sendMouseWheelEvent(SWT.MouseHorizontalWheel, hwnd, wParam, lParam) ? null : LRESULT.ZERO;
+}
+
+LRESULT wmNCPaint (long hwnd, long wParam, long lParam) {
+       return null;
+}
+
+LRESULT wmPaint (long hwnd, long wParam, long lParam) {
+
+       /* Exit early - don't draw the background */
+       if (!hooks (SWT.Paint) && !filters (SWT.Paint)) {
+               return null;
+       }
+
+       /* Issue a paint event */
+       long rgn = OS.CreateRectRgn (0, 0, 0, 0);
+       OS.GetUpdateRgn (hwnd, rgn, false);
+       long result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam);
+       GCData data = new GCData ();
+       data.hwnd = hwnd;
+       GC gc = new_GC (data);
+       if (gc != null) {
+               OS.HideCaret (hwnd);
+               RECT rect = new RECT();
+               OS.GetRgnBox (rgn, rect);
+               int width = rect.right - rect.left;
+               int height = rect.bottom - rect.top;
+               if (width != 0 && height != 0) {
+                       long hDC = gc.handle;
+                       OS.SelectClipRgn (hDC, rgn);
+                       OS.SetMetaRgn (hDC);
+                       Event event = new Event ();
+                       event.gc = gc;
+                       event.setBoundsInPixels(new Rectangle(rect.left, rect.top, width, 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 == 0) return LRESULT.ZERO;
+       return new LRESULT (result);
+}
+
+LRESULT wmPrint (long hwnd, long wParam, long 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) != 0) {
+               if (OS.IsAppThemed ()) {
+                       int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                       if ((bits & OS.WS_EX_CLIENTEDGE) != 0) {
+                               long code = callWindowProc (hwnd, OS.WM_PRINT, wParam, lParam);
+                               RECT rect = new 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 (wParam, border, border, rect.right - border, rect.bottom - border);
+                               OS.DrawThemeBackground (display.hEditTheme (), wParam, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null);
+                               return new LRESULT (code);
+                       }
+               }
+       }
+       return null;
+}
+
+LRESULT wmRButtonDblClk (long hwnd, long wParam, long 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmRButtonDown (long hwnd, long wParam, long 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmRButtonUp (long hwnd, long wParam, long 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) == 0) {
+               if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+       }
+       return result;
+}
+
+LRESULT wmSetFocus (long hwnd, long wParam, long lParam) {
+       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 == 0) return LRESULT.ZERO;
+       return new LRESULT (code);
+}
+
+LRESULT wmSysChar (long hwnd, long wParam, long lParam) {
+       Display display = this.display;
+       display.lastAscii = (int)wParam;
+       display.lastNull = wParam == 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 */
+       boolean oldKeyHit = display.mnemonicKeyHit;
+       display.mnemonicKeyHit = true;
+       long result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam);
+       boolean 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 (long hwnd, long wParam, long 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 != OS.VK_F10) {
+               /* Make sure WM_SYSKEYDOWN was sent by ALT-<aKey>. */
+               if ((lParam & 0x20000000) == 0) return null;
+       }
+
+       /* Ignore well known system keys */
+       switch ((int)wParam) {
+               case OS.VK_F4: {
+                       long hwndShell = hwnd;
+                       while (OS.GetParent (hwndShell) != 0) {
+                               if (OS.GetWindow (hwndShell, OS.GW_OWNER) != 0) break;
+                               hwndShell = OS.GetParent (hwndShell);
+                       }
+                       int bits = OS.GetWindowLong (hwndShell, OS.GWL_STYLE);
+                       if ((bits & OS.WS_SYSMENU) != 0) return null;
+               }
+       }
+
+       /* Ignore repeating modifier keys by testing key down state */
+       switch ((int)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) != 0) return null;
+       }
+
+       /* 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. */
+       int mapKey = OS.MapVirtualKey ((int)wParam, 2);
+
+       display.lastVirtual = mapKey == 0 || display.numpadKey ((int)wParam) != 0;
+       if (display.lastVirtual) {
+               display.lastKey = (int)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 == 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;
+                       }
+                       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 = (int)OS.CharLower ((short) mapKey);
+               return null;
+       }
+
+       if (!sendKeyEvent (SWT.KeyDown, OS.WM_SYSKEYDOWN, wParam, lParam)) {
+               return LRESULT.ONE;
+       }
+       // widget could be disposed at this point
+       return null;
+}
+
+LRESULT wmSysKeyUp (long hwnd, long wParam, long lParam) {
+       return wmKeyUp (hwnd, wParam, lParam);
+}
+
+LRESULT wmXButtonDblClk (long hwnd, long wParam, long 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) == 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmXButtonDown (long hwnd, long wParam, long lParam) {
+       LRESULT result = null;
+       Display display = this.display;
+       display.captureChanged = false;
+       display.xMouse = true;
+       int button = OS.HIWORD (wParam) == 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 () != hwnd) OS.SetCapture (hwnd);
+       }
+       return result;
+}
+
+LRESULT wmXButtonUp (long hwnd, long wParam, long lParam) {
+       Display display = this.display;
+       LRESULT result = null;
+       int button = OS.HIWORD (wParam) == 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) == 0) {
+               if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+       }
+       return result;
+}
+}
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/package.html b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/package.html
new file mode 100644 (file)
index 0000000..6068615
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT widget public API classes.
+<h2>
+Package Specification</h2>
+This package contains the classes which make up the public SWT widget
+API as well as the related public support classes (for example, class
+<code>Event</code>).
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/swt-awt-win32-4930r7.dll b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-awt-win32-4930r7.dll
new file mode 100644 (file)
index 0000000..5c9a056
Binary files /dev/null and b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-awt-win32-4930r7.dll differ
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/swt-gdip-win32-4930r7.dll b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-gdip-win32-4930r7.dll
new file mode 100644 (file)
index 0000000..936173b
Binary files /dev/null and b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-gdip-win32-4930r7.dll differ
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/swt-wgl-win32-4930r7.dll b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-wgl-win32-4930r7.dll
new file mode 100644 (file)
index 0000000..7cbd991
Binary files /dev/null and b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-wgl-win32-4930r7.dll differ
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/swt-win32-4930r7.dll b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-win32-4930r7.dll
new file mode 100644 (file)
index 0000000..bafb979
Binary files /dev/null and b/bundles/org.eclipse.swt.win32.win32.x86_64/swt-win32-4930r7.dll differ
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/version.txt b/bundles/org.eclipse.swt.win32.win32.x86_64/version.txt
new file mode 100644 (file)
index 0000000..ea7eb3b
--- /dev/null
@@ -0,0 +1 @@
+version 4.924
\ No newline at end of file
index 59e88c12b6a83843b1a69dbd2cb2766cc5bdbec2..45d1286fe63d8015d1b2a39d0b7b6f12d5fbac5e 100644 (file)
                <module>org.simantics.workbench.ontology</module>
                <module>org.simantics.workbench.search</module>
                <module>winterwell.markdown</module>
+               <module>org.eclipse.swt.win32.win32.x86_64</module>
        </modules>
 
        <profiles>