wintab32: Change the LoadTabletInfo failure message from ERR to TRACE.
[wine.git] / dlls / wintab32 / context.c
blob2993c4707e712fa988e3c41bd8dfc19c0c9a0f5d
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 LPOPENCONTEXT gOpenContexts;
46 static HCTX gTopContext = (HCTX)0xc00;
48 static void LOGCONTEXTAtoW(const LOGCONTEXTA *in, LOGCONTEXTW *out)
50 MultiByteToWideChar(CP_ACP, 0, in->lcName, -1, out->lcName, LCNAMELEN);
51 out->lcName[LCNAMELEN - 1] = 0;
52 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
53 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTA) - FIELD_OFFSET(LOGCONTEXTA, lcOptions));
56 static void LOGCONTEXTWtoA(const LOGCONTEXTW *in, LOGCONTEXTA *out)
58 WideCharToMultiByte(CP_ACP, 0, in->lcName, LCNAMELEN, out->lcName, LCNAMELEN, NULL, NULL);
59 out->lcName[LCNAMELEN - 1] = 0;
60 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
61 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTW) - FIELD_OFFSET(LOGCONTEXTW, lcOptions));
64 static BOOL is_logcontext_category(UINT wCategory)
66 return wCategory == WTI_DEFSYSCTX || wCategory == WTI_DEFCONTEXT || wCategory == WTI_DDCTXS;
69 static BOOL is_string_field(UINT wCategory, UINT nIndex)
71 if (wCategory == WTI_INTERFACE && nIndex == IFC_WINTABID)
72 return TRUE;
73 if (is_logcontext_category(wCategory) && nIndex == CTX_NAME)
74 return TRUE;
75 if ((wCategory >= WTI_CURSORS && wCategory <= WTI_CURSORS + 9) &&
76 (nIndex == CSR_NAME || nIndex == CSR_BTNNAMES))
77 return TRUE;
78 if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID))
79 return TRUE;
80 return FALSE;
83 static const char* DUMPBITS(int x)
85 char buf[200];
86 buf[0] = 0;
87 if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
88 if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
89 if (x&PK_TIME) strcat(buf, "PK_TIME ");
90 if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
91 if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
92 if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
93 if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
94 if (x&PK_X) strcat(buf, "PK_X ");
95 if (x&PK_Y) strcat(buf, "PK_Y ");
96 if (x&PK_Z) strcat(buf, "PK_Z ");
97 if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
98 if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
99 if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
100 if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
101 return wine_dbg_sprintf("{%s}",buf);
104 static inline void DUMPPACKET(WTPACKET packet)
106 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",
107 packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber,
108 packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ,
109 packet.pkNormalPressure, packet.pkTangentPressure,
110 packet.pkOrientation.orAzimuth, packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
111 packet.pkRotation.roPitch, packet.pkRotation.roRoll, packet.pkRotation.roYaw);
114 static inline void DUMPCONTEXT(LOGCONTEXTW lc)
116 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, "
117 "Device: %x, PktRate: %x, "
118 "%x%s, %x%s, %x%s, "
119 "BtnDnMask: %x, BtnUpMask: %x, "
120 "InOrgX: %i, InOrgY: %i, InOrgZ: %i, "
121 "InExtX: %i, InExtY: %i, InExtZ: %i, "
122 "OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i, "
123 "OutExtX: %i, OutExtY: %i, OutExtZ: %i, "
124 "SensX: %i, SensY: %i, SensZ: %i, "
125 "SysMode: %i, "
126 "SysOrgX: %i, SysOrgY: %i, "
127 "SysExtX: %i, SysExtY: %i, "
128 "SysSensX: %i, SysSensY: %i\n",
129 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
130 lc.lcDevice, lc.lcPktRate, lc.lcPktData, DUMPBITS(lc.lcPktData),
131 lc.lcPktMode, DUMPBITS(lc.lcPktMode), lc.lcMoveMask,
132 DUMPBITS(lc.lcMoveMask), lc.lcBtnDnMask, lc.lcBtnUpMask,
133 lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
134 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
135 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
136 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
137 lc.lcSysSensY);
141 /* Find an open context given the handle */
142 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
144 LPOPENCONTEXT ptr = gOpenContexts;
145 while (ptr)
147 if (ptr->handle == hCtx) return ptr;
148 ptr = ptr->next;
150 return NULL;
153 static inline BOOL LoadTablet(void)
155 static enum {TI_START = 0, TI_OK, TI_FAIL} loaded = TI_START;
157 if (loaded == TI_START)
159 if (pLoadTabletInfo && pLoadTabletInfo(hwndDefault))
161 TRACE("Initialized the tablet to hwnd %p\n", hwndDefault);
162 loaded = TI_OK;
164 else
166 TRACE("Failed to initialize the tablet to hwnd %p\n", hwndDefault);
167 loaded = TI_FAIL;
171 return loaded == TI_OK;
174 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
175 LPARAM lParam, BOOL send_always)
177 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
179 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
180 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
182 return 0;
185 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
187 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
188 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
189 else
190 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
193 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
195 LPOPENCONTEXT ptr=NULL;
197 EnterCriticalSection(&csTablet);
199 ptr = gOpenContexts;
200 while (ptr)
202 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
204 if (ptr->hwndOwner == hwnd)
206 int tgt;
207 if (!ptr->enabled)
209 ptr = ptr->next;
210 continue;
213 tgt = ptr->PacketsQueued;
215 packet->pkContext = ptr->handle;
217 /* translate packet data to the context */
219 /* Scale as per documentation */
220 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
221 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
222 ptr->context.lcOutExtY);
224 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
225 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
226 ptr->context.lcOutExtX);
228 /* flip the Y axis */
229 if (ptr->context.lcOutExtY > 0)
230 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
231 else if (ptr->context.lcOutExtY < 0)
232 packet->pkY = abs(ptr->context.lcOutExtY + packet->pkY);
234 DUMPPACKET(*packet);
236 if (tgt == ptr->QueueSize)
238 TRACE("Queue Overflow %p\n",ptr->handle);
239 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
241 else
243 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
244 ptr->PacketQueue[tgt] = *packet;
245 ptr->PacketsQueued++;
247 if (ptr->ActiveCursor != packet->pkCursor)
249 ptr->ActiveCursor = packet->pkCursor;
250 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
251 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
252 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
253 FALSE);
256 break;
258 ptr = ptr->next;
260 LeaveCriticalSection(&csTablet);
261 TRACE("Done (%p)\n",ptr);
262 return ptr;
266 * Flushes all packets from the queue.
268 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
270 context->PacketsQueued = 0;
273 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
275 memcpy(target,src,size);
276 return(size);
279 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
280 LPWTPACKET *pkt)
282 int loop;
283 int index = -1;
284 for (loop = 0; loop < context->PacketsQueued; loop++)
285 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
287 index = loop;
288 *pkt = &context->PacketQueue[loop];
289 break;
292 TRACE("%i .. %i\n",context->PacketsQueued,index);
294 return index;
298 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
299 LPWTPACKET wtp)
301 LPBYTE ptr;
303 ptr = lpPkt;
304 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
306 if (context->context.lcPktData & PK_CONTEXT)
307 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
308 if (context->context.lcPktData & PK_STATUS)
309 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
310 if (context->context.lcPktData & PK_TIME)
311 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
312 if (context->context.lcPktData & PK_CHANGED)
313 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
314 if (context->context.lcPktData & PK_SERIAL_NUMBER)
315 ptr+=CopyTabletData(ptr,&wtp->pkSerialNumber,sizeof(UINT));
316 if (context->context.lcPktData & PK_CURSOR)
317 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
318 if (context->context.lcPktData & PK_BUTTONS)
319 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
320 if (context->context.lcPktData & PK_X)
321 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
322 if (context->context.lcPktData & PK_Y)
323 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
324 if (context->context.lcPktData & PK_Z)
325 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
326 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
327 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
328 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
329 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
330 if (context->context.lcPktData & PK_ORIENTATION)
331 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
332 if (context->context.lcPktData & PK_ROTATION)
333 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
335 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
336 return ptr;
339 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
341 int rc = 0;
343 if (context->context.lcPktData & PK_CONTEXT)
344 rc +=sizeof(HCTX);
345 if (context->context.lcPktData & PK_STATUS)
346 rc +=sizeof(UINT);
347 if (context->context.lcPktData & PK_TIME)
348 rc += sizeof(LONG);
349 if (context->context.lcPktData & PK_CHANGED)
350 rc += sizeof(WTPKT);
351 if (context->context.lcPktData & PK_SERIAL_NUMBER)
352 rc += sizeof(UINT);
353 if (context->context.lcPktData & PK_CURSOR)
354 rc += sizeof(UINT);
355 if (context->context.lcPktData & PK_BUTTONS)
356 rc += sizeof(DWORD);
357 if (context->context.lcPktData & PK_X)
358 rc += sizeof(DWORD);
359 if (context->context.lcPktData & PK_Y)
360 rc += sizeof(DWORD);
361 if (context->context.lcPktData & PK_Z)
362 rc += sizeof(DWORD);
363 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
364 rc += sizeof(UINT);
365 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
366 rc += sizeof(UINT);
367 if (context->context.lcPktData & PK_ORIENTATION)
368 rc += sizeof(ORIENTATION);
369 if (context->context.lcPktData & PK_ROTATION)
370 rc += sizeof(ROTATION);
372 rc *= n;
373 memset(lpPkt,0,rc);
377 static UINT WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
379 UINT result;
381 if (!LoadTablet()) return 0;
383 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
386 * Handle system extents here, as we can use user32.dll code to set them.
388 if(wCategory == WTI_DEFSYSCTX)
390 switch(nIndex)
392 case CTX_SYSEXTX:
393 if(lpOutput != NULL)
394 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
395 return sizeof(LONG);
396 case CTX_SYSEXTY:
397 if(lpOutput != NULL)
398 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
399 return sizeof(LONG);
400 /* No action, delegate to X11Drv */
404 if (is_logcontext_category(wCategory) && nIndex == 0)
406 if (lpOutput)
408 LOGCONTEXTW buf;
409 pWTInfoW(wCategory, nIndex, &buf);
411 /* Handle system extents here, as we can use user32.dll code to set them */
412 if(wCategory == WTI_DEFSYSCTX)
414 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
415 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
418 if (bUnicode)
419 memcpy(lpOutput, &buf, sizeof(buf));
420 else
421 LOGCONTEXTWtoA(&buf, lpOutput);
424 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
426 else if (is_string_field(wCategory, nIndex) && !bUnicode)
428 int size = pWTInfoW(wCategory, nIndex, NULL);
429 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
430 pWTInfoW(wCategory, nIndex, buf);
431 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
432 HeapFree(GetProcessHeap(), 0, buf);
434 else
435 result = pWTInfoW(wCategory, nIndex, lpOutput);
437 TRACE("returns %d\n", result);
438 return result;
441 /***********************************************************************
442 * WTInfoA (WINTAB32.20)
444 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
446 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
450 /***********************************************************************
451 * WTInfoW (WINTAB32.1020)
453 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
455 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
458 /***********************************************************************
459 * WTOpenW (WINTAB32.1021)
461 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
463 LPOPENCONTEXT newcontext;
465 if (!LoadTablet()) return 0;
467 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
468 DUMPCONTEXT(*lpLogCtx);
470 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
471 newcontext->context = *lpLogCtx;
472 newcontext->hwndOwner = hWnd;
473 newcontext->ActiveCursor = -1;
474 newcontext->QueueSize = 10;
475 newcontext->PacketsQueued = 0;
476 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
478 EnterCriticalSection(&csTablet);
479 newcontext->handle = gTopContext++;
480 newcontext->next = gOpenContexts;
481 gOpenContexts = newcontext;
482 LeaveCriticalSection(&csTablet);
484 pAttachEventQueueToTablet(hWnd);
486 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
487 newcontext->context.lcStatus, TRUE);
489 if (fEnable)
491 newcontext->enabled = TRUE;
492 /* TODO: Add to top of overlap order */
493 newcontext->context.lcStatus = CXS_ONTOP;
495 else
497 newcontext->enabled = FALSE;
498 newcontext->context.lcStatus = CXS_DISABLED;
501 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
502 (WPARAM)newcontext->handle,
503 newcontext->context.lcStatus, TRUE);
505 return newcontext->handle;
508 /***********************************************************************
509 * WTOpenA (WINTAB32.21)
511 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
513 LOGCONTEXTW logCtxW;
515 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
516 return WTOpenW(hWnd, &logCtxW, fEnable);
519 /***********************************************************************
520 * WTClose (WINTAB32.22)
522 BOOL WINAPI WTClose(HCTX hCtx)
524 LPOPENCONTEXT context,ptr;
526 TRACE("(%p)\n", hCtx);
528 EnterCriticalSection(&csTablet);
530 ptr = context = gOpenContexts;
532 while (context && (context->handle != hCtx))
534 ptr = context;
535 context = context->next;
537 if (!context)
539 LeaveCriticalSection(&csTablet);
540 return TRUE;
543 if (context == gOpenContexts)
544 gOpenContexts = context->next;
545 else
546 ptr->next = context->next;
548 LeaveCriticalSection(&csTablet);
550 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
551 context->context.lcStatus,TRUE);
553 HeapFree(GetProcessHeap(),0,context->PacketQueue);
554 HeapFree(GetProcessHeap(),0,context);
556 return TRUE;
559 /***********************************************************************
560 * WTPacketsGet (WINTAB32.23)
562 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
564 int limit;
565 LPOPENCONTEXT context;
566 LPVOID ptr = lpPkts;
568 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
570 if (!hCtx)
571 return 0;
573 EnterCriticalSection(&csTablet);
575 context = TABLET_FindOpenContext(hCtx);
576 if (!context)
578 LeaveCriticalSection(&csTablet);
579 return 0;
582 if (lpPkts != NULL)
583 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
585 if (context->PacketsQueued == 0)
587 LeaveCriticalSection(&csTablet);
588 return 0;
591 limit = min(cMaxPkts,context->PacketsQueued);
593 if(ptr != NULL)
595 int i = 0;
596 for(i = 0; i < limit; i++)
597 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
601 if (limit < context->PacketsQueued)
603 memmove(context->PacketQueue, &context->PacketQueue[limit],
604 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
606 context->PacketsQueued -= limit;
607 LeaveCriticalSection(&csTablet);
609 TRACE("Copied %i packets\n",limit);
611 return limit;
614 /***********************************************************************
615 * WTPacket (WINTAB32.24)
617 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
619 int rc = 0;
620 LPOPENCONTEXT context;
621 LPWTPACKET wtp = NULL;
623 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
625 if (!hCtx)
626 return FALSE;
628 EnterCriticalSection(&csTablet);
630 context = TABLET_FindOpenContext(hCtx);
631 if (!context)
633 LeaveCriticalSection(&csTablet);
634 return FALSE;
637 rc = TABLET_FindPacket(context ,wSerial, &wtp);
639 if (rc >= 0)
641 if (lpPkt)
642 TABLET_CopyPacketData(context ,lpPkt, wtp);
644 if ((rc+1) < context->QueueSize)
646 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
647 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
649 context->PacketsQueued -= (rc+1);
651 LeaveCriticalSection(&csTablet);
653 TRACE("Returning %i\n",rc+1);
654 return rc+1;
657 /***********************************************************************
658 * WTEnable (WINTAB32.40)
660 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
662 LPOPENCONTEXT context;
664 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
666 if (!hCtx) return FALSE;
668 EnterCriticalSection(&csTablet);
669 context = TABLET_FindOpenContext(hCtx);
670 if (!context)
672 LeaveCriticalSection(&csTablet);
673 return FALSE;
676 /* if we want to enable and it is not enabled then */
677 if(fEnable && !context->enabled)
679 context->enabled = TRUE;
680 /* TODO: Add to top of overlap order */
681 context->context.lcStatus = CXS_ONTOP;
682 TABLET_PostTabletMessage(context,
683 _WT_CTXOVERLAP(context->context.lcMsgBase),
684 (WPARAM)context->handle,
685 context->context.lcStatus, TRUE);
687 /* if we want to disable and it is not disabled then */
688 else if (!fEnable && context->enabled)
690 context->enabled = FALSE;
691 /* TODO: Remove from overlap order?? needs a test */
692 context->context.lcStatus = CXS_DISABLED;
693 TABLET_FlushQueue(context);
694 TABLET_PostTabletMessage(context,
695 _WT_CTXOVERLAP(context->context.lcMsgBase),
696 (WPARAM)context->handle,
697 context->context.lcStatus, TRUE);
699 LeaveCriticalSection(&csTablet);
701 return TRUE;
704 /***********************************************************************
705 * WTOverlap (WINTAB32.41)
707 * Move context to top or bottom of overlap order
709 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
711 LPOPENCONTEXT context;
713 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
715 if (!hCtx) return FALSE;
717 EnterCriticalSection(&csTablet);
718 context = TABLET_FindOpenContext(hCtx);
719 if (!context)
721 LeaveCriticalSection(&csTablet);
722 return FALSE;
725 /* if we want to send to top and it's not already there */
726 if (fToTop && context->context.lcStatus != CXS_ONTOP)
728 /* TODO: Move context to top of overlap order */
729 FIXME("Not moving context to top of overlap order\n");
730 context->context.lcStatus = CXS_ONTOP;
731 TABLET_PostTabletMessage(context,
732 _WT_CTXOVERLAP(context->context.lcMsgBase),
733 (WPARAM)context->handle,
734 context->context.lcStatus, TRUE);
736 else if (!fToTop)
738 /* TODO: Move context to bottom of overlap order */
739 FIXME("Not moving context to bottom of overlap order\n");
740 context->context.lcStatus = CXS_OBSCURED;
741 TABLET_PostTabletMessage(context,
742 _WT_CTXOVERLAP(context->context.lcMsgBase),
743 (WPARAM)context->handle,
744 context->context.lcStatus, TRUE);
746 LeaveCriticalSection(&csTablet);
748 return TRUE;
751 /***********************************************************************
752 * WTConfig (WINTAB32.60)
754 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
756 FIXME("(%p, %p): stub\n", hCtx, hWnd);
758 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
760 return FALSE;
763 /***********************************************************************
764 * WTGetA (WINTAB32.61)
766 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
768 LPOPENCONTEXT context;
770 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
772 if (!hCtx) return FALSE;
774 EnterCriticalSection(&csTablet);
775 context = TABLET_FindOpenContext(hCtx);
776 if (!context)
778 LeaveCriticalSection(&csTablet);
779 return FALSE;
782 LOGCONTEXTWtoA(&context->context, lpLogCtx);
783 LeaveCriticalSection(&csTablet);
785 return TRUE;
788 /***********************************************************************
789 * WTGetW (WINTAB32.1061)
791 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
793 LPOPENCONTEXT context;
795 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
797 if (!hCtx) return FALSE;
799 EnterCriticalSection(&csTablet);
800 context = TABLET_FindOpenContext(hCtx);
801 if (!context)
803 LeaveCriticalSection(&csTablet);
804 return FALSE;
807 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
808 LeaveCriticalSection(&csTablet);
810 return TRUE;
813 /***********************************************************************
814 * WTSetA (WINTAB32.62)
816 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
818 LPOPENCONTEXT context;
820 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
822 if (!hCtx || !lpLogCtx) return FALSE;
824 /* TODO: if cur process not owner of hCtx only modify
825 * attribs not locked by owner */
827 EnterCriticalSection(&csTablet);
828 context = TABLET_FindOpenContext(hCtx);
829 if (!context)
831 LeaveCriticalSection(&csTablet);
832 return FALSE;
835 LOGCONTEXTAtoW(lpLogCtx, &context->context);
836 LeaveCriticalSection(&csTablet);
838 return TRUE;
841 /***********************************************************************
842 * WTSetW (WINTAB32.1062)
844 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
846 LPOPENCONTEXT context;
848 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
850 if (!hCtx || !lpLogCtx) return FALSE;
852 /* TODO: if cur process not hCtx owner only modify
853 * attribs not locked by owner */
855 EnterCriticalSection(&csTablet);
856 context = TABLET_FindOpenContext(hCtx);
857 if (!context)
859 LeaveCriticalSection(&csTablet);
860 return FALSE;
863 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
864 LeaveCriticalSection(&csTablet);
866 return TRUE;
869 /***********************************************************************
870 * WTExtGet (WINTAB32.63)
872 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
874 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
876 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
878 return FALSE;
881 /***********************************************************************
882 * WTExtSet (WINTAB32.64)
884 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
886 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
888 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
890 return FALSE;
893 /***********************************************************************
894 * WTSave (WINTAB32.65)
896 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
898 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
900 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
902 return FALSE;
905 /***********************************************************************
906 * WTRestore (WINTAB32.66)
908 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
910 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
912 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
914 return 0;
917 /***********************************************************************
918 * WTPacketsPeek (WINTAB32.80)
920 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
922 int limit;
923 LPOPENCONTEXT context;
924 LPVOID ptr = lpPkts;
926 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
928 if (!hCtx || !lpPkts) return 0;
930 EnterCriticalSection(&csTablet);
932 context = TABLET_FindOpenContext(hCtx);
934 if (!context || context->PacketsQueued == 0)
936 LeaveCriticalSection(&csTablet);
937 return 0;
940 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
941 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
943 LeaveCriticalSection(&csTablet);
944 TRACE("Copied %i packets\n",limit);
945 return limit;
948 /***********************************************************************
949 * WTDataGet (WINTAB32.81)
951 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
952 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
954 LPOPENCONTEXT context;
955 LPVOID ptr = lpPkts;
956 INT bgn = 0;
957 INT end = 0;
958 INT num = 0;
960 TRACE("(%p, %u, %u, %d, %p, %p)\n",
961 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
963 if (!hCtx) return 0;
965 EnterCriticalSection(&csTablet);
967 context = TABLET_FindOpenContext(hCtx);
969 if (!context || context->PacketsQueued == 0)
971 LeaveCriticalSection(&csTablet);
972 return 0;
975 while (bgn < context->PacketsQueued &&
976 context->PacketQueue[bgn].pkSerialNumber != wBegin)
977 bgn++;
979 end = bgn;
980 while (end < context->PacketsQueued &&
981 context->PacketQueue[end].pkSerialNumber != wEnd)
982 end++;
984 if ((bgn == end) && (end == context->PacketsQueued))
986 LeaveCriticalSection(&csTablet);
987 return 0;
990 for (num = bgn; num <= end; num++)
991 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
993 /* remove read packets */
994 if ((end+1) < context->PacketsQueued)
995 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
996 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
998 context->PacketsQueued -= ((end-bgn)+1);
999 *lpNPkts = ((end-bgn)+1);
1001 LeaveCriticalSection(&csTablet);
1002 TRACE("Copied %i packets\n",*lpNPkts);
1003 return (end - bgn)+1;
1006 /***********************************************************************
1007 * WTDataPeek (WINTAB32.82)
1009 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
1010 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
1012 LPOPENCONTEXT context;
1013 LPVOID ptr = lpPkts;
1014 INT bgn = 0;
1015 INT end = 0;
1016 INT num = 0;
1018 TRACE("(%p, %u, %u, %d, %p, %p)\n",
1019 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
1021 if (!hCtx || !lpPkts) return 0;
1023 EnterCriticalSection(&csTablet);
1025 context = TABLET_FindOpenContext(hCtx);
1027 if (!context || context->PacketsQueued == 0)
1029 LeaveCriticalSection(&csTablet);
1030 return 0;
1033 while (bgn < context->PacketsQueued &&
1034 context->PacketQueue[bgn].pkSerialNumber != wBegin)
1035 bgn++;
1037 end = bgn;
1038 while (end < context->PacketsQueued &&
1039 context->PacketQueue[end].pkSerialNumber != wEnd)
1040 end++;
1042 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
1044 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
1045 LeaveCriticalSection(&csTablet);
1046 return 0;
1049 for (num = bgn; num <= end; num++)
1050 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
1052 *lpNPkts = ((end-bgn)+1);
1053 LeaveCriticalSection(&csTablet);
1055 TRACE("Copied %i packets\n",*lpNPkts);
1056 return (end - bgn)+1;
1059 /***********************************************************************
1060 * WTQueuePacketsEx (WINTAB32.200)
1062 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
1064 LPOPENCONTEXT context;
1066 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
1068 if (!hCtx) return FALSE;
1070 EnterCriticalSection(&csTablet);
1072 context = TABLET_FindOpenContext(hCtx);
1074 if (context && context->PacketsQueued)
1076 *lpOld = context->PacketQueue[0].pkSerialNumber;
1077 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
1079 else
1081 TRACE("No packets\n");
1082 LeaveCriticalSection(&csTablet);
1083 return FALSE;
1085 LeaveCriticalSection(&csTablet);
1087 return TRUE;
1090 /***********************************************************************
1091 * WTQueueSizeGet (WINTAB32.84)
1093 int WINAPI WTQueueSizeGet(HCTX hCtx)
1095 LPOPENCONTEXT context;
1096 int queueSize = 0;
1098 TRACE("(%p)\n", hCtx);
1100 if (!hCtx) return 0;
1102 EnterCriticalSection(&csTablet);
1103 context = TABLET_FindOpenContext(hCtx);
1104 if (context)
1105 queueSize = context->QueueSize;
1106 LeaveCriticalSection(&csTablet);
1107 return queueSize;
1110 /***********************************************************************
1111 * WTQueueSizeSet (WINTAB32.85)
1113 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1115 LPOPENCONTEXT context;
1117 TRACE("(%p, %d)\n", hCtx, nPkts);
1119 if (!hCtx) return FALSE;
1121 EnterCriticalSection(&csTablet);
1123 context = TABLET_FindOpenContext(hCtx);
1124 if (!context)
1126 LeaveCriticalSection(&csTablet);
1127 return FALSE;
1130 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1131 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1133 context->QueueSize = nPkts;
1134 LeaveCriticalSection(&csTablet);
1136 return nPkts;