push 615e57025c5810454991e0c38bb21161daed7f1f
[wine/hacks.git] / dlls / wintab32 / context.c
blobbf461701c3dba91a2f8f6555398196116870c024
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;
218 else if (ptr->context.lcOutExtY < 0)
219 packet->pkY = abs(ptr->context.lcOutExtY + packet->pkY);
221 DUMPPACKET(*packet);
223 if (tgt == ptr->QueueSize)
225 TRACE("Queue Overflow %p\n",ptr->handle);
226 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
228 else
230 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
231 ptr->PacketQueue[tgt] = *packet;
232 ptr->PacketsQueued++;
234 if (ptr->ActiveCursor != packet->pkCursor)
236 ptr->ActiveCursor = packet->pkCursor;
237 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
238 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
239 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
240 FALSE);
243 break;
245 ptr = ptr->next;
247 LeaveCriticalSection(&csTablet);
248 TRACE("Done (%p)\n",ptr);
249 return ptr;
253 * Flushes all packets from the queue.
255 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
257 context->PacketsQueued = 0;
260 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
262 memcpy(target,src,size);
263 return(size);
266 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
267 LPWTPACKET *pkt)
269 int loop;
270 int index = -1;
271 for (loop = 0; loop < context->PacketsQueued; loop++)
272 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
274 index = loop;
275 *pkt = &context->PacketQueue[loop];
276 break;
279 TRACE("%i .. %i\n",context->PacketsQueued,index);
281 return index;
285 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
286 LPWTPACKET wtp)
288 LPBYTE ptr;
290 ptr = lpPkt;
291 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
293 if (context->context.lcPktData & PK_CONTEXT)
294 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
295 if (context->context.lcPktData & PK_STATUS)
296 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
297 if (context->context.lcPktData & PK_TIME)
298 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
299 if (context->context.lcPktData & PK_CHANGED)
300 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
301 if (context->context.lcPktData & PK_SERIAL_NUMBER)
302 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
303 if (context->context.lcPktData & PK_CURSOR)
304 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
305 if (context->context.lcPktData & PK_BUTTONS)
306 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
307 if (context->context.lcPktData & PK_X)
308 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
309 if (context->context.lcPktData & PK_Y)
310 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
311 if (context->context.lcPktData & PK_Z)
312 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
313 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
314 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
315 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
316 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
317 if (context->context.lcPktData & PK_ORIENTATION)
318 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
319 if (context->context.lcPktData & PK_ROTATION)
320 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
322 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
323 return ptr;
326 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
328 int rc = 0;
330 if (context->context.lcPktData & PK_CONTEXT)
331 rc +=sizeof(HCTX);
332 if (context->context.lcPktData & PK_STATUS)
333 rc +=sizeof(UINT);
334 if (context->context.lcPktData & PK_TIME)
335 rc += sizeof(LONG);
336 if (context->context.lcPktData & PK_CHANGED)
337 rc += sizeof(WTPKT);
338 if (context->context.lcPktData & PK_SERIAL_NUMBER)
339 rc += sizeof(UINT);
340 if (context->context.lcPktData & PK_CURSOR)
341 rc += sizeof(UINT);
342 if (context->context.lcPktData & PK_BUTTONS)
343 rc += sizeof(DWORD);
344 if (context->context.lcPktData & PK_X)
345 rc += sizeof(DWORD);
346 if (context->context.lcPktData & PK_Y)
347 rc += sizeof(DWORD);
348 if (context->context.lcPktData & PK_Z)
349 rc += sizeof(DWORD);
350 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
351 rc += sizeof(UINT);
352 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
353 rc += sizeof(UINT);
354 if (context->context.lcPktData & PK_ORIENTATION)
355 rc += sizeof(ORIENTATION);
356 if (context->context.lcPktData & PK_ROTATION)
357 rc += sizeof(ROTATION);
359 rc *= n;
360 memset(lpPkt,0,rc);
364 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
366 UINT result;
368 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
369 if (gLoaded == FALSE)
370 LoadTablet();
373 * Handle system extents here, as we can use user32.dll code to set them.
375 if(wCategory == WTI_DEFSYSCTX)
377 switch(nIndex)
379 case CTX_SYSEXTX:
380 if(lpOutput != NULL)
381 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
382 return sizeof(LONG);
383 case CTX_SYSEXTY:
384 if(lpOutput != NULL)
385 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
386 return sizeof(LONG);
387 /* No action, delegate to X11Drv */
391 if (is_logcontext_category(wCategory) && nIndex == 0)
393 if (lpOutput)
395 LOGCONTEXTW buf;
396 pWTInfoW(wCategory, nIndex, &buf);
398 /* Handle system extents here, as we can use user32.dll code to set them */
399 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
401 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
402 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
405 if (bUnicode)
406 memcpy(lpOutput, &buf, sizeof(buf));
407 else
408 LOGCONTEXTWtoA(&buf, lpOutput);
411 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
413 else if (is_string_field(wCategory, nIndex) && !bUnicode)
415 int size = pWTInfoW(wCategory, nIndex, NULL);
416 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
417 pWTInfoW(wCategory, nIndex, buf);
418 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
419 HeapFree(GetProcessHeap(), 0, buf);
421 else
422 result = pWTInfoW(wCategory, nIndex, lpOutput);
424 TRACE("returns %d\n", result);
425 return result;
428 /***********************************************************************
429 * WTInfoA (WINTAB32.20)
431 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
433 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
437 /***********************************************************************
438 * WTInfoW (WINTAB32.1020)
440 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
442 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
445 /***********************************************************************
446 * WTOpenW (WINTAB32.2021)
448 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
450 LPOPENCONTEXT newcontext;
452 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
453 DUMPCONTEXT(*lpLogCtx);
455 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
456 newcontext->context = *lpLogCtx;
457 newcontext->hwndOwner = hWnd;
458 newcontext->ActiveCursor = -1;
459 newcontext->QueueSize = 10;
460 newcontext->PacketsQueued = 0;
461 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
463 EnterCriticalSection(&csTablet);
464 newcontext->handle = gTopContext++;
465 newcontext->next = gOpenContexts;
466 gOpenContexts = newcontext;
467 LeaveCriticalSection(&csTablet);
469 pAttachEventQueueToTablet(hWnd);
471 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
472 newcontext->context.lcStatus, TRUE);
474 if (fEnable)
476 newcontext->enabled = TRUE;
477 /* TODO: Add to top of overlap order */
478 newcontext->context.lcStatus = CXS_ONTOP;
480 else
482 newcontext->enabled = FALSE;
483 newcontext->context.lcStatus = CXS_DISABLED;
486 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
487 (WPARAM)newcontext->handle,
488 newcontext->context.lcStatus, TRUE);
490 return newcontext->handle;
493 /***********************************************************************
494 * WTOpenA (WINTAB32.21)
496 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
498 LOGCONTEXTW logCtxW;
500 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
501 return WTOpenW(hWnd, &logCtxW, fEnable);
504 /***********************************************************************
505 * WTClose (WINTAB32.22)
507 BOOL WINAPI WTClose(HCTX hCtx)
509 LPOPENCONTEXT context,ptr;
511 TRACE("(%p)\n", hCtx);
513 EnterCriticalSection(&csTablet);
515 ptr = context = gOpenContexts;
517 while (context && (context->handle != hCtx))
519 ptr = context;
520 context = context->next;
522 if (!context)
524 LeaveCriticalSection(&csTablet);
525 return TRUE;
528 if (context == gOpenContexts)
529 gOpenContexts = context->next;
530 else
531 ptr->next = context->next;
533 LeaveCriticalSection(&csTablet);
535 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
536 context->context.lcStatus,TRUE);
538 HeapFree(GetProcessHeap(),0,context->PacketQueue);
539 HeapFree(GetProcessHeap(),0,context);
541 return TRUE;
544 /***********************************************************************
545 * WTPacketsGet (WINTAB32.23)
547 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
549 int limit;
550 LPOPENCONTEXT context;
551 LPVOID ptr = lpPkts;
553 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
555 if (!hCtx)
556 return 0;
558 EnterCriticalSection(&csTablet);
560 context = TABLET_FindOpenContext(hCtx);
562 if (lpPkts != NULL)
563 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
565 if (context->PacketsQueued == 0)
567 LeaveCriticalSection(&csTablet);
568 return 0;
571 limit = min(cMaxPkts,context->PacketsQueued);
573 if(ptr != NULL)
575 int i = 0;
576 for(i = 0; i < limit; i++)
577 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
581 if (limit < context->PacketsQueued)
583 memmove(context->PacketQueue, &context->PacketQueue[limit],
584 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
586 context->PacketsQueued -= limit;
587 LeaveCriticalSection(&csTablet);
589 TRACE("Copied %i packets\n",limit);
591 return limit;
594 /***********************************************************************
595 * WTPacket (WINTAB32.24)
597 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
599 int rc = 0;
600 LPOPENCONTEXT context;
601 LPWTPACKET wtp = NULL;
603 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
605 if (!hCtx)
606 return 0;
608 EnterCriticalSection(&csTablet);
610 context = TABLET_FindOpenContext(hCtx);
612 rc = TABLET_FindPacket(context ,wSerial, &wtp);
614 if (rc >= 0)
616 if (lpPkt)
617 TABLET_CopyPacketData(context ,lpPkt, wtp);
619 if ((rc+1) < context->QueueSize)
621 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
622 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
624 context->PacketsQueued -= (rc+1);
626 LeaveCriticalSection(&csTablet);
628 TRACE("Returning %i\n",rc+1);
629 return rc+1;
632 /***********************************************************************
633 * WTEnable (WINTAB32.40)
635 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
637 LPOPENCONTEXT context;
639 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
641 if (!hCtx) return FALSE;
643 EnterCriticalSection(&csTablet);
644 context = TABLET_FindOpenContext(hCtx);
645 /* if we want to enable and it is not enabled then */
646 if(fEnable && !context->enabled)
648 context->enabled = TRUE;
649 /* TODO: Add to top of overlap order */
650 context->context.lcStatus = CXS_ONTOP;
652 /* if we want to disable and it is not disabled then */
653 else if (!fEnable && context->enabled)
655 context->enabled = FALSE;
656 /* TODO: Remove from overlap order?? needs a test */
657 context->context.lcStatus = CXS_DISABLED;
658 TABLET_FlushQueue(context);
660 LeaveCriticalSection(&csTablet);
662 return TRUE;
665 /***********************************************************************
666 * WTOverlap (WINTAB32.41)
668 * Move context to top or bottom of overlap order
670 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
672 LPOPENCONTEXT context;
674 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
676 if (!hCtx) return FALSE;
678 EnterCriticalSection(&csTablet);
679 context = TABLET_FindOpenContext(hCtx);
680 if (fToTop)
682 /* TODO: Move context to top of overlap order */
683 FIXME("Not moving context to top of overlap order\n");
684 context->context.lcStatus = CXS_ONTOP;
686 else
688 /* TODO: Move context to bottom of overlap order */
689 FIXME("Not moving context to bottom of overlap order\n");
690 context->context.lcStatus = CXS_OBSCURED;
692 LeaveCriticalSection(&csTablet);
694 return TRUE;
697 /***********************************************************************
698 * WTConfig (WINTAB32.61)
700 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
702 FIXME("(%p, %p): stub\n", hCtx, hWnd);
704 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
706 return FALSE;
709 /***********************************************************************
710 * WTGetA (WINTAB32.61)
712 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
714 LPOPENCONTEXT context;
716 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
718 if (!hCtx) return 0;
720 EnterCriticalSection(&csTablet);
721 context = TABLET_FindOpenContext(hCtx);
722 LOGCONTEXTWtoA(&context->context, lpLogCtx);
723 LeaveCriticalSection(&csTablet);
725 return TRUE;
728 /***********************************************************************
729 * WTGetW (WINTAB32.1061)
731 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
733 LPOPENCONTEXT context;
735 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
737 if (!hCtx) return 0;
739 EnterCriticalSection(&csTablet);
740 context = TABLET_FindOpenContext(hCtx);
741 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
742 LeaveCriticalSection(&csTablet);
744 return TRUE;
747 /***********************************************************************
748 * WTSetA (WINTAB32.62)
750 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
752 LPOPENCONTEXT context;
754 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
756 if (!hCtx || !lpLogCtx) return FALSE;
758 /* TODO: if cur process not owner of hCtx only modify
759 * attribs not locked by owner */
761 EnterCriticalSection(&csTablet);
762 context = TABLET_FindOpenContext(hCtx);
763 LOGCONTEXTAtoW(lpLogCtx, &context->context);
764 LeaveCriticalSection(&csTablet);
766 return TRUE;
769 /***********************************************************************
770 * WTSetW (WINTAB32.1062)
772 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
774 LPOPENCONTEXT context;
776 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
778 if (!hCtx || !lpLogCtx) return FALSE;
780 /* TODO: if cur process not hCtx owner only modify
781 * attribs not locked by owner */
783 EnterCriticalSection(&csTablet);
784 context = TABLET_FindOpenContext(hCtx);
785 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
786 LeaveCriticalSection(&csTablet);
788 return TRUE;
791 /***********************************************************************
792 * WTExtGet (WINTAB32.63)
794 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
796 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
798 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
800 return FALSE;
803 /***********************************************************************
804 * WTExtSet (WINTAB32.64)
806 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
808 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
810 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
812 return FALSE;
815 /***********************************************************************
816 * WTSave (WINTAB32.65)
818 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
820 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
822 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
824 return FALSE;
827 /***********************************************************************
828 * WTRestore (WINTAB32.66)
830 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
832 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
834 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
836 return 0;
839 /***********************************************************************
840 * WTPacketsPeek (WINTAB32.80)
842 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
844 int limit;
845 LPOPENCONTEXT context;
846 LPVOID ptr = lpPkts;
848 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
850 if (!hCtx || !lpPkts) return 0;
852 EnterCriticalSection(&csTablet);
854 context = TABLET_FindOpenContext(hCtx);
856 if (context->PacketsQueued == 0)
858 LeaveCriticalSection(&csTablet);
859 return 0;
862 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
863 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
865 LeaveCriticalSection(&csTablet);
866 TRACE("Copied %i packets\n",limit);
867 return limit;
870 /***********************************************************************
871 * WTDataGet (WINTAB32.81)
873 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
874 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
876 LPOPENCONTEXT context;
877 LPVOID ptr = lpPkts;
878 INT bgn = 0;
879 INT end = 0;
880 INT num = 0;
882 TRACE("(%p, %u, %u, %d, %p, %p)\n",
883 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
885 if (!hCtx) return 0;
887 EnterCriticalSection(&csTablet);
889 context = TABLET_FindOpenContext(hCtx);
891 if (context->PacketsQueued == 0)
893 LeaveCriticalSection(&csTablet);
894 return 0;
897 while (bgn < context->PacketsQueued &&
898 context->PacketQueue[bgn].pkSerialNumber != wBegin)
899 bgn++;
901 end = bgn;
902 while (end < context->PacketsQueued &&
903 context->PacketQueue[end].pkSerialNumber != wEnd)
904 end++;
906 if ((bgn == end) && (end == context->PacketsQueued))
908 LeaveCriticalSection(&csTablet);
909 return 0;
912 for (num = bgn; num <= end; num++)
913 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
915 /* remove read packets */
916 if ((end+1) < context->PacketsQueued)
917 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
918 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
920 context->PacketsQueued -= ((end-bgn)+1);
921 *lpNPkts = ((end-bgn)+1);
923 LeaveCriticalSection(&csTablet);
924 TRACE("Copied %i packets\n",*lpNPkts);
925 return (end - bgn)+1;
928 /***********************************************************************
929 * WTDataPeek (WINTAB32.82)
931 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
932 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
934 LPOPENCONTEXT context;
935 LPVOID ptr = lpPkts;
936 INT bgn = 0;
937 INT end = 0;
938 INT num = 0;
940 TRACE("(%p, %u, %u, %d, %p, %p)\n",
941 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
943 if (!hCtx || !lpPkts) return 0;
945 EnterCriticalSection(&csTablet);
947 context = TABLET_FindOpenContext(hCtx);
949 if (context->PacketsQueued == 0)
951 LeaveCriticalSection(&csTablet);
952 return 0;
955 while (bgn < context->PacketsQueued &&
956 context->PacketQueue[bgn].pkSerialNumber != wBegin)
957 bgn++;
959 end = bgn;
960 while (end < context->PacketsQueued &&
961 context->PacketQueue[end].pkSerialNumber != wEnd)
962 end++;
964 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
966 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
967 LeaveCriticalSection(&csTablet);
968 return 0;
971 for (num = bgn; num <= end; num++)
972 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
974 *lpNPkts = ((end-bgn)+1);
975 LeaveCriticalSection(&csTablet);
977 TRACE("Copied %i packets\n",*lpNPkts);
978 return (end - bgn)+1;
981 /***********************************************************************
982 * WTQueuePacketsEx (WINTAB32.200)
984 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
986 LPOPENCONTEXT context;
988 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
990 if (!hCtx) return 0;
992 EnterCriticalSection(&csTablet);
994 context = TABLET_FindOpenContext(hCtx);
996 if (context->PacketsQueued)
998 *lpOld = context->PacketQueue[0].pkSerialNumber;
999 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
1001 else
1003 TRACE("No packets\n");
1004 LeaveCriticalSection(&csTablet);
1005 return FALSE;
1007 LeaveCriticalSection(&csTablet);
1009 return TRUE;
1012 /***********************************************************************
1013 * WTQueueSizeGet (WINTAB32.84)
1015 int WINAPI WTQueueSizeGet(HCTX hCtx)
1017 LPOPENCONTEXT context;
1018 TRACE("(%p)\n", hCtx);
1020 if (!hCtx) return 0;
1022 EnterCriticalSection(&csTablet);
1023 context = TABLET_FindOpenContext(hCtx);
1024 LeaveCriticalSection(&csTablet);
1025 return context->QueueSize;
1028 /***********************************************************************
1029 * WTQueueSizeSet (WINTAB32.85)
1031 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1033 LPOPENCONTEXT context;
1035 TRACE("(%p, %d)\n", hCtx, nPkts);
1037 if (!hCtx) return 0;
1039 EnterCriticalSection(&csTablet);
1041 context = TABLET_FindOpenContext(hCtx);
1043 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1044 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1046 context->QueueSize = nPkts;
1047 LeaveCriticalSection(&csTablet);
1049 return nPkts;