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)
78 if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID))
83 static char* DUMPBITS(int x, char* buf)
86 if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
87 if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
88 if (x&PK_TIME) strcat(buf, "PK_TIME ");
89 if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
90 if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
91 if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
92 if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
93 if (x&PK_X) strcat(buf, "PK_X ");
94 if (x&PK_Y) strcat(buf, "PK_Y ");
95 if (x&PK_Z) strcat(buf, "PK_Z ");
96 if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
97 if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
98 if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
99 if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
104 static inline void DUMPPACKET(WTPACKET packet)
106 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 (UINT)packet.pkStatus,
110 (UINT)packet.pkChanged,
111 packet.pkSerialNumber,
113 (UINT)packet.pkButtons,
117 packet.pkNormalPressure,
118 packet.pkTangentPressure,
119 packet.pkOrientation.orAzimuth,
120 packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
121 packet.pkRotation.roPitch,
122 packet.pkRotation.roRoll, packet.pkRotation.roYaw);
125 static inline void DUMPCONTEXT(LOGCONTEXTW lc)
132 sprintf(mmsg,"%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",
133 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
134 lc.lcDevice, lc.lcPktRate, (UINT)lc.lcPktData, DUMPBITS(lc.lcPktData,bits),
135 (UINT)lc.lcPktMode, DUMPBITS(lc.lcPktMode,bits1), (UINT)lc.lcMoveMask,
136 DUMPBITS(lc.lcMoveMask,bits2), (INT)lc.lcBtnDnMask, (INT)lc.lcBtnUpMask,
137 (INT)lc.lcInOrgX, (INT)lc.lcInOrgY, (INT)lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
138 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
139 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
140 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
142 TRACE("context: %s\n",mmsg);
146 /* Find an open context given the handle */
147 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
149 LPOPENCONTEXT ptr = gOpenContexts;
152 if (ptr->handle == hCtx) return ptr;
158 static void LoadTablet(void)
160 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
162 pLoadTabletInfo(hwndDefault);
165 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
166 LPARAM lParam, BOOL send_always)
168 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
170 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
171 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
176 static inline DWORD ScaleForContext(DWORD In, DWORD InOrg, DWORD InExt, DWORD
177 OutOrg, DWORD OutExt)
179 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
180 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
182 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
185 LPOPENCONTEXT FindOpenContext(HWND hwnd)
189 EnterCriticalSection(&csTablet);
193 TRACE("Trying Context %p (%p %p)\n",ptr->handle,hwnd,ptr->hwndOwner);
194 if (ptr->hwndOwner == hwnd) break;
196 LeaveCriticalSection(&csTablet);
200 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
202 LPOPENCONTEXT ptr=NULL;
204 EnterCriticalSection(&csTablet);
209 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
211 if (ptr->hwndOwner == hwnd)
220 tgt = ptr->PacketsQueued;
222 packet->pkContext = ptr->handle;
224 /* translate packet data to the context */
226 /* Scale as per documentation */
227 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
228 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
229 ptr->context.lcOutExtY);
231 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
232 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
233 ptr->context.lcOutExtX);
235 /* flip the Y axis */
236 if (ptr->context.lcOutExtY > 0)
237 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
241 if (tgt == ptr->QueueSize)
243 TRACE("Queue Overflow %p\n",ptr->handle);
244 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
248 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
249 memcpy(&ptr->PacketQueue[tgt], packet, sizeof
251 ptr->PacketsQueued++;
253 if (ptr->ActiveCursor != packet->pkCursor)
255 ptr->ActiveCursor = packet->pkCursor;
256 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
257 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
258 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
266 LeaveCriticalSection(&csTablet);
267 TRACE("Done (%p)\n",ptr);
272 * Flushes all packets from the queue.
274 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
276 context->PacketsQueued = 0;
279 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
281 memcpy(target,src,size);
285 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
290 for (loop = 0; loop < context->PacketsQueued; loop++)
291 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
294 *pkt = &context->PacketQueue[loop];
298 TRACE("%i .. %i\n",context->PacketsQueued,index);
304 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
311 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData,bits));
313 if (context->context.lcPktData & PK_CONTEXT)
314 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
315 if (context->context.lcPktData & PK_STATUS)
316 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
317 if (context->context.lcPktData & PK_TIME)
318 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
319 if (context->context.lcPktData & PK_CHANGED)
320 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
321 if (context->context.lcPktData & PK_SERIAL_NUMBER)
322 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
323 if (context->context.lcPktData & PK_CURSOR)
324 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
325 if (context->context.lcPktData & PK_BUTTONS)
326 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
327 if (context->context.lcPktData & PK_X)
328 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
329 if (context->context.lcPktData & PK_Y)
330 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
331 if (context->context.lcPktData & PK_Z)
332 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
333 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
334 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
335 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
336 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
337 if (context->context.lcPktData & PK_ORIENTATION)
338 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
339 if (context->context.lcPktData & PK_ROTATION)
340 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
342 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
346 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
350 if (context->context.lcPktData & PK_CONTEXT)
352 if (context->context.lcPktData & PK_STATUS)
354 if (context->context.lcPktData & PK_TIME)
356 if (context->context.lcPktData & PK_CHANGED)
358 if (context->context.lcPktData & PK_SERIAL_NUMBER)
360 if (context->context.lcPktData & PK_CURSOR)
362 if (context->context.lcPktData & PK_BUTTONS)
364 if (context->context.lcPktData & PK_X)
366 if (context->context.lcPktData & PK_Y)
368 if (context->context.lcPktData & PK_Z)
370 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
372 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
374 if (context->context.lcPktData & PK_ORIENTATION)
375 rc += sizeof(ORIENTATION);
376 if (context->context.lcPktData & PK_ROTATION)
377 rc += sizeof(ROTATION);
384 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
387 if (gLoaded == FALSE)
391 * Handle system extents here, as we can use user32.dll code to set them.
393 if(wCategory == WTI_DEFSYSCTX)
399 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
403 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
405 /* No action, delegate to X11Drv */
409 if (is_logcontext_category(wCategory) && nIndex == 0)
414 pWTInfoW(wCategory, nIndex, &buf);
416 /* Handle system extents here, as we can use user32.dll code to set them */
417 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
419 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
420 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
424 memcpy(lpOutput, &buf, sizeof(buf));
426 LOGCONTEXTWtoA(&buf, lpOutput);
429 return bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
431 else if (is_string_field(wCategory, nIndex) && !bUnicode)
433 int size = pWTInfoW(wCategory, nIndex, NULL);
434 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
435 pWTInfoW(wCategory, nIndex, buf);
436 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
437 HeapFree(GetProcessHeap(), 0, buf);
440 result = pWTInfoW(wCategory, nIndex, lpOutput);
445 /***********************************************************************
446 * WTInfoA (WINTAB32.20)
448 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
450 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
454 /***********************************************************************
455 * WTInfoW (WINTAB32.1020)
457 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
459 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
462 /***********************************************************************
463 * WTOpenW (WINTAB32.2021)
465 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
467 LPOPENCONTEXT newcontext;
469 TRACE("(%p, %p, %u)\n", hWnd, lpLogCtx, fEnable);
470 DUMPCONTEXT(*lpLogCtx);
472 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
473 memcpy(&(newcontext->context),lpLogCtx,sizeof(LOGCONTEXTW));
474 newcontext->hwndOwner = hWnd;
475 newcontext->enabled = fEnable;
476 newcontext->ActiveCursor = -1;
477 newcontext->QueueSize = 10;
478 newcontext->PacketsQueued = 0;
479 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
481 EnterCriticalSection(&csTablet);
482 newcontext->handle = gTopContext++;
483 newcontext->next = gOpenContexts;
484 gOpenContexts = newcontext;
485 LeaveCriticalSection(&csTablet);
487 pAttachEventQueueToTablet(hWnd);
489 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
490 newcontext->context.lcStatus, TRUE);
492 newcontext->context.lcStatus = CXS_ONTOP;
494 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
495 (WPARAM)newcontext->handle,
496 newcontext->context.lcStatus, TRUE);
498 return newcontext->handle;
501 /***********************************************************************
502 * WTOpenA (WINTAB32.21)
504 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
508 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
509 return WTOpenW(hWnd, &logCtxW, fEnable);
512 /***********************************************************************
513 * WTClose (WINTAB32.22)
515 BOOL WINAPI WTClose(HCTX hCtx)
517 LPOPENCONTEXT context,ptr;
519 TRACE("(%p)\n", hCtx);
521 EnterCriticalSection(&csTablet);
523 ptr = context = gOpenContexts;
525 while (context && (context->handle != hCtx))
528 context = context->next;
532 LeaveCriticalSection(&csTablet);
536 if (context == gOpenContexts)
537 gOpenContexts = context->next;
539 ptr->next = context->next;
541 LeaveCriticalSection(&csTablet);
543 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
544 context->context.lcStatus,TRUE);
546 HeapFree(GetProcessHeap(),0,context->PacketQueue);
547 HeapFree(GetProcessHeap(),0,context);
552 /***********************************************************************
553 * WTPacketsGet (WINTAB32.23)
555 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
558 LPOPENCONTEXT context;
561 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
566 EnterCriticalSection(&csTablet);
568 context = TABLET_FindOpenContext(hCtx);
571 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
573 if (context->PacketsQueued == 0)
575 LeaveCriticalSection(&csTablet);
579 limit = min(cMaxPkts,context->PacketsQueued);
584 for(i = 0; i < limit; i++)
585 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
589 if (limit < context->PacketsQueued)
591 memmove(context->PacketQueue, &context->PacketQueue[limit],
592 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
594 context->PacketsQueued -= limit;
595 LeaveCriticalSection(&csTablet);
597 TRACE("Copied %i packets\n",limit);
602 /***********************************************************************
603 * WTPacket (WINTAB32.24)
605 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
608 LPOPENCONTEXT context;
609 LPWTPACKET wtp = NULL;
611 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
616 EnterCriticalSection(&csTablet);
618 context = TABLET_FindOpenContext(hCtx);
620 rc = TABLET_FindPacket(context ,wSerial, &wtp);
625 TABLET_CopyPacketData(context ,lpPkt, wtp);
627 if ((rc+1) < context->QueueSize)
629 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
630 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
632 context->PacketsQueued -= (rc+1);
634 LeaveCriticalSection(&csTablet);
636 TRACE("Returning %i\n",rc+1);
640 /***********************************************************************
641 * WTEnable (WINTAB32.40)
643 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
645 LPOPENCONTEXT context;
647 TRACE("(%p, %u)\n", hCtx, fEnable);
651 EnterCriticalSection(&csTablet);
652 context = TABLET_FindOpenContext(hCtx);
654 TABLET_FlushQueue(context);
655 context->enabled = fEnable;
656 LeaveCriticalSection(&csTablet);
661 /***********************************************************************
662 * WTOverlap (WINTAB32.41)
664 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
666 FIXME("(%p, %u): stub\n", hCtx, fToTop);
671 /***********************************************************************
672 * WTConfig (WINTAB32.61)
674 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
676 FIXME("(%p, %p): stub\n", hCtx, hWnd);
678 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
683 /***********************************************************************
684 * WTGetA (WINTAB32.61)
686 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
688 LPOPENCONTEXT context;
690 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
694 EnterCriticalSection(&csTablet);
695 context = TABLET_FindOpenContext(hCtx);
696 LOGCONTEXTWtoA(&context->context, lpLogCtx);
697 LeaveCriticalSection(&csTablet);
702 /***********************************************************************
703 * WTGetW (WINTAB32.1061)
705 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
707 LPOPENCONTEXT context;
709 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
713 EnterCriticalSection(&csTablet);
714 context = TABLET_FindOpenContext(hCtx);
715 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
716 LeaveCriticalSection(&csTablet);
721 /***********************************************************************
722 * WTSetA (WINTAB32.62)
724 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
726 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
728 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
733 /***********************************************************************
734 * WTSetW (WINTAB32.1062)
736 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
738 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
740 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
745 /***********************************************************************
746 * WTExtGet (WINTAB32.63)
748 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
750 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
752 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
757 /***********************************************************************
758 * WTExtSet (WINTAB32.64)
760 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
762 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
764 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
769 /***********************************************************************
770 * WTSave (WINTAB32.65)
772 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
774 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
776 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
781 /***********************************************************************
782 * WTRestore (WINTAB32.66)
784 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
786 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
788 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
793 /***********************************************************************
794 * WTPacketsPeek (WINTAB32.80)
796 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
799 LPOPENCONTEXT context;
802 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
804 if (!hCtx || !lpPkts) return 0;
806 EnterCriticalSection(&csTablet);
808 context = TABLET_FindOpenContext(hCtx);
810 if (context->PacketsQueued == 0)
812 LeaveCriticalSection(&csTablet);
816 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
817 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
819 LeaveCriticalSection(&csTablet);
820 TRACE("Copied %i packets\n",limit);
824 /***********************************************************************
825 * WTDataGet (WINTAB32.81)
827 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
828 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
830 LPOPENCONTEXT context;
836 TRACE("(%p, %u, %u, %d, %p, %p)\n",
837 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
841 EnterCriticalSection(&csTablet);
843 context = TABLET_FindOpenContext(hCtx);
845 if (context->PacketsQueued == 0)
847 LeaveCriticalSection(&csTablet);
851 while (bgn < context->PacketsQueued &&
852 context->PacketQueue[bgn].pkSerialNumber != wBegin)
856 while (end < context->PacketsQueued &&
857 context->PacketQueue[end].pkSerialNumber != wEnd)
860 if ((bgn == end) && (end == context->PacketsQueued))
862 LeaveCriticalSection(&csTablet);
866 for (num = bgn; num <= end; num++)
867 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
869 /* remove read packets */
870 if ((end+1) < context->PacketsQueued)
871 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
872 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
874 context->PacketsQueued -= ((end-bgn)+1);
875 *lpNPkts = ((end-bgn)+1);
877 LeaveCriticalSection(&csTablet);
878 TRACE("Copied %i packets\n",*lpNPkts);
879 return (end - bgn)+1;
882 /***********************************************************************
883 * WTDataPeek (WINTAB32.82)
885 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
886 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
888 LPOPENCONTEXT context;
894 TRACE("(%p, %u, %u, %d, %p, %p)\n",
895 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
897 if (!hCtx || !lpPkts) return 0;
899 EnterCriticalSection(&csTablet);
901 context = TABLET_FindOpenContext(hCtx);
903 if (context->PacketsQueued == 0)
905 LeaveCriticalSection(&csTablet);
909 while (bgn < context->PacketsQueued &&
910 context->PacketQueue[bgn].pkSerialNumber != wBegin)
914 while (end < context->PacketsQueued &&
915 context->PacketQueue[end].pkSerialNumber != wEnd)
918 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
920 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
921 LeaveCriticalSection(&csTablet);
925 for (num = bgn; num <= end; num++)
926 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
928 *lpNPkts = ((end-bgn)+1);
929 LeaveCriticalSection(&csTablet);
931 TRACE("Copied %i packets\n",*lpNPkts);
932 return (end - bgn)+1;
935 /***********************************************************************
936 * WTQueuePacketsEx (WINTAB32.200)
938 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
940 LPOPENCONTEXT context;
942 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
946 EnterCriticalSection(&csTablet);
948 context = TABLET_FindOpenContext(hCtx);
950 if (context->PacketsQueued)
952 *lpOld = context->PacketQueue[0].pkSerialNumber;
953 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
957 TRACE("No packets\n");
958 LeaveCriticalSection(&csTablet);
961 LeaveCriticalSection(&csTablet);
966 /***********************************************************************
967 * WTQueueSizeGet (WINTAB32.84)
969 int WINAPI WTQueueSizeGet(HCTX hCtx)
971 LPOPENCONTEXT context;
972 TRACE("(%p)\n", hCtx);
976 EnterCriticalSection(&csTablet);
977 context = TABLET_FindOpenContext(hCtx);
978 LeaveCriticalSection(&csTablet);
979 return context->QueueSize;
982 /***********************************************************************
983 * WTQueueSizeSet (WINTAB32.85)
985 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
987 LPOPENCONTEXT context;
989 TRACE("(%p, %d)\n", hCtx, nPkts);
993 EnterCriticalSection(&csTablet);
995 context = TABLET_FindOpenContext(hCtx);
997 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
998 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1000 context->QueueSize = nPkts;
1001 LeaveCriticalSection(&csTablet);