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
45 static LPOPENCONTEXT gOpenContexts;
46 static HCTX gTopContext = (HCTX)0xc00;
48 static void LOGCONTEXTAtoW(const LOGCONTEXTA *in, LOGCONTEXTW *out)
50 MultiByteToWideChar(CP_ACP, 0, in->lcName, -1, out->lcName, LCNAMELEN);
51 out->lcName[LCNAMELEN - 1] = 0;
52 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
53 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTA) - FIELD_OFFSET(LOGCONTEXTA, lcOptions));
56 static void LOGCONTEXTWtoA(const LOGCONTEXTW *in, LOGCONTEXTA *out)
58 WideCharToMultiByte(CP_ACP, 0, in->lcName, LCNAMELEN, out->lcName, LCNAMELEN, NULL, NULL);
59 out->lcName[LCNAMELEN - 1] = 0;
60 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
61 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTW) - FIELD_OFFSET(LOGCONTEXTW, lcOptions));
64 static BOOL is_logcontext_category(UINT wCategory)
66 return wCategory == WTI_DEFSYSCTX || wCategory == WTI_DEFCONTEXT || wCategory == WTI_DDCTXS;
69 static BOOL is_string_field(UINT wCategory, UINT nIndex)
71 if (wCategory == WTI_INTERFACE && nIndex == IFC_WINTABID)
73 if (is_logcontext_category(wCategory) && nIndex == CTX_NAME)
75 if ((wCategory >= WTI_CURSORS && wCategory <= WTI_CURSORS + 9) &&
76 (nIndex == CSR_NAME || nIndex == CSR_BTNNAMES))
78 if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID))
83 static const char* DUMPBITS(int x)
87 if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
88 if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
89 if (x&PK_TIME) strcat(buf, "PK_TIME ");
90 if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
91 if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
92 if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
93 if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
94 if (x&PK_X) strcat(buf, "PK_X ");
95 if (x&PK_Y) strcat(buf, "PK_Y ");
96 if (x&PK_Z) strcat(buf, "PK_Z ");
97 if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
98 if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
99 if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
100 if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
101 return wine_dbg_sprintf("{%s}",buf);
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",
107 packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber,
108 packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ,
109 packet.pkNormalPressure, packet.pkTangentPressure,
110 packet.pkOrientation.orAzimuth, packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
111 packet.pkRotation.roPitch, packet.pkRotation.roRoll, packet.pkRotation.roYaw);
114 static inline void DUMPCONTEXT(LOGCONTEXTW lc)
116 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, "
117 "Device: %x, PktRate: %x, "
119 "BtnDnMask: %x, BtnUpMask: %x, "
120 "InOrgX: %i, InOrgY: %i, InOrgZ: %i, "
121 "InExtX: %i, InExtY: %i, InExtZ: %i, "
122 "OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i, "
123 "OutExtX: %i, OutExtY: %i, OutExtZ: %i, "
124 "SensX: %i, SensY: %i, SensZ: %i, "
126 "SysOrgX: %i, SysOrgY: %i, "
127 "SysExtX: %i, SysExtY: %i, "
128 "SysSensX: %i, SysSensY: %i\n",
129 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
130 lc.lcDevice, lc.lcPktRate, lc.lcPktData, DUMPBITS(lc.lcPktData),
131 lc.lcPktMode, DUMPBITS(lc.lcPktMode), lc.lcMoveMask,
132 DUMPBITS(lc.lcMoveMask), lc.lcBtnDnMask, lc.lcBtnUpMask,
133 lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
134 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
135 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
136 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
141 /* Find an open context given the handle */
142 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
144 LPOPENCONTEXT ptr = gOpenContexts;
147 if (ptr->handle == hCtx) return ptr;
153 static inline BOOL LoadTablet(void)
155 static enum {TI_START = 0, TI_OK, TI_FAIL} loaded = TI_START;
157 if (loaded == TI_START)
159 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
161 if (pLoadTabletInfo && pLoadTabletInfo(hwndDefault))
168 ERR("LoadTabletInfo(%p) failed\n", hwndDefault);
172 return loaded == TI_OK;
175 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
176 LPARAM lParam, BOOL send_always)
178 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
180 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
181 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
186 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
188 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
189 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
191 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
194 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
196 LPOPENCONTEXT ptr=NULL;
198 EnterCriticalSection(&csTablet);
203 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
205 if (ptr->hwndOwner == hwnd)
214 tgt = ptr->PacketsQueued;
216 packet->pkContext = ptr->handle;
218 /* translate packet data to the context */
220 /* Scale as per documentation */
221 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
222 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
223 ptr->context.lcOutExtY);
225 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
226 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
227 ptr->context.lcOutExtX);
229 /* flip the Y axis */
230 if (ptr->context.lcOutExtY > 0)
231 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
232 else if (ptr->context.lcOutExtY < 0)
233 packet->pkY = abs(ptr->context.lcOutExtY + packet->pkY);
237 if (tgt == ptr->QueueSize)
239 TRACE("Queue Overflow %p\n",ptr->handle);
240 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
244 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
245 ptr->PacketQueue[tgt] = *packet;
246 ptr->PacketsQueued++;
248 if (ptr->ActiveCursor != packet->pkCursor)
250 ptr->ActiveCursor = packet->pkCursor;
251 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
252 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
253 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
261 LeaveCriticalSection(&csTablet);
262 TRACE("Done (%p)\n",ptr);
267 * Flushes all packets from the queue.
269 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
271 context->PacketsQueued = 0;
274 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
276 memcpy(target,src,size);
280 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
285 for (loop = 0; loop < context->PacketsQueued; loop++)
286 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
289 *pkt = &context->PacketQueue[loop];
293 TRACE("%i .. %i\n",context->PacketsQueued,index);
299 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
305 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
307 if (context->context.lcPktData & PK_CONTEXT)
308 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
309 if (context->context.lcPktData & PK_STATUS)
310 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
311 if (context->context.lcPktData & PK_TIME)
312 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
313 if (context->context.lcPktData & PK_CHANGED)
314 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
315 if (context->context.lcPktData & PK_SERIAL_NUMBER)
316 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
317 if (context->context.lcPktData & PK_CURSOR)
318 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
319 if (context->context.lcPktData & PK_BUTTONS)
320 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
321 if (context->context.lcPktData & PK_X)
322 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
323 if (context->context.lcPktData & PK_Y)
324 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
325 if (context->context.lcPktData & PK_Z)
326 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
327 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
328 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
329 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
330 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
331 if (context->context.lcPktData & PK_ORIENTATION)
332 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
333 if (context->context.lcPktData & PK_ROTATION)
334 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
336 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
340 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
344 if (context->context.lcPktData & PK_CONTEXT)
346 if (context->context.lcPktData & PK_STATUS)
348 if (context->context.lcPktData & PK_TIME)
350 if (context->context.lcPktData & PK_CHANGED)
352 if (context->context.lcPktData & PK_SERIAL_NUMBER)
354 if (context->context.lcPktData & PK_CURSOR)
356 if (context->context.lcPktData & PK_BUTTONS)
358 if (context->context.lcPktData & PK_X)
360 if (context->context.lcPktData & PK_Y)
362 if (context->context.lcPktData & PK_Z)
364 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
366 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
368 if (context->context.lcPktData & PK_ORIENTATION)
369 rc += sizeof(ORIENTATION);
370 if (context->context.lcPktData & PK_ROTATION)
371 rc += sizeof(ROTATION);
378 static UINT WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
382 if (!LoadTablet()) return 0;
384 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
387 * Handle system extents here, as we can use user32.dll code to set them.
389 if(wCategory == WTI_DEFSYSCTX)
395 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
399 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
401 /* No action, delegate to X11Drv */
405 if (is_logcontext_category(wCategory) && nIndex == 0)
410 pWTInfoW(wCategory, nIndex, &buf);
412 /* Handle system extents here, as we can use user32.dll code to set them */
413 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
415 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
416 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
420 memcpy(lpOutput, &buf, sizeof(buf));
422 LOGCONTEXTWtoA(&buf, lpOutput);
425 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
427 else if (is_string_field(wCategory, nIndex) && !bUnicode)
429 int size = pWTInfoW(wCategory, nIndex, NULL);
430 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
431 pWTInfoW(wCategory, nIndex, buf);
432 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
433 HeapFree(GetProcessHeap(), 0, buf);
436 result = pWTInfoW(wCategory, nIndex, lpOutput);
438 TRACE("returns %d\n", result);
442 /***********************************************************************
443 * WTInfoA (WINTAB32.20)
445 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
447 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
451 /***********************************************************************
452 * WTInfoW (WINTAB32.1020)
454 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
456 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
459 /***********************************************************************
460 * WTOpenW (WINTAB32.2021)
462 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
464 LPOPENCONTEXT newcontext;
466 if (!LoadTablet()) return 0;
468 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
469 DUMPCONTEXT(*lpLogCtx);
471 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
472 newcontext->context = *lpLogCtx;
473 newcontext->hwndOwner = hWnd;
474 newcontext->ActiveCursor = -1;
475 newcontext->QueueSize = 10;
476 newcontext->PacketsQueued = 0;
477 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
479 EnterCriticalSection(&csTablet);
480 newcontext->handle = gTopContext++;
481 newcontext->next = gOpenContexts;
482 gOpenContexts = newcontext;
483 LeaveCriticalSection(&csTablet);
485 pAttachEventQueueToTablet(hWnd);
487 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
488 newcontext->context.lcStatus, TRUE);
492 newcontext->enabled = TRUE;
493 /* TODO: Add to top of overlap order */
494 newcontext->context.lcStatus = CXS_ONTOP;
498 newcontext->enabled = FALSE;
499 newcontext->context.lcStatus = CXS_DISABLED;
502 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
503 (WPARAM)newcontext->handle,
504 newcontext->context.lcStatus, TRUE);
506 return newcontext->handle;
509 /***********************************************************************
510 * WTOpenA (WINTAB32.21)
512 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
516 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
517 return WTOpenW(hWnd, &logCtxW, fEnable);
520 /***********************************************************************
521 * WTClose (WINTAB32.22)
523 BOOL WINAPI WTClose(HCTX hCtx)
525 LPOPENCONTEXT context,ptr;
527 TRACE("(%p)\n", hCtx);
529 EnterCriticalSection(&csTablet);
531 ptr = context = gOpenContexts;
533 while (context && (context->handle != hCtx))
536 context = context->next;
540 LeaveCriticalSection(&csTablet);
544 if (context == gOpenContexts)
545 gOpenContexts = context->next;
547 ptr->next = context->next;
549 LeaveCriticalSection(&csTablet);
551 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
552 context->context.lcStatus,TRUE);
554 HeapFree(GetProcessHeap(),0,context->PacketQueue);
555 HeapFree(GetProcessHeap(),0,context);
560 /***********************************************************************
561 * WTPacketsGet (WINTAB32.23)
563 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
566 LPOPENCONTEXT context;
569 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
574 EnterCriticalSection(&csTablet);
576 context = TABLET_FindOpenContext(hCtx);
579 LeaveCriticalSection(&csTablet);
584 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
586 if (context->PacketsQueued == 0)
588 LeaveCriticalSection(&csTablet);
592 limit = min(cMaxPkts,context->PacketsQueued);
597 for(i = 0; i < limit; i++)
598 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
602 if (limit < context->PacketsQueued)
604 memmove(context->PacketQueue, &context->PacketQueue[limit],
605 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
607 context->PacketsQueued -= limit;
608 LeaveCriticalSection(&csTablet);
610 TRACE("Copied %i packets\n",limit);
615 /***********************************************************************
616 * WTPacket (WINTAB32.24)
618 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
621 LPOPENCONTEXT context;
622 LPWTPACKET wtp = NULL;
624 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
629 EnterCriticalSection(&csTablet);
631 context = TABLET_FindOpenContext(hCtx);
634 LeaveCriticalSection(&csTablet);
638 rc = TABLET_FindPacket(context ,wSerial, &wtp);
643 TABLET_CopyPacketData(context ,lpPkt, wtp);
645 if ((rc+1) < context->QueueSize)
647 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
648 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
650 context->PacketsQueued -= (rc+1);
652 LeaveCriticalSection(&csTablet);
654 TRACE("Returning %i\n",rc+1);
658 /***********************************************************************
659 * WTEnable (WINTAB32.40)
661 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
663 LPOPENCONTEXT context;
665 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
667 if (!hCtx) return FALSE;
669 EnterCriticalSection(&csTablet);
670 context = TABLET_FindOpenContext(hCtx);
673 LeaveCriticalSection(&csTablet);
677 /* if we want to enable and it is not enabled then */
678 if(fEnable && !context->enabled)
680 context->enabled = TRUE;
681 /* TODO: Add to top of overlap order */
682 context->context.lcStatus = CXS_ONTOP;
683 TABLET_PostTabletMessage(context,
684 _WT_CTXOVERLAP(context->context.lcMsgBase),
685 (WPARAM)context->handle,
686 context->context.lcStatus, TRUE);
688 /* if we want to disable and it is not disabled then */
689 else if (!fEnable && context->enabled)
691 context->enabled = FALSE;
692 /* TODO: Remove from overlap order?? needs a test */
693 context->context.lcStatus = CXS_DISABLED;
694 TABLET_FlushQueue(context);
695 TABLET_PostTabletMessage(context,
696 _WT_CTXOVERLAP(context->context.lcMsgBase),
697 (WPARAM)context->handle,
698 context->context.lcStatus, TRUE);
700 LeaveCriticalSection(&csTablet);
705 /***********************************************************************
706 * WTOverlap (WINTAB32.41)
708 * Move context to top or bottom of overlap order
710 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
712 LPOPENCONTEXT context;
714 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
716 if (!hCtx) return FALSE;
718 EnterCriticalSection(&csTablet);
719 context = TABLET_FindOpenContext(hCtx);
722 LeaveCriticalSection(&csTablet);
726 /* if we want to send to top and it's not already there */
727 if (fToTop && context->context.lcStatus != CXS_ONTOP)
729 /* TODO: Move context to top of overlap order */
730 FIXME("Not moving context to top of overlap order\n");
731 context->context.lcStatus = CXS_ONTOP;
732 TABLET_PostTabletMessage(context,
733 _WT_CTXOVERLAP(context->context.lcMsgBase),
734 (WPARAM)context->handle,
735 context->context.lcStatus, TRUE);
739 /* TODO: Move context to bottom of overlap order */
740 FIXME("Not moving context to bottom of overlap order\n");
741 context->context.lcStatus = CXS_OBSCURED;
742 TABLET_PostTabletMessage(context,
743 _WT_CTXOVERLAP(context->context.lcMsgBase),
744 (WPARAM)context->handle,
745 context->context.lcStatus, TRUE);
747 LeaveCriticalSection(&csTablet);
752 /***********************************************************************
753 * WTConfig (WINTAB32.61)
755 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
757 FIXME("(%p, %p): stub\n", hCtx, hWnd);
759 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
764 /***********************************************************************
765 * WTGetA (WINTAB32.61)
767 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
769 LPOPENCONTEXT context;
771 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
775 EnterCriticalSection(&csTablet);
776 context = TABLET_FindOpenContext(hCtx);
779 LeaveCriticalSection(&csTablet);
783 LOGCONTEXTWtoA(&context->context, lpLogCtx);
784 LeaveCriticalSection(&csTablet);
789 /***********************************************************************
790 * WTGetW (WINTAB32.1061)
792 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
794 LPOPENCONTEXT context;
796 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
800 EnterCriticalSection(&csTablet);
801 context = TABLET_FindOpenContext(hCtx);
804 LeaveCriticalSection(&csTablet);
808 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
809 LeaveCriticalSection(&csTablet);
814 /***********************************************************************
815 * WTSetA (WINTAB32.62)
817 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
819 LPOPENCONTEXT context;
821 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
823 if (!hCtx || !lpLogCtx) return FALSE;
825 /* TODO: if cur process not owner of hCtx only modify
826 * attribs not locked by owner */
828 EnterCriticalSection(&csTablet);
829 context = TABLET_FindOpenContext(hCtx);
832 LeaveCriticalSection(&csTablet);
836 LOGCONTEXTAtoW(lpLogCtx, &context->context);
837 LeaveCriticalSection(&csTablet);
842 /***********************************************************************
843 * WTSetW (WINTAB32.1062)
845 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
847 LPOPENCONTEXT context;
849 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
851 if (!hCtx || !lpLogCtx) return FALSE;
853 /* TODO: if cur process not hCtx owner only modify
854 * attribs not locked by owner */
856 EnterCriticalSection(&csTablet);
857 context = TABLET_FindOpenContext(hCtx);
860 LeaveCriticalSection(&csTablet);
864 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
865 LeaveCriticalSection(&csTablet);
870 /***********************************************************************
871 * WTExtGet (WINTAB32.63)
873 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
875 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
877 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
882 /***********************************************************************
883 * WTExtSet (WINTAB32.64)
885 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
887 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
889 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
894 /***********************************************************************
895 * WTSave (WINTAB32.65)
897 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
899 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
901 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
906 /***********************************************************************
907 * WTRestore (WINTAB32.66)
909 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
911 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
913 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
918 /***********************************************************************
919 * WTPacketsPeek (WINTAB32.80)
921 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
924 LPOPENCONTEXT context;
927 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
929 if (!hCtx || !lpPkts) return 0;
931 EnterCriticalSection(&csTablet);
933 context = TABLET_FindOpenContext(hCtx);
935 if (!context || context->PacketsQueued == 0)
937 LeaveCriticalSection(&csTablet);
941 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
942 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
944 LeaveCriticalSection(&csTablet);
945 TRACE("Copied %i packets\n",limit);
949 /***********************************************************************
950 * WTDataGet (WINTAB32.81)
952 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
953 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
955 LPOPENCONTEXT context;
961 TRACE("(%p, %u, %u, %d, %p, %p)\n",
962 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
966 EnterCriticalSection(&csTablet);
968 context = TABLET_FindOpenContext(hCtx);
970 if (!context || context->PacketsQueued == 0)
972 LeaveCriticalSection(&csTablet);
976 while (bgn < context->PacketsQueued &&
977 context->PacketQueue[bgn].pkSerialNumber != wBegin)
981 while (end < context->PacketsQueued &&
982 context->PacketQueue[end].pkSerialNumber != wEnd)
985 if ((bgn == end) && (end == context->PacketsQueued))
987 LeaveCriticalSection(&csTablet);
991 for (num = bgn; num <= end; num++)
992 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
994 /* remove read packets */
995 if ((end+1) < context->PacketsQueued)
996 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
997 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
999 context->PacketsQueued -= ((end-bgn)+1);
1000 *lpNPkts = ((end-bgn)+1);
1002 LeaveCriticalSection(&csTablet);
1003 TRACE("Copied %i packets\n",*lpNPkts);
1004 return (end - bgn)+1;
1007 /***********************************************************************
1008 * WTDataPeek (WINTAB32.82)
1010 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
1011 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
1013 LPOPENCONTEXT context;
1014 LPVOID ptr = lpPkts;
1019 TRACE("(%p, %u, %u, %d, %p, %p)\n",
1020 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
1022 if (!hCtx || !lpPkts) return 0;
1024 EnterCriticalSection(&csTablet);
1026 context = TABLET_FindOpenContext(hCtx);
1028 if (!context || context->PacketsQueued == 0)
1030 LeaveCriticalSection(&csTablet);
1034 while (bgn < context->PacketsQueued &&
1035 context->PacketQueue[bgn].pkSerialNumber != wBegin)
1039 while (end < context->PacketsQueued &&
1040 context->PacketQueue[end].pkSerialNumber != wEnd)
1043 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
1045 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
1046 LeaveCriticalSection(&csTablet);
1050 for (num = bgn; num <= end; num++)
1051 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
1053 *lpNPkts = ((end-bgn)+1);
1054 LeaveCriticalSection(&csTablet);
1056 TRACE("Copied %i packets\n",*lpNPkts);
1057 return (end - bgn)+1;
1060 /***********************************************************************
1061 * WTQueuePacketsEx (WINTAB32.200)
1063 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
1065 LPOPENCONTEXT context;
1067 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
1069 if (!hCtx) return 0;
1071 EnterCriticalSection(&csTablet);
1073 context = TABLET_FindOpenContext(hCtx);
1075 if (context && context->PacketsQueued)
1077 *lpOld = context->PacketQueue[0].pkSerialNumber;
1078 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
1082 TRACE("No packets\n");
1083 LeaveCriticalSection(&csTablet);
1086 LeaveCriticalSection(&csTablet);
1091 /***********************************************************************
1092 * WTQueueSizeGet (WINTAB32.84)
1094 int WINAPI WTQueueSizeGet(HCTX hCtx)
1096 LPOPENCONTEXT context;
1099 TRACE("(%p)\n", hCtx);
1101 if (!hCtx) return 0;
1103 EnterCriticalSection(&csTablet);
1104 context = TABLET_FindOpenContext(hCtx);
1106 queueSize = context->QueueSize;
1107 LeaveCriticalSection(&csTablet);
1111 /***********************************************************************
1112 * WTQueueSizeSet (WINTAB32.85)
1114 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1116 LPOPENCONTEXT context;
1118 TRACE("(%p, %d)\n", hCtx, nPkts);
1120 if (!hCtx) return 0;
1122 EnterCriticalSection(&csTablet);
1124 context = TABLET_FindOpenContext(hCtx);
1127 LeaveCriticalSection(&csTablet);
1131 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1132 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1134 context->QueueSize = nPkts;
1135 LeaveCriticalSection(&csTablet);