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 ptr->PacketQueue[tgt] = *packet;
218 ptr->PacketsQueued++;
220 if (ptr->ActiveCursor != packet->pkCursor)
222 ptr->ActiveCursor = packet->pkCursor;
223 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
224 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
225 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
233 LeaveCriticalSection(&csTablet);
234 TRACE("Done (%p)\n",ptr);
239 * Flushes all packets from the queue.
241 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
243 context->PacketsQueued = 0;
246 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
248 memcpy(target,src,size);
252 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
257 for (loop = 0; loop < context->PacketsQueued; loop++)
258 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
261 *pkt = &context->PacketQueue[loop];
265 TRACE("%i .. %i\n",context->PacketsQueued,index);
271 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
277 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
279 if (context->context.lcPktData & PK_CONTEXT)
280 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
281 if (context->context.lcPktData & PK_STATUS)
282 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
283 if (context->context.lcPktData & PK_TIME)
284 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
285 if (context->context.lcPktData & PK_CHANGED)
286 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
287 if (context->context.lcPktData & PK_SERIAL_NUMBER)
288 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
289 if (context->context.lcPktData & PK_CURSOR)
290 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
291 if (context->context.lcPktData & PK_BUTTONS)
292 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
293 if (context->context.lcPktData & PK_X)
294 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
295 if (context->context.lcPktData & PK_Y)
296 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
297 if (context->context.lcPktData & PK_Z)
298 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
299 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
300 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
301 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
302 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
303 if (context->context.lcPktData & PK_ORIENTATION)
304 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
305 if (context->context.lcPktData & PK_ROTATION)
306 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
308 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
312 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
316 if (context->context.lcPktData & PK_CONTEXT)
318 if (context->context.lcPktData & PK_STATUS)
320 if (context->context.lcPktData & PK_TIME)
322 if (context->context.lcPktData & PK_CHANGED)
324 if (context->context.lcPktData & PK_SERIAL_NUMBER)
326 if (context->context.lcPktData & PK_CURSOR)
328 if (context->context.lcPktData & PK_BUTTONS)
330 if (context->context.lcPktData & PK_X)
332 if (context->context.lcPktData & PK_Y)
334 if (context->context.lcPktData & PK_Z)
336 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
338 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
340 if (context->context.lcPktData & PK_ORIENTATION)
341 rc += sizeof(ORIENTATION);
342 if (context->context.lcPktData & PK_ROTATION)
343 rc += sizeof(ROTATION);
350 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
354 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
355 if (gLoaded == FALSE)
359 * Handle system extents here, as we can use user32.dll code to set them.
361 if(wCategory == WTI_DEFSYSCTX)
367 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
371 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
373 /* No action, delegate to X11Drv */
377 if (is_logcontext_category(wCategory) && nIndex == 0)
382 pWTInfoW(wCategory, nIndex, &buf);
384 /* Handle system extents here, as we can use user32.dll code to set them */
385 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
387 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
388 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
392 memcpy(lpOutput, &buf, sizeof(buf));
394 LOGCONTEXTWtoA(&buf, lpOutput);
397 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
399 else if (is_string_field(wCategory, nIndex) && !bUnicode)
401 int size = pWTInfoW(wCategory, nIndex, NULL);
402 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
403 pWTInfoW(wCategory, nIndex, buf);
404 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
405 HeapFree(GetProcessHeap(), 0, buf);
408 result = pWTInfoW(wCategory, nIndex, lpOutput);
410 TRACE("returns %d\n", result);
414 /***********************************************************************
415 * WTInfoA (WINTAB32.20)
417 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
419 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
423 /***********************************************************************
424 * WTInfoW (WINTAB32.1020)
426 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
428 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
431 /***********************************************************************
432 * WTOpenW (WINTAB32.2021)
434 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
436 LPOPENCONTEXT newcontext;
438 TRACE("(%p, %p, %u)\n", hWnd, lpLogCtx, fEnable);
439 DUMPCONTEXT(*lpLogCtx);
441 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
442 newcontext->context = *lpLogCtx;
443 newcontext->hwndOwner = hWnd;
444 newcontext->enabled = fEnable;
445 newcontext->ActiveCursor = -1;
446 newcontext->QueueSize = 10;
447 newcontext->PacketsQueued = 0;
448 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
450 EnterCriticalSection(&csTablet);
451 newcontext->handle = gTopContext++;
452 newcontext->next = gOpenContexts;
453 gOpenContexts = newcontext;
454 LeaveCriticalSection(&csTablet);
456 pAttachEventQueueToTablet(hWnd);
458 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
459 newcontext->context.lcStatus, TRUE);
461 newcontext->context.lcStatus = CXS_ONTOP;
463 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
464 (WPARAM)newcontext->handle,
465 newcontext->context.lcStatus, TRUE);
467 return newcontext->handle;
470 /***********************************************************************
471 * WTOpenA (WINTAB32.21)
473 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
477 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
478 return WTOpenW(hWnd, &logCtxW, fEnable);
481 /***********************************************************************
482 * WTClose (WINTAB32.22)
484 BOOL WINAPI WTClose(HCTX hCtx)
486 LPOPENCONTEXT context,ptr;
488 TRACE("(%p)\n", hCtx);
490 EnterCriticalSection(&csTablet);
492 ptr = context = gOpenContexts;
494 while (context && (context->handle != hCtx))
497 context = context->next;
501 LeaveCriticalSection(&csTablet);
505 if (context == gOpenContexts)
506 gOpenContexts = context->next;
508 ptr->next = context->next;
510 LeaveCriticalSection(&csTablet);
512 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
513 context->context.lcStatus,TRUE);
515 HeapFree(GetProcessHeap(),0,context->PacketQueue);
516 HeapFree(GetProcessHeap(),0,context);
521 /***********************************************************************
522 * WTPacketsGet (WINTAB32.23)
524 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
527 LPOPENCONTEXT context;
530 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
535 EnterCriticalSection(&csTablet);
537 context = TABLET_FindOpenContext(hCtx);
540 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
542 if (context->PacketsQueued == 0)
544 LeaveCriticalSection(&csTablet);
548 limit = min(cMaxPkts,context->PacketsQueued);
553 for(i = 0; i < limit; i++)
554 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
558 if (limit < context->PacketsQueued)
560 memmove(context->PacketQueue, &context->PacketQueue[limit],
561 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
563 context->PacketsQueued -= limit;
564 LeaveCriticalSection(&csTablet);
566 TRACE("Copied %i packets\n",limit);
571 /***********************************************************************
572 * WTPacket (WINTAB32.24)
574 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
577 LPOPENCONTEXT context;
578 LPWTPACKET wtp = NULL;
580 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
585 EnterCriticalSection(&csTablet);
587 context = TABLET_FindOpenContext(hCtx);
589 rc = TABLET_FindPacket(context ,wSerial, &wtp);
594 TABLET_CopyPacketData(context ,lpPkt, wtp);
596 if ((rc+1) < context->QueueSize)
598 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
599 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
601 context->PacketsQueued -= (rc+1);
603 LeaveCriticalSection(&csTablet);
605 TRACE("Returning %i\n",rc+1);
609 /***********************************************************************
610 * WTEnable (WINTAB32.40)
612 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
614 LPOPENCONTEXT context;
616 TRACE("(%p, %u)\n", hCtx, fEnable);
620 EnterCriticalSection(&csTablet);
621 context = TABLET_FindOpenContext(hCtx);
623 TABLET_FlushQueue(context);
624 context->enabled = fEnable;
625 LeaveCriticalSection(&csTablet);
630 /***********************************************************************
631 * WTOverlap (WINTAB32.41)
633 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
635 FIXME("(%p, %u): stub\n", hCtx, fToTop);
640 /***********************************************************************
641 * WTConfig (WINTAB32.61)
643 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
645 FIXME("(%p, %p): stub\n", hCtx, hWnd);
647 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
652 /***********************************************************************
653 * WTGetA (WINTAB32.61)
655 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
657 LPOPENCONTEXT context;
659 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
663 EnterCriticalSection(&csTablet);
664 context = TABLET_FindOpenContext(hCtx);
665 LOGCONTEXTWtoA(&context->context, lpLogCtx);
666 LeaveCriticalSection(&csTablet);
671 /***********************************************************************
672 * WTGetW (WINTAB32.1061)
674 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
676 LPOPENCONTEXT context;
678 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
682 EnterCriticalSection(&csTablet);
683 context = TABLET_FindOpenContext(hCtx);
684 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
685 LeaveCriticalSection(&csTablet);
690 /***********************************************************************
691 * WTSetA (WINTAB32.62)
693 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
695 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
697 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
702 /***********************************************************************
703 * WTSetW (WINTAB32.1062)
705 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
707 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
709 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
714 /***********************************************************************
715 * WTExtGet (WINTAB32.63)
717 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
719 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
721 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
726 /***********************************************************************
727 * WTExtSet (WINTAB32.64)
729 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
731 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
733 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
738 /***********************************************************************
739 * WTSave (WINTAB32.65)
741 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
743 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
745 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
750 /***********************************************************************
751 * WTRestore (WINTAB32.66)
753 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
755 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
757 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
762 /***********************************************************************
763 * WTPacketsPeek (WINTAB32.80)
765 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
768 LPOPENCONTEXT context;
771 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
773 if (!hCtx || !lpPkts) return 0;
775 EnterCriticalSection(&csTablet);
777 context = TABLET_FindOpenContext(hCtx);
779 if (context->PacketsQueued == 0)
781 LeaveCriticalSection(&csTablet);
785 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
786 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
788 LeaveCriticalSection(&csTablet);
789 TRACE("Copied %i packets\n",limit);
793 /***********************************************************************
794 * WTDataGet (WINTAB32.81)
796 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
797 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
799 LPOPENCONTEXT context;
805 TRACE("(%p, %u, %u, %d, %p, %p)\n",
806 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
810 EnterCriticalSection(&csTablet);
812 context = TABLET_FindOpenContext(hCtx);
814 if (context->PacketsQueued == 0)
816 LeaveCriticalSection(&csTablet);
820 while (bgn < context->PacketsQueued &&
821 context->PacketQueue[bgn].pkSerialNumber != wBegin)
825 while (end < context->PacketsQueued &&
826 context->PacketQueue[end].pkSerialNumber != wEnd)
829 if ((bgn == end) && (end == context->PacketsQueued))
831 LeaveCriticalSection(&csTablet);
835 for (num = bgn; num <= end; num++)
836 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
838 /* remove read packets */
839 if ((end+1) < context->PacketsQueued)
840 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
841 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
843 context->PacketsQueued -= ((end-bgn)+1);
844 *lpNPkts = ((end-bgn)+1);
846 LeaveCriticalSection(&csTablet);
847 TRACE("Copied %i packets\n",*lpNPkts);
848 return (end - bgn)+1;
851 /***********************************************************************
852 * WTDataPeek (WINTAB32.82)
854 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
855 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
857 LPOPENCONTEXT context;
863 TRACE("(%p, %u, %u, %d, %p, %p)\n",
864 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
866 if (!hCtx || !lpPkts) return 0;
868 EnterCriticalSection(&csTablet);
870 context = TABLET_FindOpenContext(hCtx);
872 if (context->PacketsQueued == 0)
874 LeaveCriticalSection(&csTablet);
878 while (bgn < context->PacketsQueued &&
879 context->PacketQueue[bgn].pkSerialNumber != wBegin)
883 while (end < context->PacketsQueued &&
884 context->PacketQueue[end].pkSerialNumber != wEnd)
887 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
889 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
890 LeaveCriticalSection(&csTablet);
894 for (num = bgn; num <= end; num++)
895 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
897 *lpNPkts = ((end-bgn)+1);
898 LeaveCriticalSection(&csTablet);
900 TRACE("Copied %i packets\n",*lpNPkts);
901 return (end - bgn)+1;
904 /***********************************************************************
905 * WTQueuePacketsEx (WINTAB32.200)
907 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
909 LPOPENCONTEXT context;
911 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
915 EnterCriticalSection(&csTablet);
917 context = TABLET_FindOpenContext(hCtx);
919 if (context->PacketsQueued)
921 *lpOld = context->PacketQueue[0].pkSerialNumber;
922 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
926 TRACE("No packets\n");
927 LeaveCriticalSection(&csTablet);
930 LeaveCriticalSection(&csTablet);
935 /***********************************************************************
936 * WTQueueSizeGet (WINTAB32.84)
938 int WINAPI WTQueueSizeGet(HCTX hCtx)
940 LPOPENCONTEXT context;
941 TRACE("(%p)\n", hCtx);
945 EnterCriticalSection(&csTablet);
946 context = TABLET_FindOpenContext(hCtx);
947 LeaveCriticalSection(&csTablet);
948 return context->QueueSize;
951 /***********************************************************************
952 * WTQueueSizeSet (WINTAB32.85)
954 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
956 LPOPENCONTEXT context;
958 TRACE("(%p, %d)\n", hCtx, nPkts);
962 EnterCriticalSection(&csTablet);
964 context = TABLET_FindOpenContext(hCtx);
966 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
967 context->PacketQueue, sizeof(WTPACKET)*nPkts);
969 context->QueueSize = nPkts;
970 LeaveCriticalSection(&csTablet);