wintab32: Improve tracing of LOGCONTEXT struct.
[wine/wine64.git] / dlls / wintab32 / context.c
blobcf6215444f95bac8e36fed6cd49cb960a3f53976
1 /*
2 * Tablet Context
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
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
27 #include "windef.h"
28 #include "winerror.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
33 #include "wintab.h"
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 BOOL gLoaded;
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)
73 return TRUE;
74 if (is_logcontext_category(wCategory) && nIndex == CTX_NAME)
75 return TRUE;
76 if ((wCategory >= WTI_CURSORS && wCategory <= WTI_CURSORS + 9) &&
77 (nIndex == CSR_NAME || nIndex == CSR_BTNNAMES))
78 return TRUE;
79 if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID))
80 return TRUE;
81 return FALSE;
84 static const char* DUMPBITS(int x)
86 char buf[200];
87 buf[0] = 0;
88 if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
89 if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
90 if (x&PK_TIME) strcat(buf, "PK_TIME ");
91 if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
92 if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
93 if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
94 if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
95 if (x&PK_X) strcat(buf, "PK_X ");
96 if (x&PK_Y) strcat(buf, "PK_Y ");
97 if (x&PK_Z) strcat(buf, "PK_Z ");
98 if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
99 if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
100 if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
101 if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
102 return wine_dbg_sprintf("{%s}",buf);
105 static inline void DUMPPACKET(WTPACKET packet)
107 TRACE("pkContext: %p pkStatus: 0x%x pkTime : 0x%x pkChanged: 0x%x pkSerialNumber: 0x%x pkCursor : %i pkButtons: %x pkX: %i pkY: %i pkZ: %i pkNormalPressure: %i pkTangentPressure: %i pkOrientation: (%i,%i,%i) pkRotation: (%i,%i,%i)\n",
108 packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber,
109 packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ,
110 packet.pkNormalPressure, packet.pkTangentPressure,
111 packet.pkOrientation.orAzimuth, packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
112 packet.pkRotation.roPitch, packet.pkRotation.roRoll, packet.pkRotation.roYaw);
115 static inline void DUMPCONTEXT(LOGCONTEXTW lc)
117 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, "
118 "Device: %x, PktRate: %x, "
119 "%x%s, %x%s, %x%s, "
120 "BtnDnMask: %x, BtnUpMask: %x, "
121 "InOrgX: %i, InOrgY: %i, InOrgZ: %i, "
122 "InExtX: %i, InExtY: %i, InExtZ: %i, "
123 "OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i, "
124 "OutExtX: %i, OutExtY: %i, OutExtZ: %i, "
125 "SensX: %i, SensY: %i, SensZ: %i, "
126 "SysMode: %i, "
127 "SysOrgX: %i, SysOrgY: %i, "
128 "SysExtX: %i, SysExtY: %i, "
129 "SysSensX: %i, SysSensY: %i\n",
130 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
131 lc.lcDevice, lc.lcPktRate, lc.lcPktData, DUMPBITS(lc.lcPktData),
132 lc.lcPktMode, DUMPBITS(lc.lcPktMode), lc.lcMoveMask,
133 DUMPBITS(lc.lcMoveMask), lc.lcBtnDnMask, lc.lcBtnUpMask,
134 lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
135 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
136 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
137 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
138 lc.lcSysSensY);
142 /* Find an open context given the handle */
143 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
145 LPOPENCONTEXT ptr = gOpenContexts;
146 while (ptr)
148 if (ptr->handle == hCtx) return ptr;
149 ptr = ptr->next;
151 return NULL;
154 static void LoadTablet(void)
156 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
157 gLoaded= TRUE;
158 pLoadTabletInfo(hwndDefault);
161 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
162 LPARAM lParam, BOOL send_always)
164 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
166 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
167 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
169 return 0;
172 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
174 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
175 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
176 else
177 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
180 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
182 LPOPENCONTEXT ptr=NULL;
184 EnterCriticalSection(&csTablet);
186 ptr = gOpenContexts;
187 while (ptr)
189 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
191 if (ptr->hwndOwner == hwnd)
193 int tgt;
194 if (!ptr->enabled)
196 ptr = ptr->next;
197 continue;
200 tgt = ptr->PacketsQueued;
202 packet->pkContext = ptr->handle;
204 /* translate packet data to the context */
206 /* Scale as per documentation */
207 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
208 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
209 ptr->context.lcOutExtY);
211 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
212 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
213 ptr->context.lcOutExtX);
215 /* flip the Y axis */
216 if (ptr->context.lcOutExtY > 0)
217 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
219 DUMPPACKET(*packet);
221 if (tgt == ptr->QueueSize)
223 TRACE("Queue Overflow %p\n",ptr->handle);
224 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
226 else
228 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
229 ptr->PacketQueue[tgt] = *packet;
230 ptr->PacketsQueued++;
232 if (ptr->ActiveCursor != packet->pkCursor)
234 ptr->ActiveCursor = packet->pkCursor;
235 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
236 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
237 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
238 FALSE);
241 break;
243 ptr = ptr->next;
245 LeaveCriticalSection(&csTablet);
246 TRACE("Done (%p)\n",ptr);
247 return ptr;
251 * Flushes all packets from the queue.
253 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
255 context->PacketsQueued = 0;
258 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
260 memcpy(target,src,size);
261 return(size);
264 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
265 LPWTPACKET *pkt)
267 int loop;
268 int index = -1;
269 for (loop = 0; loop < context->PacketsQueued; loop++)
270 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
272 index = loop;
273 *pkt = &context->PacketQueue[loop];
274 break;
277 TRACE("%i .. %i\n",context->PacketsQueued,index);
279 return index;
283 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
284 LPWTPACKET wtp)
286 LPBYTE ptr;
288 ptr = lpPkt;
289 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
291 if (context->context.lcPktData & PK_CONTEXT)
292 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
293 if (context->context.lcPktData & PK_STATUS)
294 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
295 if (context->context.lcPktData & PK_TIME)
296 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
297 if (context->context.lcPktData & PK_CHANGED)
298 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
299 if (context->context.lcPktData & PK_SERIAL_NUMBER)
300 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
301 if (context->context.lcPktData & PK_CURSOR)
302 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
303 if (context->context.lcPktData & PK_BUTTONS)
304 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
305 if (context->context.lcPktData & PK_X)
306 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
307 if (context->context.lcPktData & PK_Y)
308 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
309 if (context->context.lcPktData & PK_Z)
310 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
311 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
312 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
313 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
314 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
315 if (context->context.lcPktData & PK_ORIENTATION)
316 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
317 if (context->context.lcPktData & PK_ROTATION)
318 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
320 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
321 return ptr;
324 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
326 int rc = 0;
328 if (context->context.lcPktData & PK_CONTEXT)
329 rc +=sizeof(HCTX);
330 if (context->context.lcPktData & PK_STATUS)
331 rc +=sizeof(UINT);
332 if (context->context.lcPktData & PK_TIME)
333 rc += sizeof(LONG);
334 if (context->context.lcPktData & PK_CHANGED)
335 rc += sizeof(WTPKT);
336 if (context->context.lcPktData & PK_SERIAL_NUMBER)
337 rc += sizeof(UINT);
338 if (context->context.lcPktData & PK_CURSOR)
339 rc += sizeof(UINT);
340 if (context->context.lcPktData & PK_BUTTONS)
341 rc += sizeof(DWORD);
342 if (context->context.lcPktData & PK_X)
343 rc += sizeof(DWORD);
344 if (context->context.lcPktData & PK_Y)
345 rc += sizeof(DWORD);
346 if (context->context.lcPktData & PK_Z)
347 rc += sizeof(DWORD);
348 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
349 rc += sizeof(UINT);
350 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
351 rc += sizeof(UINT);
352 if (context->context.lcPktData & PK_ORIENTATION)
353 rc += sizeof(ORIENTATION);
354 if (context->context.lcPktData & PK_ROTATION)
355 rc += sizeof(ROTATION);
357 rc *= n;
358 memset(lpPkt,0,rc);
362 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
364 UINT result;
366 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
367 if (gLoaded == FALSE)
368 LoadTablet();
371 * Handle system extents here, as we can use user32.dll code to set them.
373 if(wCategory == WTI_DEFSYSCTX)
375 switch(nIndex)
377 case CTX_SYSEXTX:
378 if(lpOutput != NULL)
379 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
380 return sizeof(LONG);
381 case CTX_SYSEXTY:
382 if(lpOutput != NULL)
383 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
384 return sizeof(LONG);
385 /* No action, delegate to X11Drv */
389 if (is_logcontext_category(wCategory) && nIndex == 0)
391 if (lpOutput)
393 LOGCONTEXTW buf;
394 pWTInfoW(wCategory, nIndex, &buf);
396 /* Handle system extents here, as we can use user32.dll code to set them */
397 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
399 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
400 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
403 if (bUnicode)
404 memcpy(lpOutput, &buf, sizeof(buf));
405 else
406 LOGCONTEXTWtoA(&buf, lpOutput);
409 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
411 else if (is_string_field(wCategory, nIndex) && !bUnicode)
413 int size = pWTInfoW(wCategory, nIndex, NULL);
414 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
415 pWTInfoW(wCategory, nIndex, buf);
416 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
417 HeapFree(GetProcessHeap(), 0, buf);
419 else
420 result = pWTInfoW(wCategory, nIndex, lpOutput);
422 TRACE("returns %d\n", result);
423 return result;
426 /***********************************************************************
427 * WTInfoA (WINTAB32.20)
429 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
431 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
435 /***********************************************************************
436 * WTInfoW (WINTAB32.1020)
438 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
440 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
443 /***********************************************************************
444 * WTOpenW (WINTAB32.2021)
446 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
448 LPOPENCONTEXT newcontext;
450 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
451 DUMPCONTEXT(*lpLogCtx);
453 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
454 newcontext->context = *lpLogCtx;
455 newcontext->hwndOwner = hWnd;
456 newcontext->ActiveCursor = -1;
457 newcontext->QueueSize = 10;
458 newcontext->PacketsQueued = 0;
459 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
461 EnterCriticalSection(&csTablet);
462 newcontext->handle = gTopContext++;
463 newcontext->next = gOpenContexts;
464 gOpenContexts = newcontext;
465 LeaveCriticalSection(&csTablet);
467 pAttachEventQueueToTablet(hWnd);
469 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
470 newcontext->context.lcStatus, TRUE);
472 if (fEnable)
474 newcontext->enabled = TRUE;
475 /* TODO: Add to top of overlap order */
476 newcontext->context.lcStatus = CXS_ONTOP;
478 else
480 newcontext->enabled = FALSE;
481 newcontext->context.lcStatus = CXS_DISABLED;
484 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
485 (WPARAM)newcontext->handle,
486 newcontext->context.lcStatus, TRUE);
488 return newcontext->handle;
491 /***********************************************************************
492 * WTOpenA (WINTAB32.21)
494 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
496 LOGCONTEXTW logCtxW;
498 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
499 return WTOpenW(hWnd, &logCtxW, fEnable);
502 /***********************************************************************
503 * WTClose (WINTAB32.22)
505 BOOL WINAPI WTClose(HCTX hCtx)
507 LPOPENCONTEXT context,ptr;
509 TRACE("(%p)\n", hCtx);
511 EnterCriticalSection(&csTablet);
513 ptr = context = gOpenContexts;
515 while (context && (context->handle != hCtx))
517 ptr = context;
518 context = context->next;
520 if (!context)
522 LeaveCriticalSection(&csTablet);
523 return TRUE;
526 if (context == gOpenContexts)
527 gOpenContexts = context->next;
528 else
529 ptr->next = context->next;
531 LeaveCriticalSection(&csTablet);
533 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
534 context->context.lcStatus,TRUE);
536 HeapFree(GetProcessHeap(),0,context->PacketQueue);
537 HeapFree(GetProcessHeap(),0,context);
539 return TRUE;
542 /***********************************************************************
543 * WTPacketsGet (WINTAB32.23)
545 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
547 int limit;
548 LPOPENCONTEXT context;
549 LPVOID ptr = lpPkts;
551 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
553 if (!hCtx)
554 return 0;
556 EnterCriticalSection(&csTablet);
558 context = TABLET_FindOpenContext(hCtx);
560 if (lpPkts != NULL)
561 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
563 if (context->PacketsQueued == 0)
565 LeaveCriticalSection(&csTablet);
566 return 0;
569 limit = min(cMaxPkts,context->PacketsQueued);
571 if(ptr != NULL)
573 int i = 0;
574 for(i = 0; i < limit; i++)
575 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
579 if (limit < context->PacketsQueued)
581 memmove(context->PacketQueue, &context->PacketQueue[limit],
582 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
584 context->PacketsQueued -= limit;
585 LeaveCriticalSection(&csTablet);
587 TRACE("Copied %i packets\n",limit);
589 return limit;
592 /***********************************************************************
593 * WTPacket (WINTAB32.24)
595 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
597 int rc = 0;
598 LPOPENCONTEXT context;
599 LPWTPACKET wtp = NULL;
601 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
603 if (!hCtx)
604 return 0;
606 EnterCriticalSection(&csTablet);
608 context = TABLET_FindOpenContext(hCtx);
610 rc = TABLET_FindPacket(context ,wSerial, &wtp);
612 if (rc >= 0)
614 if (lpPkt)
615 TABLET_CopyPacketData(context ,lpPkt, wtp);
617 if ((rc+1) < context->QueueSize)
619 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
620 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
622 context->PacketsQueued -= (rc+1);
624 LeaveCriticalSection(&csTablet);
626 TRACE("Returning %i\n",rc+1);
627 return rc+1;
630 /***********************************************************************
631 * WTEnable (WINTAB32.40)
633 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
635 LPOPENCONTEXT context;
637 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
639 if (!hCtx) return FALSE;
641 EnterCriticalSection(&csTablet);
642 context = TABLET_FindOpenContext(hCtx);
643 /* if we want to enable and it is not enabled then */
644 if(fEnable && !context->enabled)
646 context->enabled = TRUE;
647 /* TODO: Add to top of overlap order */
648 context->context.lcStatus = CXS_ONTOP;
650 /* if we want to disable and it is not disabled then */
651 else if (!fEnable && context->enabled)
653 context->enabled = FALSE;
654 /* TODO: Remove from overlap order?? needs a test */
655 context->context.lcStatus = CXS_DISABLED;
656 TABLET_FlushQueue(context);
658 LeaveCriticalSection(&csTablet);
660 return TRUE;
663 /***********************************************************************
664 * WTOverlap (WINTAB32.41)
666 * Move context to top or bottom of overlap order
668 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
670 LPOPENCONTEXT context;
672 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
674 if (!hCtx) return FALSE;
676 EnterCriticalSection(&csTablet);
677 context = TABLET_FindOpenContext(hCtx);
678 if (fToTop)
680 /* TODO: Move context to top of overlap order */
681 FIXME("Not moving context to top of overlap order\n");
682 context->context.lcStatus = CXS_ONTOP;
684 else
686 /* TODO: Move context to bottom of overlap order */
687 FIXME("Not moving context to bottom of overlap order\n");
688 context->context.lcStatus = CXS_OBSCURED;
690 LeaveCriticalSection(&csTablet);
692 return TRUE;
695 /***********************************************************************
696 * WTConfig (WINTAB32.61)
698 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
700 FIXME("(%p, %p): stub\n", hCtx, hWnd);
702 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
704 return FALSE;
707 /***********************************************************************
708 * WTGetA (WINTAB32.61)
710 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
712 LPOPENCONTEXT context;
714 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
716 if (!hCtx) return 0;
718 EnterCriticalSection(&csTablet);
719 context = TABLET_FindOpenContext(hCtx);
720 LOGCONTEXTWtoA(&context->context, lpLogCtx);
721 LeaveCriticalSection(&csTablet);
723 return TRUE;
726 /***********************************************************************
727 * WTGetW (WINTAB32.1061)
729 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
731 LPOPENCONTEXT context;
733 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
735 if (!hCtx) return 0;
737 EnterCriticalSection(&csTablet);
738 context = TABLET_FindOpenContext(hCtx);
739 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
740 LeaveCriticalSection(&csTablet);
742 return TRUE;
745 /***********************************************************************
746 * WTSetA (WINTAB32.62)
748 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
750 LPOPENCONTEXT context;
752 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
754 if (!hCtx || !lpLogCtx) return FALSE;
756 /* TODO: if cur process not owner of hCtx only modify
757 * attribs not locked by owner */
759 EnterCriticalSection(&csTablet);
760 context = TABLET_FindOpenContext(hCtx);
761 LOGCONTEXTAtoW(lpLogCtx, &context->context);
762 LeaveCriticalSection(&csTablet);
764 return TRUE;
767 /***********************************************************************
768 * WTSetW (WINTAB32.1062)
770 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
772 LPOPENCONTEXT context;
774 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
776 if (!hCtx || !lpLogCtx) return FALSE;
778 /* TODO: if cur process not hCtx owner only modify
779 * attribs not locked by owner */
781 EnterCriticalSection(&csTablet);
782 context = TABLET_FindOpenContext(hCtx);
783 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
784 LeaveCriticalSection(&csTablet);
786 return TRUE;
789 /***********************************************************************
790 * WTExtGet (WINTAB32.63)
792 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
794 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
796 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
798 return FALSE;
801 /***********************************************************************
802 * WTExtSet (WINTAB32.64)
804 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
806 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
808 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
810 return FALSE;
813 /***********************************************************************
814 * WTSave (WINTAB32.65)
816 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
818 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
820 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
822 return FALSE;
825 /***********************************************************************
826 * WTRestore (WINTAB32.66)
828 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
830 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
832 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
834 return 0;
837 /***********************************************************************
838 * WTPacketsPeek (WINTAB32.80)
840 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
842 int limit;
843 LPOPENCONTEXT context;
844 LPVOID ptr = lpPkts;
846 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
848 if (!hCtx || !lpPkts) return 0;
850 EnterCriticalSection(&csTablet);
852 context = TABLET_FindOpenContext(hCtx);
854 if (context->PacketsQueued == 0)
856 LeaveCriticalSection(&csTablet);
857 return 0;
860 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
861 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
863 LeaveCriticalSection(&csTablet);
864 TRACE("Copied %i packets\n",limit);
865 return limit;
868 /***********************************************************************
869 * WTDataGet (WINTAB32.81)
871 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
872 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
874 LPOPENCONTEXT context;
875 LPVOID ptr = lpPkts;
876 INT bgn = 0;
877 INT end = 0;
878 INT num = 0;
880 TRACE("(%p, %u, %u, %d, %p, %p)\n",
881 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
883 if (!hCtx) return 0;
885 EnterCriticalSection(&csTablet);
887 context = TABLET_FindOpenContext(hCtx);
889 if (context->PacketsQueued == 0)
891 LeaveCriticalSection(&csTablet);
892 return 0;
895 while (bgn < context->PacketsQueued &&
896 context->PacketQueue[bgn].pkSerialNumber != wBegin)
897 bgn++;
899 end = bgn;
900 while (end < context->PacketsQueued &&
901 context->PacketQueue[end].pkSerialNumber != wEnd)
902 end++;
904 if ((bgn == end) && (end == context->PacketsQueued))
906 LeaveCriticalSection(&csTablet);
907 return 0;
910 for (num = bgn; num <= end; num++)
911 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
913 /* remove read packets */
914 if ((end+1) < context->PacketsQueued)
915 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
916 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
918 context->PacketsQueued -= ((end-bgn)+1);
919 *lpNPkts = ((end-bgn)+1);
921 LeaveCriticalSection(&csTablet);
922 TRACE("Copied %i packets\n",*lpNPkts);
923 return (end - bgn)+1;
926 /***********************************************************************
927 * WTDataPeek (WINTAB32.82)
929 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
930 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
932 LPOPENCONTEXT context;
933 LPVOID ptr = lpPkts;
934 INT bgn = 0;
935 INT end = 0;
936 INT num = 0;
938 TRACE("(%p, %u, %u, %d, %p, %p)\n",
939 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
941 if (!hCtx || !lpPkts) return 0;
943 EnterCriticalSection(&csTablet);
945 context = TABLET_FindOpenContext(hCtx);
947 if (context->PacketsQueued == 0)
949 LeaveCriticalSection(&csTablet);
950 return 0;
953 while (bgn < context->PacketsQueued &&
954 context->PacketQueue[bgn].pkSerialNumber != wBegin)
955 bgn++;
957 end = bgn;
958 while (end < context->PacketsQueued &&
959 context->PacketQueue[end].pkSerialNumber != wEnd)
960 end++;
962 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
964 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
965 LeaveCriticalSection(&csTablet);
966 return 0;
969 for (num = bgn; num <= end; num++)
970 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
972 *lpNPkts = ((end-bgn)+1);
973 LeaveCriticalSection(&csTablet);
975 TRACE("Copied %i packets\n",*lpNPkts);
976 return (end - bgn)+1;
979 /***********************************************************************
980 * WTQueuePacketsEx (WINTAB32.200)
982 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
984 LPOPENCONTEXT context;
986 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
988 if (!hCtx) return 0;
990 EnterCriticalSection(&csTablet);
992 context = TABLET_FindOpenContext(hCtx);
994 if (context->PacketsQueued)
996 *lpOld = context->PacketQueue[0].pkSerialNumber;
997 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
999 else
1001 TRACE("No packets\n");
1002 LeaveCriticalSection(&csTablet);
1003 return FALSE;
1005 LeaveCriticalSection(&csTablet);
1007 return TRUE;
1010 /***********************************************************************
1011 * WTQueueSizeGet (WINTAB32.84)
1013 int WINAPI WTQueueSizeGet(HCTX hCtx)
1015 LPOPENCONTEXT context;
1016 TRACE("(%p)\n", hCtx);
1018 if (!hCtx) return 0;
1020 EnterCriticalSection(&csTablet);
1021 context = TABLET_FindOpenContext(hCtx);
1022 LeaveCriticalSection(&csTablet);
1023 return context->QueueSize;
1026 /***********************************************************************
1027 * WTQueueSizeSet (WINTAB32.85)
1029 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1031 LPOPENCONTEXT context;
1033 TRACE("(%p, %d)\n", hCtx, nPkts);
1035 if (!hCtx) return 0;
1037 EnterCriticalSection(&csTablet);
1039 context = TABLET_FindOpenContext(hCtx);
1041 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1042 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1044 context->QueueSize = nPkts;
1045 LeaveCriticalSection(&csTablet);
1047 return nPkts;