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
34 #include "wintab_internal.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(wintab32
);
41 * Documentation found at
42 * http://www.csl.sony.co.jp/projects/ar/restricted/wintabl.html
46 static LPOPENCONTEXT gOpenContexts
;
47 static HCTX gTopContext
= (HCTX
)0xc00;
49 static void LOGCONTEXTAtoW(const LOGCONTEXTA
*in
, LOGCONTEXTW
*out
)
51 MultiByteToWideChar(CP_ACP
, 0, in
->lcName
, -1, out
->lcName
, LCNAMELEN
);
52 out
->lcName
[LCNAMELEN
- 1] = 0;
53 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
54 memcpy(&out
->lcOptions
, &in
->lcOptions
, sizeof(LOGCONTEXTA
) - FIELD_OFFSET(LOGCONTEXTA
, lcOptions
));
57 static void LOGCONTEXTWtoA(const LOGCONTEXTW
*in
, LOGCONTEXTA
*out
)
59 WideCharToMultiByte(CP_ACP
, 0, in
->lcName
, LCNAMELEN
, out
->lcName
, LCNAMELEN
, NULL
, NULL
);
60 out
->lcName
[LCNAMELEN
- 1] = 0;
61 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
62 memcpy(&out
->lcOptions
, &in
->lcOptions
, sizeof(LOGCONTEXTW
) - FIELD_OFFSET(LOGCONTEXTW
, lcOptions
));
65 static BOOL
is_logcontext_category(UINT wCategory
)
67 return wCategory
== WTI_DEFSYSCTX
|| wCategory
== WTI_DEFCONTEXT
|| wCategory
== WTI_DDCTXS
;
70 static BOOL
is_string_field(UINT wCategory
, UINT nIndex
)
72 if (wCategory
== WTI_INTERFACE
&& nIndex
== IFC_WINTABID
)
74 if (is_logcontext_category(wCategory
) && nIndex
== CTX_NAME
)
76 if ((wCategory
>= WTI_CURSORS
&& wCategory
<= WTI_CURSORS
+ 9) &&
77 (nIndex
== CSR_NAME
|| nIndex
== CSR_BTNNAMES
))
79 if (wCategory
== WTI_DEVICES
&& (nIndex
== DVC_NAME
|| nIndex
== DVC_PNPID
))
84 static const char* DUMPBITS(int x
)
88 if (x
&PK_CONTEXT
) strcat(buf
,"PK_CONTEXT ");
89 if (x
&PK_STATUS
) strcat(buf
, "PK_STATUS ");
90 if (x
&PK_TIME
) strcat(buf
, "PK_TIME ");
91 if (x
&PK_CHANGED
) strcat(buf
, "PK_CHANGED ");
92 if (x
&PK_SERIAL_NUMBER
) strcat(buf
, "PK_SERIAL_NUMBER ");
93 if (x
&PK_CURSOR
) strcat(buf
, "PK_CURSOR ");
94 if (x
&PK_BUTTONS
) strcat(buf
, "PK_BUTTONS ");
95 if (x
&PK_X
) strcat(buf
, "PK_X ");
96 if (x
&PK_Y
) strcat(buf
, "PK_Y ");
97 if (x
&PK_Z
) strcat(buf
, "PK_Z ");
98 if (x
&PK_NORMAL_PRESSURE
) strcat(buf
, "PK_NORMAL_PRESSURE ");
99 if (x
&PK_TANGENT_PRESSURE
) strcat(buf
, "PK_TANGENT_PRESSURE ");
100 if (x
&PK_ORIENTATION
) strcat(buf
, "PK_ORIENTATION ");
101 if (x
&PK_ROTATION
) strcat(buf
, "PK_ROTATION ");
102 return wine_dbg_sprintf("{%s}",buf
);
105 static inline void DUMPPACKET(WTPACKET packet
)
107 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",
108 packet
.pkContext
, packet
.pkStatus
, packet
.pkTime
, packet
.pkChanged
, packet
.pkSerialNumber
,
109 packet
.pkCursor
, packet
.pkButtons
, packet
.pkX
, packet
.pkY
, packet
.pkZ
,
110 packet
.pkNormalPressure
, packet
.pkTangentPressure
,
111 packet
.pkOrientation
.orAzimuth
, packet
.pkOrientation
.orAltitude
, packet
.pkOrientation
.orTwist
,
112 packet
.pkRotation
.roPitch
, packet
.pkRotation
.roRoll
, packet
.pkRotation
.roYaw
);
115 static inline void DUMPCONTEXT(LOGCONTEXTW lc
)
117 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, "
118 "Device: %x, PktRate: %x, "
120 "BtnDnMask: %x, BtnUpMask: %x, "
121 "InOrgX: %i, InOrgY: %i, InOrgZ: %i, "
122 "InExtX: %i, InExtY: %i, InExtZ: %i, "
123 "OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i, "
124 "OutExtX: %i, OutExtY: %i, OutExtZ: %i, "
125 "SensX: %i, SensY: %i, SensZ: %i, "
127 "SysOrgX: %i, SysOrgY: %i, "
128 "SysExtX: %i, SysExtY: %i, "
129 "SysSensX: %i, SysSensY: %i\n",
130 wine_dbgstr_w(lc
.lcName
), lc
.lcOptions
, lc
.lcStatus
, lc
.lcLocks
, lc
.lcMsgBase
,
131 lc
.lcDevice
, lc
.lcPktRate
, lc
.lcPktData
, DUMPBITS(lc
.lcPktData
),
132 lc
.lcPktMode
, DUMPBITS(lc
.lcPktMode
), lc
.lcMoveMask
,
133 DUMPBITS(lc
.lcMoveMask
), lc
.lcBtnDnMask
, lc
.lcBtnUpMask
,
134 lc
.lcInOrgX
, lc
.lcInOrgY
, lc
.lcInOrgZ
, lc
.lcInExtX
, lc
.lcInExtY
,
135 lc
.lcInExtZ
, lc
.lcOutOrgX
, lc
.lcOutOrgY
, lc
.lcOutOrgZ
, lc
.lcOutExtX
,
136 lc
.lcOutExtY
, lc
.lcOutExtZ
, lc
.lcSensX
, lc
.lcSensY
, lc
.lcSensZ
, lc
.lcSysMode
,
137 lc
.lcSysOrgX
, lc
.lcSysOrgY
, lc
.lcSysExtX
, lc
.lcSysExtY
, lc
.lcSysSensX
,
142 /* Find an open context given the handle */
143 static LPOPENCONTEXT
TABLET_FindOpenContext(HCTX hCtx
)
145 LPOPENCONTEXT ptr
= gOpenContexts
;
148 if (ptr
->handle
== hCtx
) return ptr
;
154 static void LoadTablet(void)
156 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault
);
158 pLoadTabletInfo(hwndDefault
);
161 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext
, UINT msg
, WPARAM wParam
,
162 LPARAM lParam
, BOOL send_always
)
164 if ((send_always
) || (newcontext
->context
.lcOptions
& CXO_MESSAGES
))
166 TRACE("Posting message %x to %p\n",msg
, newcontext
->hwndOwner
);
167 return PostMessageA(newcontext
->hwndOwner
, msg
, wParam
, lParam
);
172 static inline DWORD
ScaleForContext(DWORD In
, LONG InOrg
, LONG InExt
, LONG OutOrg
, LONG OutExt
)
174 if (((InExt
> 0 )&&(OutExt
> 0)) || ((InExt
<0) && (OutExt
< 0)))
175 return ((In
- InOrg
) * abs(OutExt
) / abs(InExt
)) + OutOrg
;
177 return ((abs(InExt
) - (In
- InOrg
))*abs(OutExt
) / abs(InExt
)) + OutOrg
;
180 LPOPENCONTEXT
AddPacketToContextQueue(LPWTPACKET packet
, HWND hwnd
)
182 LPOPENCONTEXT ptr
=NULL
;
184 EnterCriticalSection(&csTablet
);
189 TRACE("Trying Queue %p (%p %p)\n", ptr
->handle
, hwnd
, ptr
->hwndOwner
);
191 if (ptr
->hwndOwner
== hwnd
)
200 tgt
= ptr
->PacketsQueued
;
202 packet
->pkContext
= ptr
->handle
;
204 /* translate packet data to the context */
206 /* Scale as per documentation */
207 packet
->pkY
= ScaleForContext(packet
->pkY
, ptr
->context
.lcInOrgY
,
208 ptr
->context
.lcInExtY
, ptr
->context
.lcOutOrgY
,
209 ptr
->context
.lcOutExtY
);
211 packet
->pkX
= ScaleForContext(packet
->pkX
, ptr
->context
.lcInOrgX
,
212 ptr
->context
.lcInExtX
, ptr
->context
.lcOutOrgX
,
213 ptr
->context
.lcOutExtX
);
215 /* flip the Y axis */
216 if (ptr
->context
.lcOutExtY
> 0)
217 packet
->pkY
= ptr
->context
.lcOutExtY
- packet
->pkY
;
218 else if (ptr
->context
.lcOutExtY
< 0)
219 packet
->pkY
= abs(ptr
->context
.lcOutExtY
+ packet
->pkY
);
223 if (tgt
== ptr
->QueueSize
)
225 TRACE("Queue Overflow %p\n",ptr
->handle
);
226 ptr
->PacketQueue
[tgt
-1].pkStatus
|= TPS_QUEUE_ERR
;
230 TRACE("Placed in queue %p index %i\n",ptr
->handle
,tgt
);
231 ptr
->PacketQueue
[tgt
] = *packet
;
232 ptr
->PacketsQueued
++;
234 if (ptr
->ActiveCursor
!= packet
->pkCursor
)
236 ptr
->ActiveCursor
= packet
->pkCursor
;
237 if (ptr
->context
.lcOptions
& CXO_CSRMESSAGES
)
238 TABLET_PostTabletMessage(ptr
, _WT_CSRCHANGE(ptr
->context
.lcMsgBase
),
239 (WPARAM
)packet
->pkSerialNumber
, (LPARAM
)ptr
->handle
,
247 LeaveCriticalSection(&csTablet
);
248 TRACE("Done (%p)\n",ptr
);
253 * Flushes all packets from the queue.
255 static inline void TABLET_FlushQueue(LPOPENCONTEXT context
)
257 context
->PacketsQueued
= 0;
260 static inline int CopyTabletData(LPVOID target
, LPVOID src
, INT size
)
262 memcpy(target
,src
,size
);
266 static INT
TABLET_FindPacket(LPOPENCONTEXT context
, UINT wSerial
,
271 for (loop
= 0; loop
< context
->PacketsQueued
; loop
++)
272 if (context
->PacketQueue
[loop
].pkSerialNumber
== wSerial
)
275 *pkt
= &context
->PacketQueue
[loop
];
279 TRACE("%i .. %i\n",context
->PacketsQueued
,index
);
285 static LPVOID
TABLET_CopyPacketData(LPOPENCONTEXT context
, LPVOID lpPkt
,
291 TRACE("Packet Bits %s\n",DUMPBITS(context
->context
.lcPktData
));
293 if (context
->context
.lcPktData
& PK_CONTEXT
)
294 ptr
+=CopyTabletData(ptr
,&wtp
->pkContext
,sizeof(HCTX
));
295 if (context
->context
.lcPktData
& PK_STATUS
)
296 ptr
+=CopyTabletData(ptr
,&wtp
->pkStatus
,sizeof(UINT
));
297 if (context
->context
.lcPktData
& PK_TIME
)
298 ptr
+=CopyTabletData(ptr
,&wtp
->pkTime
,sizeof(LONG
));
299 if (context
->context
.lcPktData
& PK_CHANGED
)
300 ptr
+=CopyTabletData(ptr
,&wtp
->pkChanged
,sizeof(WTPKT
));
301 if (context
->context
.lcPktData
& PK_SERIAL_NUMBER
)
302 ptr
+=CopyTabletData(ptr
,&wtp
->pkChanged
,sizeof(UINT
));
303 if (context
->context
.lcPktData
& PK_CURSOR
)
304 ptr
+=CopyTabletData(ptr
,&wtp
->pkCursor
,sizeof(UINT
));
305 if (context
->context
.lcPktData
& PK_BUTTONS
)
306 ptr
+=CopyTabletData(ptr
,&wtp
->pkButtons
,sizeof(DWORD
));
307 if (context
->context
.lcPktData
& PK_X
)
308 ptr
+=CopyTabletData(ptr
,&wtp
->pkX
,sizeof(DWORD
));
309 if (context
->context
.lcPktData
& PK_Y
)
310 ptr
+=CopyTabletData(ptr
,&wtp
->pkY
,sizeof(DWORD
));
311 if (context
->context
.lcPktData
& PK_Z
)
312 ptr
+=CopyTabletData(ptr
,&wtp
->pkZ
,sizeof(DWORD
));
313 if (context
->context
.lcPktData
& PK_NORMAL_PRESSURE
)
314 ptr
+=CopyTabletData(ptr
,&wtp
->pkNormalPressure
,sizeof(UINT
));
315 if (context
->context
.lcPktData
& PK_TANGENT_PRESSURE
)
316 ptr
+=CopyTabletData(ptr
,&wtp
->pkTangentPressure
,sizeof(UINT
));
317 if (context
->context
.lcPktData
& PK_ORIENTATION
)
318 ptr
+=CopyTabletData(ptr
,&wtp
->pkOrientation
,sizeof(ORIENTATION
));
319 if (context
->context
.lcPktData
& PK_ROTATION
)
320 ptr
+=CopyTabletData(ptr
,&wtp
->pkRotation
,sizeof(ROTATION
));
322 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
326 static VOID
TABLET_BlankPacketData(LPOPENCONTEXT context
, LPVOID lpPkt
, INT n
)
330 if (context
->context
.lcPktData
& PK_CONTEXT
)
332 if (context
->context
.lcPktData
& PK_STATUS
)
334 if (context
->context
.lcPktData
& PK_TIME
)
336 if (context
->context
.lcPktData
& PK_CHANGED
)
338 if (context
->context
.lcPktData
& PK_SERIAL_NUMBER
)
340 if (context
->context
.lcPktData
& PK_CURSOR
)
342 if (context
->context
.lcPktData
& PK_BUTTONS
)
344 if (context
->context
.lcPktData
& PK_X
)
346 if (context
->context
.lcPktData
& PK_Y
)
348 if (context
->context
.lcPktData
& PK_Z
)
350 if (context
->context
.lcPktData
& PK_NORMAL_PRESSURE
)
352 if (context
->context
.lcPktData
& PK_TANGENT_PRESSURE
)
354 if (context
->context
.lcPktData
& PK_ORIENTATION
)
355 rc
+= sizeof(ORIENTATION
);
356 if (context
->context
.lcPktData
& PK_ROTATION
)
357 rc
+= sizeof(ROTATION
);
364 static UINT
WTInfoT(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
, BOOL bUnicode
)
368 TRACE("(%d, %d, %p, %d)\n", wCategory
, nIndex
, lpOutput
, bUnicode
);
369 if (gLoaded
== FALSE
)
373 * Handle system extents here, as we can use user32.dll code to set them.
375 if(wCategory
== WTI_DEFSYSCTX
)
381 *(LONG
*)lpOutput
= GetSystemMetrics(SM_CXSCREEN
);
385 *(LONG
*)lpOutput
= GetSystemMetrics(SM_CYSCREEN
);
387 /* No action, delegate to X11Drv */
391 if (is_logcontext_category(wCategory
) && nIndex
== 0)
396 pWTInfoW(wCategory
, nIndex
, &buf
);
398 /* Handle system extents here, as we can use user32.dll code to set them */
399 if(wCategory
== WTI_DEFSYSCTX
&& nIndex
== 0)
401 buf
.lcSysExtX
= GetSystemMetrics(SM_CXSCREEN
);
402 buf
.lcSysExtY
= GetSystemMetrics(SM_CYSCREEN
);
406 memcpy(lpOutput
, &buf
, sizeof(buf
));
408 LOGCONTEXTWtoA(&buf
, lpOutput
);
411 result
= bUnicode
? sizeof(LOGCONTEXTW
) : sizeof(LOGCONTEXTA
);
413 else if (is_string_field(wCategory
, nIndex
) && !bUnicode
)
415 int size
= pWTInfoW(wCategory
, nIndex
, NULL
);
416 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, size
);
417 pWTInfoW(wCategory
, nIndex
, buf
);
418 result
= WideCharToMultiByte(CP_ACP
, 0, buf
, size
/sizeof(WCHAR
), lpOutput
, lpOutput
? 2*size
: 0, NULL
, NULL
);
419 HeapFree(GetProcessHeap(), 0, buf
);
422 result
= pWTInfoW(wCategory
, nIndex
, lpOutput
);
424 TRACE("returns %d\n", result
);
428 /***********************************************************************
429 * WTInfoA (WINTAB32.20)
431 UINT WINAPI
WTInfoA(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
433 return WTInfoT(wCategory
, nIndex
, lpOutput
, FALSE
);
437 /***********************************************************************
438 * WTInfoW (WINTAB32.1020)
440 UINT WINAPI
WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
442 return WTInfoT(wCategory
, nIndex
, lpOutput
, TRUE
);
445 /***********************************************************************
446 * WTOpenW (WINTAB32.2021)
448 HCTX WINAPI
WTOpenW(HWND hWnd
, LPLOGCONTEXTW lpLogCtx
, BOOL fEnable
)
450 LPOPENCONTEXT newcontext
;
452 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd
, lpLogCtx
, fEnable
);
453 DUMPCONTEXT(*lpLogCtx
);
455 newcontext
= HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT
));
456 newcontext
->context
= *lpLogCtx
;
457 newcontext
->hwndOwner
= hWnd
;
458 newcontext
->ActiveCursor
= -1;
459 newcontext
->QueueSize
= 10;
460 newcontext
->PacketsQueued
= 0;
461 newcontext
->PacketQueue
=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET
)*10);
463 EnterCriticalSection(&csTablet
);
464 newcontext
->handle
= gTopContext
++;
465 newcontext
->next
= gOpenContexts
;
466 gOpenContexts
= newcontext
;
467 LeaveCriticalSection(&csTablet
);
469 pAttachEventQueueToTablet(hWnd
);
471 TABLET_PostTabletMessage(newcontext
, _WT_CTXOPEN(newcontext
->context
.lcMsgBase
), (WPARAM
)newcontext
->handle
,
472 newcontext
->context
.lcStatus
, TRUE
);
476 newcontext
->enabled
= TRUE
;
477 /* TODO: Add to top of overlap order */
478 newcontext
->context
.lcStatus
= CXS_ONTOP
;
482 newcontext
->enabled
= FALSE
;
483 newcontext
->context
.lcStatus
= CXS_DISABLED
;
486 TABLET_PostTabletMessage(newcontext
, _WT_CTXOVERLAP(newcontext
->context
.lcMsgBase
),
487 (WPARAM
)newcontext
->handle
,
488 newcontext
->context
.lcStatus
, TRUE
);
490 return newcontext
->handle
;
493 /***********************************************************************
494 * WTOpenA (WINTAB32.21)
496 HCTX WINAPI
WTOpenA(HWND hWnd
, LPLOGCONTEXTA lpLogCtx
, BOOL fEnable
)
500 LOGCONTEXTAtoW(lpLogCtx
, &logCtxW
);
501 return WTOpenW(hWnd
, &logCtxW
, fEnable
);
504 /***********************************************************************
505 * WTClose (WINTAB32.22)
507 BOOL WINAPI
WTClose(HCTX hCtx
)
509 LPOPENCONTEXT context
,ptr
;
511 TRACE("(%p)\n", hCtx
);
513 EnterCriticalSection(&csTablet
);
515 ptr
= context
= gOpenContexts
;
517 while (context
&& (context
->handle
!= hCtx
))
520 context
= context
->next
;
524 LeaveCriticalSection(&csTablet
);
528 if (context
== gOpenContexts
)
529 gOpenContexts
= context
->next
;
531 ptr
->next
= context
->next
;
533 LeaveCriticalSection(&csTablet
);
535 TABLET_PostTabletMessage(context
, _WT_CTXCLOSE(context
->context
.lcMsgBase
), (WPARAM
)context
->handle
,
536 context
->context
.lcStatus
,TRUE
);
538 HeapFree(GetProcessHeap(),0,context
->PacketQueue
);
539 HeapFree(GetProcessHeap(),0,context
);
544 /***********************************************************************
545 * WTPacketsGet (WINTAB32.23)
547 int WINAPI
WTPacketsGet(HCTX hCtx
, int cMaxPkts
, LPVOID lpPkts
)
550 LPOPENCONTEXT context
;
553 TRACE("(%p, %d, %p)\n", hCtx
, cMaxPkts
, lpPkts
);
558 EnterCriticalSection(&csTablet
);
560 context
= TABLET_FindOpenContext(hCtx
);
563 TABLET_BlankPacketData(context
,lpPkts
,cMaxPkts
);
565 if (context
->PacketsQueued
== 0)
567 LeaveCriticalSection(&csTablet
);
571 limit
= min(cMaxPkts
,context
->PacketsQueued
);
576 for(i
= 0; i
< limit
; i
++)
577 ptr
=TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[i
]);
581 if (limit
< context
->PacketsQueued
)
583 memmove(context
->PacketQueue
, &context
->PacketQueue
[limit
],
584 (context
->PacketsQueued
- (limit
))*sizeof(WTPACKET
));
586 context
->PacketsQueued
-= limit
;
587 LeaveCriticalSection(&csTablet
);
589 TRACE("Copied %i packets\n",limit
);
594 /***********************************************************************
595 * WTPacket (WINTAB32.24)
597 BOOL WINAPI
WTPacket(HCTX hCtx
, UINT wSerial
, LPVOID lpPkt
)
600 LPOPENCONTEXT context
;
601 LPWTPACKET wtp
= NULL
;
603 TRACE("(%p, %d, %p)\n", hCtx
, wSerial
, lpPkt
);
608 EnterCriticalSection(&csTablet
);
610 context
= TABLET_FindOpenContext(hCtx
);
612 rc
= TABLET_FindPacket(context
,wSerial
, &wtp
);
617 TABLET_CopyPacketData(context
,lpPkt
, wtp
);
619 if ((rc
+1) < context
->QueueSize
)
621 memmove(context
->PacketQueue
, &context
->PacketQueue
[rc
+1],
622 (context
->PacketsQueued
- (rc
+1))*sizeof(WTPACKET
));
624 context
->PacketsQueued
-= (rc
+1);
626 LeaveCriticalSection(&csTablet
);
628 TRACE("Returning %i\n",rc
+1);
632 /***********************************************************************
633 * WTEnable (WINTAB32.40)
635 BOOL WINAPI
WTEnable(HCTX hCtx
, BOOL fEnable
)
637 LPOPENCONTEXT context
;
639 TRACE("hCtx=%p, fEnable=%u\n", hCtx
, fEnable
);
641 if (!hCtx
) return FALSE
;
643 EnterCriticalSection(&csTablet
);
644 context
= TABLET_FindOpenContext(hCtx
);
645 /* if we want to enable and it is not enabled then */
646 if(fEnable
&& !context
->enabled
)
648 context
->enabled
= TRUE
;
649 /* TODO: Add to top of overlap order */
650 context
->context
.lcStatus
= CXS_ONTOP
;
651 TABLET_PostTabletMessage(context
,
652 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
653 (WPARAM
)context
->handle
,
654 context
->context
.lcStatus
, TRUE
);
656 /* if we want to disable and it is not disabled then */
657 else if (!fEnable
&& context
->enabled
)
659 context
->enabled
= FALSE
;
660 /* TODO: Remove from overlap order?? needs a test */
661 context
->context
.lcStatus
= CXS_DISABLED
;
662 TABLET_FlushQueue(context
);
663 TABLET_PostTabletMessage(context
,
664 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
665 (WPARAM
)context
->handle
,
666 context
->context
.lcStatus
, TRUE
);
668 LeaveCriticalSection(&csTablet
);
673 /***********************************************************************
674 * WTOverlap (WINTAB32.41)
676 * Move context to top or bottom of overlap order
678 BOOL WINAPI
WTOverlap(HCTX hCtx
, BOOL fToTop
)
680 LPOPENCONTEXT context
;
682 TRACE("hCtx=%p, fToTop=%u\n", hCtx
, fToTop
);
684 if (!hCtx
) return FALSE
;
686 EnterCriticalSection(&csTablet
);
687 context
= TABLET_FindOpenContext(hCtx
);
690 LeaveCriticalSection(&csTablet
);
694 /* if we want to send to top and it's not already there */
695 if (fToTop
&& context
->context
.lcStatus
!= CXS_ONTOP
)
697 /* TODO: Move context to top of overlap order */
698 FIXME("Not moving context to top of overlap order\n");
699 context
->context
.lcStatus
= CXS_ONTOP
;
700 TABLET_PostTabletMessage(context
,
701 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
702 (WPARAM
)context
->handle
,
703 context
->context
.lcStatus
, TRUE
);
707 /* TODO: Move context to bottom of overlap order */
708 FIXME("Not moving context to bottom of overlap order\n");
709 context
->context
.lcStatus
= CXS_OBSCURED
;
710 TABLET_PostTabletMessage(context
,
711 _WT_CTXOVERLAP(context
->context
.lcMsgBase
),
712 (WPARAM
)context
->handle
,
713 context
->context
.lcStatus
, TRUE
);
715 LeaveCriticalSection(&csTablet
);
720 /***********************************************************************
721 * WTConfig (WINTAB32.61)
723 BOOL WINAPI
WTConfig(HCTX hCtx
, HWND hWnd
)
725 FIXME("(%p, %p): stub\n", hCtx
, hWnd
);
727 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
732 /***********************************************************************
733 * WTGetA (WINTAB32.61)
735 BOOL WINAPI
WTGetA(HCTX hCtx
, LPLOGCONTEXTA lpLogCtx
)
737 LPOPENCONTEXT context
;
739 TRACE("(%p, %p)\n", hCtx
, lpLogCtx
);
743 EnterCriticalSection(&csTablet
);
744 context
= TABLET_FindOpenContext(hCtx
);
745 LOGCONTEXTWtoA(&context
->context
, lpLogCtx
);
746 LeaveCriticalSection(&csTablet
);
751 /***********************************************************************
752 * WTGetW (WINTAB32.1061)
754 BOOL WINAPI
WTGetW(HCTX hCtx
, LPLOGCONTEXTW lpLogCtx
)
756 LPOPENCONTEXT context
;
758 TRACE("(%p, %p)\n", hCtx
, lpLogCtx
);
762 EnterCriticalSection(&csTablet
);
763 context
= TABLET_FindOpenContext(hCtx
);
764 memmove(lpLogCtx
,&context
->context
,sizeof(LOGCONTEXTW
));
765 LeaveCriticalSection(&csTablet
);
770 /***********************************************************************
771 * WTSetA (WINTAB32.62)
773 BOOL WINAPI
WTSetA(HCTX hCtx
, LPLOGCONTEXTA lpLogCtx
)
775 LPOPENCONTEXT context
;
777 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx
, lpLogCtx
);
779 if (!hCtx
|| !lpLogCtx
) return FALSE
;
781 /* TODO: if cur process not owner of hCtx only modify
782 * attribs not locked by owner */
784 EnterCriticalSection(&csTablet
);
785 context
= TABLET_FindOpenContext(hCtx
);
788 LeaveCriticalSection(&csTablet
);
792 LOGCONTEXTAtoW(lpLogCtx
, &context
->context
);
793 LeaveCriticalSection(&csTablet
);
798 /***********************************************************************
799 * WTSetW (WINTAB32.1062)
801 BOOL WINAPI
WTSetW(HCTX hCtx
, LPLOGCONTEXTW lpLogCtx
)
803 LPOPENCONTEXT context
;
805 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx
, lpLogCtx
);
807 if (!hCtx
|| !lpLogCtx
) return FALSE
;
809 /* TODO: if cur process not hCtx owner only modify
810 * attribs not locked by owner */
812 EnterCriticalSection(&csTablet
);
813 context
= TABLET_FindOpenContext(hCtx
);
816 LeaveCriticalSection(&csTablet
);
820 memmove(&context
->context
, lpLogCtx
, sizeof(LOGCONTEXTW
));
821 LeaveCriticalSection(&csTablet
);
826 /***********************************************************************
827 * WTExtGet (WINTAB32.63)
829 BOOL WINAPI
WTExtGet(HCTX hCtx
, UINT wExt
, LPVOID lpData
)
831 FIXME("(%p, %u, %p): stub\n", hCtx
, wExt
, lpData
);
833 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
838 /***********************************************************************
839 * WTExtSet (WINTAB32.64)
841 BOOL WINAPI
WTExtSet(HCTX hCtx
, UINT wExt
, LPVOID lpData
)
843 FIXME("(%p, %u, %p): stub\n", hCtx
, wExt
, lpData
);
845 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
850 /***********************************************************************
851 * WTSave (WINTAB32.65)
853 BOOL WINAPI
WTSave(HCTX hCtx
, LPVOID lpSaveInfo
)
855 FIXME("(%p, %p): stub\n", hCtx
, lpSaveInfo
);
857 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
862 /***********************************************************************
863 * WTRestore (WINTAB32.66)
865 HCTX WINAPI
WTRestore(HWND hWnd
, LPVOID lpSaveInfo
, BOOL fEnable
)
867 FIXME("(%p, %p, %u): stub\n", hWnd
, lpSaveInfo
, fEnable
);
869 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
874 /***********************************************************************
875 * WTPacketsPeek (WINTAB32.80)
877 int WINAPI
WTPacketsPeek(HCTX hCtx
, int cMaxPkts
, LPVOID lpPkts
)
880 LPOPENCONTEXT context
;
883 TRACE("(%p, %d, %p)\n", hCtx
, cMaxPkts
, lpPkts
);
885 if (!hCtx
|| !lpPkts
) return 0;
887 EnterCriticalSection(&csTablet
);
889 context
= TABLET_FindOpenContext(hCtx
);
891 if (context
->PacketsQueued
== 0)
893 LeaveCriticalSection(&csTablet
);
897 for (limit
= 0; limit
< cMaxPkts
&& limit
< context
->PacketsQueued
; limit
++)
898 ptr
= TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[limit
]);
900 LeaveCriticalSection(&csTablet
);
901 TRACE("Copied %i packets\n",limit
);
905 /***********************************************************************
906 * WTDataGet (WINTAB32.81)
908 int WINAPI
WTDataGet(HCTX hCtx
, UINT wBegin
, UINT wEnd
,
909 int cMaxPkts
, LPVOID lpPkts
, LPINT lpNPkts
)
911 LPOPENCONTEXT context
;
917 TRACE("(%p, %u, %u, %d, %p, %p)\n",
918 hCtx
, wBegin
, wEnd
, cMaxPkts
, lpPkts
, lpNPkts
);
922 EnterCriticalSection(&csTablet
);
924 context
= TABLET_FindOpenContext(hCtx
);
926 if (context
->PacketsQueued
== 0)
928 LeaveCriticalSection(&csTablet
);
932 while (bgn
< context
->PacketsQueued
&&
933 context
->PacketQueue
[bgn
].pkSerialNumber
!= wBegin
)
937 while (end
< context
->PacketsQueued
&&
938 context
->PacketQueue
[end
].pkSerialNumber
!= wEnd
)
941 if ((bgn
== end
) && (end
== context
->PacketsQueued
))
943 LeaveCriticalSection(&csTablet
);
947 for (num
= bgn
; num
<= end
; num
++)
948 ptr
= TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[num
]);
950 /* remove read packets */
951 if ((end
+1) < context
->PacketsQueued
)
952 memmove( &context
->PacketQueue
[bgn
], &context
->PacketQueue
[end
+1],
953 (context
->PacketsQueued
- (end
+1)) * sizeof (WTPACKET
));
955 context
->PacketsQueued
-= ((end
-bgn
)+1);
956 *lpNPkts
= ((end
-bgn
)+1);
958 LeaveCriticalSection(&csTablet
);
959 TRACE("Copied %i packets\n",*lpNPkts
);
960 return (end
- bgn
)+1;
963 /***********************************************************************
964 * WTDataPeek (WINTAB32.82)
966 int WINAPI
WTDataPeek(HCTX hCtx
, UINT wBegin
, UINT wEnd
,
967 int cMaxPkts
, LPVOID lpPkts
, LPINT lpNPkts
)
969 LPOPENCONTEXT context
;
975 TRACE("(%p, %u, %u, %d, %p, %p)\n",
976 hCtx
, wBegin
, wEnd
, cMaxPkts
, lpPkts
, lpNPkts
);
978 if (!hCtx
|| !lpPkts
) return 0;
980 EnterCriticalSection(&csTablet
);
982 context
= TABLET_FindOpenContext(hCtx
);
984 if (context
->PacketsQueued
== 0)
986 LeaveCriticalSection(&csTablet
);
990 while (bgn
< context
->PacketsQueued
&&
991 context
->PacketQueue
[bgn
].pkSerialNumber
!= wBegin
)
995 while (end
< context
->PacketsQueued
&&
996 context
->PacketQueue
[end
].pkSerialNumber
!= wEnd
)
999 if (bgn
== context
->PacketsQueued
|| end
== context
->PacketsQueued
)
1001 TRACE("%i %i %i\n", bgn
, end
, context
->PacketsQueued
);
1002 LeaveCriticalSection(&csTablet
);
1006 for (num
= bgn
; num
<= end
; num
++)
1007 ptr
= TABLET_CopyPacketData(context
,ptr
, &context
->PacketQueue
[num
]);
1009 *lpNPkts
= ((end
-bgn
)+1);
1010 LeaveCriticalSection(&csTablet
);
1012 TRACE("Copied %i packets\n",*lpNPkts
);
1013 return (end
- bgn
)+1;
1016 /***********************************************************************
1017 * WTQueuePacketsEx (WINTAB32.200)
1019 BOOL WINAPI
WTQueuePacketsEx(HCTX hCtx
, UINT
*lpOld
, UINT
*lpNew
)
1021 LPOPENCONTEXT context
;
1023 TRACE("(%p, %p, %p)\n", hCtx
, lpOld
, lpNew
);
1025 if (!hCtx
) return 0;
1027 EnterCriticalSection(&csTablet
);
1029 context
= TABLET_FindOpenContext(hCtx
);
1031 if (context
->PacketsQueued
)
1033 *lpOld
= context
->PacketQueue
[0].pkSerialNumber
;
1034 *lpNew
= context
->PacketQueue
[context
->PacketsQueued
-1].pkSerialNumber
;
1038 TRACE("No packets\n");
1039 LeaveCriticalSection(&csTablet
);
1042 LeaveCriticalSection(&csTablet
);
1047 /***********************************************************************
1048 * WTQueueSizeGet (WINTAB32.84)
1050 int WINAPI
WTQueueSizeGet(HCTX hCtx
)
1052 LPOPENCONTEXT context
;
1053 TRACE("(%p)\n", hCtx
);
1055 if (!hCtx
) return 0;
1057 EnterCriticalSection(&csTablet
);
1058 context
= TABLET_FindOpenContext(hCtx
);
1059 LeaveCriticalSection(&csTablet
);
1060 return context
->QueueSize
;
1063 /***********************************************************************
1064 * WTQueueSizeSet (WINTAB32.85)
1066 BOOL WINAPI
WTQueueSizeSet(HCTX hCtx
, int nPkts
)
1068 LPOPENCONTEXT context
;
1070 TRACE("(%p, %d)\n", hCtx
, nPkts
);
1072 if (!hCtx
) return 0;
1074 EnterCriticalSection(&csTablet
);
1076 context
= TABLET_FindOpenContext(hCtx
);
1078 context
->PacketQueue
= HeapReAlloc(GetProcessHeap(), 0,
1079 context
->PacketQueue
, sizeof(WTPACKET
)*nPkts
);
1081 context
->QueueSize
= nPkts
;
1082 LeaveCriticalSection(&csTablet
);