winebuild: Generate MS-style imports using the OriginalFirstThunk field.
[wine.git] / dlls / wintab32 / context.c
blob9551d8787f17d4849703f1b1474d09e9262aa007
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\n",
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, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
162 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
163 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
164 else
165 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
168 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
170 LPOPENCONTEXT ptr=NULL;
172 EnterCriticalSection(&csTablet);
174 ptr = gOpenContexts;
175 while (ptr)
177 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
179 if (ptr->hwndOwner == hwnd)
181 int tgt;
182 if (!ptr->enabled)
184 ptr = ptr->next;
185 continue;
188 tgt = ptr->PacketsQueued;
190 packet->pkContext = ptr->handle;
192 /* translate packet data to the context */
194 /* Scale as per documentation */
195 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
196 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
197 ptr->context.lcOutExtY);
199 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
200 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
201 ptr->context.lcOutExtX);
203 /* flip the Y axis */
204 if (ptr->context.lcOutExtY > 0)
205 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
207 DUMPPACKET(*packet);
209 if (tgt == ptr->QueueSize)
211 TRACE("Queue Overflow %p\n",ptr->handle);
212 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
214 else
216 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
217 ptr->PacketQueue[tgt] = *packet;
218 ptr->PacketsQueued++;
220 if (ptr->ActiveCursor != packet->pkCursor)
222 ptr->ActiveCursor = packet->pkCursor;
223 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
224 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
225 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
226 FALSE);
229 break;
231 ptr = ptr->next;
233 LeaveCriticalSection(&csTablet);
234 TRACE("Done (%p)\n",ptr);
235 return ptr;
239 * Flushes all packets from the queue.
241 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
243 context->PacketsQueued = 0;
246 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
248 memcpy(target,src,size);
249 return(size);
252 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
253 LPWTPACKET *pkt)
255 int loop;
256 int index = -1;
257 for (loop = 0; loop < context->PacketsQueued; loop++)
258 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
260 index = loop;
261 *pkt = &context->PacketQueue[loop];
262 break;
265 TRACE("%i .. %i\n",context->PacketsQueued,index);
267 return index;
271 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
272 LPWTPACKET wtp)
274 LPBYTE ptr;
276 ptr = lpPkt;
277 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
279 if (context->context.lcPktData & PK_CONTEXT)
280 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
281 if (context->context.lcPktData & PK_STATUS)
282 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
283 if (context->context.lcPktData & PK_TIME)
284 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
285 if (context->context.lcPktData & PK_CHANGED)
286 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
287 if (context->context.lcPktData & PK_SERIAL_NUMBER)
288 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
289 if (context->context.lcPktData & PK_CURSOR)
290 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
291 if (context->context.lcPktData & PK_BUTTONS)
292 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
293 if (context->context.lcPktData & PK_X)
294 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
295 if (context->context.lcPktData & PK_Y)
296 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
297 if (context->context.lcPktData & PK_Z)
298 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
299 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
300 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
301 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
302 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
303 if (context->context.lcPktData & PK_ORIENTATION)
304 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
305 if (context->context.lcPktData & PK_ROTATION)
306 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
308 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
309 return ptr;
312 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
314 int rc = 0;
316 if (context->context.lcPktData & PK_CONTEXT)
317 rc +=sizeof(HCTX);
318 if (context->context.lcPktData & PK_STATUS)
319 rc +=sizeof(UINT);
320 if (context->context.lcPktData & PK_TIME)
321 rc += sizeof(LONG);
322 if (context->context.lcPktData & PK_CHANGED)
323 rc += sizeof(WTPKT);
324 if (context->context.lcPktData & PK_SERIAL_NUMBER)
325 rc += sizeof(UINT);
326 if (context->context.lcPktData & PK_CURSOR)
327 rc += sizeof(UINT);
328 if (context->context.lcPktData & PK_BUTTONS)
329 rc += sizeof(DWORD);
330 if (context->context.lcPktData & PK_X)
331 rc += sizeof(DWORD);
332 if (context->context.lcPktData & PK_Y)
333 rc += sizeof(DWORD);
334 if (context->context.lcPktData & PK_Z)
335 rc += sizeof(DWORD);
336 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
337 rc += sizeof(UINT);
338 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
339 rc += sizeof(UINT);
340 if (context->context.lcPktData & PK_ORIENTATION)
341 rc += sizeof(ORIENTATION);
342 if (context->context.lcPktData & PK_ROTATION)
343 rc += sizeof(ROTATION);
345 rc *= n;
346 memset(lpPkt,0,rc);
350 UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
352 UINT result;
354 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
355 if (gLoaded == FALSE)
356 LoadTablet();
359 * Handle system extents here, as we can use user32.dll code to set them.
361 if(wCategory == WTI_DEFSYSCTX)
363 switch(nIndex)
365 case CTX_SYSEXTX:
366 if(lpOutput != NULL)
367 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
368 return sizeof(LONG);
369 case CTX_SYSEXTY:
370 if(lpOutput != NULL)
371 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
372 return sizeof(LONG);
373 /* No action, delegate to X11Drv */
377 if (is_logcontext_category(wCategory) && nIndex == 0)
379 if (lpOutput)
381 LOGCONTEXTW buf;
382 pWTInfoW(wCategory, nIndex, &buf);
384 /* Handle system extents here, as we can use user32.dll code to set them */
385 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
387 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
388 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
391 if (bUnicode)
392 memcpy(lpOutput, &buf, sizeof(buf));
393 else
394 LOGCONTEXTWtoA(&buf, lpOutput);
397 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
399 else if (is_string_field(wCategory, nIndex) && !bUnicode)
401 int size = pWTInfoW(wCategory, nIndex, NULL);
402 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
403 pWTInfoW(wCategory, nIndex, buf);
404 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
405 HeapFree(GetProcessHeap(), 0, buf);
407 else
408 result = pWTInfoW(wCategory, nIndex, lpOutput);
410 TRACE("returns %d\n", result);
411 return result;
414 /***********************************************************************
415 * WTInfoA (WINTAB32.20)
417 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
419 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
423 /***********************************************************************
424 * WTInfoW (WINTAB32.1020)
426 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
428 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
431 /***********************************************************************
432 * WTOpenW (WINTAB32.2021)
434 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
436 LPOPENCONTEXT newcontext;
438 TRACE("(%p, %p, %u)\n", hWnd, lpLogCtx, fEnable);
439 DUMPCONTEXT(*lpLogCtx);
441 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
442 newcontext->context = *lpLogCtx;
443 newcontext->hwndOwner = hWnd;
444 newcontext->enabled = fEnable;
445 newcontext->ActiveCursor = -1;
446 newcontext->QueueSize = 10;
447 newcontext->PacketsQueued = 0;
448 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
450 EnterCriticalSection(&csTablet);
451 newcontext->handle = gTopContext++;
452 newcontext->next = gOpenContexts;
453 gOpenContexts = newcontext;
454 LeaveCriticalSection(&csTablet);
456 pAttachEventQueueToTablet(hWnd);
458 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
459 newcontext->context.lcStatus, TRUE);
461 newcontext->context.lcStatus = CXS_ONTOP;
463 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
464 (WPARAM)newcontext->handle,
465 newcontext->context.lcStatus, TRUE);
467 return newcontext->handle;
470 /***********************************************************************
471 * WTOpenA (WINTAB32.21)
473 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
475 LOGCONTEXTW logCtxW;
477 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
478 return WTOpenW(hWnd, &logCtxW, fEnable);
481 /***********************************************************************
482 * WTClose (WINTAB32.22)
484 BOOL WINAPI WTClose(HCTX hCtx)
486 LPOPENCONTEXT context,ptr;
488 TRACE("(%p)\n", hCtx);
490 EnterCriticalSection(&csTablet);
492 ptr = context = gOpenContexts;
494 while (context && (context->handle != hCtx))
496 ptr = context;
497 context = context->next;
499 if (!context)
501 LeaveCriticalSection(&csTablet);
502 return TRUE;
505 if (context == gOpenContexts)
506 gOpenContexts = context->next;
507 else
508 ptr->next = context->next;
510 LeaveCriticalSection(&csTablet);
512 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
513 context->context.lcStatus,TRUE);
515 HeapFree(GetProcessHeap(),0,context->PacketQueue);
516 HeapFree(GetProcessHeap(),0,context);
518 return TRUE;
521 /***********************************************************************
522 * WTPacketsGet (WINTAB32.23)
524 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
526 int limit;
527 LPOPENCONTEXT context;
528 LPVOID ptr = lpPkts;
530 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
532 if (!hCtx)
533 return 0;
535 EnterCriticalSection(&csTablet);
537 context = TABLET_FindOpenContext(hCtx);
539 if (lpPkts != NULL)
540 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
542 if (context->PacketsQueued == 0)
544 LeaveCriticalSection(&csTablet);
545 return 0;
548 limit = min(cMaxPkts,context->PacketsQueued);
550 if(ptr != NULL)
552 int i = 0;
553 for(i = 0; i < limit; i++)
554 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
558 if (limit < context->PacketsQueued)
560 memmove(context->PacketQueue, &context->PacketQueue[limit],
561 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
563 context->PacketsQueued -= limit;
564 LeaveCriticalSection(&csTablet);
566 TRACE("Copied %i packets\n",limit);
568 return limit;
571 /***********************************************************************
572 * WTPacket (WINTAB32.24)
574 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
576 int rc = 0;
577 LPOPENCONTEXT context;
578 LPWTPACKET wtp = NULL;
580 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
582 if (!hCtx)
583 return 0;
585 EnterCriticalSection(&csTablet);
587 context = TABLET_FindOpenContext(hCtx);
589 rc = TABLET_FindPacket(context ,wSerial, &wtp);
591 if (rc >= 0)
593 if (lpPkt)
594 TABLET_CopyPacketData(context ,lpPkt, wtp);
596 if ((rc+1) < context->QueueSize)
598 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
599 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
601 context->PacketsQueued -= (rc+1);
603 LeaveCriticalSection(&csTablet);
605 TRACE("Returning %i\n",rc+1);
606 return rc+1;
609 /***********************************************************************
610 * WTEnable (WINTAB32.40)
612 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
614 LPOPENCONTEXT context;
616 TRACE("(%p, %u)\n", hCtx, fEnable);
618 if (!hCtx) return 0;
620 EnterCriticalSection(&csTablet);
621 context = TABLET_FindOpenContext(hCtx);
622 if(!fEnable)
623 TABLET_FlushQueue(context);
624 context->enabled = fEnable;
625 LeaveCriticalSection(&csTablet);
627 return TRUE;
630 /***********************************************************************
631 * WTOverlap (WINTAB32.41)
633 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
635 FIXME("(%p, %u): stub\n", hCtx, fToTop);
637 return TRUE;
640 /***********************************************************************
641 * WTConfig (WINTAB32.61)
643 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
645 FIXME("(%p, %p): stub\n", hCtx, hWnd);
647 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
649 return FALSE;
652 /***********************************************************************
653 * WTGetA (WINTAB32.61)
655 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
657 LPOPENCONTEXT context;
659 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
661 if (!hCtx) return 0;
663 EnterCriticalSection(&csTablet);
664 context = TABLET_FindOpenContext(hCtx);
665 LOGCONTEXTWtoA(&context->context, lpLogCtx);
666 LeaveCriticalSection(&csTablet);
668 return TRUE;
671 /***********************************************************************
672 * WTGetW (WINTAB32.1061)
674 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
676 LPOPENCONTEXT context;
678 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
680 if (!hCtx) return 0;
682 EnterCriticalSection(&csTablet);
683 context = TABLET_FindOpenContext(hCtx);
684 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
685 LeaveCriticalSection(&csTablet);
687 return TRUE;
690 /***********************************************************************
691 * WTSetA (WINTAB32.62)
693 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
695 LPOPENCONTEXT context;
697 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
699 if (!hCtx || !lpLogCtx) return FALSE;
701 /* TODO: if cur process not owner of hCtx only modify
702 * attribs not locked by owner */
704 EnterCriticalSection(&csTablet);
705 context = TABLET_FindOpenContext(hCtx);
706 LOGCONTEXTAtoW(lpLogCtx, &context->context);
707 LeaveCriticalSection(&csTablet);
709 return TRUE;
712 /***********************************************************************
713 * WTSetW (WINTAB32.1062)
715 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
717 LPOPENCONTEXT context;
719 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
721 if (!hCtx || !lpLogCtx) return FALSE;
723 /* TODO: if cur process not hCtx owner only modify
724 * attribs not locked by owner */
726 EnterCriticalSection(&csTablet);
727 context = TABLET_FindOpenContext(hCtx);
728 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
729 LeaveCriticalSection(&csTablet);
731 return TRUE;
734 /***********************************************************************
735 * WTExtGet (WINTAB32.63)
737 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
739 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
741 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
743 return FALSE;
746 /***********************************************************************
747 * WTExtSet (WINTAB32.64)
749 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
751 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
753 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
755 return FALSE;
758 /***********************************************************************
759 * WTSave (WINTAB32.65)
761 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
763 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
765 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
767 return FALSE;
770 /***********************************************************************
771 * WTRestore (WINTAB32.66)
773 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
775 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
777 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
779 return 0;
782 /***********************************************************************
783 * WTPacketsPeek (WINTAB32.80)
785 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
787 int limit;
788 LPOPENCONTEXT context;
789 LPVOID ptr = lpPkts;
791 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
793 if (!hCtx || !lpPkts) return 0;
795 EnterCriticalSection(&csTablet);
797 context = TABLET_FindOpenContext(hCtx);
799 if (context->PacketsQueued == 0)
801 LeaveCriticalSection(&csTablet);
802 return 0;
805 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
806 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
808 LeaveCriticalSection(&csTablet);
809 TRACE("Copied %i packets\n",limit);
810 return limit;
813 /***********************************************************************
814 * WTDataGet (WINTAB32.81)
816 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
817 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
819 LPOPENCONTEXT context;
820 LPVOID ptr = lpPkts;
821 INT bgn = 0;
822 INT end = 0;
823 INT num = 0;
825 TRACE("(%p, %u, %u, %d, %p, %p)\n",
826 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
828 if (!hCtx) return 0;
830 EnterCriticalSection(&csTablet);
832 context = TABLET_FindOpenContext(hCtx);
834 if (context->PacketsQueued == 0)
836 LeaveCriticalSection(&csTablet);
837 return 0;
840 while (bgn < context->PacketsQueued &&
841 context->PacketQueue[bgn].pkSerialNumber != wBegin)
842 bgn++;
844 end = bgn;
845 while (end < context->PacketsQueued &&
846 context->PacketQueue[end].pkSerialNumber != wEnd)
847 end++;
849 if ((bgn == end) && (end == context->PacketsQueued))
851 LeaveCriticalSection(&csTablet);
852 return 0;
855 for (num = bgn; num <= end; num++)
856 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
858 /* remove read packets */
859 if ((end+1) < context->PacketsQueued)
860 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
861 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
863 context->PacketsQueued -= ((end-bgn)+1);
864 *lpNPkts = ((end-bgn)+1);
866 LeaveCriticalSection(&csTablet);
867 TRACE("Copied %i packets\n",*lpNPkts);
868 return (end - bgn)+1;
871 /***********************************************************************
872 * WTDataPeek (WINTAB32.82)
874 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
875 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
877 LPOPENCONTEXT context;
878 LPVOID ptr = lpPkts;
879 INT bgn = 0;
880 INT end = 0;
881 INT num = 0;
883 TRACE("(%p, %u, %u, %d, %p, %p)\n",
884 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
886 if (!hCtx || !lpPkts) return 0;
888 EnterCriticalSection(&csTablet);
890 context = TABLET_FindOpenContext(hCtx);
892 if (context->PacketsQueued == 0)
894 LeaveCriticalSection(&csTablet);
895 return 0;
898 while (bgn < context->PacketsQueued &&
899 context->PacketQueue[bgn].pkSerialNumber != wBegin)
900 bgn++;
902 end = bgn;
903 while (end < context->PacketsQueued &&
904 context->PacketQueue[end].pkSerialNumber != wEnd)
905 end++;
907 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
909 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
910 LeaveCriticalSection(&csTablet);
911 return 0;
914 for (num = bgn; num <= end; num++)
915 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
917 *lpNPkts = ((end-bgn)+1);
918 LeaveCriticalSection(&csTablet);
920 TRACE("Copied %i packets\n",*lpNPkts);
921 return (end - bgn)+1;
924 /***********************************************************************
925 * WTQueuePacketsEx (WINTAB32.200)
927 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
929 LPOPENCONTEXT context;
931 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
933 if (!hCtx) return 0;
935 EnterCriticalSection(&csTablet);
937 context = TABLET_FindOpenContext(hCtx);
939 if (context->PacketsQueued)
941 *lpOld = context->PacketQueue[0].pkSerialNumber;
942 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
944 else
946 TRACE("No packets\n");
947 LeaveCriticalSection(&csTablet);
948 return FALSE;
950 LeaveCriticalSection(&csTablet);
952 return TRUE;
955 /***********************************************************************
956 * WTQueueSizeGet (WINTAB32.84)
958 int WINAPI WTQueueSizeGet(HCTX hCtx)
960 LPOPENCONTEXT context;
961 TRACE("(%p)\n", hCtx);
963 if (!hCtx) return 0;
965 EnterCriticalSection(&csTablet);
966 context = TABLET_FindOpenContext(hCtx);
967 LeaveCriticalSection(&csTablet);
968 return context->QueueSize;
971 /***********************************************************************
972 * WTQueueSizeSet (WINTAB32.85)
974 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
976 LPOPENCONTEXT context;
978 TRACE("(%p, %d)\n", hCtx, nPkts);
980 if (!hCtx) return 0;
982 EnterCriticalSection(&csTablet);
984 context = TABLET_FindOpenContext(hCtx);
986 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
987 context->PacketQueue, sizeof(WTPACKET)*nPkts);
989 context->QueueSize = nPkts;
990 LeaveCriticalSection(&csTablet);
992 return nPkts;