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);