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("context: %s, %x, %x, %x, %x, %x, %x, %x%s, %x%s, %x%s, %x, %x, %i, %i, %i, %i ,%i, %i, %i, %i, %i,%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i %i %i\n",
118 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
119 lc.lcDevice, lc.lcPktRate, lc.lcPktData, DUMPBITS(lc.lcPktData),
120 lc.lcPktMode, DUMPBITS(lc.lcPktMode), lc.lcMoveMask,
121 DUMPBITS(lc.lcMoveMask), lc.lcBtnDnMask, lc.lcBtnUpMask,
122 lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
123 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
124 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
125 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
130 /* Find an open context given the handle */
131 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
133 LPOPENCONTEXT ptr = gOpenContexts;
136 if (ptr->handle == hCtx) return ptr;
142 static void LoadTablet(void)
144 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
146 pLoadTabletInfo(hwndDefault);
149 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
150 LPARAM lParam, BOOL send_always)
152 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
154 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
155 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
160 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
162 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
163 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
165 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
168 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
170 LPOPENCONTEXT ptr=NULL;
172 EnterCriticalSection(&csTablet);
177 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
179 if (ptr->hwndOwner == hwnd)
188 tgt = ptr->PacketsQueued;
190 packet->pkContext = ptr->handle;
192 /* translate packet data to the context */
194 /* Scale as per documentation */
195 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
196 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
197 ptr->context.lcOutExtY);
199 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
200 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
201 ptr->context.lcOutExtX);
203 /* flip the Y axis */
204 if (ptr->context.lcOutExtY > 0)
205 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
209 if (tgt == ptr->QueueSize)
211 TRACE("Queue Overflow %p\n",ptr->handle);
212 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
216 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
217 memcpy(&ptr->PacketQueue[tgt], packet, sizeof
219 ptr->PacketsQueued++;
221 if (ptr->ActiveCursor != packet->pkCursor)
223 ptr->ActiveCursor = packet->pkCursor;
224 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
225 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
226 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
234 LeaveCriticalSection(&csTablet);
235 TRACE("Done (%p)\n",ptr);
240 * Flushes all packets from the queue.
242 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
244 context->PacketsQueued = 0;
247 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
249 memcpy(target,src,size);
253 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
258 for (loop = 0; loop < context->PacketsQueued; loop++)
259 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
262 *pkt = &context->PacketQueue[loop];
266 TRACE("%i .. %i\n",context->PacketsQueued,index);
272 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
278 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
280 if (context->context.lcPktData & PK_CONTEXT)
281 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
282 if (context->context.lcPktData & PK_STATUS)
283 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
284 if (context->context.lcPktData & PK_TIME)
285 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
286 if (context->context.lcPktData & PK_CHANGED)
287 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
288 if (context->context.lcPktData & PK_SERIAL_NUMBER)
289 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
290 if (context->context.lcPktData & PK_CURSOR)
291 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
292 if (context->context.lcPktData & PK_BUTTONS)
293 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
294 if (context->context.lcPktData & PK_X)
295 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
296 if (context->context.lcPktData & PK_Y)
297 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
298 if (context->context.lcPktData & PK_Z)
299 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
300 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
301 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
302 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
303 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
304 if (context->context.lcPktData & PK_ORIENTATION)
305 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
306 if (context->context.lcPktData & PK_ROTATION)
307 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
309 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
313 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
317 if (context->context.lcPktData & PK_CONTEXT)
319 if (context->context.lcPktData & PK_STATUS)
321 if (context->context.lcPktData & PK_TIME)
323 if (context->context.lcPktData & PK_CHANGED)
325 if (context->context.lcPktData & PK_SERIAL_NUMBER)
327 if (context->context.lcPktData & PK_CURSOR)
329 if (context->context.lcPktData & PK_BUTTONS)
331 if (context->context.lcPktData & PK_X)
333 if (context->context.lcPktData & PK_Y)
335 if (context->context.lcPktData & PK_Z)
337 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
339 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
341 if (context->context.lcPktData & PK_ORIENTATION)
342 rc += sizeof(ORIENTATION);
343 if (context->context.lcPktData & PK_ROTATION)
344 rc += sizeof(ROTATION);
351 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
355 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
356 if (gLoaded == FALSE)
360 * Handle system extents here, as we can use user32.dll code to set them.
362 if(wCategory == WTI_DEFSYSCTX)
368 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
372 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
374 /* No action, delegate to X11Drv */
378 if (is_logcontext_category(wCategory) && nIndex == 0)
383 pWTInfoW(wCategory, nIndex, &buf);
385 /* Handle system extents here, as we can use user32.dll code to set them */
386 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
388 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
389 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
393 memcpy(lpOutput, &buf, sizeof(buf));
395 LOGCONTEXTWtoA(&buf, lpOutput);
398 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
400 else if (is_string_field(wCategory, nIndex) && !bUnicode)
402 int size = pWTInfoW(wCategory, nIndex, NULL);
403 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
404 pWTInfoW(wCategory, nIndex, buf);
405 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
406 HeapFree(GetProcessHeap(), 0, buf);
409 result = pWTInfoW(wCategory, nIndex, lpOutput);
411 TRACE("returns %d\n", result);
415 /***********************************************************************
416 * WTInfoA (WINTAB32.20)
418 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
420 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
424 /***********************************************************************
425 * WTInfoW (WINTAB32.1020)
427 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
429 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
432 /***********************************************************************
433 * WTOpenW (WINTAB32.2021)
435 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
437 LPOPENCONTEXT newcontext;
439 TRACE("(%p, %p, %u)\n", hWnd, lpLogCtx, fEnable);
440 DUMPCONTEXT(*lpLogCtx);
442 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
443 memcpy(&(newcontext->context),lpLogCtx,sizeof(LOGCONTEXTW));
444 newcontext->hwndOwner = hWnd;
445 newcontext->enabled = fEnable;
446 newcontext->ActiveCursor = -1;
447 newcontext->QueueSize = 10;
448 newcontext->PacketsQueued = 0;
449 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
451 EnterCriticalSection(&csTablet);
452 newcontext->handle = gTopContext++;
453 newcontext->next = gOpenContexts;
454 gOpenContexts = newcontext;
455 LeaveCriticalSection(&csTablet);
457 pAttachEventQueueToTablet(hWnd);
459 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
460 newcontext->context.lcStatus, TRUE);
462 newcontext->context.lcStatus = CXS_ONTOP;
464 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
465 (WPARAM)newcontext->handle,
466 newcontext->context.lcStatus, TRUE);
468 return newcontext->handle;
471 /***********************************************************************
472 * WTOpenA (WINTAB32.21)
474 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
478 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
479 return WTOpenW(hWnd, &logCtxW, fEnable);
482 /***********************************************************************
483 * WTClose (WINTAB32.22)
485 BOOL WINAPI WTClose(HCTX hCtx)
487 LPOPENCONTEXT context,ptr;
489 TRACE("(%p)\n", hCtx);
491 EnterCriticalSection(&csTablet);
493 ptr = context = gOpenContexts;
495 while (context && (context->handle != hCtx))
498 context = context->next;
502 LeaveCriticalSection(&csTablet);
506 if (context == gOpenContexts)
507 gOpenContexts = context->next;
509 ptr->next = context->next;
511 LeaveCriticalSection(&csTablet);
513 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
514 context->context.lcStatus,TRUE);
516 HeapFree(GetProcessHeap(),0,context->PacketQueue);
517 HeapFree(GetProcessHeap(),0,context);
522 /***********************************************************************
523 * WTPacketsGet (WINTAB32.23)
525 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
528 LPOPENCONTEXT context;
531 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
536 EnterCriticalSection(&csTablet);
538 context = TABLET_FindOpenContext(hCtx);
541 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
543 if (context->PacketsQueued == 0)
545 LeaveCriticalSection(&csTablet);
549 limit = min(cMaxPkts,context->PacketsQueued);
554 for(i = 0; i < limit; i++)
555 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
559 if (limit < context->PacketsQueued)
561 memmove(context->PacketQueue, &context->PacketQueue[limit],
562 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
564 context->PacketsQueued -= limit;
565 LeaveCriticalSection(&csTablet);
567 TRACE("Copied %i packets\n",limit);
572 /***********************************************************************
573 * WTPacket (WINTAB32.24)
575 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
578 LPOPENCONTEXT context;
579 LPWTPACKET wtp = NULL;
581 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
586 EnterCriticalSection(&csTablet);
588 context = TABLET_FindOpenContext(hCtx);
590 rc = TABLET_FindPacket(context ,wSerial, &wtp);
595 TABLET_CopyPacketData(context ,lpPkt, wtp);
597 if ((rc+1) < context->QueueSize)
599 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
600 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
602 context->PacketsQueued -= (rc+1);
604 LeaveCriticalSection(&csTablet);
606 TRACE("Returning %i\n",rc+1);
610 /***********************************************************************
611 * WTEnable (WINTAB32.40)
613 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
615 LPOPENCONTEXT context;
617 TRACE("(%p, %u)\n", hCtx, fEnable);
621 EnterCriticalSection(&csTablet);
622 context = TABLET_FindOpenContext(hCtx);
624 TABLET_FlushQueue(context);
625 context->enabled = fEnable;
626 LeaveCriticalSection(&csTablet);
631 /***********************************************************************
632 * WTOverlap (WINTAB32.41)
634 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
636 FIXME("(%p, %u): stub\n", hCtx, fToTop);
641 /***********************************************************************
642 * WTConfig (WINTAB32.61)
644 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
646 FIXME("(%p, %p): stub\n", hCtx, hWnd);
648 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
653 /***********************************************************************
654 * WTGetA (WINTAB32.61)
656 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
658 LPOPENCONTEXT context;
660 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
664 EnterCriticalSection(&csTablet);
665 context = TABLET_FindOpenContext(hCtx);
666 LOGCONTEXTWtoA(&context->context, lpLogCtx);
667 LeaveCriticalSection(&csTablet);
672 /***********************************************************************
673 * WTGetW (WINTAB32.1061)
675 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
677 LPOPENCONTEXT context;
679 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
683 EnterCriticalSection(&csTablet);
684 context = TABLET_FindOpenContext(hCtx);
685 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
686 LeaveCriticalSection(&csTablet);
691 /***********************************************************************
692 * WTSetA (WINTAB32.62)
694 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
696 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
698 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
703 /***********************************************************************
704 * WTSetW (WINTAB32.1062)
706 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
708 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
710 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
715 /***********************************************************************
716 * WTExtGet (WINTAB32.63)
718 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
720 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
722 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
727 /***********************************************************************
728 * WTExtSet (WINTAB32.64)
730 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
732 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
734 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
739 /***********************************************************************
740 * WTSave (WINTAB32.65)
742 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
744 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
746 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
751 /***********************************************************************
752 * WTRestore (WINTAB32.66)
754 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
756 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
758 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
763 /***********************************************************************
764 * WTPacketsPeek (WINTAB32.80)
766 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
769 LPOPENCONTEXT context;
772 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
774 if (!hCtx || !lpPkts) return 0;
776 EnterCriticalSection(&csTablet);
778 context = TABLET_FindOpenContext(hCtx);
780 if (context->PacketsQueued == 0)
782 LeaveCriticalSection(&csTablet);
786 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
787 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
789 LeaveCriticalSection(&csTablet);
790 TRACE("Copied %i packets\n",limit);
794 /***********************************************************************
795 * WTDataGet (WINTAB32.81)
797 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
798 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
800 LPOPENCONTEXT context;
806 TRACE("(%p, %u, %u, %d, %p, %p)\n",
807 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
811 EnterCriticalSection(&csTablet);
813 context = TABLET_FindOpenContext(hCtx);
815 if (context->PacketsQueued == 0)
817 LeaveCriticalSection(&csTablet);
821 while (bgn < context->PacketsQueued &&
822 context->PacketQueue[bgn].pkSerialNumber != wBegin)
826 while (end < context->PacketsQueued &&
827 context->PacketQueue[end].pkSerialNumber != wEnd)
830 if ((bgn == end) && (end == context->PacketsQueued))
832 LeaveCriticalSection(&csTablet);
836 for (num = bgn; num <= end; num++)
837 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
839 /* remove read packets */
840 if ((end+1) < context->PacketsQueued)
841 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
842 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
844 context->PacketsQueued -= ((end-bgn)+1);
845 *lpNPkts = ((end-bgn)+1);
847 LeaveCriticalSection(&csTablet);
848 TRACE("Copied %i packets\n",*lpNPkts);
849 return (end - bgn)+1;
852 /***********************************************************************
853 * WTDataPeek (WINTAB32.82)
855 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
856 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
858 LPOPENCONTEXT context;
864 TRACE("(%p, %u, %u, %d, %p, %p)\n",
865 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
867 if (!hCtx || !lpPkts) return 0;
869 EnterCriticalSection(&csTablet);
871 context = TABLET_FindOpenContext(hCtx);
873 if (context->PacketsQueued == 0)
875 LeaveCriticalSection(&csTablet);
879 while (bgn < context->PacketsQueued &&
880 context->PacketQueue[bgn].pkSerialNumber != wBegin)
884 while (end < context->PacketsQueued &&
885 context->PacketQueue[end].pkSerialNumber != wEnd)
888 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
890 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
891 LeaveCriticalSection(&csTablet);
895 for (num = bgn; num <= end; num++)
896 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
898 *lpNPkts = ((end-bgn)+1);
899 LeaveCriticalSection(&csTablet);
901 TRACE("Copied %i packets\n",*lpNPkts);
902 return (end - bgn)+1;
905 /***********************************************************************
906 * WTQueuePacketsEx (WINTAB32.200)
908 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
910 LPOPENCONTEXT context;
912 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
916 EnterCriticalSection(&csTablet);
918 context = TABLET_FindOpenContext(hCtx);
920 if (context->PacketsQueued)
922 *lpOld = context->PacketQueue[0].pkSerialNumber;
923 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
927 TRACE("No packets\n");
928 LeaveCriticalSection(&csTablet);
931 LeaveCriticalSection(&csTablet);
936 /***********************************************************************
937 * WTQueueSizeGet (WINTAB32.84)
939 int WINAPI WTQueueSizeGet(HCTX hCtx)
941 LPOPENCONTEXT context;
942 TRACE("(%p)\n", hCtx);
946 EnterCriticalSection(&csTablet);
947 context = TABLET_FindOpenContext(hCtx);
948 LeaveCriticalSection(&csTablet);
949 return context->QueueSize;
952 /***********************************************************************
953 * WTQueueSizeSet (WINTAB32.85)
955 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
957 LPOPENCONTEXT context;
959 TRACE("(%p, %d)\n", hCtx, nPkts);
963 EnterCriticalSection(&csTablet);
965 context = TABLET_FindOpenContext(hCtx);
967 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
968 context->PacketQueue, sizeof(WTPACKET)*nPkts);
970 context->QueueSize = nPkts;
971 LeaveCriticalSection(&csTablet);