widl: Set the default calling convention at header generation time, not at parsing...
[wine/hramrach.git] / dlls / wintab32 / context.c
blob30f00216c81616fe23539b60bae401585e70abbb
1 /*
2 * Tablet Context
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2003 CodeWeavers, Aric Stewart
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
27 #include "windef.h"
28 #include "winerror.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
33 #include "wintab.h"
34 #include "wintab_internal.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
41 * Documentation found at
42 * http://www.csl.sony.co.jp/projects/ar/restricted/wintabl.html
45 static BOOL gLoaded;
46 static LPOPENCONTEXT gOpenContexts;
47 static HCTX gTopContext = (HCTX)0xc00;
49 static void LOGCONTEXTAtoW(const LOGCONTEXTA *in, LOGCONTEXTW *out)
51 MultiByteToWideChar(CP_ACP, 0, in->lcName, -1, out->lcName, LCNAMELEN);
52 out->lcName[LCNAMELEN - 1] = 0;
53 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
54 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTA) - FIELD_OFFSET(LOGCONTEXTA, lcOptions));
57 static void LOGCONTEXTWtoA(const LOGCONTEXTW *in, LOGCONTEXTA *out)
59 WideCharToMultiByte(CP_ACP, 0, in->lcName, LCNAMELEN, out->lcName, LCNAMELEN, NULL, NULL);
60 out->lcName[LCNAMELEN - 1] = 0;
61 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
62 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTW) - FIELD_OFFSET(LOGCONTEXTW, lcOptions));
65 static BOOL is_logcontext_category(UINT wCategory)
67 return wCategory == WTI_DEFSYSCTX || wCategory == WTI_DEFCONTEXT || wCategory == WTI_DDCTXS;
70 static BOOL is_string_field(UINT wCategory, UINT nIndex)
72 if (wCategory == WTI_INTERFACE && nIndex == IFC_WINTABID)
73 return TRUE;
74 if (is_logcontext_category(wCategory) && nIndex == CTX_NAME)
75 return TRUE;
76 if ((wCategory >= WTI_CURSORS && wCategory <= WTI_CURSORS + 9) &&
77 (nIndex == CSR_NAME || nIndex == CSR_BTNNAMES))
78 return TRUE;
79 if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID))
80 return TRUE;
81 return FALSE;
84 static const char* DUMPBITS(int x)
86 char buf[200];
87 buf[0] = 0;
88 if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
89 if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
90 if (x&PK_TIME) strcat(buf, "PK_TIME ");
91 if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
92 if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
93 if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
94 if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
95 if (x&PK_X) strcat(buf, "PK_X ");
96 if (x&PK_Y) strcat(buf, "PK_Y ");
97 if (x&PK_Z) strcat(buf, "PK_Z ");
98 if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
99 if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
100 if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
101 if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
102 return wine_dbg_sprintf("{%s}",buf);
105 static inline void DUMPPACKET(WTPACKET packet)
107 TRACE("pkContext: %p pkStatus: 0x%x pkTime : 0x%x pkChanged: 0x%x pkSerialNumber: 0x%x pkCursor : %i pkButtons: %x pkX: %i pkY: %i pkZ: %i pkNormalPressure: %i pkTangentPressure: %i pkOrientation: (%i,%i,%i) pkRotation: (%i,%i,%i)\n",
108 packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber,
109 packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ,
110 packet.pkNormalPressure, packet.pkTangentPressure,
111 packet.pkOrientation.orAzimuth, packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
112 packet.pkRotation.roPitch, packet.pkRotation.roRoll, packet.pkRotation.roYaw);
115 static inline void DUMPCONTEXT(LOGCONTEXTW lc)
117 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, "
118 "Device: %x, PktRate: %x, "
119 "%x%s, %x%s, %x%s, "
120 "BtnDnMask: %x, BtnUpMask: %x, "
121 "InOrgX: %i, InOrgY: %i, InOrgZ: %i, "
122 "InExtX: %i, InExtY: %i, InExtZ: %i, "
123 "OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i, "
124 "OutExtX: %i, OutExtY: %i, OutExtZ: %i, "
125 "SensX: %i, SensY: %i, SensZ: %i, "
126 "SysMode: %i, "
127 "SysOrgX: %i, SysOrgY: %i, "
128 "SysExtX: %i, SysExtY: %i, "
129 "SysSensX: %i, SysSensY: %i\n",
130 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase,
131 lc.lcDevice, lc.lcPktRate, lc.lcPktData, DUMPBITS(lc.lcPktData),
132 lc.lcPktMode, DUMPBITS(lc.lcPktMode), lc.lcMoveMask,
133 DUMPBITS(lc.lcMoveMask), lc.lcBtnDnMask, lc.lcBtnUpMask,
134 lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ, lc.lcInExtX, lc.lcInExtY,
135 lc.lcInExtZ, lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ, lc.lcOutExtX,
136 lc.lcOutExtY, lc.lcOutExtZ, lc.lcSensX, lc.lcSensY, lc.lcSensZ, lc.lcSysMode,
137 lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY, lc.lcSysSensX,
138 lc.lcSysSensY);
142 /* Find an open context given the handle */
143 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
145 LPOPENCONTEXT ptr = gOpenContexts;
146 while (ptr)
148 if (ptr->handle == hCtx) return ptr;
149 ptr = ptr->next;
151 return NULL;
154 static void LoadTablet(void)
156 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
157 gLoaded= TRUE;
158 if (pLoadTabletInfo)
159 pLoadTabletInfo(hwndDefault);
162 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
163 LPARAM lParam, BOOL send_always)
165 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
167 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
168 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
170 return 0;
173 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
175 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
176 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
177 else
178 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
181 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
183 LPOPENCONTEXT ptr=NULL;
185 EnterCriticalSection(&csTablet);
187 ptr = gOpenContexts;
188 while (ptr)
190 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
192 if (ptr->hwndOwner == hwnd)
194 int tgt;
195 if (!ptr->enabled)
197 ptr = ptr->next;
198 continue;
201 tgt = ptr->PacketsQueued;
203 packet->pkContext = ptr->handle;
205 /* translate packet data to the context */
207 /* Scale as per documentation */
208 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
209 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
210 ptr->context.lcOutExtY);
212 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
213 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
214 ptr->context.lcOutExtX);
216 /* flip the Y axis */
217 if (ptr->context.lcOutExtY > 0)
218 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
219 else if (ptr->context.lcOutExtY < 0)
220 packet->pkY = abs(ptr->context.lcOutExtY + packet->pkY);
222 DUMPPACKET(*packet);
224 if (tgt == ptr->QueueSize)
226 TRACE("Queue Overflow %p\n",ptr->handle);
227 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
229 else
231 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
232 ptr->PacketQueue[tgt] = *packet;
233 ptr->PacketsQueued++;
235 if (ptr->ActiveCursor != packet->pkCursor)
237 ptr->ActiveCursor = packet->pkCursor;
238 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
239 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
240 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
241 FALSE);
244 break;
246 ptr = ptr->next;
248 LeaveCriticalSection(&csTablet);
249 TRACE("Done (%p)\n",ptr);
250 return ptr;
254 * Flushes all packets from the queue.
256 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
258 context->PacketsQueued = 0;
261 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
263 memcpy(target,src,size);
264 return(size);
267 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
268 LPWTPACKET *pkt)
270 int loop;
271 int index = -1;
272 for (loop = 0; loop < context->PacketsQueued; loop++)
273 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
275 index = loop;
276 *pkt = &context->PacketQueue[loop];
277 break;
280 TRACE("%i .. %i\n",context->PacketsQueued,index);
282 return index;
286 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
287 LPWTPACKET wtp)
289 LPBYTE ptr;
291 ptr = lpPkt;
292 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
294 if (context->context.lcPktData & PK_CONTEXT)
295 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
296 if (context->context.lcPktData & PK_STATUS)
297 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
298 if (context->context.lcPktData & PK_TIME)
299 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
300 if (context->context.lcPktData & PK_CHANGED)
301 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
302 if (context->context.lcPktData & PK_SERIAL_NUMBER)
303 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
304 if (context->context.lcPktData & PK_CURSOR)
305 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
306 if (context->context.lcPktData & PK_BUTTONS)
307 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
308 if (context->context.lcPktData & PK_X)
309 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
310 if (context->context.lcPktData & PK_Y)
311 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
312 if (context->context.lcPktData & PK_Z)
313 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
314 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
315 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
316 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
317 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
318 if (context->context.lcPktData & PK_ORIENTATION)
319 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
320 if (context->context.lcPktData & PK_ROTATION)
321 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
323 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
324 return ptr;
327 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
329 int rc = 0;
331 if (context->context.lcPktData & PK_CONTEXT)
332 rc +=sizeof(HCTX);
333 if (context->context.lcPktData & PK_STATUS)
334 rc +=sizeof(UINT);
335 if (context->context.lcPktData & PK_TIME)
336 rc += sizeof(LONG);
337 if (context->context.lcPktData & PK_CHANGED)
338 rc += sizeof(WTPKT);
339 if (context->context.lcPktData & PK_SERIAL_NUMBER)
340 rc += sizeof(UINT);
341 if (context->context.lcPktData & PK_CURSOR)
342 rc += sizeof(UINT);
343 if (context->context.lcPktData & PK_BUTTONS)
344 rc += sizeof(DWORD);
345 if (context->context.lcPktData & PK_X)
346 rc += sizeof(DWORD);
347 if (context->context.lcPktData & PK_Y)
348 rc += sizeof(DWORD);
349 if (context->context.lcPktData & PK_Z)
350 rc += sizeof(DWORD);
351 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
352 rc += sizeof(UINT);
353 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
354 rc += sizeof(UINT);
355 if (context->context.lcPktData & PK_ORIENTATION)
356 rc += sizeof(ORIENTATION);
357 if (context->context.lcPktData & PK_ROTATION)
358 rc += sizeof(ROTATION);
360 rc *= n;
361 memset(lpPkt,0,rc);
365 static UINT WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
367 UINT result;
369 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
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 result = 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 TRACE("returns %d\n", result);
426 return result;
429 /***********************************************************************
430 * WTInfoA (WINTAB32.20)
432 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
434 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
438 /***********************************************************************
439 * WTInfoW (WINTAB32.1020)
441 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
443 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
446 /***********************************************************************
447 * WTOpenW (WINTAB32.2021)
449 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
451 LPOPENCONTEXT newcontext;
453 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
454 DUMPCONTEXT(*lpLogCtx);
456 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
457 newcontext->context = *lpLogCtx;
458 newcontext->hwndOwner = hWnd;
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 if (fEnable)
477 newcontext->enabled = TRUE;
478 /* TODO: Add to top of overlap order */
479 newcontext->context.lcStatus = CXS_ONTOP;
481 else
483 newcontext->enabled = FALSE;
484 newcontext->context.lcStatus = CXS_DISABLED;
487 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
488 (WPARAM)newcontext->handle,
489 newcontext->context.lcStatus, TRUE);
491 return newcontext->handle;
494 /***********************************************************************
495 * WTOpenA (WINTAB32.21)
497 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
499 LOGCONTEXTW logCtxW;
501 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
502 return WTOpenW(hWnd, &logCtxW, fEnable);
505 /***********************************************************************
506 * WTClose (WINTAB32.22)
508 BOOL WINAPI WTClose(HCTX hCtx)
510 LPOPENCONTEXT context,ptr;
512 TRACE("(%p)\n", hCtx);
514 EnterCriticalSection(&csTablet);
516 ptr = context = gOpenContexts;
518 while (context && (context->handle != hCtx))
520 ptr = context;
521 context = context->next;
523 if (!context)
525 LeaveCriticalSection(&csTablet);
526 return TRUE;
529 if (context == gOpenContexts)
530 gOpenContexts = context->next;
531 else
532 ptr->next = context->next;
534 LeaveCriticalSection(&csTablet);
536 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
537 context->context.lcStatus,TRUE);
539 HeapFree(GetProcessHeap(),0,context->PacketQueue);
540 HeapFree(GetProcessHeap(),0,context);
542 return TRUE;
545 /***********************************************************************
546 * WTPacketsGet (WINTAB32.23)
548 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
550 int limit;
551 LPOPENCONTEXT context;
552 LPVOID ptr = lpPkts;
554 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
556 if (!hCtx)
557 return 0;
559 EnterCriticalSection(&csTablet);
561 context = TABLET_FindOpenContext(hCtx);
562 if (!context)
564 LeaveCriticalSection(&csTablet);
565 return 0;
568 if (lpPkts != NULL)
569 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
571 if (context->PacketsQueued == 0)
573 LeaveCriticalSection(&csTablet);
574 return 0;
577 limit = min(cMaxPkts,context->PacketsQueued);
579 if(ptr != NULL)
581 int i = 0;
582 for(i = 0; i < limit; i++)
583 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
587 if (limit < context->PacketsQueued)
589 memmove(context->PacketQueue, &context->PacketQueue[limit],
590 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
592 context->PacketsQueued -= limit;
593 LeaveCriticalSection(&csTablet);
595 TRACE("Copied %i packets\n",limit);
597 return limit;
600 /***********************************************************************
601 * WTPacket (WINTAB32.24)
603 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
605 int rc = 0;
606 LPOPENCONTEXT context;
607 LPWTPACKET wtp = NULL;
609 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
611 if (!hCtx)
612 return 0;
614 EnterCriticalSection(&csTablet);
616 context = TABLET_FindOpenContext(hCtx);
617 if (!context)
619 LeaveCriticalSection(&csTablet);
620 return 0;
623 rc = TABLET_FindPacket(context ,wSerial, &wtp);
625 if (rc >= 0)
627 if (lpPkt)
628 TABLET_CopyPacketData(context ,lpPkt, wtp);
630 if ((rc+1) < context->QueueSize)
632 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
633 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
635 context->PacketsQueued -= (rc+1);
637 LeaveCriticalSection(&csTablet);
639 TRACE("Returning %i\n",rc+1);
640 return rc+1;
643 /***********************************************************************
644 * WTEnable (WINTAB32.40)
646 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
648 LPOPENCONTEXT context;
650 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
652 if (!hCtx) return FALSE;
654 EnterCriticalSection(&csTablet);
655 context = TABLET_FindOpenContext(hCtx);
656 if (!context)
658 LeaveCriticalSection(&csTablet);
659 return 0;
662 /* if we want to enable and it is not enabled then */
663 if(fEnable && !context->enabled)
665 context->enabled = TRUE;
666 /* TODO: Add to top of overlap order */
667 context->context.lcStatus = CXS_ONTOP;
668 TABLET_PostTabletMessage(context,
669 _WT_CTXOVERLAP(context->context.lcMsgBase),
670 (WPARAM)context->handle,
671 context->context.lcStatus, TRUE);
673 /* if we want to disable and it is not disabled then */
674 else if (!fEnable && context->enabled)
676 context->enabled = FALSE;
677 /* TODO: Remove from overlap order?? needs a test */
678 context->context.lcStatus = CXS_DISABLED;
679 TABLET_FlushQueue(context);
680 TABLET_PostTabletMessage(context,
681 _WT_CTXOVERLAP(context->context.lcMsgBase),
682 (WPARAM)context->handle,
683 context->context.lcStatus, TRUE);
685 LeaveCriticalSection(&csTablet);
687 return TRUE;
690 /***********************************************************************
691 * WTOverlap (WINTAB32.41)
693 * Move context to top or bottom of overlap order
695 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
697 LPOPENCONTEXT context;
699 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
701 if (!hCtx) return FALSE;
703 EnterCriticalSection(&csTablet);
704 context = TABLET_FindOpenContext(hCtx);
705 if (!context)
707 LeaveCriticalSection(&csTablet);
708 return FALSE;
711 /* if we want to send to top and it's not already there */
712 if (fToTop && context->context.lcStatus != CXS_ONTOP)
714 /* TODO: Move context to top of overlap order */
715 FIXME("Not moving context to top of overlap order\n");
716 context->context.lcStatus = CXS_ONTOP;
717 TABLET_PostTabletMessage(context,
718 _WT_CTXOVERLAP(context->context.lcMsgBase),
719 (WPARAM)context->handle,
720 context->context.lcStatus, TRUE);
722 else if (!fToTop)
724 /* TODO: Move context to bottom of overlap order */
725 FIXME("Not moving context to bottom of overlap order\n");
726 context->context.lcStatus = CXS_OBSCURED;
727 TABLET_PostTabletMessage(context,
728 _WT_CTXOVERLAP(context->context.lcMsgBase),
729 (WPARAM)context->handle,
730 context->context.lcStatus, TRUE);
732 LeaveCriticalSection(&csTablet);
734 return TRUE;
737 /***********************************************************************
738 * WTConfig (WINTAB32.61)
740 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
742 FIXME("(%p, %p): stub\n", hCtx, hWnd);
744 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
746 return FALSE;
749 /***********************************************************************
750 * WTGetA (WINTAB32.61)
752 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
754 LPOPENCONTEXT context;
756 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
758 if (!hCtx) return 0;
760 EnterCriticalSection(&csTablet);
761 context = TABLET_FindOpenContext(hCtx);
762 if (!context)
764 LeaveCriticalSection(&csTablet);
765 return 0;
768 LOGCONTEXTWtoA(&context->context, lpLogCtx);
769 LeaveCriticalSection(&csTablet);
771 return TRUE;
774 /***********************************************************************
775 * WTGetW (WINTAB32.1061)
777 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
779 LPOPENCONTEXT context;
781 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
783 if (!hCtx) return 0;
785 EnterCriticalSection(&csTablet);
786 context = TABLET_FindOpenContext(hCtx);
787 if (!context)
789 LeaveCriticalSection(&csTablet);
790 return 0;
793 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
794 LeaveCriticalSection(&csTablet);
796 return TRUE;
799 /***********************************************************************
800 * WTSetA (WINTAB32.62)
802 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
804 LPOPENCONTEXT context;
806 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
808 if (!hCtx || !lpLogCtx) return FALSE;
810 /* TODO: if cur process not owner of hCtx only modify
811 * attribs not locked by owner */
813 EnterCriticalSection(&csTablet);
814 context = TABLET_FindOpenContext(hCtx);
815 if (!context)
817 LeaveCriticalSection(&csTablet);
818 return FALSE;
821 LOGCONTEXTAtoW(lpLogCtx, &context->context);
822 LeaveCriticalSection(&csTablet);
824 return TRUE;
827 /***********************************************************************
828 * WTSetW (WINTAB32.1062)
830 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
832 LPOPENCONTEXT context;
834 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
836 if (!hCtx || !lpLogCtx) return FALSE;
838 /* TODO: if cur process not hCtx owner only modify
839 * attribs not locked by owner */
841 EnterCriticalSection(&csTablet);
842 context = TABLET_FindOpenContext(hCtx);
843 if (!context)
845 LeaveCriticalSection(&csTablet);
846 return FALSE;
849 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
850 LeaveCriticalSection(&csTablet);
852 return TRUE;
855 /***********************************************************************
856 * WTExtGet (WINTAB32.63)
858 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
860 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
862 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
864 return FALSE;
867 /***********************************************************************
868 * WTExtSet (WINTAB32.64)
870 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
872 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
874 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
876 return FALSE;
879 /***********************************************************************
880 * WTSave (WINTAB32.65)
882 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
884 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
886 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
888 return FALSE;
891 /***********************************************************************
892 * WTRestore (WINTAB32.66)
894 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
896 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
898 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
900 return 0;
903 /***********************************************************************
904 * WTPacketsPeek (WINTAB32.80)
906 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
908 int limit;
909 LPOPENCONTEXT context;
910 LPVOID ptr = lpPkts;
912 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
914 if (!hCtx || !lpPkts) return 0;
916 EnterCriticalSection(&csTablet);
918 context = TABLET_FindOpenContext(hCtx);
920 if (!context || context->PacketsQueued == 0)
922 LeaveCriticalSection(&csTablet);
923 return 0;
926 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
927 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
929 LeaveCriticalSection(&csTablet);
930 TRACE("Copied %i packets\n",limit);
931 return limit;
934 /***********************************************************************
935 * WTDataGet (WINTAB32.81)
937 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
938 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
940 LPOPENCONTEXT context;
941 LPVOID ptr = lpPkts;
942 INT bgn = 0;
943 INT end = 0;
944 INT num = 0;
946 TRACE("(%p, %u, %u, %d, %p, %p)\n",
947 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
949 if (!hCtx) return 0;
951 EnterCriticalSection(&csTablet);
953 context = TABLET_FindOpenContext(hCtx);
955 if (!context || context->PacketsQueued == 0)
957 LeaveCriticalSection(&csTablet);
958 return 0;
961 while (bgn < context->PacketsQueued &&
962 context->PacketQueue[bgn].pkSerialNumber != wBegin)
963 bgn++;
965 end = bgn;
966 while (end < context->PacketsQueued &&
967 context->PacketQueue[end].pkSerialNumber != wEnd)
968 end++;
970 if ((bgn == end) && (end == context->PacketsQueued))
972 LeaveCriticalSection(&csTablet);
973 return 0;
976 for (num = bgn; num <= end; num++)
977 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
979 /* remove read packets */
980 if ((end+1) < context->PacketsQueued)
981 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
982 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
984 context->PacketsQueued -= ((end-bgn)+1);
985 *lpNPkts = ((end-bgn)+1);
987 LeaveCriticalSection(&csTablet);
988 TRACE("Copied %i packets\n",*lpNPkts);
989 return (end - bgn)+1;
992 /***********************************************************************
993 * WTDataPeek (WINTAB32.82)
995 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
996 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
998 LPOPENCONTEXT context;
999 LPVOID ptr = lpPkts;
1000 INT bgn = 0;
1001 INT end = 0;
1002 INT num = 0;
1004 TRACE("(%p, %u, %u, %d, %p, %p)\n",
1005 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
1007 if (!hCtx || !lpPkts) return 0;
1009 EnterCriticalSection(&csTablet);
1011 context = TABLET_FindOpenContext(hCtx);
1013 if (!context || context->PacketsQueued == 0)
1015 LeaveCriticalSection(&csTablet);
1016 return 0;
1019 while (bgn < context->PacketsQueued &&
1020 context->PacketQueue[bgn].pkSerialNumber != wBegin)
1021 bgn++;
1023 end = bgn;
1024 while (end < context->PacketsQueued &&
1025 context->PacketQueue[end].pkSerialNumber != wEnd)
1026 end++;
1028 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
1030 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
1031 LeaveCriticalSection(&csTablet);
1032 return 0;
1035 for (num = bgn; num <= end; num++)
1036 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
1038 *lpNPkts = ((end-bgn)+1);
1039 LeaveCriticalSection(&csTablet);
1041 TRACE("Copied %i packets\n",*lpNPkts);
1042 return (end - bgn)+1;
1045 /***********************************************************************
1046 * WTQueuePacketsEx (WINTAB32.200)
1048 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
1050 LPOPENCONTEXT context;
1052 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
1054 if (!hCtx) return 0;
1056 EnterCriticalSection(&csTablet);
1058 context = TABLET_FindOpenContext(hCtx);
1060 if (context && context->PacketsQueued)
1062 *lpOld = context->PacketQueue[0].pkSerialNumber;
1063 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
1065 else
1067 TRACE("No packets\n");
1068 LeaveCriticalSection(&csTablet);
1069 return FALSE;
1071 LeaveCriticalSection(&csTablet);
1073 return TRUE;
1076 /***********************************************************************
1077 * WTQueueSizeGet (WINTAB32.84)
1079 int WINAPI WTQueueSizeGet(HCTX hCtx)
1081 LPOPENCONTEXT context;
1082 int queueSize = 0;
1084 TRACE("(%p)\n", hCtx);
1086 if (!hCtx) return 0;
1088 EnterCriticalSection(&csTablet);
1089 context = TABLET_FindOpenContext(hCtx);
1090 if (context)
1091 queueSize = context->QueueSize;
1092 LeaveCriticalSection(&csTablet);
1093 return queueSize;
1096 /***********************************************************************
1097 * WTQueueSizeSet (WINTAB32.85)
1099 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1101 LPOPENCONTEXT context;
1103 TRACE("(%p, %d)\n", hCtx, nPkts);
1105 if (!hCtx) return 0;
1107 EnterCriticalSection(&csTablet);
1109 context = TABLET_FindOpenContext(hCtx);
1110 if (!context)
1112 LeaveCriticalSection(&csTablet);
1113 return 0;
1116 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1117 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1119 context->QueueSize = nPkts;
1120 LeaveCriticalSection(&csTablet);
1122 return nPkts;