*/}}
Browse Source

Wacom wintab support

YimingWu 1 year ago
parent
commit
45d33e6399
11 changed files with 1573 additions and 22 deletions
  1. 9 2
      CMakeLists.txt
  2. 4 0
      la_controllers.c
  3. 7 1
      la_interface.h
  4. 45 17
      la_kernel.c
  5. 5 0
      resources/la_properties.c
  6. 6 2
      resources/la_templates.c
  7. 34 0
      wintab/msgdef.h
  8. 269 0
      wintab/pktdef.h
  9. 920 0
      wintab/wintab.h
  10. 168 0
      wintab/wintab_utils.c
  11. 106 0
      wintab/wintab_utils.h

+ 9 - 2
CMakeLists.txt

@@ -19,12 +19,13 @@ find_package(GLEW REQUIRED)
 add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
 add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
 
-file(GLOB_RECURSE SOURCE_FILES 
+file(GLOB SOURCE_FILES 
 	./*.c ./*.cpp ./resources/*.c ./resources/*.cpp)
 
-file(GLOB_RECURSE HEADER_FILES 
+file(GLOB HEADER_FILES 
 	./*.h ./*.hpp ./resources/*.h ./resources/*.hpp)
 
+
 add_definitions(-DLAGUI_FONT_CUSTOM_PATH=\"${LAGUI_FONT_CUSTOM_PATH}\")
 add_definitions(-w)
 
@@ -37,6 +38,12 @@ include_directories(
     lagui
 )
 
+if(WIN32)
+list(APPEND SOURCE_FILES ./wintab/wintab_utils.c)
+file(GLOB wintabfiles ./wintab/*.h )
+list(APPEND HEADER_FILES ${wintabfiles})
+endif()
+
 set(LAGUI_FONTS
     "fonts/NotoEmoji-Regular.ttf"
     "fonts/NotoSansCJK-Regular.ttc"

+ 4 - 0
la_controllers.c

@@ -125,6 +125,10 @@ int OPINV_RefreshControllers(){
     la_RefreshControllers();
 #ifdef __linux__
     la_ScanWacomDevices(MAIN.dpy,XIAllDevices);
+#endif
+#ifdef _WIN32
+    MAIN.WinTabOpened = 0;
+    if(MAIN.CurrentWindow){ la_OpenWacomWinTab(MAIN.CurrentWindow->win); }
 #endif
     return LA_FINISHED;
 }

+ 7 - 1
la_interface.h

@@ -350,7 +350,8 @@ STRUCTURE(LA){
 #ifdef _WIN32
     HINSTANCE hinstance;
     HDC hdc;
-    int WinTabAvaliable;
+    int WinTabAvailable, WinTabOpened, WinTabMaxPenPressure, WinTabMaxEraserPressure;
+    int InkOrWinTab;
 #endif
 #ifdef __linux__
     XVisualInfo* xvi;
@@ -1791,7 +1792,12 @@ laUiType *la_RegisterUiType(const char *Identifer, int ForType, const char *UseO
 void laSetWindowCursor(int id);
 void laRenameWindow(laWindow* wnd, char* name);
 
+#ifdef __linux__
 void la_ScanWacomDevices(SYSTEMDISPLAY *display, int deviceid);
+#endif
+#ifdef _WIN32
+void la_OpenWacomWinTab(HWND hwnd);
+#endif
 
 void laSetFontFolderPath(char* absolute);
 int laGetReady();

+ 45 - 17
la_kernel.c

@@ -228,24 +228,28 @@ void la_DestroySystemWindowX11(laWindow* w) {
 };
 #endif //linux
 #ifdef _WIN32
+#include <msgdef.h>
 #include <wintab.h>
-void la_ScanWacomDevices(){
-    if(!MAIN.WinTabAvailable) return;
+#include <wintab_utils.h>
+#define PACKETDATA	(PK_X | PK_Y | PK_STATUS | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_TIME | PK_CURSOR)
+#define PACKETMODE	PK_BUTTONS
+#include <pktdef.h>
+
+void la_OpenWacomWinTab(HWND hwnd){
+    if((!MAIN.WinTabAvailable)||(MAIN.WinTabOpened)) return;
+
+    static LOGCONTEXT glogContext = { 0 };
 
     HCTX hctx = NULL;
-	UINT wDevice = 0;
-	UINT wExtX = 0;
-	UINT wExtY = 0;
-	UINT wWTInfoRetVal = 0;
-	AXIS TabletX = { 0 };
-	AXIS TabletY = { 0 };
+	UINT wDevice = 0; UINT wExtX = 0; UINT wExtY = 0;
+	UINT wWTInfoRetVal = 0; AXIS TabletX = { 0 }; AXIS TabletY = { 0 };
 
 	glogContext.lcOptions |= CXO_SYSTEM;
 	wWTInfoRetVal = gpWTInfoA(WTI_DEFSYSCTX, 0, &glogContext);
 	assert(wWTInfoRetVal == sizeof(LOGCONTEXT));
 
 	assert(glogContext.lcOptions & CXO_SYSTEM);
-	wsprintf(glogContext.lcName, "PrsTest Digitizing %p", hInst);
+	wsprintf(glogContext.lcName, "PrsTest Digitizing %p", MAIN.hinstance);
 	glogContext.lcOptions |= CXO_MESSAGES;
 	glogContext.lcPktData = PACKETDATA;
 	glogContext.lcPktMode = PACKETMODE;
@@ -258,6 +262,9 @@ void la_ScanWacomDevices(){
 	wWTInfoRetVal = gpWTInfoA(WTI_DEVICES, DVC_Y, &TabletY);
 	assert(wWTInfoRetVal == sizeof(AXIS));
 
+    AXIS tabletPressure = { 0 };
+    gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &tabletPressure); MAIN.WinTabMaxPenPressure = tabletPressure.axMax + 1;
+
 	glogContext.lcInOrgX = 0;
 	glogContext.lcInOrgY = 0;
 	glogContext.lcInExtX = TabletX.axMax;
@@ -266,11 +273,15 @@ void la_ScanWacomDevices(){
 	glogContext.lcOutOrgX = GetSystemMetrics(SM_XVIRTUALSCREEN);
 	glogContext.lcOutOrgY = GetSystemMetrics(SM_YVIRTUALSCREEN);
 	glogContext.lcOutExtX = GetSystemMetrics(SM_CXVIRTUALSCREEN); //SM_CXSCREEN);
-	glogContext.lcOutExtY = -GetSystemMetrics(SM_CYVIRTUALSCREEN);	//lower left to upper left. SM_CYSCREEN);
+	glogContext.lcOutExtY = -GetSystemMetrics(SM_CYVIRTUALSCREEN);	// lower left to upper left. SM_CYSCREEN);
+
+	hctx = gpWTOpenA(hwnd, &glogContext, FALSE);
 
-	hctx = gpWTOpenA(hWnd, &glogContext, FALSE);
+    if (!hctx)return;
 
-	return hctx;
+    gpWTEnable(hctx, 1); MAIN.WinTabOpened = 1;
+
+    logPrintNew("Successfully opened Wacom input device via WinTab.\n");
 }
 
 void laHideCursor() {
@@ -358,6 +369,7 @@ SYSWINDOW la_CreateWindowWin32(int x, int y, int w, int h, char* title, int Sync
         x, y, w, h, 0, 0, *inst, 0);
     if (!hwnd) { int a = GetLastError(); printf("%d", a); return 0; }
 
+    if (!MAIN.WinTabOpened) { la_OpenWacomWinTab(hwnd); }
     return hwnd;
 };
 void la_DestroySystemWindowWin32(laWindow* w) {
@@ -794,10 +806,10 @@ int laGetReadyWith(int GLMajor, int GLMinor, int BufferSamples){
         return 0;
     }
 
-    logPrintNew("Trying to load WinTab for stylus input...\n"); int WtAvailable=1;
-    if (!LoadWintab()){ logPrint("WinTab not available."); WtAvailable=0; }
-	if (!gpWTInfoA(0, 0, NULL)){ logPrint("WinTab servicenot available. (gpWTInfoA() returns 0)."); WtAvailable=0; }
-    if(WtAvailable){ MAIN.WinTabAvailable=1; }
+    logPrint("Trying to load WinTab for stylus input...\n"); int WtAvailable=1;
+    if (!LoadWintab()){ logPrint("WinTab not available.\n"); WtAvailable=0; }
+	if (!gpWTInfoA(0, 0, NULL)){ logPrint("WinTab service is not available. (gpWTInfoA() returns 0).\n"); WtAvailable=0; }
+    if (WtAvailable){ MAIN.WinTabAvailable=1; logPrint("WinTab service is available.\n"); }
 
 #endif
 
@@ -845,6 +857,8 @@ int laGetReadyWith(int GLMajor, int GLMinor, int BufferSamples){
     MAIN.IdleTime = 0.75;
     MAIN.TooltipCloseDistance = 30;
 
+    MAIN.InkOrWinTab = 1; /* Default use wacom wintab input. */
+
     //display:
     MAIN.FloatingAlpha = 0.7;
     MAIN.SolidShadowLength = 20;
@@ -956,6 +970,7 @@ void laShutoff(int SavePrefereces){
 #endif
 #ifdef _WIN32
     wglDeleteContext(MAIN.glc);
+    UnloadWintab();
 #endif
 }
 
@@ -6668,6 +6683,9 @@ LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
     UINT32 pointerId; POINTER_INPUT_TYPE pointerType;
     POINTER_PEN_INFO penInfo; POINTER_TOUCH_INFO touchInfo;
     POINT point;
+    PACKET pkt;
+    static POINT ptOld, ptNew;
+    static UINT prsOld, prsNew;
     if (!hwnd) return DefWindowProc(hwnd, message, wparam, lparam);
     switch (message) {
     case WM_PAINT:
@@ -6675,7 +6693,7 @@ LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
         break;
     case WM_MOUSEMOVE:
         la_SendMouseEvent(hwnd, LA_MOUSEMOVE, PARAM_2_FROM(lparam));
-        MAIN.IsPen = 0; MAIN.PointerIsEraser = 0;
+        MAIN.IsPen = 0;
         break;
 
     case WM_LBUTTONDOWN: la_SendMouseEvent(hwnd, LA_L_MOUSE_DOWN, PARAM_2_FROM(lparam)); break;
@@ -6690,6 +6708,15 @@ LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
         else if ((wheelmark = HIWORD(wparam)) < 0) WheelDir = LA_MOUSEDOWN;
         la_SendMouseEvent(hwnd, WheelDir|LA_KEY_MOUSE_SCROLL, PARAM_2_FROM(lparam));
         break;
+    case WT_PACKET:
+        if (!MAIN.InkOrWinTab) { break; /* Use Windows Ink. */ }
+        if (gpWTPacket((HCTX)lparam, wparam, &pkt)){
+            MAIN.StylusPressure = (real)pkt.pkNormalPressure/MAIN.WinTabMaxPenPressure;
+            real angle = (real)pkt.pkOrientation.orAzimuth / 3600*TNS_PI*2+TNS_PI/2;
+            MAIN.StylusAngleX = cos(angle); MAIN.StylusAngleY = sin(angle);
+            MAIN.IsPen = 1; MAIN.PointerIsEraser=((pkt.pkStatus & TPS_INVERT)==TPS_INVERT);
+        }
+        break;
 
     case WM_SYSCOMMAND:
         switch (wparam) {
@@ -6706,6 +6733,7 @@ LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
         la_CommandResizeWindow(hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam));
         break;
     case WM_POINTERUPDATE:
+        if (MAIN.InkOrWinTab) { break;/* Use WinTab. */ }
         pointerId = GET_POINTERID_WPARAM(wparam);
         pointerType = PT_POINTER;
 

+ 5 - 0
resources/la_properties.c

@@ -1150,6 +1150,11 @@ void la_RegisterInternalProps(){
         
             laAddIntProperty(p, "wacom_device_stylus", "Stylus Device", "Wacom stylus device ID", LA_WIDGET_INT_PLAIN, 0,0,0,0,0,0,0,offsetof(LA, WacomDeviceStylus), 0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
             laAddIntProperty(p, "wacom_device_eraser", "Eraser Device", "Wacom eraser device ID", LA_WIDGET_INT_PLAIN, 0,0,0,0,0,0,0,offsetof(LA, WacomDeviceEraser), 0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
+            
+            ep = laAddEnumProperty(p, "wacom_driver", "Wacom driver", "Wacom driver to read pressure info from on windows", 0, 0, 0, 0, 0, offsetof(LA, InkOrWinTab), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); {
+                laAddEnumItemAs(ep, "WINDOWS_INK", "Windows Ink", "Use Windows Ink pressure events (WM_POINTERUPDATE).", 0, 0);
+                laAddEnumItemAs(ep, "WINTAB", "WinTab", "Use wacom WinTab driver to read pressure events (WT_PACKET).", 1, 0);
+            }
 
             laAddFloatProperty(p, "color_picker_gamma", "Color Picker Gamma", "Allows less saturated colors to have more areas", 0,0,0,3.0,1.0, 0.05,1.5, 0,offsetof(LA, ColorPickerGamma), 0,laset_ColorPickerGamma,0,0,0,0,0,0,0,0,0);
         }

+ 6 - 2
resources/la_templates.c

@@ -1322,11 +1322,15 @@ void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorIn
 
             laShowLabel(muil, mc, "Wacom Devices:", 0, 0);
 #ifdef _WIN32
-            laShowLabel(muil, mc, "Not yet implemened on Windows.", 0, 0);
-#endif
+            b=laBeginRow(muil,mcl,0,0); laShowLabel(muil, mcl, "Driver:", 0, 0)->Flags|=LA_TEXT_ALIGN_RIGHT;
+            laShowItem(muil, mcl, 0, "LA_refresh_controllers")->Flags|=LA_UI_FLAGS_ICON;
+            laEndRow(muil, b);
+            laShowItem(muil, mcr, 0, "la.user_preferences.wacom_driver");
+#else
             laShowItem(muil, mcl, 0, "la.user_preferences.wacom_device_stylus");
             laShowItem(muil, mcl, 0, "la.user_preferences.wacom_device_eraser");
             laShowItemFull(muil, mcr, 0, "LA_refresh_controllers",0,"text=Refresh",0,0);
+#endif
         }
 
         muil = laAddTabPage(bracket, "Resource");{

+ 34 - 0
wintab/msgdef.h

@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------s
+	NAME
+		MSGPACK.H
+
+	PURPOSE
+		Selected message unpacking macros from windowsx.h
+		to circumvent compile-time memory headaches.
+
+	COPYRIGHT
+		This file is Copyright (c) Wacom Company, Ltd. 2020 All Rights Reserved
+		with portions copyright 1991-1998 by LCS/Telegraphics.
+
+		The text and information contained in this file may be freely used,
+		copied, or distributed without compensation or licensing restrictions.
+---------------------------------------------------------------------------- */
+#pragma once
+
+#ifdef WIN32
+#define GET_WM_ACTIVATE_STATE(wp, lp)           LOWORD(wp)
+#define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
+#define GET_WM_COMMAND_HWND(wp, lp)             (HWND)(lp)
+#define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
+#define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
+    (void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))
+/* -------------------------------------------------------------------------- */
+#else
+#define GET_WM_ACTIVATE_STATE(wp, lp)               (wp)
+#define GET_WM_COMMAND_ID(wp, lp)                   (wp)
+#define GET_WM_COMMAND_HWND(wp, lp)                 (HWND)LOWORD(lp)
+#define GET_WM_COMMAND_CMD(wp, lp)                  HIWORD(lp)
+#define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
+    (void)(fn)((hwnd), WM_COMMAND, (WPARAM)(int)(id), MAKELPARAM((UINT)(hwndCtl), (codeNotify)))
+/* -------------------------------------------------------------------------- */
+#endif

+ 269 - 0
wintab/pktdef.h

@@ -0,0 +1,269 @@
+/*----------------------------------------------------------------------------s
+	NAME
+		PKTDEF.H
+
+	PURPOSE
+		Used to help construct a Wintab PACKETDATA definition the application
+		uses to specify what data to receive in a Wintab data packet
+
+	COPYRIGHT
+		This file is Copyright (c) Wacom Company, Ltd. 2020 All Rights Reserved
+		with portions copyright 1991-1998 by LCS/Telegraphics.
+
+		The text and information contained in this file may be freely used,
+		copied, or distributed without compensation or licensing restrictions.
+---------------------------------------------------------------------------- */
+#pragma once
+
+/*------------------------------------------------------------------------------
+
+How to use pktdef.h:
+
+1. Include wintab.h
+2. if using just one packet format:
+	a. Define PACKETDATA and PACKETMODE as or'ed combinations of WTPKT bits
+	   (use the PK_* identifiers).
+	b. Include pktdef.h.
+	c. The generated structure typedef will be called PACKET.  Use PACKETDATA
+	   and PACKETMODE to fill in the LOGCONTEXT structure.
+3. If using multiple packet formats, for each one:
+	a. Define PACKETNAME. Its text value will be a prefix for this packet's
+	   parameters and names.
+	b. Define <PACKETNAME>PACKETDATA and <PACKETNAME>PACKETMODE similar to
+	   2.a. above.
+	c. Include pktdef.h.
+	d. The generated structure typedef will be called
+	   <PACKETNAME>PACKET. Compare with 2.c. above and example #2 below.
+4. If using extension data for extensions that report thier data in the packet,
+   do the following additional steps for each extension:
+	a. Before including pktdef.h, define <PACKETNAME>PACKET<EXTENSION>
+	   as either PKEXT_ABSOLUTE or PKEXT_RELATIVE.
+	b. The generated structure typedef will contain a field for the
+	   extension data.
+	c. Scan the WTI_EXTENSION categories to find the extension's
+	   packet mask bit.
+	d. OR the packet mask bit with <PACKETNAME>PACKETDATA and use the
+	   result in the lcPktData field of the LOGCONTEXT structure.
+	e. If <PACKETNAME>PACKET<EXTENSION> was PKEXT_RELATIVE, OR the
+	   packet mask bit with <PACKETNAME>PACKETMODE and use the result
+	   in the lcPktMode field of the LOGCONTEXT structure.
+5. If using extension data for extensions that report thier data in the extensions packet,
+   do the following additional steps for each extension:
+	a. Before including pktdef.h, define <PACKETNAME>PACKET<EXTENSION> as PKEXT_ABSOLUTE.
+	b. The generated extension structure typedef will contain a field for the
+	   extension data.
+	c. Call WTExtSet to activate the extention.  Use the context id in the WT_PACKETEXT
+	   message to retrieve the extension data <PACKETNAME>PACKETEXT.
+
+
+Example #1.	-- single packet format
+
+#include <wintab.h>
+#define PACKETDATA	PK_X | PK_Y | PK_BUTTONS	/@ x, y, buttons @/
+#define PACKETMODE	PK_BUTTONS					/@ buttons relative mode @/
+#include <pktdef.h>
+...
+	lc.lcPktData = PACKETDATA;
+	lc.lcPktMode = PACKETMODE;
+
+Example #2. -- multiple formats
+
+#include <wintab.h>
+#define PACKETNAME		MOE
+#define MOEPACKETDATA	PK_X | PK_Y | PK_BUTTONS	/@ x, y, buttons @/
+#define MOEPACKETMODE	PK_BUTTONS					/@ buttons relative mode @/
+#include <pktdef.h>
+#define PACKETNAME		LARRY
+#define LARRYPACKETDATA	PK_Y | PK_Z | PK_BUTTONS	/@ y, z, buttons @/
+#define LARRYPACKETMODE	PK_BUTTONS					/@ buttons relative mode @/
+#include <pktdef.h>
+#define PACKETNAME		CURLY
+#define CURLYPACKETDATA	PK_X | PK_Z | PK_BUTTONS	/@ x, z, buttons @/
+#define CURLYPACKETMODE	PK_BUTTONS					/@ buttons relative mode @/
+#include <pktdef.h>
+...
+	lcMOE.lcPktData = MOEPACKETDATA;
+	lcMOE.lcPktMode = MOEPACKETMODE;
+...
+	lcLARRY.lcPktData = LARRYPACKETDATA;
+	lcLARRY.lcPktMode = LARRYPACKETMODE;
+...
+	lcCURLY.lcPktData = CURLYPACKETDATA;
+	lcCURLY.lcPktMode = CURLYPACKETMODE;
+
+Example #3. -- extension packet data "XFOO".
+
+#include <wintab.h>
+#define PACKETDATA	PK_X | PK_Y | PK_BUTTONS	/@ x, y, buttons @/
+#define PACKETMODE	PK_BUTTONS					/@ buttons relative mode @/
+#define PACKETXFOO	PKEXT_ABSOLUTE				/@ XFOO absolute mode @/
+#include <pktdef.h>
+...
+UINT ScanExts(UINT wTag)
+{
+	UINT i;
+	UINT wScanTag;
+
+	/@ scan for wTag's info category. @/
+	for (i = 0; WTInfo(WTI_EXTENSIONS + i, EXT_TAG, &wScanTag); i++) {
+		 if (wTag == wScanTag) {
+			/@ return category offset from WTI_EXTENSIONS. @/
+			return i;
+		}
+	}
+	/@ return error code. @/
+	return 0xFFFF;
+}
+...
+	lc.lcPktData = PACKETDATA;
+	lc.lcPktMode = PACKETMODE;
+#ifdef PACKETXFOO
+	categoryXFOO = ScanExts(WTX_XFOO);
+	WTInfo(WTI_EXTENSIONS + categoryXFOO, EXT_MASK, &maskXFOO);
+	lc.lcPktData |= maskXFOO;
+#if PACKETXFOO == PKEXT_RELATIVE
+	lc.lcPktMode |= maskXFOO;
+#endif
+#endif
+	WTOpen(hWnd, &lc, TRUE);
+
+
+------------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+#ifndef PACKETNAME
+	/* if no packet name prefix */
+#define __PFX(x)	x
+#define __IFX(x,y)	x ## y
+#else
+	/* add prefixes and infixes to packet format names */
+#define __PFX(x)		__PFX2(PACKETNAME,x)
+#define __PFX2(p,x)		__PFX3(p,x)
+#define __PFX3(p,x)		p ## x
+#define __IFX(x,y)		__IFX2(x,PACKETNAME,y)
+#define __IFX2(x,i,y)	__IFX3(x,i,y)
+#define __IFX3(x,i,y)	x ## i ## y
+#endif
+
+#define __SFX2(x,s)		__SFX3(x,s)
+#define __SFX3(x,s)		x ## s
+
+#define __TAG  	__IFX(tag,PACKET)
+#define __TYPES	__PFX(PACKET), * __IFX(P,PACKET), NEAR * __IFX(NP,PACKET), FAR * __IFX(LP,PACKET)
+
+#define __TAGE  	__IFX(tag,PACKETEXT)
+#define __TYPESE	__PFX(PACKETEXT), * __IFX(P,PACKETEXT), NEAR * __IFX(NP,PACKETEXT), FAR * __IFX(LP,PACKETEXT)
+
+#define __DATA		(__PFX(PACKETDATA))
+#define __MODE		(__PFX(PACKETMODE))
+#define __EXT(x)	__SFX2(__PFX(PACKET),x)
+
+
+	typedef struct __TAG {
+#if (__DATA & PK_CONTEXT)
+		HCTX			pkContext;
+#endif
+#if (__DATA & PK_STATUS)
+		UINT			pkStatus;
+#endif
+#if (__DATA & PK_TIME)
+		DWORD			pkTime;
+#endif
+#if (__DATA & PK_CHANGED)
+		WTPKT			pkChanged;
+#endif
+#if (__DATA & PK_SERIAL_NUMBER)
+		UINT			pkSerialNumber;
+#endif
+#if (__DATA & PK_CURSOR)
+		UINT			pkCursor;
+#endif
+#if (__DATA & PK_BUTTONS)
+		DWORD			pkButtons;
+#endif
+#if (__DATA & PK_X)
+		LONG			pkX;
+#endif
+#if (__DATA & PK_Y)
+		LONG			pkY;
+#endif
+#if (__DATA & PK_Z)
+		LONG			pkZ;
+#endif
+#if (__DATA & PK_NORMAL_PRESSURE)
+#if (__MODE & PK_NORMAL_PRESSURE)
+		/* relative */
+		int			pkNormalPressure;
+#else
+		/* absolute */
+		UINT		pkNormalPressure;
+#endif
+#endif
+#if (__DATA & PK_TANGENT_PRESSURE)
+#if (__MODE & PK_TANGENT_PRESSURE)
+		/* relative */
+		int			pkTangentPressure;
+#else
+		/* absolute */
+		UINT		pkTangentPressure;
+#endif
+#endif
+#if (__DATA & PK_ORIENTATION)
+		ORIENTATION		pkOrientation;
+#endif
+#if (__DATA & PK_ROTATION)
+		ROTATION		pkRotation; /* 1.1 */
+#endif
+
+#ifndef NOWTEXTENSIONS
+		/* extensions begin here. */
+#if (__EXT(FKEYS) == PKEXT_RELATIVE) || (__EXT(FKEYS) == PKEXT_ABSOLUTE)
+		UINT			pkFKeys;
+#endif
+#if (__EXT(TILT) == PKEXT_RELATIVE) || (__EXT(TILT) == PKEXT_ABSOLUTE)
+		TILT			pkTilt;
+#endif
+#endif
+
+	} __TYPES;
+
+#ifndef NOWTEXTENSIONS
+	typedef struct __TAGE {
+		EXTENSIONBASE	pkBase;
+
+#if (__EXT(EXPKEYS) == PKEXT_RELATIVE) || (__EXT(EXPKEYS) == PKEXT_ABSOLUTE)
+		EXPKEYSDATA pkExpKeys; /* 1.4 */
+#endif
+#if (__EXT(TOUCHSTRIP) == PKEXT_RELATIVE) || (__EXT(TOUCHSTRIP) == PKEXT_ABSOLUTE)
+		SLIDERDATA	pkTouchStrip; /* 1.4 */
+#endif
+#if (__EXT(TOUCHRING) == PKEXT_RELATIVE) || (__EXT(TOUCHRING) == PKEXT_ABSOLUTE)
+		SLIDERDATA	pkTouchRing; /* 1.4 */
+#endif
+
+	} __TYPESE;
+#endif
+
+#undef PACKETNAME
+#undef __TAG
+#undef __TAGE
+#undef __TAG2
+#undef __TYPES
+#undef __TYPESE
+#undef __TYPES2
+#undef __DATA
+#undef __MODE
+#undef __PFX
+#undef __PFX2
+#undef __PFX3
+#undef __IFX
+#undef __IFX2
+#undef __IFX3
+#undef __SFX2
+#undef __SFX3
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */

+ 920 - 0
wintab/wintab.h

@@ -0,0 +1,920 @@
+/* -------------------------------- wintab.h -------------------------------- */
+/* Combined 16 & 32-bit version. */
+
+/*------------------------------------------------------------------------------
+The text and information contained in this file may be freely used,
+copied, or distributed without compensation or licensing restrictions.
+
+This file is Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved
+with portions copyright 1991-1998 by LCS/Telegraphics.
+------------------------------------------------------------------------------*/
+
+#ifndef _INC_WINTAB	/* prevent multiple includes */
+#define _INC_WINTAB
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+	/* -------------------------------------------------------------------------- */
+	/* Messages */
+#ifndef NOWTMESSAGES
+
+#define WT_DEFBASE			0x7FF0
+#define WT_MAXOFFSET			0xF
+
+#define _WT_PACKET(b)		((b)+0)
+#define _WT_CTXOPEN(b)		((b)+1)
+#define _WT_CTXCLOSE(b)		((b)+2)
+#define _WT_CTXUPDATE(b)	((b)+3)
+#define _WT_CTXOVERLAP(b)	((b)+4)
+#define _WT_PROXIMITY(b)	((b)+5)
+#define _WT_INFOCHANGE(b)	((b)+6)
+#define _WT_CSRCHANGE(b)	((b)+7) /* 1.1 */
+#define _WT_PACKETEXT(b)	((b)+8) /* 1.4 */
+#define _WT_MAX(b)			((b)+WT_MAXOFFSET)
+
+#define WT_PACKET				_WT_PACKET(WT_DEFBASE)
+#define WT_CTXOPEN			_WT_CTXOPEN(WT_DEFBASE)
+#define WT_CTXCLOSE			_WT_CTXCLOSE(WT_DEFBASE)
+#define WT_CTXUPDATE			_WT_CTXUPDATE(WT_DEFBASE)
+#define WT_CTXOVERLAP		_WT_CTXOVERLAP(WT_DEFBASE)
+#define WT_PROXIMITY			_WT_PROXIMITY(WT_DEFBASE)
+#define WT_INFOCHANGE		_WT_INFOCHANGE(WT_DEFBASE)
+#define WT_CSRCHANGE			_WT_CSRCHANGE(WT_DEFBASE) /* 1.1 */
+#define WT_PACKETEXT			_WT_PACKETEXT(WT_DEFBASE) /* 1.4 */
+#define WT_MAX					_WT_MAX(WT_DEFBASE)
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* Data Types */
+
+/* -------------------------------------------------------------------------- */
+/* COMMON DATA DEFS */
+
+	DECLARE_HANDLE(HMGR);		/* manager handle */
+	DECLARE_HANDLE(HCTX);		/* context handle */
+	DECLARE_HANDLE(HWTHOOK);	/* hook handle */
+
+	typedef DWORD WTPKT;			/* packet mask */
+
+
+#ifndef NOWTPKT
+
+	/* WTPKT bits */
+#define PK_CONTEXT				0x0001	/* reporting context */
+#define PK_STATUS					0x0002	/* status bits */
+#define PK_TIME					0x0004	/* time stamp */
+#define PK_CHANGED				0x0008	/* change bit vector */
+#define PK_SERIAL_NUMBER		0x0010	/* packet serial number */
+#define PK_CURSOR					0x0020	/* reporting cursor */
+#define PK_BUTTONS				0x0040	/* button information */
+#define PK_X						0x0080	/* x axis */
+#define PK_Y						0x0100	/* y axis */
+#define PK_Z						0x0200	/* z axis */
+#define PK_NORMAL_PRESSURE		0x0400	/* normal or tip pressure */
+#define PK_TANGENT_PRESSURE	0x0800	/* tangential or barrel pressure */
+#define PK_ORIENTATION			0x1000	/* orientation info: tilts */
+#define PK_ROTATION				0x2000	/* rotation info; 1.1 */
+
+#endif
+
+	typedef DWORD FIX32;				/* fixed-point arithmetic type */
+
+#ifndef NOFIX32
+#define INT(x)			HIWORD(x)
+#define FRAC(x)		LOWORD(x)
+
+#define CASTFIX32(x)	((FIX32)((x)*65536L))
+
+#define ROUND(x)		(INT(x) + (FRAC(x) > (WORD)0x8000))
+
+#define FIX_MUL(c, a, b)							\
+		(c = (((DWORD)FRAC(a) * FRAC(b)) >> 16) +	\
+			(DWORD)INT(a) * FRAC(b) +					\
+			(DWORD)INT(b) * FRAC(a) +					\
+			((DWORD)INT(a) * INT(b) << 16))
+
+#ifdef _WINDLL
+#define FIX_DIV_SC static
+#else
+#define FIX_DIV_SC
+#endif
+
+#define FIX_DIV(c, a, b)						\
+		{													\
+			FIX_DIV_SC DWORD temp, rem, btemp;	\
+															\
+			/* fraction done bytewise */			\
+			temp = ((a / b) << 16);					\
+			rem = a % b;								\
+			btemp = b;									\
+			if (INT(btemp) < 256) {					\
+				rem <<= 8;								\
+			}												\
+			else {										\
+				btemp >>= 8;							\
+			}												\
+			temp += ((rem / btemp) << 8);			\
+			rem %= btemp;								\
+			rem <<= 8;									\
+			temp += rem / btemp;						\
+			c = temp;									\
+		}
+#endif
+
+	/* -------------------------------------------------------------------------- */
+	/* INFO DATA DEFS */
+
+#ifndef NOWTINFO
+
+#ifndef NOWTAXIS
+
+	typedef struct tagAXIS {
+		LONG	axMin;
+		LONG	axMax;
+		UINT	axUnits;
+		FIX32	axResolution;
+	} AXIS, * PAXIS, NEAR* NPAXIS, FAR* LPAXIS;
+
+	/* unit specifiers */
+#define TU_NONE			0
+#define TU_INCHES		1
+#define TU_CENTIMETERS	2
+#define TU_CIRCLE		3
+
+#endif
+
+#ifndef NOWTSYSBUTTONS
+
+/* system button assignment values */
+#define SBN_NONE			0x00
+#define SBN_LCLICK		0x01
+#define SBN_LDBLCLICK	0x02
+#define SBN_LDRAG			0x03
+#define SBN_RCLICK		0x04
+#define SBN_RDBLCLICK	0x05
+#define SBN_RDRAG			0x06
+#define SBN_MCLICK		0x07
+#define SBN_MDBLCLICK	0x08
+#define SBN_MDRAG			0x09
+/* for Pen Windows */
+#define SBN_PTCLICK		0x10
+#define SBN_PTDBLCLICK	0x20
+#define SBN_PTDRAG		0x30
+#define SBN_PNCLICK		0x40
+#define SBN_PNDBLCLICK	0x50
+#define SBN_PNDRAG		0x60
+#define SBN_P1CLICK		0x70
+#define SBN_P1DBLCLICK	0x80
+#define SBN_P1DRAG		0x90
+#define SBN_P2CLICK		0xA0
+#define SBN_P2DBLCLICK	0xB0
+#define SBN_P2DRAG		0xC0
+#define SBN_P3CLICK		0xD0
+#define SBN_P3DBLCLICK	0xE0
+#define SBN_P3DRAG		0xF0
+
+#endif
+
+#ifndef NOWTCAPABILITIES
+
+/* hardware capabilities */
+#define HWC_INTEGRATED		0x0001
+#define HWC_TOUCH				0x0002
+#define HWC_HARDPROX			0x0004
+#define HWC_PHYSID_CURSORS	0x0008 /* 1.1 */
+#endif
+
+#ifndef NOWTIFC
+
+#ifndef NOWTCURSORS
+
+/* cursor capabilities */
+#define CRC_MULTIMODE	0x0001 /* 1.1 */
+#define CRC_AGGREGATE	0x0002 /* 1.1 */
+#define CRC_INVERT		0x0004 /* 1.1 */
+
+#endif 
+
+/* info categories */
+#define WTI_INTERFACE		1
+#define IFC_WINTABID			1
+#define IFC_SPECVERSION		2
+#define IFC_IMPLVERSION		3
+#define IFC_NDEVICES			4
+#define IFC_NCURSORS			5
+#define IFC_NCONTEXTS		6
+#define IFC_CTXOPTIONS		7
+#define IFC_CTXSAVESIZE		8
+#define IFC_NEXTENSIONS		9
+#define IFC_NMANAGERS		10
+#define IFC_MAX				10
+
+
+#endif
+
+#ifndef NOWTSTATUS
+
+#define WTI_STATUS			2
+#define STA_CONTEXTS			1
+#define STA_SYSCTXS			2
+#define STA_PKTRATE			3
+#define STA_PKTDATA			4
+#define STA_MANAGERS			5
+#define STA_SYSTEM			6
+#define STA_BUTTONUSE		7
+#define STA_SYSBTNUSE		8
+#define STA_MAX				8
+
+#endif
+
+#ifndef NOWTDEFCONTEXT
+
+#define WTI_DEFCONTEXT	3
+#define WTI_DEFSYSCTX	4
+#define WTI_DDCTXS		400 /* 1.1 */
+#define WTI_DSCTXS		500 /* 1.1 */
+#define CTX_NAME			1
+#define CTX_OPTIONS		2
+#define CTX_STATUS		3
+#define CTX_LOCKS			4
+#define CTX_MSGBASE		5
+#define CTX_DEVICE		6
+#define CTX_PKTRATE		7
+#define CTX_PKTDATA		8
+#define CTX_PKTMODE		9
+#define CTX_MOVEMASK		10
+#define CTX_BTNDNMASK	11
+#define CTX_BTNUPMASK	12
+#define CTX_INORGX		13
+#define CTX_INORGY		14
+#define CTX_INORGZ		15
+#define CTX_INEXTX		16
+#define CTX_INEXTY		17
+#define CTX_INEXTZ		18
+#define CTX_OUTORGX		19
+#define CTX_OUTORGY		20
+#define CTX_OUTORGZ		21
+#define CTX_OUTEXTX		22
+#define CTX_OUTEXTY		23
+#define CTX_OUTEXTZ		24
+#define CTX_SENSX			25
+#define CTX_SENSY			26
+#define CTX_SENSZ			27
+#define CTX_SYSMODE		28
+#define CTX_SYSORGX		29
+#define CTX_SYSORGY		30
+#define CTX_SYSEXTX		31
+#define CTX_SYSEXTY		32
+#define CTX_SYSSENSX		33
+#define CTX_SYSSENSY		34
+#define CTX_MAX			34
+
+#endif
+
+#ifndef NOWTDEVICES
+
+#define WTI_DEVICES		100
+#define DVC_NAME			1
+#define DVC_HARDWARE		2
+#define DVC_NCSRTYPES	3
+#define DVC_FIRSTCSR		4
+#define DVC_PKTRATE		5
+#define DVC_PKTDATA		6
+#define DVC_PKTMODE		7
+#define DVC_CSRDATA		8
+#define DVC_XMARGIN		9
+#define DVC_YMARGIN		10
+#define DVC_ZMARGIN		11
+#define DVC_X				12
+#define DVC_Y				13
+#define DVC_Z				14
+#define DVC_NPRESSURE	15
+#define DVC_TPRESSURE	16
+#define DVC_ORIENTATION	17
+#define DVC_ROTATION		18 /* 1.1 */
+#define DVC_PNPID			19 /* 1.1 */
+#define DVC_MAX			19
+
+#endif
+
+#ifndef NOWTCURSORS
+
+#define WTI_CURSORS			200
+#define CSR_NAME				1
+#define CSR_ACTIVE			2
+#define CSR_PKTDATA			3
+#define CSR_BUTTONS			4
+#define CSR_BUTTONBITS		5
+#define CSR_BTNNAMES			6
+#define CSR_BUTTONMAP		7
+#define CSR_SYSBTNMAP		8
+#define CSR_NPBUTTON			9
+#define CSR_NPBTNMARKS		10
+#define CSR_NPRESPONSE		11
+#define CSR_TPBUTTON			12
+#define CSR_TPBTNMARKS		13
+#define CSR_TPRESPONSE		14
+#define CSR_PHYSID			15 /* 1.1 */
+#define CSR_MODE				16 /* 1.1 */
+#define CSR_MINPKTDATA		17 /* 1.1 */
+#define CSR_MINBUTTONS		18 /* 1.1 */
+#define CSR_CAPABILITIES	19 /* 1.1 */
+#define CSR_TYPE				20 /* 1.2 */
+#define CSR_MAX				20
+
+#endif
+
+#ifndef NOWTEXTENSIONS
+
+#define WTI_EXTENSIONS	300
+#define EXT_NAME			1
+#define EXT_TAG			2
+#define EXT_MASK			3
+#define EXT_SIZE			4
+#define EXT_AXES			5
+#define EXT_DEFAULT		6
+#define EXT_DEFCONTEXT	7
+#define EXT_DEFSYSCTX	8
+#define EXT_CURSORS		9
+#define EXT_DEVICES     110 /* Allow 100 cursors */
+#define EXT_MAX			210 /* Allow 100 devices */
+
+#endif
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* CONTEXT DATA DEFS */
+
+#define LCNAMELEN		40
+#define LC_NAMELEN	40
+#ifdef WIN32
+	typedef struct tagLOGCONTEXTA {
+		char	lcName[LCNAMELEN];
+		UINT	lcOptions;
+		UINT	lcStatus;
+		UINT	lcLocks;
+		UINT	lcMsgBase;
+		UINT	lcDevice;
+		UINT	lcPktRate;
+		WTPKT	lcPktData;
+		WTPKT	lcPktMode;
+		WTPKT	lcMoveMask;
+		DWORD	lcBtnDnMask;
+		DWORD	lcBtnUpMask;
+		LONG	lcInOrgX;
+		LONG	lcInOrgY;
+		LONG	lcInOrgZ;
+		LONG	lcInExtX;
+		LONG	lcInExtY;
+		LONG	lcInExtZ;
+		LONG	lcOutOrgX;
+		LONG	lcOutOrgY;
+		LONG	lcOutOrgZ;
+		LONG	lcOutExtX;
+		LONG	lcOutExtY;
+		LONG	lcOutExtZ;
+		FIX32	lcSensX;
+		FIX32	lcSensY;
+		FIX32	lcSensZ;
+		BOOL	lcSysMode;
+		int	lcSysOrgX;
+		int	lcSysOrgY;
+		int	lcSysExtX;
+		int	lcSysExtY;
+		FIX32	lcSysSensX;
+		FIX32	lcSysSensY;
+	} LOGCONTEXTA, * PLOGCONTEXTA, NEAR* NPLOGCONTEXTA, FAR* LPLOGCONTEXTA;
+	typedef struct tagLOGCONTEXTW {
+		WCHAR	lcName[LCNAMELEN];
+		UINT	lcOptions;
+		UINT	lcStatus;
+		UINT	lcLocks;
+		UINT	lcMsgBase;
+		UINT	lcDevice;
+		UINT	lcPktRate;
+		WTPKT	lcPktData;
+		WTPKT	lcPktMode;
+		WTPKT	lcMoveMask;
+		DWORD	lcBtnDnMask;
+		DWORD	lcBtnUpMask;
+		LONG	lcInOrgX;
+		LONG	lcInOrgY;
+		LONG	lcInOrgZ;
+		LONG	lcInExtX;
+		LONG	lcInExtY;
+		LONG	lcInExtZ;
+		LONG	lcOutOrgX;
+		LONG	lcOutOrgY;
+		LONG	lcOutOrgZ;
+		LONG	lcOutExtX;
+		LONG	lcOutExtY;
+		LONG	lcOutExtZ;
+		FIX32	lcSensX;
+		FIX32	lcSensY;
+		FIX32	lcSensZ;
+		BOOL	lcSysMode;
+		int	lcSysOrgX;
+		int	lcSysOrgY;
+		int	lcSysExtX;
+		int	lcSysExtY;
+		FIX32	lcSysSensX;
+		FIX32	lcSysSensY;
+	} LOGCONTEXTW, * PLOGCONTEXTW, NEAR* NPLOGCONTEXTW, FAR* LPLOGCONTEXTW;
+#ifdef UNICODE
+	typedef LOGCONTEXTW LOGCONTEXT;
+	typedef PLOGCONTEXTW PLOGCONTEXT;
+	typedef NPLOGCONTEXTW NPLOGCONTEXT;
+	typedef LPLOGCONTEXTW LPLOGCONTEXT;
+#else
+	typedef LOGCONTEXTA LOGCONTEXT;
+	typedef PLOGCONTEXTA PLOGCONTEXT;
+	typedef NPLOGCONTEXTA NPLOGCONTEXT;
+	typedef LPLOGCONTEXTA LPLOGCONTEXT;
+#endif /* UNICODE */
+#else /* WIN32 */
+	typedef struct tagLOGCONTEXT {
+		char	lcName[LCNAMELEN];
+		UINT	lcOptions;
+		UINT	lcStatus;
+		UINT	lcLocks;
+		UINT	lcMsgBase;
+		UINT	lcDevice;
+		UINT	lcPktRate;
+		WTPKT	lcPktData;
+		WTPKT	lcPktMode;
+		WTPKT	lcMoveMask;
+		DWORD	lcBtnDnMask;
+		DWORD	lcBtnUpMask;
+		LONG	lcInOrgX;
+		LONG	lcInOrgY;
+		LONG	lcInOrgZ;
+		LONG	lcInExtX;
+		LONG	lcInExtY;
+		LONG	lcInExtZ;
+		LONG	lcOutOrgX;
+		LONG	lcOutOrgY;
+		LONG	lcOutOrgZ;
+		LONG	lcOutExtX;
+		LONG	lcOutExtY;
+		LONG	lcOutExtZ;
+		FIX32	lcSensX;
+		FIX32	lcSensY;
+		FIX32	lcSensZ;
+		BOOL	lcSysMode;
+		int	lcSysOrgX;
+		int	lcSysOrgY;
+		int	lcSysExtX;
+		int	lcSysExtY;
+		FIX32	lcSysSensX;
+		FIX32	lcSysSensY;
+	} LOGCONTEXT, * PLOGCONTEXT, NEAR* NPLOGCONTEXT, FAR* LPLOGCONTEXT;
+#endif /* WIN32 */
+
+	/* context option values */
+#define CXO_SYSTEM		0x0001
+#define CXO_PEN			0x0002
+#define CXO_MESSAGES		0x0004
+#define CXO_MARGIN		0x8000
+#define CXO_MGNINSIDE	0x4000
+#define CXO_CSRMESSAGES	0x0008 /* 1.1 */
+
+/* context status values */
+#define CXS_DISABLED		0x0001
+#define CXS_OBSCURED		0x0002
+#define CXS_ONTOP			0x0004
+
+/* context lock values */
+#define CXL_INSIZE		0x0001
+#define CXL_INASPECT		0x0002
+#define CXL_SENSITIVITY	0x0004
+#define CXL_MARGIN		0x0008
+#define CXL_SYSOUT		0x0010
+
+/* -------------------------------------------------------------------------- */
+/* EVENT DATA DEFS */
+
+/* For packet structure definition, see pktdef.h */
+
+/* packet status values */
+#define TPS_PROXIMITY		0x0001
+#define TPS_QUEUE_ERR		0x0002
+#define TPS_MARGIN			0x0004
+#define TPS_GRAB				0x0008
+#define TPS_INVERT			0x0010 /* 1.1 */
+
+	typedef struct tagORIENTATION {
+		int orAzimuth;
+		int orAltitude;
+		int orTwist;
+	} ORIENTATION, * PORIENTATION, NEAR* NPORIENTATION, FAR* LPORIENTATION;
+
+	typedef struct tagROTATION { /* 1.1 */
+		int roPitch;
+		int roRoll;
+		int roYaw;
+	} ROTATION, * PROTATION, NEAR* NPROTATION, FAR* LPROTATION;
+	// grandfather in obsolete member names.
+#define rotPitch	roPitch
+#define rotRoll	roRoll
+#define rotYaw		roYaw
+
+
+/* relative buttons */
+#define TBN_NONE	0
+#define TBN_UP		1
+#define TBN_DOWN	2
+
+/* -------------------------------------------------------------------------- */
+/* DEVICE CONFIG CONSTANTS */
+
+#ifndef NOWTDEVCFG
+
+#define WTDC_NONE		0
+#define WTDC_CANCEL		1
+#define WTDC_OK			2
+#define WTDC_RESTART	3
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* HOOK CONSTANTS */
+
+#ifndef NOWTHOOKS
+
+#define WTH_PLAYBACK			1
+#define WTH_RECORD			2
+
+#define WTHC_GETLPLPFN		(-3)
+#define WTHC_LPLPFNNEXT		(-2)
+#define WTHC_LPFNNEXT		(-1)
+#define WTHC_ACTION			0
+#define WTHC_GETNEXT			1
+#define WTHC_SKIP				2
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* PREFERENCE FUNCTION CONSTANTS */
+
+#ifndef NOWTPREF
+
+#define WTP_LPDEFAULT	((LPVOID)-1L)
+#define WTP_DWDEFAULT	((DWORD)-1L)
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* EXTENSION TAGS AND CONSTANTS */
+
+#ifndef NOWTEXTENSIONS
+
+/* constants for use with pktdef.h */
+#define PKEXT_ABSOLUTE	1
+#define PKEXT_RELATIVE	2
+
+/* Extension tags. */
+#define WTX_OBT				0	/* Out of bounds tracking */
+#define WTX_FKEYS				1	/* Function keys */
+#define WTX_TILT				2	/* Raw Cartesian tilt; 1.1 */
+#define WTX_CSRMASK			3	/* select input by cursor type; 1.1 */
+#define WTX_XBTNMASK			4	/* Extended button mask; 1.1 */
+#define WTX_EXPKEYS			5	/* ExpressKeys; 1.3 - DEPRECATED: see WTX_EXPKEYS2 */
+#define WTX_TOUCHSTRIP		6	/* TouchStrips; 1.4 */
+#define WTX_TOUCHRING		7	/* TouchRings; 1.4 */
+#define WTX_EXPKEYS2			8	/* ExpressKeys; 1.4 */
+
+	typedef struct tagXBTNMASK {
+		BYTE xBtnDnMask[32];
+		BYTE xBtnUpMask[32];
+	} XBTNMASK;
+
+	typedef struct tagTILT { /* 1.1 */
+		int tiltX;
+		int tiltY;
+	} TILT;
+
+	typedef struct tagEXTENSIONBASE { /* 1.4 */
+		HCTX		nContext;
+		UINT		nStatus;
+		DWORD		nTime;
+		UINT		nSerialNumber;
+	} EXTENSIONBASE;
+
+	typedef struct tagEXPKEYSDATA { /* 1.4 */
+		BYTE		nTablet;
+		BYTE		nControl;
+		BYTE		nLocation;
+		BYTE		nReserved;
+		DWORD		nState;
+	} EXPKEYSDATA;
+
+	typedef struct tagSLIDERDATA { /* 1.4 */
+		BYTE		nTablet;
+		BYTE		nControl;
+		BYTE		nMode;
+		BYTE		nReserved;
+		DWORD		nPosition;
+	} SLIDERDATA;
+
+	typedef struct tagEXTPROPERTY { /* 1.4 */
+		BYTE		version;				// Structure version, 0 for now
+		BYTE		tabletIndex;		// 0-based index for tablet
+		BYTE		controlIndex;		// 0-based index for control 
+		BYTE		functionIndex;		// 0-based index for control's sub-function
+		WORD		propertyID;			// property ID
+		WORD		reserved;			// DWORD-alignment filler
+		DWORD		dataSize;			// number of bytes in data[] buffer
+		BYTE		data[1];				// raw data
+	} EXTPROPERTY;
+
+#define TABLET_PROPERTY_CONTROLCOUNT	 0			// UINT32: number of physical controls on tablet
+#define TABLET_PROPERTY_FUNCCOUNT		 1			// UINT32: number of functions of control
+#define TABLET_PROPERTY_AVAILABLE		 2			// BOOL: control/mode is available for override
+#define TABLET_PROPERTY_MIN				 3			// UINT32: minimum value
+#define TABLET_PROPERTY_MAX				 4			// UINT32: maximum value
+#define TABLET_PROPERTY_OVERRIDE			 5			// BOOL: control is overridden
+#define TABLET_PROPERTY_OVERRIDE_NAME	 6			// UTF-8: Displayable name when control is overridden
+#define TABLET_PROPERTY_LOCATION			 11		// UINT32: Physical location of control (see TABLET_LOC_*)
+
+#define TABLET_LOC_LEFT				0
+#define TABLET_LOC_RIGHT			1
+#define TABLET_LOC_TOP				2
+#define TABLET_LOC_BOTTOM			3
+#define TABLET_LOC_TRANSDUCER		4
+
+#endif
+
+	/* -------------------------------------------------------------------------- */
+	/* -------------------------------------------------------------------------- */
+	/* Functions */
+
+#ifndef API
+#ifndef WINAPI
+#define API			FAR PASCAL
+#else
+#define API			WINAPI
+#endif
+#endif
+
+#ifndef NOWTCALLBACKS
+
+#ifndef CALLBACK
+#define CALLBACK	FAR PASCAL
+#endif
+
+#ifndef NOWTMANAGERFXNS
+/* callback function types */
+	typedef BOOL(WINAPI* WTENUMPROC)(HCTX, LPARAM); /* changed CALLBACK->WINAPI, 1.1 */
+	typedef BOOL(WINAPI* WTCONFIGPROC)(HCTX, HWND);
+	typedef LRESULT(WINAPI* WTHOOKPROC)(int, WPARAM, LPARAM);
+	typedef WTHOOKPROC FAR* LPWTHOOKPROC;
+#endif
+
+#endif
+
+
+#ifndef NOWTFUNCTIONS
+
+#ifndef NOWTBASICFXNS
+	/* BASIC FUNCTIONS */
+#ifdef WIN32
+	UINT API WTInfoA(UINT, UINT, LPVOID);
+#define ORD_WTInfoA						20
+	UINT API WTInfoW(UINT, UINT, LPVOID);
+#define ORD_WTInfoW						1020
+#ifdef UNICODE
+#define WTInfo			WTInfoW
+#define ORD_WTInfo	ORD_WTInfoW
+#else
+#define WTInfo			WTInfoA
+#define ORD_WTInfo	ORD_WTInfoA
+#endif /* !UNICODE */
+#else
+	UINT API WTInfo(UINT, UINT, LPVOID);
+#define ORD_WTInfo							20
+#endif
+#ifdef WIN32
+	HCTX API WTOpenA(HWND, LPLOGCONTEXTA, BOOL);
+#define ORD_WTOpenA							21
+	HCTX API WTOpenW(HWND, LPLOGCONTEXTW, BOOL);
+#define ORD_WTOpenW							1021
+#ifdef UNICODE
+#define WTOpen			WTOpenW
+#define ORD_WTOpen	ORD_WTOpenW
+#else
+#define WTOpen			WTOpenA
+#define ORD_WTOpen	ORD_WTOpenA
+#endif /* !UNICODE */
+#else
+	HCTX API WTOpen(HWND, LPLOGCONTEXT, BOOL);
+#define ORD_WTOpen							21
+#endif
+	BOOL API WTClose(HCTX);
+#define ORD_WTClose							22
+	int API WTPacketsGet(HCTX, int, LPVOID);
+#define ORD_WTPacketsGet					23
+	BOOL API WTPacket(HCTX, UINT, LPVOID);
+#define ORD_WTPacket							24
+#endif
+
+#ifndef NOWTVISIBILITYFXNS
+	/* VISIBILITY FUNCTIONS */
+	BOOL API WTEnable(HCTX, BOOL);
+#define ORD_WTEnable							40
+	BOOL API WTOverlap(HCTX, BOOL);
+#define ORD_WTOverlap						41
+#endif
+
+#ifndef NOWTCTXEDITFXNS
+	/* CONTEXT EDITING FUNCTIONS */
+	BOOL API WTConfig(HCTX, HWND);
+#define ORD_WTConfig							60
+#ifdef WIN32
+	BOOL API WTGetA(HCTX, LPLOGCONTEXTA);
+#define ORD_WTGetA							61
+	BOOL API WTGetW(HCTX, LPLOGCONTEXTW);
+#define ORD_WTGetW							1061
+#ifdef UNICODE
+#define WTGet			WTGetW
+#define ORD_WTGet		ORD_WTGetW
+#else
+#define WTGet			WTGetA
+#define ORD_WTGet		ORD_WTGetA
+#endif /* !UNICODE */
+#else
+	BOOL API WTGet(HCTX, LPLOGCONTEXT);
+#define ORD_WTGet								61
+#endif
+#ifdef WIN32
+	BOOL API WTSetA(HCTX, LPLOGCONTEXTA);
+#define ORD_WTSetA							62
+	BOOL API WTSetW(HCTX, LPLOGCONTEXTW);
+#define ORD_WTSetW							1062
+#ifdef UNICODE
+#define WTSet			WTSetW
+#define ORD_WTSet		ORD_WTSetW
+#else
+#define WTSet			WTSetA
+#define ORD_WTSet		ORD_WTSetA
+#endif /* !UNICODE */
+#else
+	BOOL API WTSet(HCTX, LPLOGCONTEXT);
+#define ORD_WTSet								62
+#endif
+	BOOL API WTExtGet(HCTX, UINT, LPVOID);
+#define ORD_WTExtGet							63
+	BOOL API WTExtSet(HCTX, UINT, LPVOID);
+#define ORD_WTExtSet							64
+	BOOL API WTSave(HCTX, LPVOID);
+#define ORD_WTSave							65
+	HCTX API WTRestore(HWND, LPVOID, BOOL);
+#define ORD_WTRestore						66
+#endif
+
+#ifndef NOWTQUEUEFXNS
+	/* ADVANCED PACKET AND QUEUE FUNCTIONS */
+	int API WTPacketsPeek(HCTX, int, LPVOID);
+#define ORD_WTPacketsPeek					80
+	int API WTDataGet(HCTX, UINT, UINT, int, LPVOID, LPINT);
+#define ORD_WTDataGet						81
+	int API WTDataPeek(HCTX, UINT, UINT, int, LPVOID, LPINT);
+#define ORD_WTDataPeek						82
+#ifndef WIN32
+	/* OBSOLETE IN WIN32! */
+	DWORD API WTQueuePackets(HCTX);
+#define ORD_WTQueuePackets					83
+#endif
+	int API WTQueueSizeGet(HCTX);
+#define ORD_WTQueueSizeGet					84
+	BOOL API WTQueueSizeSet(HCTX, int);
+#define ORD_WTQueueSizeSet					85
+#endif
+
+#ifndef NOWTHMGRFXNS
+	/* MANAGER HANDLE FUNCTIONS */
+	HMGR API WTMgrOpen(HWND, UINT);
+#define ORD_WTMgrOpen						100
+	BOOL API WTMgrClose(HMGR);
+#define ORD_WTMgrClose						101
+#endif
+
+#ifndef NOWTMGRCTXFXNS
+	/* MANAGER CONTEXT FUNCTIONS */
+	BOOL API WTMgrContextEnum(HMGR, WTENUMPROC, LPARAM);
+#define ORD_WTMgrContextEnum				120
+	HWND API WTMgrContextOwner(HMGR, HCTX);
+#define ORD_WTMgrContextOwner				121
+	HCTX API WTMgrDefContext(HMGR, BOOL);
+#define ORD_WTMgrDefContext				122
+	HCTX API WTMgrDefContextEx(HMGR, UINT, BOOL); /* 1.1 */
+#define ORD_WTMgrDefContextEx				206
+#endif
+
+#ifndef NOWTMGRCONFIGFXNS
+	/* MANAGER CONFIG BOX  FUNCTIONS */
+	UINT API WTMgrDeviceConfig(HMGR, UINT, HWND);
+#define ORD_WTMgrDeviceConfig				140
+#ifndef WIN32
+	/* OBSOLETE IN WIN32! */
+	BOOL API WTMgrConfigReplace(HMGR, BOOL, WTCONFIGPROC);
+#define ORD_WTMgrConfigReplace			141
+#endif
+#endif
+
+#ifndef NOWTMGRHOOKFXNS
+	/* MANAGER PACKET HOOK FUNCTIONS */
+#ifndef WIN32
+/* OBSOLETE IN WIN32! */
+	WTHOOKPROC API WTMgrPacketHook(HMGR, BOOL, int, WTHOOKPROC);
+#define ORD_WTMgrPacketHook				160
+	LRESULT API WTMgrPacketHookDefProc(int, WPARAM, LPARAM, LPWTHOOKPROC);
+#define ORD_WTMgrPacketHookDefProc		161
+#endif
+#endif
+
+#ifndef NOWTMGRPREFFXNS
+	/* MANAGER PREFERENCE DATA FUNCTIONS */
+	BOOL API WTMgrExt(HMGR, UINT, LPVOID);
+#define ORD_WTMgrExt							180
+	BOOL API WTMgrCsrEnable(HMGR, UINT, BOOL);
+#define ORD_WTMgrCsrEnable					181
+	BOOL API WTMgrCsrButtonMap(HMGR, UINT, LPBYTE, LPBYTE);
+#define ORD_WTMgrCsrButtonMap				182
+	BOOL API WTMgrCsrPressureBtnMarks(HMGR, UINT, DWORD, DWORD);
+#define ORD_WTMgrCsrPressureBtnMarks	183
+	BOOL API WTMgrCsrPressureResponse(HMGR, UINT, UINT FAR*, UINT FAR*);
+#define ORD_WTMgrCsrPressureResponse	184
+	BOOL API WTMgrCsrExt(HMGR, UINT, UINT, LPVOID);
+#define ORD_WTMgrCsrExt						185
+#endif
+
+	/* Win32 replacements for non-portable functions. */
+#ifndef NOWTQUEUEFXNS
+/* ADVANCED PACKET AND QUEUE FUNCTIONS */
+	BOOL API WTQueuePacketsEx(HCTX, UINT FAR*, UINT FAR*);
+#define ORD_WTQueuePacketsEx				200
+#endif
+
+#ifndef NOWTMGRCONFIGFXNS
+	/* MANAGER CONFIG BOX  FUNCTIONS */
+#ifdef WIN32
+	BOOL API WTMgrConfigReplaceExA(HMGR, BOOL, LPSTR, LPSTR);
+#define ORD_WTMgrConfigReplaceExA		202
+	BOOL API WTMgrConfigReplaceExW(HMGR, BOOL, LPWSTR, LPSTR);
+#define ORD_WTMgrConfigReplaceExW		1202
+#ifdef UNICODE
+#define WTMgrConfigReplaceEx			WTMgrConfigReplaceExW
+#define ORD_WTMgrConfigReplaceEx		ORD_WTMgrConfigReplaceExW
+#else
+#define WTMgrConfigReplaceEx			WTMgrConfigReplaceExA
+#define ORD_WTMgrConfigReplaceEx		ORD_WTMgrConfigReplaceExA
+#endif /* !UNICODE */
+#else
+	BOOL API WTMgrConfigReplaceEx(HMGR, BOOL, LPSTR, LPSTR);
+#define ORD_WTMgrConfigReplaceEx			202
+#endif
+#endif
+
+#ifndef NOWTMGRHOOKFXNS
+	/* MANAGER PACKET HOOK FUNCTIONS */
+#ifdef WIN32
+	HWTHOOK API WTMgrPacketHookExA(HMGR, int, LPSTR, LPSTR);
+#define ORD_WTMgrPacketHookExA			203
+	HWTHOOK API WTMgrPacketHookExW(HMGR, int, LPWSTR, LPSTR);
+#define ORD_WTMgrPacketHookExW			1203
+#ifdef UNICODE
+#define WTMgrPacketHookEx			WTMgrPacketHookExW
+#define ORD_WTMgrPacketHookEx		ORD_WTMgrPacketHookExW
+#else
+#define WTMgrPacketHookEx			WTMgrPacketHookExA
+#define ORD_WTMgrPacketHookEx		ORD_WTMgrPacketHookExA
+#endif /* !UNICODE */
+#else
+	HWTHOOK API WTMgrPacketHookEx(HMGR, int, LPSTR, LPSTR);
+#define ORD_WTMgrPacketHookEx				203
+#endif
+	BOOL API WTMgrPacketUnhook(HWTHOOK);
+#define ORD_WTMgrPacketUnhook				204
+	LRESULT API WTMgrPacketHookNext(HWTHOOK, int, WPARAM, LPARAM);
+#define ORD_WTMgrPacketHookNext			205
+#endif
+
+#ifndef NOWTMGRPREFFXNS
+	/* MANAGER PREFERENCE DATA FUNCTIONS */
+	BOOL API WTMgrCsrPressureBtnMarksEx(HMGR, UINT, UINT FAR*, UINT FAR*);
+#define ORD_WTMgrCsrPressureBtnMarksEx	201
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif /* #define _INC_WINTAB */
+

+ 168 - 0
wintab/wintab_utils.c

@@ -0,0 +1,168 @@
+/*----------------------------------------------------------------------------
+
+	NAME
+		Utils.c
+
+	PURPOSE
+		Some general-purpose functions for the WinTab demos.
+
+	COPYRIGHT
+		Copyright (c) Wacom Company, Ltd. 2014 All Rights Reserved
+		All rights reserved.
+
+		The text and information contained in this file may be freely used,
+		copied, or distributed without compensation or licensing restrictions.
+
+---------------------------------------------------------------------------- */
+
+#include "wintab_utils.h"
+
+#ifdef WACOM_DEBUG
+
+void WacomTrace(char* lpszFormat, ...);
+
+#define WACOM_ASSERT( x ) assert( x )
+#define WACOM_TRACE(...)  WacomTrace(__VA_ARGS__)
+#else
+#define WACOM_TRACE(...)
+#define WACOM_ASSERT( x )
+
+#endif // WACOM_DEBUG
+
+//////////////////////////////////////////////////////////////////////////////
+HINSTANCE ghWintab = NULL;
+
+WTINFOA gpWTInfoA = NULL;
+WTOPENA gpWTOpenA = NULL;
+WTGETA gpWTGetA = NULL;
+WTSETA gpWTSetA = NULL;
+WTCLOSE gpWTClose = NULL;
+WTPACKET gpWTPacket = NULL;
+WTENABLE gpWTEnable = NULL;
+WTOVERLAP gpWTOverlap = NULL;
+WTSAVE gpWTSave = NULL;
+WTCONFIG gpWTConfig = NULL;
+WTRESTORE gpWTRestore = NULL;
+WTEXTSET gpWTExtSet = NULL;
+WTEXTGET gpWTExtGet = NULL;
+WTQUEUESIZESET gpWTQueueSizeSet = NULL;
+WTDATAPEEK gpWTDataPeek = NULL;
+WTPACKETSGET gpWTPacketsGet = NULL;
+
+// TODO - add more wintab32 function pointers as needed
+
+char* pszProgramName = NULL;
+
+#define GETPROCADDRESS(type, func) \
+	gp##func = (type)GetProcAddress(ghWintab, #func); \
+	if (!gp##func){ WACOM_ASSERT(FALSE); UnloadWintab(); return FALSE; }
+
+//////////////////////////////////////////////////////////////////////////////
+// Purpose
+//		Find wintab32.dll and load it.  
+//		Find the exported functions we need from it.
+//
+//	Returns
+//		TRUE on success.
+//		FALSE on failure.
+//
+BOOL LoadWintab(void)
+{
+	ghWintab = LoadLibraryA("Wintab32.dll");
+	if (!ghWintab)
+	{
+		DWORD err = GetLastError();
+		WACOM_TRACE("LoadLibrary error: %i\n", err);
+		OutputDebugStringA("Could not load Wintab32.dll");
+		return FALSE;
+	}
+
+	// Explicitly find the exported Wintab functions in which we are interested.
+	// We are using the ASCII, not unicode versions (where applicable).
+	GETPROCADDRESS(WTOPENA, WTOpenA);
+	GETPROCADDRESS(WTINFOA, WTInfoA);
+	GETPROCADDRESS(WTGETA, WTGetA);
+	GETPROCADDRESS(WTSETA, WTSetA);
+	GETPROCADDRESS(WTPACKET, WTPacket);
+	GETPROCADDRESS(WTCLOSE, WTClose);
+	GETPROCADDRESS(WTENABLE, WTEnable);
+	GETPROCADDRESS(WTOVERLAP, WTOverlap);
+	GETPROCADDRESS(WTSAVE, WTSave);
+	GETPROCADDRESS(WTCONFIG, WTConfig);
+	GETPROCADDRESS(WTRESTORE, WTRestore);
+	GETPROCADDRESS(WTEXTSET, WTExtSet);
+	GETPROCADDRESS(WTEXTGET, WTExtGet);
+	GETPROCADDRESS(WTQUEUESIZESET, WTQueueSizeSet);
+	GETPROCADDRESS(WTDATAPEEK, WTDataPeek);
+	GETPROCADDRESS(WTPACKETSGET, WTPacketsGet);
+
+
+	// TODO - don't forget to NULL out pointers in UnloadWintab().
+	return TRUE;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Purpose
+//		Uninitializes use of wintab32.dll
+//
+// Returns
+//		Nothing.
+//
+void UnloadWintab(void)
+{
+	WACOM_TRACE("UnloadWintab()\n");
+
+	if (ghWintab)
+	{
+		FreeLibrary(ghWintab);
+		ghWintab = NULL;
+	}
+
+	gpWTOpenA = NULL;
+	gpWTClose = NULL;
+	gpWTInfoA = NULL;
+	gpWTPacket = NULL;
+	gpWTEnable = NULL;
+	gpWTOverlap = NULL;
+	gpWTSave = NULL;
+	gpWTConfig = NULL;
+	gpWTGetA = NULL;
+	gpWTSetA = NULL;
+	gpWTRestore = NULL;
+	gpWTExtSet = NULL;
+	gpWTExtGet = NULL;
+	gpWTQueueSizeSet = NULL;
+	gpWTDataPeek = NULL;
+	gpWTPacketsGet = NULL;
+}
+
+#ifdef WACOM_DEBUG
+
+//////////////////////////////////////////////////////////////////////////////
+
+void WacomTrace(char* lpszFormat, ...)
+{
+	char szTraceMessage[128];
+
+	int nBytesWritten;
+
+	va_list args;
+
+	WACOM_ASSERT(lpszFormat);
+
+	va_start(args, lpszFormat);
+
+	nBytesWritten = _vsnprintf(szTraceMessage, sizeof(szTraceMessage) - 1,
+		lpszFormat, args);
+
+	if (nBytesWritten > 0)
+	{
+		OutputDebugStringA(szTraceMessage);
+	}
+
+	va_end(args);
+}
+
+#endif // WACOM_DEBUG

+ 106 - 0
wintab/wintab_utils.h

@@ -0,0 +1,106 @@
+/*----------------------------------------------------------------------------s
+	NAME
+		Utils.h
+
+	PURPOSE
+		Defines for the general-purpose functions for the WinTab demos.
+
+	COPYRIGHT
+		This file is Copyright (c) Wacom Company, Ltd. 2020 All Rights Reserved
+		with portions copyright 1991-1998 by LCS/Telegraphics.
+
+		The text and information contained in this file may be freely used,
+		copied, or distributed without compensation or licensing restrictions.
+---------------------------------------------------------------------------- */
+#pragma once
+
+#include	<windows.h>
+#include	<stdio.h>
+#include	<assert.h>
+#include	<stdarg.h>
+
+#include	"wintab.h"
+
+#ifndef bool
+#define bool int
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+#define WACOM_DEBUG
+
+// Ignore warnings about using unsafe string functions.
+#pragma warning( disable : 4996 )
+
+//////////////////////////////////////////////////////////////////////////////
+// Function pointers to Wintab functions exported from wintab32.dll. 
+typedef UINT(API* WTINFOA) (UINT, UINT, LPVOID);
+typedef HCTX(API* WTOPENA)(HWND, LPLOGCONTEXTA, bool);
+typedef bool (API* WTGETA) (HCTX, LPLOGCONTEXT);
+typedef bool (API* WTSETA) (HCTX, LPLOGCONTEXT);
+typedef bool (API* WTCLOSE) (HCTX);
+typedef bool (API* WTENABLE) (HCTX, bool);
+typedef bool (API* WTPACKET) (HCTX, UINT, LPVOID);
+typedef bool (API* WTOVERLAP) (HCTX, bool);
+typedef bool (API* WTSAVE) (HCTX, LPVOID);
+typedef bool (API* WTCONFIG) (HCTX, HWND);
+typedef HCTX(API* WTRESTORE) (HWND, LPVOID, bool);
+typedef bool (API* WTEXTSET) (HCTX, UINT, LPVOID);
+typedef bool (API* WTEXTGET) (HCTX, UINT, LPVOID);
+typedef bool (API* WTQUEUESIZESET) (HCTX, int);
+typedef int  (API* WTDATAPEEK) (HCTX, UINT, UINT, int, LPVOID, LPINT);
+typedef int  (API* WTPACKETSGET) (HCTX, int, LPVOID);
+typedef HMGR(API* WTMGROPEN) (HWND, UINT);
+typedef bool (API* WTMGRCLOSE) (HMGR);
+typedef HCTX(API* WTMGRDEFCONTEXT) (HMGR, bool);
+typedef HCTX(API* WTMGRDEFCONTEXTEX) (HMGR, UINT, bool);
+
+// TODO - add more wintab32 function defs as needed
+
+//////////////////////////////////////////////////////////////////////////////
+extern char* gpszProgramName;
+
+// Loaded Wintab32 API functions.
+extern HINSTANCE ghWintab;
+
+extern WTINFOA gpWTInfoA;
+extern WTOPENA gpWTOpenA;
+extern WTGETA gpWTGetA;
+extern WTSETA gpWTSetA;
+extern WTCLOSE gpWTClose;
+extern WTPACKET gpWTPacket;
+extern WTENABLE gpWTEnable;
+extern WTOVERLAP gpWTOverlap;
+extern WTSAVE gpWTSave;
+extern WTCONFIG gpWTConfig;
+extern WTRESTORE gpWTRestore;
+extern WTEXTSET gpWTExtSet;
+extern WTEXTGET gpWTExtGet;
+extern WTQUEUESIZESET gpWTQueueSizeSet;
+extern WTDATAPEEK gpWTDataPeek;
+extern WTPACKETSGET gpWTPacketsGet;
+extern WTMGROPEN gpWTMgrOpen;
+extern WTMGRCLOSE gpWTMgrClose;
+extern WTMGRDEFCONTEXT gpWTMgrDefContext;
+extern WTMGRDEFCONTEXTEX gpWTMgrDefContextEx;
+
+// TODO - add more wintab32 function pointers as needed
+
+//////////////////////////////////////////////////////////////////////////////
+bool LoadWintab(void);
+void UnloadWintab(void);
+
+void ShowError(char* pszErrorMessage);
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef WACOM_DEBUG
+
+void WacomTrace(char* lpszFormat, ...);
+
+#define WACOM_ASSERT( x ) assert( x )
+#define WACOM_TRACE(...)  WacomTrace(__VA_ARGS__)
+#else
+#define WACOM_TRACE(...)
+#define WACOM_ASSERT( x )
+
+#endif // WACOM_DEBUG
+