po: Update Lithuanian translation.
[wine.git] / dlls / wintab32 / context.c
blobff9a4ca677af7dfe73e5e06c2588ccb77bde45fa
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 <stdio.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winerror.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
32 #include "wintab.h"
33 #include "wintab_internal.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
40 * Documentation found at
41 * http://www.csl.sony.co.jp/projects/ar/restricted/wintabl.html
44 static LPOPENCONTEXT gOpenContexts;
45 static HCTX gTopContext = (HCTX)0xc00;
47 static void LOGCONTEXTAtoW(const LOGCONTEXTA *in, LOGCONTEXTW *out)
49 MultiByteToWideChar(CP_ACP, 0, in->lcName, -1, out->lcName, LCNAMELEN);
50 out->lcName[LCNAMELEN - 1] = 0;
51 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
52 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTA) - FIELD_OFFSET(LOGCONTEXTA, lcOptions));
55 static void LOGCONTEXTWtoA(const LOGCONTEXTW *in, LOGCONTEXTA *out)
57 WideCharToMultiByte(CP_ACP, 0, in->lcName, LCNAMELEN, out->lcName, LCNAMELEN, NULL, NULL);
58 out->lcName[LCNAMELEN - 1] = 0;
59 /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */
60 memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTW) - FIELD_OFFSET(LOGCONTEXTW, lcOptions));
63 static BOOL is_logcontext_category(UINT wCategory)
65 return wCategory == WTI_DEFSYSCTX || wCategory == WTI_DEFCONTEXT || wCategory == WTI_DDCTXS;
68 static BOOL is_string_field(UINT wCategory, UINT nIndex)
70 if (wCategory == WTI_INTERFACE && nIndex == IFC_WINTABID)
71 return TRUE;
72 if (is_logcontext_category(wCategory) && nIndex == CTX_NAME)
73 return TRUE;
74 if ((wCategory >= WTI_CURSORS && wCategory <= WTI_CURSORS + 9) &&
75 (nIndex == CSR_NAME || nIndex == CSR_BTNNAMES))
76 return TRUE;
77 if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID))
78 return TRUE;
79 return FALSE;
82 static const char* DUMPBITS(int x)
84 char buf[200];
85 buf[0] = 0;
86 if (x&PK_CONTEXT) strcat(buf,"PK_CONTEXT ");
87 if (x&PK_STATUS) strcat(buf, "PK_STATUS ");
88 if (x&PK_TIME) strcat(buf, "PK_TIME ");
89 if (x&PK_CHANGED) strcat(buf, "PK_CHANGED ");
90 if (x&PK_SERIAL_NUMBER) strcat(buf, "PK_SERIAL_NUMBER ");
91 if (x&PK_CURSOR) strcat(buf, "PK_CURSOR ");
92 if (x&PK_BUTTONS) strcat(buf, "PK_BUTTONS ");
93 if (x&PK_X) strcat(buf, "PK_X ");
94 if (x&PK_Y) strcat(buf, "PK_Y ");
95 if (x&PK_Z) strcat(buf, "PK_Z ");
96 if (x&PK_NORMAL_PRESSURE) strcat(buf, "PK_NORMAL_PRESSURE ");
97 if (x&PK_TANGENT_PRESSURE) strcat(buf, "PK_TANGENT_PRESSURE ");
98 if (x&PK_ORIENTATION) strcat(buf, "PK_ORIENTATION ");
99 if (x&PK_ROTATION) strcat(buf, "PK_ROTATION ");
100 return wine_dbg_sprintf("{%s}",buf);
103 static inline void DUMPPACKET(WTPACKET packet)
105 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",
106 packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber,
107 packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ,
108 packet.pkNormalPressure, packet.pkTangentPressure,
109 packet.pkOrientation.orAzimuth, packet.pkOrientation.orAltitude, packet.pkOrientation.orTwist,
110 packet.pkRotation.roPitch, packet.pkRotation.roRoll, packet.pkRotation.roYaw);
113 static inline void DUMPCONTEXT(LOGCONTEXTW lc)
115 TRACE("Name: %s, Options: %x, Status: %x, Locks: %x, MsgBase: %x, Device: %x\n",
116 wine_dbgstr_w(lc.lcName), lc.lcOptions, lc.lcStatus, lc.lcLocks, lc.lcMsgBase, lc.lcDevice);
117 TRACE("PktRate %x\n", lc.lcPktRate);
118 TRACE("PktData 0x%04x %s\n", lc.lcPktData, DUMPBITS(lc.lcPktData));
119 TRACE("PktMode 0x%04x %s\n", lc.lcPktMode, DUMPBITS(lc.lcPktMode));
120 TRACE("MovMask 0x%04x %s\n", lc.lcMoveMask, DUMPBITS(lc.lcMoveMask));
121 TRACE("BtnDnMask: %x, BtnUpMask: %x\n", lc.lcBtnDnMask, lc.lcBtnUpMask);
122 TRACE("InOrgX: %i, InOrgY: %i, InOrgZ: %i\n", lc.lcInOrgX, lc.lcInOrgY, lc.lcInOrgZ);
123 TRACE("InExtX: %i, InExtY: %i, InExtZ: %i\n", lc.lcInExtX, lc.lcInExtY, lc.lcInExtZ);
124 TRACE("OutOrgX: %i, OutOrgY: %i, OutOrgZ: %i\n", lc.lcOutOrgX, lc.lcOutOrgY, lc.lcOutOrgZ);
125 TRACE("OutExtX: %i, OutExtY: %i, OutExtZ: %i\n", lc.lcOutExtX, lc.lcOutExtY, lc.lcOutExtZ);
126 TRACE("SensX: %i, SensY: %i, SensZ: %i\n", lc.lcSensX, lc.lcSensY, lc.lcSensZ);
127 TRACE("SysMode: %i\n", lc.lcSysMode);
128 TRACE("SysOrgX: %i, SysOrgY: %i\n", lc.lcSysOrgX, lc.lcSysOrgY);
129 TRACE("SysExtX: %i, SysExtY: %i\n", lc.lcSysExtX, lc.lcSysExtY);
130 TRACE("SysSensX: %i, SysSensY: %i\n", lc.lcSysSensX, lc.lcSysSensY);
134 /* Find an open context given the handle */
135 static LPOPENCONTEXT TABLET_FindOpenContext(HCTX hCtx)
137 LPOPENCONTEXT ptr = gOpenContexts;
138 while (ptr)
140 if (ptr->handle == hCtx) return ptr;
141 ptr = ptr->next;
143 return NULL;
146 static inline BOOL LoadTablet(void)
148 static enum {TI_START = 0, TI_OK, TI_FAIL} loaded = TI_START;
150 if (loaded == TI_START)
152 if (pLoadTabletInfo && pLoadTabletInfo(hwndDefault))
154 TRACE("Initialized the tablet to hwnd %p\n", hwndDefault);
155 loaded = TI_OK;
157 else
159 TRACE("Failed to initialize the tablet to hwnd %p\n", hwndDefault);
160 loaded = TI_FAIL;
164 return loaded == TI_OK;
167 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
168 LPARAM lParam, BOOL send_always)
170 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
172 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
173 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
175 return 0;
178 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
180 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
181 return MulDiv(In - InOrg, abs(OutExt), abs(InExt)) + OutOrg;
182 else
183 return MulDiv(abs(InExt) - (In - InOrg), abs(OutExt), abs(InExt)) + OutOrg;
186 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
188 LPOPENCONTEXT ptr=NULL;
190 EnterCriticalSection(&csTablet);
192 ptr = gOpenContexts;
193 while (ptr)
195 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
197 if (ptr->hwndOwner == hwnd)
199 int tgt;
200 if (!ptr->enabled)
202 ptr = ptr->next;
203 continue;
206 tgt = ptr->PacketsQueued;
208 packet->pkContext = ptr->handle;
210 /* translate packet data to the context */
211 packet->pkChanged = packet->pkChanged & ptr->context.lcPktData;
213 /* Scale as per documentation */
214 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
215 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
216 ptr->context.lcOutExtY);
218 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
219 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
220 ptr->context.lcOutExtX);
222 /* flip the Y axis */
223 if (ptr->context.lcOutExtY > 0)
224 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
225 else if (ptr->context.lcOutExtY < 0)
226 packet->pkY = abs(ptr->context.lcOutExtY + packet->pkY);
228 DUMPPACKET(*packet);
230 if (tgt == ptr->QueueSize)
232 TRACE("Queue Overflow %p\n",ptr->handle);
233 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
235 else
237 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
238 ptr->PacketQueue[tgt] = *packet;
239 ptr->PacketsQueued++;
241 if (ptr->ActiveCursor != packet->pkCursor)
243 ptr->ActiveCursor = packet->pkCursor;
244 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
245 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
246 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
247 FALSE);
250 break;
252 ptr = ptr->next;
254 LeaveCriticalSection(&csTablet);
255 TRACE("Done (%p)\n",ptr);
256 return ptr;
260 * Flushes all packets from the queue.
262 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
264 context->PacketsQueued = 0;
267 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
269 memcpy(target,src,size);
270 return(size);
273 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
274 LPWTPACKET *pkt)
276 int loop;
277 int index = -1;
278 for (loop = 0; loop < context->PacketsQueued; loop++)
279 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
281 index = loop;
282 *pkt = &context->PacketQueue[loop];
283 break;
286 TRACE("%i .. %i\n",context->PacketsQueued,index);
288 return index;
292 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
293 LPWTPACKET wtp)
295 LPBYTE ptr;
297 ptr = lpPkt;
298 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
300 if (context->context.lcPktData & PK_CONTEXT)
301 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
302 if (context->context.lcPktData & PK_STATUS)
303 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
304 if (context->context.lcPktData & PK_TIME)
305 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
306 if (context->context.lcPktData & PK_CHANGED)
307 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
308 if (context->context.lcPktData & PK_SERIAL_NUMBER)
309 ptr+=CopyTabletData(ptr,&wtp->pkSerialNumber,sizeof(UINT));
310 if (context->context.lcPktData & PK_CURSOR)
311 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
312 if (context->context.lcPktData & PK_BUTTONS)
313 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
314 if (context->context.lcPktData & PK_X)
315 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
316 if (context->context.lcPktData & PK_Y)
317 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
318 if (context->context.lcPktData & PK_Z)
319 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
320 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
321 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
322 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
323 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
324 if (context->context.lcPktData & PK_ORIENTATION)
325 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
326 if (context->context.lcPktData & PK_ROTATION)
327 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
329 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
330 return ptr;
333 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
335 int rc = 0;
337 if (context->context.lcPktData & PK_CONTEXT)
338 rc +=sizeof(HCTX);
339 if (context->context.lcPktData & PK_STATUS)
340 rc +=sizeof(UINT);
341 if (context->context.lcPktData & PK_TIME)
342 rc += sizeof(LONG);
343 if (context->context.lcPktData & PK_CHANGED)
344 rc += sizeof(WTPKT);
345 if (context->context.lcPktData & PK_SERIAL_NUMBER)
346 rc += sizeof(UINT);
347 if (context->context.lcPktData & PK_CURSOR)
348 rc += sizeof(UINT);
349 if (context->context.lcPktData & PK_BUTTONS)
350 rc += sizeof(DWORD);
351 if (context->context.lcPktData & PK_X)
352 rc += sizeof(DWORD);
353 if (context->context.lcPktData & PK_Y)
354 rc += sizeof(DWORD);
355 if (context->context.lcPktData & PK_Z)
356 rc += sizeof(DWORD);
357 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
358 rc += sizeof(UINT);
359 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
360 rc += sizeof(UINT);
361 if (context->context.lcPktData & PK_ORIENTATION)
362 rc += sizeof(ORIENTATION);
363 if (context->context.lcPktData & PK_ROTATION)
364 rc += sizeof(ROTATION);
366 rc *= n;
367 memset(lpPkt,0,rc);
371 static UINT WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
373 UINT result;
375 if (!LoadTablet()) return 0;
377 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
380 * Handle system extents here, as we can use user32.dll code to set them.
382 if(wCategory == WTI_DEFSYSCTX)
384 switch(nIndex)
386 case CTX_SYSEXTX:
387 if(lpOutput != NULL)
388 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
389 return sizeof(LONG);
390 case CTX_SYSEXTY:
391 if(lpOutput != NULL)
392 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
393 return sizeof(LONG);
394 /* No action, delegate to X11Drv */
398 if (is_logcontext_category(wCategory) && nIndex == 0)
400 if (lpOutput)
402 LOGCONTEXTW buf;
403 pWTInfoW(wCategory, nIndex, &buf);
405 /* Handle system extents here, as we can use user32.dll code to set them */
406 if(wCategory == WTI_DEFSYSCTX)
408 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
409 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
412 if (bUnicode)
413 memcpy(lpOutput, &buf, sizeof(buf));
414 else
415 LOGCONTEXTWtoA(&buf, lpOutput);
418 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
420 else if (is_string_field(wCategory, nIndex) && !bUnicode)
422 int size = pWTInfoW(wCategory, nIndex, NULL);
423 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
424 pWTInfoW(wCategory, nIndex, buf);
425 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
426 HeapFree(GetProcessHeap(), 0, buf);
428 else
429 result = pWTInfoW(wCategory, nIndex, lpOutput);
431 TRACE("returns %d\n", result);
432 return result;
435 /***********************************************************************
436 * WTInfoA (WINTAB32.20)
438 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
440 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
444 /***********************************************************************
445 * WTInfoW (WINTAB32.1020)
447 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
449 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
452 /***********************************************************************
453 * WTOpenW (WINTAB32.1021)
455 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
457 LPOPENCONTEXT newcontext;
459 if (!LoadTablet()) return 0;
461 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
462 DUMPCONTEXT(*lpLogCtx);
464 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
465 newcontext->context = *lpLogCtx;
466 newcontext->hwndOwner = hWnd;
467 newcontext->ActiveCursor = -1;
468 newcontext->QueueSize = 10;
469 newcontext->PacketsQueued = 0;
470 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
472 EnterCriticalSection(&csTablet);
473 newcontext->handle = gTopContext++;
474 newcontext->next = gOpenContexts;
475 gOpenContexts = newcontext;
476 LeaveCriticalSection(&csTablet);
478 pAttachEventQueueToTablet(hWnd);
480 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
481 newcontext->context.lcStatus, TRUE);
483 if (fEnable)
485 newcontext->enabled = TRUE;
486 /* TODO: Add to top of overlap order */
487 newcontext->context.lcStatus = CXS_ONTOP;
489 else
491 newcontext->enabled = FALSE;
492 newcontext->context.lcStatus = CXS_DISABLED;
495 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
496 (WPARAM)newcontext->handle,
497 newcontext->context.lcStatus, TRUE);
499 return newcontext->handle;
502 /***********************************************************************
503 * WTOpenA (WINTAB32.21)
505 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
507 LOGCONTEXTW logCtxW;
509 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
510 return WTOpenW(hWnd, &logCtxW, fEnable);
513 /***********************************************************************
514 * WTClose (WINTAB32.22)
516 BOOL WINAPI WTClose(HCTX hCtx)
518 LPOPENCONTEXT context,ptr;
520 TRACE("(%p)\n", hCtx);
522 EnterCriticalSection(&csTablet);
524 ptr = context = gOpenContexts;
526 while (context && (context->handle != hCtx))
528 ptr = context;
529 context = context->next;
531 if (!context)
533 LeaveCriticalSection(&csTablet);
534 return TRUE;
537 if (context == gOpenContexts)
538 gOpenContexts = context->next;
539 else
540 ptr->next = context->next;
542 LeaveCriticalSection(&csTablet);
544 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
545 context->context.lcStatus,TRUE);
547 HeapFree(GetProcessHeap(),0,context->PacketQueue);
548 HeapFree(GetProcessHeap(),0,context);
550 return TRUE;
553 /***********************************************************************
554 * WTPacketsGet (WINTAB32.23)
556 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
558 int limit;
559 LPOPENCONTEXT context;
560 LPVOID ptr = lpPkts;
562 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
564 if (!hCtx)
565 return 0;
567 EnterCriticalSection(&csTablet);
569 context = TABLET_FindOpenContext(hCtx);
570 if (!context)
572 LeaveCriticalSection(&csTablet);
573 return 0;
576 if (lpPkts != NULL)
577 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
579 if (context->PacketsQueued == 0)
581 LeaveCriticalSection(&csTablet);
582 return 0;
585 limit = min(cMaxPkts,context->PacketsQueued);
587 if(ptr != NULL)
589 int i = 0;
590 for(i = 0; i < limit; i++)
591 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
595 if (limit < context->PacketsQueued)
597 memmove(context->PacketQueue, &context->PacketQueue[limit],
598 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
600 context->PacketsQueued -= limit;
601 LeaveCriticalSection(&csTablet);
603 TRACE("Copied %i packets\n",limit);
605 return limit;
608 /***********************************************************************
609 * WTPacket (WINTAB32.24)
611 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
613 int rc = 0;
614 LPOPENCONTEXT context;
615 LPWTPACKET wtp = NULL;
617 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
619 if (!hCtx)
620 return FALSE;
622 EnterCriticalSection(&csTablet);
624 context = TABLET_FindOpenContext(hCtx);
625 if (!context)
627 LeaveCriticalSection(&csTablet);
628 return FALSE;
631 rc = TABLET_FindPacket(context ,wSerial, &wtp);
633 if (rc >= 0)
635 if (lpPkt)
636 TABLET_CopyPacketData(context ,lpPkt, wtp);
638 if ((rc+1) < context->QueueSize)
640 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
641 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
643 context->PacketsQueued -= (rc+1);
645 LeaveCriticalSection(&csTablet);
647 TRACE("Returning %i\n",rc+1);
648 return rc+1;
651 /***********************************************************************
652 * WTEnable (WINTAB32.40)
654 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
656 LPOPENCONTEXT context;
658 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
660 if (!hCtx) return FALSE;
662 EnterCriticalSection(&csTablet);
663 context = TABLET_FindOpenContext(hCtx);
664 if (!context)
666 LeaveCriticalSection(&csTablet);
667 return FALSE;
670 /* if we want to enable and it is not enabled then */
671 if(fEnable && !context->enabled)
673 context->enabled = TRUE;
674 /* TODO: Add to top of overlap order */
675 context->context.lcStatus = CXS_ONTOP;
676 TABLET_PostTabletMessage(context,
677 _WT_CTXOVERLAP(context->context.lcMsgBase),
678 (WPARAM)context->handle,
679 context->context.lcStatus, TRUE);
681 /* if we want to disable and it is not disabled then */
682 else if (!fEnable && context->enabled)
684 context->enabled = FALSE;
685 /* TODO: Remove from overlap order?? needs a test */
686 context->context.lcStatus = CXS_DISABLED;
687 TABLET_FlushQueue(context);
688 TABLET_PostTabletMessage(context,
689 _WT_CTXOVERLAP(context->context.lcMsgBase),
690 (WPARAM)context->handle,
691 context->context.lcStatus, TRUE);
693 LeaveCriticalSection(&csTablet);
695 return TRUE;
698 /***********************************************************************
699 * WTOverlap (WINTAB32.41)
701 * Move context to top or bottom of overlap order
703 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
705 LPOPENCONTEXT context;
707 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
709 if (!hCtx) return FALSE;
711 EnterCriticalSection(&csTablet);
712 context = TABLET_FindOpenContext(hCtx);
713 if (!context)
715 LeaveCriticalSection(&csTablet);
716 return FALSE;
719 /* if we want to send to top and it's not already there */
720 if (fToTop && context->context.lcStatus != CXS_ONTOP)
722 /* TODO: Move context to top of overlap order */
723 FIXME("Not moving context to top of overlap order\n");
724 context->context.lcStatus = CXS_ONTOP;
725 TABLET_PostTabletMessage(context,
726 _WT_CTXOVERLAP(context->context.lcMsgBase),
727 (WPARAM)context->handle,
728 context->context.lcStatus, TRUE);
730 else if (!fToTop)
732 /* TODO: Move context to bottom of overlap order */
733 FIXME("Not moving context to bottom of overlap order\n");
734 context->context.lcStatus = CXS_OBSCURED;
735 TABLET_PostTabletMessage(context,
736 _WT_CTXOVERLAP(context->context.lcMsgBase),
737 (WPARAM)context->handle,
738 context->context.lcStatus, TRUE);
740 LeaveCriticalSection(&csTablet);
742 return TRUE;
745 /***********************************************************************
746 * WTConfig (WINTAB32.60)
748 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
750 FIXME("(%p, %p): stub\n", hCtx, hWnd);
752 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
754 return FALSE;
757 /***********************************************************************
758 * WTGetA (WINTAB32.61)
760 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
762 LPOPENCONTEXT context;
764 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
766 if (!hCtx) return FALSE;
768 EnterCriticalSection(&csTablet);
769 context = TABLET_FindOpenContext(hCtx);
770 if (!context)
772 LeaveCriticalSection(&csTablet);
773 return FALSE;
776 LOGCONTEXTWtoA(&context->context, lpLogCtx);
777 LeaveCriticalSection(&csTablet);
779 return TRUE;
782 /***********************************************************************
783 * WTGetW (WINTAB32.1061)
785 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
787 LPOPENCONTEXT context;
789 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
791 if (!hCtx) return FALSE;
793 EnterCriticalSection(&csTablet);
794 context = TABLET_FindOpenContext(hCtx);
795 if (!context)
797 LeaveCriticalSection(&csTablet);
798 return FALSE;
801 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
802 LeaveCriticalSection(&csTablet);
804 return TRUE;
807 /***********************************************************************
808 * WTSetA (WINTAB32.62)
810 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
812 LPOPENCONTEXT context;
814 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
816 if (!hCtx || !lpLogCtx) return FALSE;
818 /* TODO: if cur process not owner of hCtx only modify
819 * attribs not locked by owner */
821 EnterCriticalSection(&csTablet);
822 context = TABLET_FindOpenContext(hCtx);
823 if (!context)
825 LeaveCriticalSection(&csTablet);
826 return FALSE;
829 LOGCONTEXTAtoW(lpLogCtx, &context->context);
830 LeaveCriticalSection(&csTablet);
832 return TRUE;
835 /***********************************************************************
836 * WTSetW (WINTAB32.1062)
838 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
840 LPOPENCONTEXT context;
842 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
844 if (!hCtx || !lpLogCtx) return FALSE;
846 /* TODO: if cur process not hCtx owner only modify
847 * attribs not locked by owner */
849 EnterCriticalSection(&csTablet);
850 context = TABLET_FindOpenContext(hCtx);
851 if (!context)
853 LeaveCriticalSection(&csTablet);
854 return FALSE;
857 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
858 LeaveCriticalSection(&csTablet);
860 return TRUE;
863 /***********************************************************************
864 * WTExtGet (WINTAB32.63)
866 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
868 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
870 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
872 return FALSE;
875 /***********************************************************************
876 * WTExtSet (WINTAB32.64)
878 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
880 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
884 return FALSE;
887 /***********************************************************************
888 * WTSave (WINTAB32.65)
890 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
892 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
894 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
896 return FALSE;
899 /***********************************************************************
900 * WTRestore (WINTAB32.66)
902 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
904 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
906 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
908 return 0;
911 /***********************************************************************
912 * WTPacketsPeek (WINTAB32.80)
914 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
916 int limit;
917 LPOPENCONTEXT context;
918 LPVOID ptr = lpPkts;
920 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
922 if (!hCtx || !lpPkts) return 0;
924 EnterCriticalSection(&csTablet);
926 context = TABLET_FindOpenContext(hCtx);
928 if (!context || context->PacketsQueued == 0)
930 LeaveCriticalSection(&csTablet);
931 return 0;
934 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
935 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
937 LeaveCriticalSection(&csTablet);
938 TRACE("Copied %i packets\n",limit);
939 return limit;
942 /***********************************************************************
943 * WTDataGet (WINTAB32.81)
945 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
946 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
948 LPOPENCONTEXT context;
949 LPVOID ptr = lpPkts;
950 INT bgn = 0;
951 INT end = 0;
952 INT num = 0;
954 TRACE("(%p, %u, %u, %d, %p, %p)\n",
955 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
957 if (!hCtx) return 0;
959 EnterCriticalSection(&csTablet);
961 context = TABLET_FindOpenContext(hCtx);
963 if (!context || context->PacketsQueued == 0)
965 LeaveCriticalSection(&csTablet);
966 return 0;
969 while (bgn < context->PacketsQueued &&
970 context->PacketQueue[bgn].pkSerialNumber != wBegin)
971 bgn++;
973 end = bgn;
974 while (end < context->PacketsQueued &&
975 context->PacketQueue[end].pkSerialNumber != wEnd)
976 end++;
978 if ((bgn == end) && (end == context->PacketsQueued))
980 LeaveCriticalSection(&csTablet);
981 return 0;
984 for (num = bgn; num <= end; num++)
985 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
987 /* remove read packets */
988 if ((end+1) < context->PacketsQueued)
989 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
990 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
992 context->PacketsQueued -= ((end-bgn)+1);
993 *lpNPkts = ((end-bgn)+1);
995 LeaveCriticalSection(&csTablet);
996 TRACE("Copied %i packets\n",*lpNPkts);
997 return (end - bgn)+1;
1000 /***********************************************************************
1001 * WTDataPeek (WINTAB32.82)
1003 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
1004 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
1006 LPOPENCONTEXT context;
1007 LPVOID ptr = lpPkts;
1008 INT bgn = 0;
1009 INT end = 0;
1010 INT num = 0;
1012 TRACE("(%p, %u, %u, %d, %p, %p)\n",
1013 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
1015 if (!hCtx || !lpPkts) return 0;
1017 EnterCriticalSection(&csTablet);
1019 context = TABLET_FindOpenContext(hCtx);
1021 if (!context || context->PacketsQueued == 0)
1023 LeaveCriticalSection(&csTablet);
1024 return 0;
1027 while (bgn < context->PacketsQueued &&
1028 context->PacketQueue[bgn].pkSerialNumber != wBegin)
1029 bgn++;
1031 end = bgn;
1032 while (end < context->PacketsQueued &&
1033 context->PacketQueue[end].pkSerialNumber != wEnd)
1034 end++;
1036 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
1038 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
1039 LeaveCriticalSection(&csTablet);
1040 return 0;
1043 for (num = bgn; num <= end; num++)
1044 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
1046 *lpNPkts = ((end-bgn)+1);
1047 LeaveCriticalSection(&csTablet);
1049 TRACE("Copied %i packets\n",*lpNPkts);
1050 return (end - bgn)+1;
1053 /***********************************************************************
1054 * WTQueuePacketsEx (WINTAB32.200)
1056 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
1058 LPOPENCONTEXT context;
1060 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
1062 if (!hCtx) return FALSE;
1064 EnterCriticalSection(&csTablet);
1066 context = TABLET_FindOpenContext(hCtx);
1068 if (context && context->PacketsQueued)
1070 *lpOld = context->PacketQueue[0].pkSerialNumber;
1071 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
1073 else
1075 TRACE("No packets\n");
1076 LeaveCriticalSection(&csTablet);
1077 return FALSE;
1079 LeaveCriticalSection(&csTablet);
1081 return TRUE;
1084 /***********************************************************************
1085 * WTQueueSizeGet (WINTAB32.84)
1087 int WINAPI WTQueueSizeGet(HCTX hCtx)
1089 LPOPENCONTEXT context;
1090 int queueSize = 0;
1092 TRACE("(%p)\n", hCtx);
1094 if (!hCtx) return 0;
1096 EnterCriticalSection(&csTablet);
1097 context = TABLET_FindOpenContext(hCtx);
1098 if (context)
1099 queueSize = context->QueueSize;
1100 LeaveCriticalSection(&csTablet);
1101 return queueSize;
1104 /***********************************************************************
1105 * WTQueueSizeSet (WINTAB32.85)
1107 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1109 LPOPENCONTEXT context;
1111 TRACE("(%p, %d)\n", hCtx, nPkts);
1113 if (!hCtx) return FALSE;
1115 EnterCriticalSection(&csTablet);
1117 context = TABLET_FindOpenContext(hCtx);
1118 if (!context)
1120 LeaveCriticalSection(&csTablet);
1121 return FALSE;
1124 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1125 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1127 context->QueueSize = nPkts;
1128 LeaveCriticalSection(&csTablet);
1130 return nPkts;