wintab32: Fix debug traces to use wine_dbg_sprintf.
[wine/dcerpc.git] / dlls / wintab32 / context.c
blob7974972ba11415ccbbf5531dd6440ef02062da66
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("context: %s, %x, %x, %x, %x, %x, %x, %x%s, %x%s, %x%s, %x, %x, %i, %i, %i, %i ,%i, %i, %i, %i, %i,%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i %i %i",
118 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
119 lc.lcDevice, lc.lcPktRate, lc.lcPktData, DUMPBITS(lc.lcPktData),
120 lc.lcPktMode, DUMPBITS(lc.lcPktMode), lc.lcMoveMask,
121 DUMPBITS(lc.lcMoveMask), lc.lcBtnDnMask, lc.lcBtnUpMask,
122 lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
123 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
124 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
125 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
126 lc.lcSysSensY);
130 /* Find an open context given the handle */
131 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
133 LPOPENCONTEXT ptr = gOpenContexts;
134 while (ptr)
136 if (ptr->handle == hCtx) return ptr;
137 ptr = ptr->next;
139 return NULL;
142 static void LoadTablet(void)
144 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
145 gLoaded= TRUE;
146 pLoadTabletInfo(hwndDefault);
149 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
150 LPARAM lParam, BOOL send_always)
152 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
154 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
155 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
157 return 0;
160 static inline DWORD ScaleForContext(DWORD In, DWORD InOrg, DWORD InExt, DWORD
161 OutOrg, DWORD OutExt)
163 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
164 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
165 else
166 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
169 LPOPENCONTEXT FindOpenContext(HWND hwnd)
171 LPOPENCONTEXT ptr;
173 EnterCriticalSection(&csTablet);
174 ptr = gOpenContexts;
175 while (ptr)
177 TRACE("Trying Context %p (%p %p)\n",ptr->handle,hwnd,ptr->hwndOwner);
178 if (ptr->hwndOwner == hwnd) break;
180 LeaveCriticalSection(&csTablet);
181 return ptr;
184 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
186 LPOPENCONTEXT ptr=NULL;
188 EnterCriticalSection(&csTablet);
190 ptr = gOpenContexts;
191 while (ptr)
193 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
195 if (ptr->hwndOwner == hwnd)
197 int tgt;
198 if (!ptr->enabled)
200 ptr = ptr->next;
201 continue;
204 tgt = ptr->PacketsQueued;
206 packet->pkContext = ptr->handle;
208 /* translate packet data to the context */
210 /* Scale as per documentation */
211 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
212 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
213 ptr->context.lcOutExtY);
215 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
216 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
217 ptr->context.lcOutExtX);
219 /* flip the Y axis */
220 if (ptr->context.lcOutExtY > 0)
221 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
223 DUMPPACKET(*packet);
225 if (tgt == ptr->QueueSize)
227 TRACE("Queue Overflow %p\n",ptr->handle);
228 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
230 else
232 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
233 memcpy(&ptr->PacketQueue[tgt], packet, sizeof
234 (WTPACKET));
235 ptr->PacketsQueued++;
237 if (ptr->ActiveCursor != packet->pkCursor)
239 ptr->ActiveCursor = packet->pkCursor;
240 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
241 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
242 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
243 FALSE);
246 break;
248 ptr = ptr->next;
250 LeaveCriticalSection(&csTablet);
251 TRACE("Done (%p)\n",ptr);
252 return ptr;
256 * Flushes all packets from the queue.
258 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
260 context->PacketsQueued = 0;
263 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
265 memcpy(target,src,size);
266 return(size);
269 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
270 LPWTPACKET *pkt)
272 int loop;
273 int index = -1;
274 for (loop = 0; loop < context->PacketsQueued; loop++)
275 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
277 index = loop;
278 *pkt = &context->PacketQueue[loop];
279 break;
282 TRACE("%i .. %i\n",context->PacketsQueued,index);
284 return index;
288 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
289 LPWTPACKET wtp)
291 LPBYTE ptr;
293 ptr = lpPkt;
294 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
296 if (context->context.lcPktData & PK_CONTEXT)
297 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
298 if (context->context.lcPktData & PK_STATUS)
299 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
300 if (context->context.lcPktData & PK_TIME)
301 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
302 if (context->context.lcPktData & PK_CHANGED)
303 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
304 if (context->context.lcPktData & PK_SERIAL_NUMBER)
305 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
306 if (context->context.lcPktData & PK_CURSOR)
307 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
308 if (context->context.lcPktData & PK_BUTTONS)
309 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
310 if (context->context.lcPktData & PK_X)
311 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
312 if (context->context.lcPktData & PK_Y)
313 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
314 if (context->context.lcPktData & PK_Z)
315 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
316 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
317 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
318 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
319 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
320 if (context->context.lcPktData & PK_ORIENTATION)
321 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
322 if (context->context.lcPktData & PK_ROTATION)
323 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
325 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
326 return ptr;
329 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
331 int rc = 0;
333 if (context->context.lcPktData & PK_CONTEXT)
334 rc +=sizeof(HCTX);
335 if (context->context.lcPktData & PK_STATUS)
336 rc +=sizeof(UINT);
337 if (context->context.lcPktData & PK_TIME)
338 rc += sizeof(LONG);
339 if (context->context.lcPktData & PK_CHANGED)
340 rc += sizeof(WTPKT);
341 if (context->context.lcPktData & PK_SERIAL_NUMBER)
342 rc += sizeof(UINT);
343 if (context->context.lcPktData & PK_CURSOR)
344 rc += sizeof(UINT);
345 if (context->context.lcPktData & PK_BUTTONS)
346 rc += sizeof(DWORD);
347 if (context->context.lcPktData & PK_X)
348 rc += sizeof(DWORD);
349 if (context->context.lcPktData & PK_Y)
350 rc += sizeof(DWORD);
351 if (context->context.lcPktData & PK_Z)
352 rc += sizeof(DWORD);
353 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
354 rc += sizeof(UINT);
355 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
356 rc += sizeof(UINT);
357 if (context->context.lcPktData & PK_ORIENTATION)
358 rc += sizeof(ORIENTATION);
359 if (context->context.lcPktData & PK_ROTATION)
360 rc += sizeof(ROTATION);
362 rc *= n;
363 memset(lpPkt,0,rc);
367 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
369 UINT result;
370 if (gLoaded == FALSE)
371 LoadTablet();
374 * Handle system extents here, as we can use user32.dll code to set them.
376 if(wCategory == WTI_DEFSYSCTX)
378 switch(nIndex)
380 case CTX_SYSEXTX:
381 if(lpOutput != NULL)
382 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
383 return sizeof(LONG);
384 case CTX_SYSEXTY:
385 if(lpOutput != NULL)
386 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
387 return sizeof(LONG);
388 /* No action, delegate to X11Drv */
392 if (is_logcontext_category(wCategory) && nIndex == 0)
394 if (lpOutput)
396 LOGCONTEXTW buf;
397 pWTInfoW(wCategory, nIndex, &buf);
399 /* Handle system extents here, as we can use user32.dll code to set them */
400 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
402 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
403 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
406 if (bUnicode)
407 memcpy(lpOutput, &buf, sizeof(buf));
408 else
409 LOGCONTEXTWtoA(&buf, lpOutput);
412 return bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
414 else if (is_string_field(wCategory, nIndex) && !bUnicode)
416 int size = pWTInfoW(wCategory, nIndex, NULL);
417 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
418 pWTInfoW(wCategory, nIndex, buf);
419 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
420 HeapFree(GetProcessHeap(), 0, buf);
422 else
423 result = pWTInfoW(wCategory, nIndex, lpOutput);
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("(%p, %p, %u)\n", hWnd, lpLogCtx, fEnable);
453 DUMPCONTEXT(*lpLogCtx);
455 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
456 memcpy(&(newcontext->context),lpLogCtx,sizeof(LOGCONTEXTW));
457 newcontext->hwndOwner = hWnd;
458 newcontext->enabled = fEnable;
459 newcontext->ActiveCursor = -1;
460 newcontext->QueueSize = 10;
461 newcontext->PacketsQueued = 0;
462 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
464 EnterCriticalSection(&csTablet);
465 newcontext->handle = gTopContext++;
466 newcontext->next = gOpenContexts;
467 gOpenContexts = newcontext;
468 LeaveCriticalSection(&csTablet);
470 pAttachEventQueueToTablet(hWnd);
472 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
473 newcontext->context.lcStatus, TRUE);
475 newcontext->context.lcStatus = CXS_ONTOP;
477 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
478 (WPARAM)newcontext->handle,
479 newcontext->context.lcStatus, TRUE);
481 return newcontext->handle;
484 /***********************************************************************
485 * WTOpenA (WINTAB32.21)
487 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
489 LOGCONTEXTW logCtxW;
491 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
492 return WTOpenW(hWnd, &logCtxW, fEnable);
495 /***********************************************************************
496 * WTClose (WINTAB32.22)
498 BOOL WINAPI WTClose(HCTX hCtx)
500 LPOPENCONTEXT context,ptr;
502 TRACE("(%p)\n", hCtx);
504 EnterCriticalSection(&csTablet);
506 ptr = context = gOpenContexts;
508 while (context && (context->handle != hCtx))
510 ptr = context;
511 context = context->next;
513 if (!context)
515 LeaveCriticalSection(&csTablet);
516 return TRUE;
519 if (context == gOpenContexts)
520 gOpenContexts = context->next;
521 else
522 ptr->next = context->next;
524 LeaveCriticalSection(&csTablet);
526 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
527 context->context.lcStatus,TRUE);
529 HeapFree(GetProcessHeap(),0,context->PacketQueue);
530 HeapFree(GetProcessHeap(),0,context);
532 return TRUE;
535 /***********************************************************************
536 * WTPacketsGet (WINTAB32.23)
538 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
540 int limit;
541 LPOPENCONTEXT context;
542 LPVOID ptr = lpPkts;
544 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
546 if (!hCtx)
547 return 0;
549 EnterCriticalSection(&csTablet);
551 context = TABLET_FindOpenContext(hCtx);
553 if (lpPkts != NULL)
554 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
556 if (context->PacketsQueued == 0)
558 LeaveCriticalSection(&csTablet);
559 return 0;
562 limit = min(cMaxPkts,context->PacketsQueued);
564 if(ptr != NULL)
566 int i = 0;
567 for(i = 0; i < limit; i++)
568 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
572 if (limit < context->PacketsQueued)
574 memmove(context->PacketQueue, &context->PacketQueue[limit],
575 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
577 context->PacketsQueued -= limit;
578 LeaveCriticalSection(&csTablet);
580 TRACE("Copied %i packets\n",limit);
582 return limit;
585 /***********************************************************************
586 * WTPacket (WINTAB32.24)
588 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
590 int rc = 0;
591 LPOPENCONTEXT context;
592 LPWTPACKET wtp = NULL;
594 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
596 if (!hCtx)
597 return 0;
599 EnterCriticalSection(&csTablet);
601 context = TABLET_FindOpenContext(hCtx);
603 rc = TABLET_FindPacket(context ,wSerial, &wtp);
605 if (rc >= 0)
607 if (lpPkt)
608 TABLET_CopyPacketData(context ,lpPkt, wtp);
610 if ((rc+1) < context->QueueSize)
612 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
613 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
615 context->PacketsQueued -= (rc+1);
617 LeaveCriticalSection(&csTablet);
619 TRACE("Returning %i\n",rc+1);
620 return rc+1;
623 /***********************************************************************
624 * WTEnable (WINTAB32.40)
626 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
628 LPOPENCONTEXT context;
630 TRACE("(%p, %u)\n", hCtx, fEnable);
632 if (!hCtx) return 0;
634 EnterCriticalSection(&csTablet);
635 context = TABLET_FindOpenContext(hCtx);
636 if(!fEnable)
637 TABLET_FlushQueue(context);
638 context->enabled = fEnable;
639 LeaveCriticalSection(&csTablet);
641 return TRUE;
644 /***********************************************************************
645 * WTOverlap (WINTAB32.41)
647 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
649 FIXME("(%p, %u): stub\n", hCtx, fToTop);
651 return TRUE;
654 /***********************************************************************
655 * WTConfig (WINTAB32.61)
657 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
659 FIXME("(%p, %p): stub\n", hCtx, hWnd);
661 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
663 return FALSE;
666 /***********************************************************************
667 * WTGetA (WINTAB32.61)
669 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
671 LPOPENCONTEXT context;
673 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
675 if (!hCtx) return 0;
677 EnterCriticalSection(&csTablet);
678 context = TABLET_FindOpenContext(hCtx);
679 LOGCONTEXTWtoA(&context->context, lpLogCtx);
680 LeaveCriticalSection(&csTablet);
682 return TRUE;
685 /***********************************************************************
686 * WTGetW (WINTAB32.1061)
688 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
690 LPOPENCONTEXT context;
692 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
694 if (!hCtx) return 0;
696 EnterCriticalSection(&csTablet);
697 context = TABLET_FindOpenContext(hCtx);
698 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
699 LeaveCriticalSection(&csTablet);
701 return TRUE;
704 /***********************************************************************
705 * WTSetA (WINTAB32.62)
707 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
709 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
711 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
713 return FALSE;
716 /***********************************************************************
717 * WTSetW (WINTAB32.1062)
719 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
721 FIXME("(%p, %p): stub\n", hCtx, lpLogCtx);
723 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
725 return FALSE;
728 /***********************************************************************
729 * WTExtGet (WINTAB32.63)
731 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
733 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
735 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
737 return FALSE;
740 /***********************************************************************
741 * WTExtSet (WINTAB32.64)
743 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
745 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
747 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
749 return FALSE;
752 /***********************************************************************
753 * WTSave (WINTAB32.65)
755 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
757 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
759 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
761 return FALSE;
764 /***********************************************************************
765 * WTRestore (WINTAB32.66)
767 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
769 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
771 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
773 return 0;
776 /***********************************************************************
777 * WTPacketsPeek (WINTAB32.80)
779 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
781 int limit;
782 LPOPENCONTEXT context;
783 LPVOID ptr = lpPkts;
785 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
787 if (!hCtx || !lpPkts) return 0;
789 EnterCriticalSection(&csTablet);
791 context = TABLET_FindOpenContext(hCtx);
793 if (context->PacketsQueued == 0)
795 LeaveCriticalSection(&csTablet);
796 return 0;
799 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
800 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
802 LeaveCriticalSection(&csTablet);
803 TRACE("Copied %i packets\n",limit);
804 return limit;
807 /***********************************************************************
808 * WTDataGet (WINTAB32.81)
810 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
811 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
813 LPOPENCONTEXT context;
814 LPVOID ptr = lpPkts;
815 INT bgn = 0;
816 INT end = 0;
817 INT num = 0;
819 TRACE("(%p, %u, %u, %d, %p, %p)\n",
820 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
822 if (!hCtx) return 0;
824 EnterCriticalSection(&csTablet);
826 context = TABLET_FindOpenContext(hCtx);
828 if (context->PacketsQueued == 0)
830 LeaveCriticalSection(&csTablet);
831 return 0;
834 while (bgn < context->PacketsQueued &&
835 context->PacketQueue[bgn].pkSerialNumber != wBegin)
836 bgn++;
838 end = bgn;
839 while (end < context->PacketsQueued &&
840 context->PacketQueue[end].pkSerialNumber != wEnd)
841 end++;
843 if ((bgn == end) && (end == context->PacketsQueued))
845 LeaveCriticalSection(&csTablet);
846 return 0;
849 for (num = bgn; num <= end; num++)
850 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
852 /* remove read packets */
853 if ((end+1) < context->PacketsQueued)
854 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
855 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
857 context->PacketsQueued -= ((end-bgn)+1);
858 *lpNPkts = ((end-bgn)+1);
860 LeaveCriticalSection(&csTablet);
861 TRACE("Copied %i packets\n",*lpNPkts);
862 return (end - bgn)+1;
865 /***********************************************************************
866 * WTDataPeek (WINTAB32.82)
868 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
869 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
871 LPOPENCONTEXT context;
872 LPVOID ptr = lpPkts;
873 INT bgn = 0;
874 INT end = 0;
875 INT num = 0;
877 TRACE("(%p, %u, %u, %d, %p, %p)\n",
878 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
880 if (!hCtx || !lpPkts) return 0;
882 EnterCriticalSection(&csTablet);
884 context = TABLET_FindOpenContext(hCtx);
886 if (context->PacketsQueued == 0)
888 LeaveCriticalSection(&csTablet);
889 return 0;
892 while (bgn < context->PacketsQueued &&
893 context->PacketQueue[bgn].pkSerialNumber != wBegin)
894 bgn++;
896 end = bgn;
897 while (end < context->PacketsQueued &&
898 context->PacketQueue[end].pkSerialNumber != wEnd)
899 end++;
901 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
903 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
904 LeaveCriticalSection(&csTablet);
905 return 0;
908 for (num = bgn; num <= end; num++)
909 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
911 *lpNPkts = ((end-bgn)+1);
912 LeaveCriticalSection(&csTablet);
914 TRACE("Copied %i packets\n",*lpNPkts);
915 return (end - bgn)+1;
918 /***********************************************************************
919 * WTQueuePacketsEx (WINTAB32.200)
921 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
923 LPOPENCONTEXT context;
925 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
927 if (!hCtx) return 0;
929 EnterCriticalSection(&csTablet);
931 context = TABLET_FindOpenContext(hCtx);
933 if (context->PacketsQueued)
935 *lpOld = context->PacketQueue[0].pkSerialNumber;
936 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
938 else
940 TRACE("No packets\n");
941 LeaveCriticalSection(&csTablet);
942 return FALSE;
944 LeaveCriticalSection(&csTablet);
946 return TRUE;
949 /***********************************************************************
950 * WTQueueSizeGet (WINTAB32.84)
952 int WINAPI WTQueueSizeGet(HCTX hCtx)
954 LPOPENCONTEXT context;
955 TRACE("(%p)\n", hCtx);
957 if (!hCtx) return 0;
959 EnterCriticalSection(&csTablet);
960 context = TABLET_FindOpenContext(hCtx);
961 LeaveCriticalSection(&csTablet);
962 return context->QueueSize;
965 /***********************************************************************
966 * WTQueueSizeSet (WINTAB32.85)
968 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
970 LPOPENCONTEXT context;
972 TRACE("(%p, %d)\n", hCtx, nPkts);
974 if (!hCtx) return 0;
976 EnterCriticalSection(&csTablet);
978 context = TABLET_FindOpenContext(hCtx);
980 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
981 context->PacketQueue, sizeof(WTPACKET)*nPkts);
983 context->QueueSize = nPkts;
984 LeaveCriticalSection(&csTablet);
986 return nPkts;