4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2003 CodeWeavers, Aric Stewart
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wintab_internal.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(wintab32
);
40 * Documentation found at
41 * http://www.csl.sony.co.jp/projects/ar/restricted/wintabl.html
44 static LPOPENCONTEXT gOpenContexts
;
45 static HCTX gTopContext
= (HCTX
)0xc00;
47 static void LOGCONTEXTAtoW(const LOGCONTEXTA
*in
, LOGCONTEXTW
*out
)
49 MultiByteToWideChar(CP_ACP
, 0, in
->lcName
, -1, out
->lcName
, LCNAMELEN
);
50 out
->lcName
[LCNAMELEN
- 1] = 0;
51 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
52 memcpy(&out
->lcOptions
, &in
->lcOptions
, sizeof(LOGCONTEXTA
) - FIELD_OFFSET(LOGCONTEXTA
, lcOptions
));
55 static void LOGCONTEXTWtoA(const LOGCONTEXTW
*in
, LOGCONTEXTA
*out
)
57 WideCharToMultiByte(CP_ACP
, 0, in
->lcName
, LCNAMELEN
, out
->lcName
, LCNAMELEN
, NULL
, NULL
);
58 out
->lcName
[LCNAMELEN
- 1] = 0;
59 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
60 memcpy(&out
->lcOptions
, &in
->lcOptions
, sizeof(LOGCONTEXTW
) - FIELD_OFFSET(LOGCONTEXTW
, lcOptions
));
63 static BOOL
is_logcontext_category(UINT wCategory
)
65 return wCategory
== WTI_DEFSYSCTX
|| wCategory
== WTI_DEFCONTEXT
|| wCategory
== WTI_DDCTXS
;
68 static BOOL
is_string_field(UINT wCategory
, UINT nIndex
)
70 if (wCategory
== WTI_INTERFACE
&& nIndex
== IFC_WINTABID
)
72 if (is_logcontext_category(wCategory
) && nIndex
== CTX_NAME
)
74 if ((wCategory
>= WTI_CURSORS
&& wCategory
<= WTI_CURSORS
+ 9) &&
75 (nIndex
== CSR_NAME
|| nIndex
== CSR_BTNNAMES
))
77 if (wCategory
== WTI_DEVICES
&& (nIndex
== DVC_NAME
|| nIndex
== DVC_PNPID
))
82 static const char* DUMPBITS(int x
)
86 if (x
&PK_CONTEXT
) strcat(buf
,"PK_CONTEXT ");
87 if (x
&PK_STATUS
) strcat(buf
, "PK_STATUS ");
88 if (x
&PK_TIME
) strcat(buf
, "PK_TIME ");
89 if (x
&PK_CHANGED
) strcat(buf
, "PK_CHANGED ");
90 if (x
&PK_SERIAL_NUMBER
) strcat(buf
, "PK_SERIAL_NUMBER ");
91 if (x
&PK_CURSOR
) strcat(buf
, "PK_CURSOR ");
92 if (x
&PK_BUTTONS
) strcat(buf
, "PK_BUTTONS ");
93 if (x
&PK_X
) strcat(buf
, "PK_X ");
94 if (x
&PK_Y
) strcat(buf
, "PK_Y ");
95 if (x
&PK_Z
) strcat(buf
, "PK_Z ");
96 if (x
&PK_NORMAL_PRESSURE
) strcat(buf
, "PK_NORMAL_PRESSURE ");
97 if (x
&PK_TANGENT_PRESSURE
) strcat(buf
, "PK_TANGENT_PRESSURE ");
98 if (x
&PK_ORIENTATION
) strcat(buf
, "PK_ORIENTATION ");
99 if (x
&PK_ROTATION
) strcat(buf
, "PK_ROTATION ");
100 return wine_dbg_sprintf("{%s}",buf
);
103 static inline void DUMPPACKET(WTPACKET packet
)
105 TRACE("pkContext: %p pkStatus: 0x%x pkTime : 0x%x pkChanged: 0x%x pkSerialNumber: 0x%x pkCursor : %i pkButtons: %x pkX: %i pkY: %i pkZ: %i pkNormalPressure: %i pkTangentPressure: %i pkOrientation: (%i,%i,%i) pkRotation: (%i,%i,%i)\n",
106 packet
.pkContext
, packet
.pkStatus
, packet
.pkTime
, packet
.pkChanged
, packet
.pkSerialNumber
,
107 packet
.pkCursor
, packet
.pkButtons
, packet
.pkX
, packet
.pkY
, packet
.pkZ
,
108 packet
.pkNormalPressure
, packet
.pkTangentPressure
,
109 packet
.pkOrientation
.orAzimuth
, packet
.pkOrientation
.orAltitude
, packet
.pkOrientation
.orTwist
,
110 packet
.pkRotation
.roPitch
, packet
.pkRotation
.roRoll
, packet
.pkRotation
.roYaw
);
113 static inline void DUMPCONTEXT(LOGCONTEXTW lc
)
115 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, Device: %x\n",
116 wine_dbgstr_w(lc
.lcName
), lc
.lcOptions
, lc
.lcStatus
, lc
.lcLocks
, lc
.lcMsgBase
, lc
.lcDevice
);
117 TRACE("PktRate %x\n", lc
.lcPktRate
);
118 TRACE("PktData 0x%04x %s\n", lc
.lcPktData
, DUMPBITS(lc
.lcPktData
));
119 TRACE("PktMode 0x%04x %s\n", lc
.lcPktMode
, DUMPBITS(lc
.lcPktMode
));
120 TRACE("MovMask 0x%04x %s\n", lc
.lcMoveMask
, DUMPBITS(lc
.lcMoveMask
));
121 TRACE("BtnDnMask: %x, BtnUpMask: %x\n", lc
.lcBtnDnMask
, lc
.lcBtnUpMask
);
122 TRACE("InOrgX: %i, InOrgY: %i, InOrgZ: %i\n", lc
.lcInOrgX
, lc
.lcInOrgY
, lc
.lcInOrgZ
);
123 TRACE("InExtX: %i, InExtY: %i, InExtZ: %i\n", lc
.lcInExtX
, lc
.lcInExtY
, lc
.lcInExtZ
);
124 TRACE("OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i\n", lc
.lcOutOrgX
, lc
.lcOutOrgY
, lc
.lcOutOrgZ
);
125 TRACE("OutExtX: %i, OutExtY: %i, OutExtZ: %i\n", lc
.lcOutExtX
, lc
.lcOutExtY
, lc
.lcOutExtZ
);
126 TRACE("SensX: %i, SensY: %i, SensZ: %i\n", lc
.lcSensX
, lc
.lcSensY
, lc
.lcSensZ
);
127 TRACE("SysMode: %i\n", lc
.lcSysMode
);
128 TRACE("SysOrgX: %i, SysOrgY: %i\n", lc
.lcSysOrgX
, lc
.lcSysOrgY
);
129 TRACE("SysExtX: %i, SysExtY: %i\n", lc
.lcSysExtX
, lc
.lcSysExtY
);
130 TRACE("SysSensX: %i, SysSensY: %i\n", lc
.lcSysSensX
, lc
.lcSysSensY
);
134 /* Find an open context given the handle */
135 static LPOPENCONTEXT
TABLET_FindOpenContext(HCTX hCtx
)
137 LPOPENCONTEXT ptr
= gOpenContexts
;
140 if (ptr
->handle
== hCtx
) return ptr
;
146 static inline BOOL
LoadTablet(void)
148 static enum {TI_START
= 0, TI_OK
, TI_FAIL
} loaded
= TI_START
;
150 if (loaded
== TI_START
)
152 if (pLoadTabletInfo
&& pLoadTabletInfo(hwndDefault
))
154 TRACE("Initialized the tablet to hwnd %p\n", hwndDefault
);
159 TRACE("Failed to initialize the tablet to hwnd %p\n", hwndDefault
);
164 return loaded
== TI_OK
;
167 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext
, UINT msg
, WPARAM wParam
,
168 LPARAM lParam
, BOOL send_always
)
170 if ((send_always
) || (newcontext
->context
.lcOptions
& CXO_MESSAGES
))
172 TRACE("Posting message %x to %p\n",msg
, newcontext
->hwndOwner
);
173 return PostMessageA(newcontext
->hwndOwner
, msg
, wParam
, lParam
);
178 static inline DWORD
ScaleForContext(DWORD In
, LONG InOrg
, LONG InExt
, LONG OutOrg
, LONG OutExt
)
180 if (((InExt
> 0 )&&(OutExt
> 0)) || ((InExt
<0) && (OutExt
< 0)))
181 return MulDiv(In
- InOrg
, abs(OutExt
), abs(InExt
)) + OutOrg
;
183 return MulDiv(abs(InExt
) - (In
- InOrg
), abs(OutExt
), abs(InExt
)) + OutOrg
;
186 LPOPENCONTEXT
AddPacketToContextQueue(LPWTPACKET packet
, HWND hwnd
)
188 LPOPENCONTEXT ptr
=NULL
;
190 EnterCriticalSection(&csTablet
);
195 TRACE("Trying Queue %p (%p %p)\n", ptr
->handle
, hwnd
, ptr
->hwndOwner
);
197 if (ptr
->hwndOwner
== hwnd
)
206 tgt
= ptr
->PacketsQueued
;
208 packet
->pkContext
= ptr
->handle
;
210 /* translate packet data to the context */
211 packet
->pkChanged
= packet
->pkChanged
& ptr
->context
.lcPktData
;
213 /* Scale as per documentation */
214 packet
->pkY
= ScaleForContext(packet
->pkY
, ptr
->context
.lcInOrgY
,
215 ptr
->context
.lcInExtY
, ptr
->context
.lcOutOrgY
,
216 ptr
->context
.lcOutExtY
);
218 packet
->pkX
= ScaleForContext(packet
->pkX
, ptr
->context
.lcInOrgX
,
219 ptr
->context
.lcInExtX
, ptr
->context
.lcOutOrgX
,
220 ptr
->context
.lcOutExtX
);
222 /* flip the Y axis */
223 if (ptr
->context
.lcOutExtY
> 0)
224 packet
->pkY
= ptr
->context
.lcOutExtY
- packet
->pkY
;
225 else if (ptr
->context
.lcOutExtY
< 0)
226 packet
->pkY
= abs(ptr
->context
.lcOutExtY
+ packet
->pkY
);
230 if (tgt
== ptr
->QueueSize
)
232 TRACE("Queue Overflow %p\n",ptr
->handle
);
233 ptr
->PacketQueue
[tgt
-1].pkStatus
|= TPS_QUEUE_ERR
;
237 TRACE("Placed in queue %p index %i\n",ptr
->handle
,tgt
);
238 ptr
->PacketQueue
[tgt
] = *packet
;
239 ptr
->PacketsQueued
++;
241 if (ptr
->ActiveCursor
!= packet
->pkCursor
)
243 ptr
->ActiveCursor
= packet
->pkCursor
;
244 if (ptr
->context
.lcOptions
& CXO_CSRMESSAGES
)
245 TABLET_PostTabletMessage(ptr
, _WT_CSRCHANGE(ptr
->context
.lcMsgBase
),
246 (WPARAM
)packet
->pkSerialNumber
, (LPARAM
)ptr
->handle
,
254 LeaveCriticalSection(&csTablet
);
255 TRACE("Done (%p)\n",ptr
);
260 * Flushes all packets from the queue.
262 static inline void TABLET_FlushQueue(LPOPENCONTEXT context
)
264 context
->PacketsQueued
= 0;
267 static inline int CopyTabletData(LPVOID target
, LPVOID src
, INT size
)
269 memcpy(target
,src
,size
);
273 static INT
TABLET_FindPacket(LPOPENCONTEXT context
, UINT wSerial
,
278 for (loop
= 0; loop
< context
->PacketsQueued
; loop
++)
279 if (context
->PacketQueue
[loop
].pkSerialNumber
== wSerial
)
282 *pkt
= &context
->PacketQueue
[loop
];
286 TRACE("%i .. %i\n",context
->PacketsQueued
,index
);
292 static LPVOID
TABLET_CopyPacketData(LPOPENCONTEXT context
, LPVOID lpPkt
,
298 TRACE("Packet Bits %s\n",DUMPBITS(context
->context
.lcPktData
));
300 if (context
->context
.lcPktData
& PK_CONTEXT
)
301 ptr
+=CopyTabletData(ptr
,&wtp
->pkContext
,sizeof(HCTX
));
302 if (context
->context
.lcPktData
& PK_STATUS
)
303 ptr
+=CopyTabletData(ptr
,&wtp
->pkStatus
,sizeof(UINT
));
304 if (context
->context
.lcPktData
& PK_TIME
)
305 ptr
+=CopyTabletData(ptr
,&wtp
->pkTime
,sizeof(LONG
));
306 if (context
->context
.lcPktData
& PK_CHANGED
)
307 ptr
+=CopyTabletData(ptr
,&wtp
->pkChanged
,sizeof(WTPKT
));
308 if (context
->context
.lcPktData
& PK_SERIAL_NUMBER
)
309 ptr
+=CopyTabletData(ptr
,&wtp
->pkSerialNumber
,sizeof(UINT
));
310 if (context
->context
.lcPktData
& PK_CURSOR
)
311 ptr
+=CopyTabletData(ptr
,&wtp
->pkCursor
,sizeof(UINT
));
312 if (context
->context
.lcPktData
& PK_BUTTONS
)
313 ptr
+=CopyTabletData(ptr
,&wtp
->pkButtons
,sizeof(DWORD
));
314 if (context
->context
.lcPktData
& PK_X
)
315 ptr
+=CopyTabletData(ptr
,&wtp
->pkX
,sizeof(DWORD
));
316 if (context
->context
.lcPktData
& PK_Y
)
317 ptr
+=CopyTabletData(ptr
,&wtp
->pkY
,sizeof(DWORD
));
318 if (context
->context
.lcPktData
& PK_Z
)
319 ptr
+=CopyTabletData(ptr
,&wtp
->pkZ
,sizeof(DWORD
));
320 if (context
->context
.lcPktData
& PK_NORMAL_PRESSURE
)
321 ptr
+=CopyTabletData(ptr
,&wtp
->pkNormalPressure
,sizeof(UINT
));
322 if (context
->context
.lcPktData
& PK_TANGENT_PRESSURE
)
323 ptr
+=CopyTabletData(ptr
,&wtp
->pkTangentPressure
,sizeof(UINT
));
324 if (context
->context
.lcPktData
& PK_ORIENTATION
)
325 ptr
+=CopyTabletData(ptr
,&wtp
->pkOrientation
,sizeof(ORIENTATION
));
326 if (context
->context
.lcPktData
& PK_ROTATION
)
327 ptr
+=CopyTabletData(ptr
,&wtp
->pkRotation
,sizeof(ROTATION
));
329 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
333 static VOID
TABLET_BlankPacketData(LPOPENCONTEXT context
, LPVOID lpPkt
, INT n
)
337 if (context
->context
.lcPktData
& PK_CONTEXT
)
339 if (context
->context
.lcPktData
& PK_STATUS
)
341 if (context
->context
.lcPktData
& PK_TIME
)
343 if (context
->context
.lcPktData
& PK_CHANGED
)
345 if (context
->context
.lcPktData
& PK_SERIAL_NUMBER
)
347 if (context
->context
.lcPktData
& PK_CURSOR
)
349 if (context
->context
.lcPktData
& PK_BUTTONS
)
351 if (context
->context
.lcPktData
& PK_X
)
353 if (context
->context
.lcPktData
& PK_Y
)
355 if (context
->context
.lcPktData
& PK_Z
)
357 if (context
->context
.lcPktData
& PK_NORMAL_PRESSURE
)
359 if (context
->context
.lcPktData
& PK_TANGENT_PRESSURE
)
361 if (context
->context
.lcPktData
& PK_ORIENTATION
)
362 rc
+= sizeof(ORIENTATION
);
363 if (context
->context
.lcPktData
& PK_ROTATION
)
364 rc
+= sizeof(ROTATION
);
371 static UINT
WTInfoT(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
, BOOL bUnicode
)
375 if (!LoadTablet()) return 0;
377 TRACE("(%d, %d, %p, %d)\n", wCategory
, nIndex
, lpOutput
, bUnicode
);
380 * Handle system extents here, as we can use user32.dll code to set them.
382 if(wCategory
== WTI_DEFSYSCTX
)
388 *(LONG
*)lpOutput
= GetSystemMetrics(SM_CXSCREEN
);
392 *(LONG
*)lpOutput
= GetSystemMetrics(SM_CYSCREEN
);
394 /* No action, delegate to X11Drv */
398 if (is_logcontext_category(wCategory
) && nIndex
== 0)
403 pWTInfoW(wCategory
, nIndex
, &buf
);
405 /* Handle system extents here, as we can use user32.dll code to set them */
406 if(wCategory
== WTI_DEFSYSCTX
)
408 buf
.lcSysExtX
= GetSystemMetrics(SM_CXSCREEN
);
409 buf
.lcSysExtY
= GetSystemMetrics(SM_CYSCREEN
);
413 memcpy(lpOutput
, &buf
, sizeof(buf
));
415 LOGCONTEXTWtoA(&buf
, lpOutput
);
418 result
= bUnicode
? sizeof(LOGCONTEXTW
) : sizeof(LOGCONTEXTA
);
420 else if (is_string_field(wCategory
, nIndex
) && !bUnicode
)
422 int size
= pWTInfoW(wCategory
, nIndex
, NULL
);
423 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, size
);
424 pWTInfoW(wCategory
, nIndex
, buf
);
425 result
= WideCharToMultiByte(CP_ACP
, 0, buf
, size
/sizeof(WCHAR
), lpOutput
, lpOutput
? 2*size
: 0, NULL
, NULL
);
426 HeapFree(GetProcessHeap(), 0, buf
);
429 result
= pWTInfoW(wCategory
, nIndex
, lpOutput
);
431 TRACE("returns %d\n", result
);
435 /***********************************************************************
436 * WTInfoA (WINTAB32.20)
438 UINT WINAPI
WTInfoA(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
440 return WTInfoT(wCategory
, nIndex
, lpOutput
, FALSE
);
444 /***********************************************************************
445 * WTInfoW (WINTAB32.1020)
447 UINT WINAPI
WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
449 return WTInfoT(wCategory
, nIndex
, lpOutput
, TRUE
);
452 /***********************************************************************
453 * WTOpenW (WINTAB32.1021)
455 HCTX WINAPI
WTOpenW(HWND hWnd
, LPLOGCONTEXTW lpLogCtx
, BOOL fEnable
)
457 LPOPENCONTEXT newcontext
;
459 if (!LoadTablet()) return 0;
461 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd
, lpLogCtx
, fEnable
);
462 DUMPCONTEXT(*lpLogCtx
);
464 newcontext
= HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT
));
465 newcontext
->context
= *lpLogCtx
;
466 newcontext
->hwndOwner
= hWnd
;
467 newcontext
->ActiveCursor
= -1;
468 newcontext
->QueueSize
= 10;
469 newcontext
->PacketsQueued
= 0;
470 newcontext
->PacketQueue
=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET
)*10);
472 EnterCriticalSection(&csTablet
);
473 newcontext
->handle
= gTopContext
++;
474 newcontext
->next
= gOpenContexts
;
475 gOpenContexts
= newcontext
;
476 LeaveCriticalSection(&csTablet
);
478 pAttachEventQueueToTablet(hWnd
);
480 TABLET_PostTabletMessage(newcontext
, _WT_CTXOPEN(newcontext
->context
.lcMsgBase
), (WPARAM
)newcontext
->handle
,
481 newcontext
->context
.lcStatus
, TRUE
);
485 newcontext
->enabled
= TRUE
;
486 /* TODO: Add to top of overlap order */
487 newcontext
->context
.lcStatus
= CXS_ONTOP
;
491 newcontext
->enabled
= FALSE
;
492 newcontext
->context
.lcStatus
= CXS_DISABLED
;
495 TABLET_PostTabletMessage(newcontext
, _WT_CTXOVERLAP(newcontext
->context
.lcMsgBase
),
496 (WPARAM
)newcontext
->handle
,
497 newcontext
->context
.lcStatus
, TRUE
);
499 return newcontext
->handle
;
502 /***********************************************************************
503 * WTOpenA (WINTAB32.21)
505 HCTX WINAPI
WTOpenA(HWND hWnd
, LPLOGCONTEXTA lpLogCtx
, BOOL fEnable
)
509 LOGCONTEXTAtoW(lpLogCtx
, &logCtxW
);
510 return WTOpenW(hWnd
, &logCtxW
, fEnable
);
513 /***********************************************************************
514 * WTClose (WINTAB32.22)
516 BOOL WINAPI
WTClose(HCTX hCtx
)
518 LPOPENCONTEXT context
,ptr
;
520 TRACE("(%p)\n", hCtx
);
522 EnterCriticalSection(&csTablet
);
524 ptr
= context
= gOpenContexts
;
526 while (context
&& (context
->handle
!= hCtx
))
529 context
= context
->next
;
533 LeaveCriticalSection(&csTablet
);
537 if (context
== gOpenContexts
)
538 gOpenContexts
= context
->next
;
540 ptr
->next
= context
->next
;
542 LeaveCriticalSection(&csTablet
);
544 TABLET_PostTabletMessage(context
, _WT_CTXCLOSE(context
->context
.lcMsgBase
), (WPARAM
)context
->handle
,
545 context
->context
.lcStatus
,TRUE
);
547 HeapFree(GetProcessHeap(),0,context
->PacketQueue
);
548 HeapFree(GetProcessHeap(),0,context
);
553 /***********************************************************************
554 * WTPacketsGet (WINTAB32.23)
556 int WINAPI
WTPacketsGet(HCTX hCtx
, int cMaxPkts
, LPVOID lpPkts
)
559 LPOPENCONTEXT context
;
562 TRACE("(%p, %d, %p)\n", hCtx
, cMaxPkts
, lpPkts
);
567 EnterCriticalSection(&csTablet
);
569 context
= TABLET_FindOpenContext(hCtx
);
572 LeaveCriticalSection(&csTablet
);
577 TABLET_BlankPacketData(context
,lpPkts
,cMaxPkts
);
579 if (context
->PacketsQueued
== 0)
581 LeaveCriticalSection(&csTablet
);
585 limit
= min(cMaxPkts
,context
->PacketsQueued
);
590 for(i
= 0; i
< limit
; i
++)
591 ptr
=TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[i
]);
595 if (limit
< context
->PacketsQueued
)
597 memmove(context
->PacketQueue
, &context
->PacketQueue
[limit
],
598 (context
->PacketsQueued
- (limit
))*sizeof(WTPACKET
));
600 context
->PacketsQueued
-= limit
;
601 LeaveCriticalSection(&csTablet
);
603 TRACE("Copied %i packets\n",limit
);
608 /***********************************************************************
609 * WTPacket (WINTAB32.24)
611 BOOL WINAPI
WTPacket(HCTX hCtx
, UINT wSerial
, LPVOID lpPkt
)
614 LPOPENCONTEXT context
;
615 LPWTPACKET wtp
= NULL
;
617 TRACE("(%p, %d, %p)\n", hCtx
, wSerial
, lpPkt
);
622 EnterCriticalSection(&csTablet
);
624 context
= TABLET_FindOpenContext(hCtx
);
627 LeaveCriticalSection(&csTablet
);
631 rc
= TABLET_FindPacket(context
,wSerial
, &wtp
);
636 TABLET_CopyPacketData(context
,lpPkt
, wtp
);
638 if ((rc
+1) < context
->QueueSize
)
640 memmove(context
->PacketQueue
, &context
->PacketQueue
[rc
+1],
641 (context
->PacketsQueued
- (rc
+1))*sizeof(WTPACKET
));
643 context
->PacketsQueued
-= (rc
+1);
645 LeaveCriticalSection(&csTablet
);
647 TRACE("Returning %i\n",rc
+1);
651 /***********************************************************************
652 * WTEnable (WINTAB32.40)
654 BOOL WINAPI
WTEnable(HCTX hCtx
, BOOL fEnable
)
656 LPOPENCONTEXT context
;
658 TRACE("hCtx=%p, fEnable=%u\n", hCtx
, fEnable
);
660 if (!hCtx
) return FALSE
;
662 EnterCriticalSection(&csTablet
);
663 context
= TABLET_FindOpenContext(hCtx
);
666 LeaveCriticalSection(&csTablet
);
670 /* if we want to enable and it is not enabled then */
671 if(fEnable
&& !context
->enabled
)
673 context
->enabled
= TRUE
;
674 /* TODO: Add to top of overlap order */
675 context
->context
.lcStatus
= CXS_ONTOP
;
676 TABLET_PostTabletMessage(context
,
677 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
678 (WPARAM
)context
->handle
,
679 context
->context
.lcStatus
, TRUE
);
681 /* if we want to disable and it is not disabled then */
682 else if (!fEnable
&& context
->enabled
)
684 context
->enabled
= FALSE
;
685 /* TODO: Remove from overlap order?? needs a test */
686 context
->context
.lcStatus
= CXS_DISABLED
;
687 TABLET_FlushQueue(context
);
688 TABLET_PostTabletMessage(context
,
689 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
690 (WPARAM
)context
->handle
,
691 context
->context
.lcStatus
, TRUE
);
693 LeaveCriticalSection(&csTablet
);
698 /***********************************************************************
699 * WTOverlap (WINTAB32.41)
701 * Move context to top or bottom of overlap order
703 BOOL WINAPI
WTOverlap(HCTX hCtx
, BOOL fToTop
)
705 LPOPENCONTEXT context
;
707 TRACE("hCtx=%p, fToTop=%u\n", hCtx
, fToTop
);
709 if (!hCtx
) return FALSE
;
711 EnterCriticalSection(&csTablet
);
712 context
= TABLET_FindOpenContext(hCtx
);
715 LeaveCriticalSection(&csTablet
);
719 /* if we want to send to top and it's not already there */
720 if (fToTop
&& context
->context
.lcStatus
!= CXS_ONTOP
)
722 /* TODO: Move context to top of overlap order */
723 FIXME("Not moving context to top of overlap order\n");
724 context
->context
.lcStatus
= CXS_ONTOP
;
725 TABLET_PostTabletMessage(context
,
726 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
727 (WPARAM
)context
->handle
,
728 context
->context
.lcStatus
, TRUE
);
732 /* TODO: Move context to bottom of overlap order */
733 FIXME("Not moving context to bottom of overlap order\n");
734 context
->context
.lcStatus
= CXS_OBSCURED
;
735 TABLET_PostTabletMessage(context
,
736 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
737 (WPARAM
)context
->handle
,
738 context
->context
.lcStatus
, TRUE
);
740 LeaveCriticalSection(&csTablet
);
745 /***********************************************************************
746 * WTConfig (WINTAB32.60)
748 BOOL WINAPI
WTConfig(HCTX hCtx
, HWND hWnd
)
750 FIXME("(%p, %p): stub\n", hCtx
, hWnd
);
752 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
757 /***********************************************************************
758 * WTGetA (WINTAB32.61)
760 BOOL WINAPI
WTGetA(HCTX hCtx
, LPLOGCONTEXTA lpLogCtx
)
762 LPOPENCONTEXT context
;
764 TRACE("(%p, %p)\n", hCtx
, lpLogCtx
);
766 if (!hCtx
) return FALSE
;
768 EnterCriticalSection(&csTablet
);
769 context
= TABLET_FindOpenContext(hCtx
);
772 LeaveCriticalSection(&csTablet
);
776 LOGCONTEXTWtoA(&context
->context
, lpLogCtx
);
777 LeaveCriticalSection(&csTablet
);
782 /***********************************************************************
783 * WTGetW (WINTAB32.1061)
785 BOOL WINAPI
WTGetW(HCTX hCtx
, LPLOGCONTEXTW lpLogCtx
)
787 LPOPENCONTEXT context
;
789 TRACE("(%p, %p)\n", hCtx
, lpLogCtx
);
791 if (!hCtx
) return FALSE
;
793 EnterCriticalSection(&csTablet
);
794 context
= TABLET_FindOpenContext(hCtx
);
797 LeaveCriticalSection(&csTablet
);
801 memmove(lpLogCtx
,&context
->context
,sizeof(LOGCONTEXTW
));
802 LeaveCriticalSection(&csTablet
);
807 /***********************************************************************
808 * WTSetA (WINTAB32.62)
810 BOOL WINAPI
WTSetA(HCTX hCtx
, LPLOGCONTEXTA lpLogCtx
)
812 LPOPENCONTEXT context
;
814 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx
, lpLogCtx
);
816 if (!hCtx
|| !lpLogCtx
) return FALSE
;
818 /* TODO: if cur process not owner of hCtx only modify
819 * attribs not locked by owner */
821 EnterCriticalSection(&csTablet
);
822 context
= TABLET_FindOpenContext(hCtx
);
825 LeaveCriticalSection(&csTablet
);
829 LOGCONTEXTAtoW(lpLogCtx
, &context
->context
);
830 LeaveCriticalSection(&csTablet
);
835 /***********************************************************************
836 * WTSetW (WINTAB32.1062)
838 BOOL WINAPI
WTSetW(HCTX hCtx
, LPLOGCONTEXTW lpLogCtx
)
840 LPOPENCONTEXT context
;
842 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx
, lpLogCtx
);
844 if (!hCtx
|| !lpLogCtx
) return FALSE
;
846 /* TODO: if cur process not hCtx owner only modify
847 * attribs not locked by owner */
849 EnterCriticalSection(&csTablet
);
850 context
= TABLET_FindOpenContext(hCtx
);
853 LeaveCriticalSection(&csTablet
);
857 memmove(&context
->context
, lpLogCtx
, sizeof(LOGCONTEXTW
));
858 LeaveCriticalSection(&csTablet
);
863 /***********************************************************************
864 * WTExtGet (WINTAB32.63)
866 BOOL WINAPI
WTExtGet(HCTX hCtx
, UINT wExt
, LPVOID lpData
)
868 FIXME("(%p, %u, %p): stub\n", hCtx
, wExt
, lpData
);
870 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
875 /***********************************************************************
876 * WTExtSet (WINTAB32.64)
878 BOOL WINAPI
WTExtSet(HCTX hCtx
, UINT wExt
, LPVOID lpData
)
880 FIXME("(%p, %u, %p): stub\n", hCtx
, wExt
, lpData
);
882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
887 /***********************************************************************
888 * WTSave (WINTAB32.65)
890 BOOL WINAPI
WTSave(HCTX hCtx
, LPVOID lpSaveInfo
)
892 FIXME("(%p, %p): stub\n", hCtx
, lpSaveInfo
);
894 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
899 /***********************************************************************
900 * WTRestore (WINTAB32.66)
902 HCTX WINAPI
WTRestore(HWND hWnd
, LPVOID lpSaveInfo
, BOOL fEnable
)
904 FIXME("(%p, %p, %u): stub\n", hWnd
, lpSaveInfo
, fEnable
);
906 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
911 /***********************************************************************
912 * WTPacketsPeek (WINTAB32.80)
914 int WINAPI
WTPacketsPeek(HCTX hCtx
, int cMaxPkts
, LPVOID lpPkts
)
917 LPOPENCONTEXT context
;
920 TRACE("(%p, %d, %p)\n", hCtx
, cMaxPkts
, lpPkts
);
922 if (!hCtx
|| !lpPkts
) return 0;
924 EnterCriticalSection(&csTablet
);
926 context
= TABLET_FindOpenContext(hCtx
);
928 if (!context
|| context
->PacketsQueued
== 0)
930 LeaveCriticalSection(&csTablet
);
934 for (limit
= 0; limit
< cMaxPkts
&& limit
< context
->PacketsQueued
; limit
++)
935 ptr
= TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[limit
]);
937 LeaveCriticalSection(&csTablet
);
938 TRACE("Copied %i packets\n",limit
);
942 /***********************************************************************
943 * WTDataGet (WINTAB32.81)
945 int WINAPI
WTDataGet(HCTX hCtx
, UINT wBegin
, UINT wEnd
,
946 int cMaxPkts
, LPVOID lpPkts
, LPINT lpNPkts
)
948 LPOPENCONTEXT context
;
954 TRACE("(%p, %u, %u, %d, %p, %p)\n",
955 hCtx
, wBegin
, wEnd
, cMaxPkts
, lpPkts
, lpNPkts
);
959 EnterCriticalSection(&csTablet
);
961 context
= TABLET_FindOpenContext(hCtx
);
963 if (!context
|| context
->PacketsQueued
== 0)
965 LeaveCriticalSection(&csTablet
);
969 while (bgn
< context
->PacketsQueued
&&
970 context
->PacketQueue
[bgn
].pkSerialNumber
!= wBegin
)
974 while (end
< context
->PacketsQueued
&&
975 context
->PacketQueue
[end
].pkSerialNumber
!= wEnd
)
978 if ((bgn
== end
) && (end
== context
->PacketsQueued
))
980 LeaveCriticalSection(&csTablet
);
984 for (num
= bgn
; num
<= end
; num
++)
985 ptr
= TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[num
]);
987 /* remove read packets */
988 if ((end
+1) < context
->PacketsQueued
)
989 memmove( &context
->PacketQueue
[bgn
], &context
->PacketQueue
[end
+1],
990 (context
->PacketsQueued
- (end
+1)) * sizeof (WTPACKET
));
992 context
->PacketsQueued
-= ((end
-bgn
)+1);
993 *lpNPkts
= ((end
-bgn
)+1);
995 LeaveCriticalSection(&csTablet
);
996 TRACE("Copied %i packets\n",*lpNPkts
);
997 return (end
- bgn
)+1;
1000 /***********************************************************************
1001 * WTDataPeek (WINTAB32.82)
1003 int WINAPI
WTDataPeek(HCTX hCtx
, UINT wBegin
, UINT wEnd
,
1004 int cMaxPkts
, LPVOID lpPkts
, LPINT lpNPkts
)
1006 LPOPENCONTEXT context
;
1007 LPVOID ptr
= lpPkts
;
1012 TRACE("(%p, %u, %u, %d, %p, %p)\n",
1013 hCtx
, wBegin
, wEnd
, cMaxPkts
, lpPkts
, lpNPkts
);
1015 if (!hCtx
|| !lpPkts
) return 0;
1017 EnterCriticalSection(&csTablet
);
1019 context
= TABLET_FindOpenContext(hCtx
);
1021 if (!context
|| context
->PacketsQueued
== 0)
1023 LeaveCriticalSection(&csTablet
);
1027 while (bgn
< context
->PacketsQueued
&&
1028 context
->PacketQueue
[bgn
].pkSerialNumber
!= wBegin
)
1032 while (end
< context
->PacketsQueued
&&
1033 context
->PacketQueue
[end
].pkSerialNumber
!= wEnd
)
1036 if (bgn
== context
->PacketsQueued
|| end
== context
->PacketsQueued
)
1038 TRACE("%i %i %i\n", bgn
, end
, context
->PacketsQueued
);
1039 LeaveCriticalSection(&csTablet
);
1043 for (num
= bgn
; num
<= end
; num
++)
1044 ptr
= TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[num
]);
1046 *lpNPkts
= ((end
-bgn
)+1);
1047 LeaveCriticalSection(&csTablet
);
1049 TRACE("Copied %i packets\n",*lpNPkts
);
1050 return (end
- bgn
)+1;
1053 /***********************************************************************
1054 * WTQueuePacketsEx (WINTAB32.200)
1056 BOOL WINAPI
WTQueuePacketsEx(HCTX hCtx
, UINT
*lpOld
, UINT
*lpNew
)
1058 LPOPENCONTEXT context
;
1060 TRACE("(%p, %p, %p)\n", hCtx
, lpOld
, lpNew
);
1062 if (!hCtx
) return FALSE
;
1064 EnterCriticalSection(&csTablet
);
1066 context
= TABLET_FindOpenContext(hCtx
);
1068 if (context
&& context
->PacketsQueued
)
1070 *lpOld
= context
->PacketQueue
[0].pkSerialNumber
;
1071 *lpNew
= context
->PacketQueue
[context
->PacketsQueued
-1].pkSerialNumber
;
1075 TRACE("No packets\n");
1076 LeaveCriticalSection(&csTablet
);
1079 LeaveCriticalSection(&csTablet
);
1084 /***********************************************************************
1085 * WTQueueSizeGet (WINTAB32.84)
1087 int WINAPI
WTQueueSizeGet(HCTX hCtx
)
1089 LPOPENCONTEXT context
;
1092 TRACE("(%p)\n", hCtx
);
1094 if (!hCtx
) return 0;
1096 EnterCriticalSection(&csTablet
);
1097 context
= TABLET_FindOpenContext(hCtx
);
1099 queueSize
= context
->QueueSize
;
1100 LeaveCriticalSection(&csTablet
);
1104 /***********************************************************************
1105 * WTQueueSizeSet (WINTAB32.85)
1107 BOOL WINAPI
WTQueueSizeSet(HCTX hCtx
, int nPkts
)
1109 LPOPENCONTEXT context
;
1111 TRACE("(%p, %d)\n", hCtx
, nPkts
);
1113 if (!hCtx
) return FALSE
;
1115 EnterCriticalSection(&csTablet
);
1117 context
= TABLET_FindOpenContext(hCtx
);
1120 LeaveCriticalSection(&csTablet
);
1124 context
->PacketQueue
= HeapReAlloc(GetProcessHeap(), 0,
1125 context
->PacketQueue
, sizeof(WTPACKET
)*nPkts
);
1127 context
->QueueSize
= nPkts
;
1128 LeaveCriticalSection(&csTablet
);