push 8edcbf8579c1d48dd3fb4c679acf4b3012a9efac
[wine/hacks.git] / dlls / wintab32 / context.c
blob9b1da185a3284ca4eda1ba8a69dbb5a4b0dab4e5
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("hWnd=%p, lpLogCtx=%p, fEnable=%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->ActiveCursor = -1;
445 newcontext->QueueSize = 10;
446 newcontext->PacketsQueued = 0;
447 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
449 EnterCriticalSection(&csTablet);
450 newcontext->handle = gTopContext++;
451 newcontext->next = gOpenContexts;
452 gOpenContexts = newcontext;
453 LeaveCriticalSection(&csTablet);
455 pAttachEventQueueToTablet(hWnd);
457 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
458 newcontext->context.lcStatus, TRUE);
460 if (fEnable)
462 newcontext->enabled = TRUE;
463 /* TODO: Add to top of overlap order */
464 newcontext->context.lcStatus = CXS_ONTOP;
466 else
468 newcontext->enabled = FALSE;
469 newcontext->context.lcStatus = CXS_DISABLED;
472 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
473 (WPARAM)newcontext->handle,
474 newcontext->context.lcStatus, TRUE);
476 return newcontext->handle;
479 /***********************************************************************
480 * WTOpenA (WINTAB32.21)
482 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
484 LOGCONTEXTW logCtxW;
486 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
487 return WTOpenW(hWnd, &logCtxW, fEnable);
490 /***********************************************************************
491 * WTClose (WINTAB32.22)
493 BOOL WINAPI WTClose(HCTX hCtx)
495 LPOPENCONTEXT context,ptr;
497 TRACE("(%p)\n", hCtx);
499 EnterCriticalSection(&csTablet);
501 ptr = context = gOpenContexts;
503 while (context && (context->handle != hCtx))
505 ptr = context;
506 context = context->next;
508 if (!context)
510 LeaveCriticalSection(&csTablet);
511 return TRUE;
514 if (context == gOpenContexts)
515 gOpenContexts = context->next;
516 else
517 ptr->next = context->next;
519 LeaveCriticalSection(&csTablet);
521 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
522 context->context.lcStatus,TRUE);
524 HeapFree(GetProcessHeap(),0,context->PacketQueue);
525 HeapFree(GetProcessHeap(),0,context);
527 return TRUE;
530 /***********************************************************************
531 * WTPacketsGet (WINTAB32.23)
533 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
535 int limit;
536 LPOPENCONTEXT context;
537 LPVOID ptr = lpPkts;
539 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
541 if (!hCtx)
542 return 0;
544 EnterCriticalSection(&csTablet);
546 context = TABLET_FindOpenContext(hCtx);
548 if (lpPkts != NULL)
549 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
551 if (context->PacketsQueued == 0)
553 LeaveCriticalSection(&csTablet);
554 return 0;
557 limit = min(cMaxPkts,context->PacketsQueued);
559 if(ptr != NULL)
561 int i = 0;
562 for(i = 0; i < limit; i++)
563 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
567 if (limit < context->PacketsQueued)
569 memmove(context->PacketQueue, &context->PacketQueue[limit],
570 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
572 context->PacketsQueued -= limit;
573 LeaveCriticalSection(&csTablet);
575 TRACE("Copied %i packets\n",limit);
577 return limit;
580 /***********************************************************************
581 * WTPacket (WINTAB32.24)
583 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
585 int rc = 0;
586 LPOPENCONTEXT context;
587 LPWTPACKET wtp = NULL;
589 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
591 if (!hCtx)
592 return 0;
594 EnterCriticalSection(&csTablet);
596 context = TABLET_FindOpenContext(hCtx);
598 rc = TABLET_FindPacket(context ,wSerial, &wtp);
600 if (rc >= 0)
602 if (lpPkt)
603 TABLET_CopyPacketData(context ,lpPkt, wtp);
605 if ((rc+1) < context->QueueSize)
607 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
608 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
610 context->PacketsQueued -= (rc+1);
612 LeaveCriticalSection(&csTablet);
614 TRACE("Returning %i\n",rc+1);
615 return rc+1;
618 /***********************************************************************
619 * WTEnable (WINTAB32.40)
621 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
623 LPOPENCONTEXT context;
625 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
627 if (!hCtx) return FALSE;
629 EnterCriticalSection(&csTablet);
630 context = TABLET_FindOpenContext(hCtx);
631 /* if we want to enable and it is not enabled then */
632 if(fEnable && !context->enabled)
634 context->enabled = TRUE;
635 /* TODO: Add to top of overlap order */
636 context->context.lcStatus = CXS_ONTOP;
638 /* if we want to disable and it is not disabled then */
639 else if (!fEnable && context->enabled)
641 context->enabled = FALSE;
642 /* TODO: Remove from overlap order?? needs a test */
643 context->context.lcStatus = CXS_DISABLED;
644 TABLET_FlushQueue(context);
646 LeaveCriticalSection(&csTablet);
648 return TRUE;
651 /***********************************************************************
652 * WTOverlap (WINTAB32.41)
654 * Move context to top or bottom of overlap order
656 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
658 LPOPENCONTEXT context;
660 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
662 if (!hCtx) return FALSE;
664 EnterCriticalSection(&csTablet);
665 context = TABLET_FindOpenContext(hCtx);
666 if (fToTop)
668 /* TODO: Move context to top of overlap order */
669 FIXME("Not moving context to top of overlap order\n");
670 context->context.lcStatus = CXS_ONTOP;
672 else
674 /* TODO: Move context to bottom of overlap order */
675 FIXME("Not moving context to bottom of overlap order\n");
676 context->context.lcStatus = CXS_OBSCURED;
678 LeaveCriticalSection(&csTablet);
680 return TRUE;
683 /***********************************************************************
684 * WTConfig (WINTAB32.61)
686 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
688 FIXME("(%p, %p): stub\n", hCtx, hWnd);
690 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
692 return FALSE;
695 /***********************************************************************
696 * WTGetA (WINTAB32.61)
698 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
700 LPOPENCONTEXT context;
702 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
704 if (!hCtx) return 0;
706 EnterCriticalSection(&csTablet);
707 context = TABLET_FindOpenContext(hCtx);
708 LOGCONTEXTWtoA(&context->context, lpLogCtx);
709 LeaveCriticalSection(&csTablet);
711 return TRUE;
714 /***********************************************************************
715 * WTGetW (WINTAB32.1061)
717 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
719 LPOPENCONTEXT context;
721 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
723 if (!hCtx) return 0;
725 EnterCriticalSection(&csTablet);
726 context = TABLET_FindOpenContext(hCtx);
727 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
728 LeaveCriticalSection(&csTablet);
730 return TRUE;
733 /***********************************************************************
734 * WTSetA (WINTAB32.62)
736 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
738 LPOPENCONTEXT context;
740 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
742 if (!hCtx || !lpLogCtx) return FALSE;
744 /* TODO: if cur process not owner of hCtx only modify
745 * attribs not locked by owner */
747 EnterCriticalSection(&csTablet);
748 context = TABLET_FindOpenContext(hCtx);
749 LOGCONTEXTAtoW(lpLogCtx, &context->context);
750 LeaveCriticalSection(&csTablet);
752 return TRUE;
755 /***********************************************************************
756 * WTSetW (WINTAB32.1062)
758 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
760 LPOPENCONTEXT context;
762 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
764 if (!hCtx || !lpLogCtx) return FALSE;
766 /* TODO: if cur process not hCtx owner only modify
767 * attribs not locked by owner */
769 EnterCriticalSection(&csTablet);
770 context = TABLET_FindOpenContext(hCtx);
771 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
772 LeaveCriticalSection(&csTablet);
774 return TRUE;
777 /***********************************************************************
778 * WTExtGet (WINTAB32.63)
780 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
782 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
784 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
786 return FALSE;
789 /***********************************************************************
790 * WTExtSet (WINTAB32.64)
792 BOOL WINAPI WTExtSet(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 * WTSave (WINTAB32.65)
804 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
806 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
808 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
810 return FALSE;
813 /***********************************************************************
814 * WTRestore (WINTAB32.66)
816 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
818 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
820 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
822 return 0;
825 /***********************************************************************
826 * WTPacketsPeek (WINTAB32.80)
828 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
830 int limit;
831 LPOPENCONTEXT context;
832 LPVOID ptr = lpPkts;
834 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
836 if (!hCtx || !lpPkts) return 0;
838 EnterCriticalSection(&csTablet);
840 context = TABLET_FindOpenContext(hCtx);
842 if (context->PacketsQueued == 0)
844 LeaveCriticalSection(&csTablet);
845 return 0;
848 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
849 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
851 LeaveCriticalSection(&csTablet);
852 TRACE("Copied %i packets\n",limit);
853 return limit;
856 /***********************************************************************
857 * WTDataGet (WINTAB32.81)
859 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
860 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
862 LPOPENCONTEXT context;
863 LPVOID ptr = lpPkts;
864 INT bgn = 0;
865 INT end = 0;
866 INT num = 0;
868 TRACE("(%p, %u, %u, %d, %p, %p)\n",
869 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
871 if (!hCtx) return 0;
873 EnterCriticalSection(&csTablet);
875 context = TABLET_FindOpenContext(hCtx);
877 if (context->PacketsQueued == 0)
879 LeaveCriticalSection(&csTablet);
880 return 0;
883 while (bgn < context->PacketsQueued &&
884 context->PacketQueue[bgn].pkSerialNumber != wBegin)
885 bgn++;
887 end = bgn;
888 while (end < context->PacketsQueued &&
889 context->PacketQueue[end].pkSerialNumber != wEnd)
890 end++;
892 if ((bgn == end) && (end == context->PacketsQueued))
894 LeaveCriticalSection(&csTablet);
895 return 0;
898 for (num = bgn; num <= end; num++)
899 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
901 /* remove read packets */
902 if ((end+1) < context->PacketsQueued)
903 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
904 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
906 context->PacketsQueued -= ((end-bgn)+1);
907 *lpNPkts = ((end-bgn)+1);
909 LeaveCriticalSection(&csTablet);
910 TRACE("Copied %i packets\n",*lpNPkts);
911 return (end - bgn)+1;
914 /***********************************************************************
915 * WTDataPeek (WINTAB32.82)
917 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
918 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
920 LPOPENCONTEXT context;
921 LPVOID ptr = lpPkts;
922 INT bgn = 0;
923 INT end = 0;
924 INT num = 0;
926 TRACE("(%p, %u, %u, %d, %p, %p)\n",
927 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
929 if (!hCtx || !lpPkts) return 0;
931 EnterCriticalSection(&csTablet);
933 context = TABLET_FindOpenContext(hCtx);
935 if (context->PacketsQueued == 0)
937 LeaveCriticalSection(&csTablet);
938 return 0;
941 while (bgn < context->PacketsQueued &&
942 context->PacketQueue[bgn].pkSerialNumber != wBegin)
943 bgn++;
945 end = bgn;
946 while (end < context->PacketsQueued &&
947 context->PacketQueue[end].pkSerialNumber != wEnd)
948 end++;
950 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
952 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
953 LeaveCriticalSection(&csTablet);
954 return 0;
957 for (num = bgn; num <= end; num++)
958 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
960 *lpNPkts = ((end-bgn)+1);
961 LeaveCriticalSection(&csTablet);
963 TRACE("Copied %i packets\n",*lpNPkts);
964 return (end - bgn)+1;
967 /***********************************************************************
968 * WTQueuePacketsEx (WINTAB32.200)
970 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
972 LPOPENCONTEXT context;
974 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
976 if (!hCtx) return 0;
978 EnterCriticalSection(&csTablet);
980 context = TABLET_FindOpenContext(hCtx);
982 if (context->PacketsQueued)
984 *lpOld = context->PacketQueue[0].pkSerialNumber;
985 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
987 else
989 TRACE("No packets\n");
990 LeaveCriticalSection(&csTablet);
991 return FALSE;
993 LeaveCriticalSection(&csTablet);
995 return TRUE;
998 /***********************************************************************
999 * WTQueueSizeGet (WINTAB32.84)
1001 int WINAPI WTQueueSizeGet(HCTX hCtx)
1003 LPOPENCONTEXT context;
1004 TRACE("(%p)\n", hCtx);
1006 if (!hCtx) return 0;
1008 EnterCriticalSection(&csTablet);
1009 context = TABLET_FindOpenContext(hCtx);
1010 LeaveCriticalSection(&csTablet);
1011 return context->QueueSize;
1014 /***********************************************************************
1015 * WTQueueSizeSet (WINTAB32.85)
1017 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1019 LPOPENCONTEXT context;
1021 TRACE("(%p, %d)\n", hCtx, nPkts);
1023 if (!hCtx) return 0;
1025 EnterCriticalSection(&csTablet);
1027 context = TABLET_FindOpenContext(hCtx);
1029 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1030 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1032 context->QueueSize = nPkts;
1033 LeaveCriticalSection(&csTablet);
1035 return nPkts;