winex11: Add window data structure locking to the X window creation paths.
[wine.git] / dlls / wintab32 / context.c
blobc8940b38da636d9b41bf9fef72fdd1d4f7cf6b5e
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 TRACE("Initializing the tablet to hwnd %p\n",hwndDefault);
161 if (pLoadTabletInfo && pLoadTabletInfo(hwndDefault))
163 loaded = TI_OK;
165 else
167 loaded = TI_FAIL;
168 ERR("LoadTabletInfo(%p) failed\n", hwndDefault);
172 return loaded == TI_OK;
175 int TABLET_PostTabletMessage(LPOPENCONTEXT newcontext, UINT msg, WPARAM wParam,
176 LPARAM lParam, BOOL send_always)
178 if ((send_always) || (newcontext->context.lcOptions & CXO_MESSAGES))
180 TRACE("Posting message %x to %p\n",msg, newcontext->hwndOwner);
181 return PostMessageA(newcontext->hwndOwner, msg, wParam, lParam);
183 return 0;
186 static inline DWORD ScaleForContext(DWORD In, LONG InOrg, LONG InExt, LONG OutOrg, LONG OutExt)
188 if (((InExt > 0 )&&(OutExt > 0)) || ((InExt<0) && (OutExt < 0)))
189 return ((In - InOrg) * abs(OutExt) / abs(InExt)) + OutOrg;
190 else
191 return ((abs(InExt) - (In - InOrg))*abs(OutExt) / abs(InExt)) + OutOrg;
194 LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
196 LPOPENCONTEXT ptr=NULL;
198 EnterCriticalSection(&csTablet);
200 ptr = gOpenContexts;
201 while (ptr)
203 TRACE("Trying Queue %p (%p %p)\n", ptr->handle, hwnd, ptr->hwndOwner);
205 if (ptr->hwndOwner == hwnd)
207 int tgt;
208 if (!ptr->enabled)
210 ptr = ptr->next;
211 continue;
214 tgt = ptr->PacketsQueued;
216 packet->pkContext = ptr->handle;
218 /* translate packet data to the context */
220 /* Scale as per documentation */
221 packet->pkY = ScaleForContext(packet->pkY, ptr->context.lcInOrgY,
222 ptr->context.lcInExtY, ptr->context.lcOutOrgY,
223 ptr->context.lcOutExtY);
225 packet->pkX = ScaleForContext(packet->pkX, ptr->context.lcInOrgX,
226 ptr->context.lcInExtX, ptr->context.lcOutOrgX,
227 ptr->context.lcOutExtX);
229 /* flip the Y axis */
230 if (ptr->context.lcOutExtY > 0)
231 packet->pkY = ptr->context.lcOutExtY - packet->pkY;
232 else if (ptr->context.lcOutExtY < 0)
233 packet->pkY = abs(ptr->context.lcOutExtY + packet->pkY);
235 DUMPPACKET(*packet);
237 if (tgt == ptr->QueueSize)
239 TRACE("Queue Overflow %p\n",ptr->handle);
240 ptr->PacketQueue[tgt-1].pkStatus |= TPS_QUEUE_ERR;
242 else
244 TRACE("Placed in queue %p index %i\n",ptr->handle,tgt);
245 ptr->PacketQueue[tgt] = *packet;
246 ptr->PacketsQueued++;
248 if (ptr->ActiveCursor != packet->pkCursor)
250 ptr->ActiveCursor = packet->pkCursor;
251 if (ptr->context.lcOptions & CXO_CSRMESSAGES)
252 TABLET_PostTabletMessage(ptr, _WT_CSRCHANGE(ptr->context.lcMsgBase),
253 (WPARAM)packet->pkSerialNumber, (LPARAM)ptr->handle,
254 FALSE);
257 break;
259 ptr = ptr->next;
261 LeaveCriticalSection(&csTablet);
262 TRACE("Done (%p)\n",ptr);
263 return ptr;
267 * Flushes all packets from the queue.
269 static inline void TABLET_FlushQueue(LPOPENCONTEXT context)
271 context->PacketsQueued = 0;
274 static inline int CopyTabletData(LPVOID target, LPVOID src, INT size)
276 memcpy(target,src,size);
277 return(size);
280 static INT TABLET_FindPacket(LPOPENCONTEXT context, UINT wSerial,
281 LPWTPACKET *pkt)
283 int loop;
284 int index = -1;
285 for (loop = 0; loop < context->PacketsQueued; loop++)
286 if (context->PacketQueue[loop].pkSerialNumber == wSerial)
288 index = loop;
289 *pkt = &context->PacketQueue[loop];
290 break;
293 TRACE("%i .. %i\n",context->PacketsQueued,index);
295 return index;
299 static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
300 LPWTPACKET wtp)
302 LPBYTE ptr;
304 ptr = lpPkt;
305 TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
307 if (context->context.lcPktData & PK_CONTEXT)
308 ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX));
309 if (context->context.lcPktData & PK_STATUS)
310 ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
311 if (context->context.lcPktData & PK_TIME)
312 ptr+=CopyTabletData(ptr,&wtp->pkTime,sizeof(LONG));
313 if (context->context.lcPktData & PK_CHANGED)
314 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(WTPKT));
315 if (context->context.lcPktData & PK_SERIAL_NUMBER)
316 ptr+=CopyTabletData(ptr,&wtp->pkChanged,sizeof(UINT));
317 if (context->context.lcPktData & PK_CURSOR)
318 ptr+=CopyTabletData(ptr,&wtp->pkCursor,sizeof(UINT));
319 if (context->context.lcPktData & PK_BUTTONS)
320 ptr+=CopyTabletData(ptr,&wtp->pkButtons,sizeof(DWORD));
321 if (context->context.lcPktData & PK_X)
322 ptr+=CopyTabletData(ptr,&wtp->pkX,sizeof(DWORD));
323 if (context->context.lcPktData & PK_Y)
324 ptr+=CopyTabletData(ptr,&wtp->pkY,sizeof(DWORD));
325 if (context->context.lcPktData & PK_Z)
326 ptr+=CopyTabletData(ptr,&wtp->pkZ,sizeof(DWORD));
327 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
328 ptr+=CopyTabletData(ptr,&wtp->pkNormalPressure,sizeof(UINT));
329 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
330 ptr+=CopyTabletData(ptr,&wtp->pkTangentPressure,sizeof(UINT));
331 if (context->context.lcPktData & PK_ORIENTATION)
332 ptr+=CopyTabletData(ptr,&wtp->pkOrientation,sizeof(ORIENTATION));
333 if (context->context.lcPktData & PK_ROTATION)
334 ptr+=CopyTabletData(ptr,&wtp->pkRotation,sizeof(ROTATION));
336 /*TRACE("Copied %i bytes\n",(INT)ptr - (INT)lpPkt); */
337 return ptr;
340 static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n)
342 int rc = 0;
344 if (context->context.lcPktData & PK_CONTEXT)
345 rc +=sizeof(HCTX);
346 if (context->context.lcPktData & PK_STATUS)
347 rc +=sizeof(UINT);
348 if (context->context.lcPktData & PK_TIME)
349 rc += sizeof(LONG);
350 if (context->context.lcPktData & PK_CHANGED)
351 rc += sizeof(WTPKT);
352 if (context->context.lcPktData & PK_SERIAL_NUMBER)
353 rc += sizeof(UINT);
354 if (context->context.lcPktData & PK_CURSOR)
355 rc += sizeof(UINT);
356 if (context->context.lcPktData & PK_BUTTONS)
357 rc += sizeof(DWORD);
358 if (context->context.lcPktData & PK_X)
359 rc += sizeof(DWORD);
360 if (context->context.lcPktData & PK_Y)
361 rc += sizeof(DWORD);
362 if (context->context.lcPktData & PK_Z)
363 rc += sizeof(DWORD);
364 if (context->context.lcPktData & PK_NORMAL_PRESSURE)
365 rc += sizeof(UINT);
366 if (context->context.lcPktData & PK_TANGENT_PRESSURE)
367 rc += sizeof(UINT);
368 if (context->context.lcPktData & PK_ORIENTATION)
369 rc += sizeof(ORIENTATION);
370 if (context->context.lcPktData & PK_ROTATION)
371 rc += sizeof(ROTATION);
373 rc *= n;
374 memset(lpPkt,0,rc);
378 static UINT WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode)
380 UINT result;
382 if (!LoadTablet()) return 0;
384 TRACE("(%d, %d, %p, %d)\n", wCategory, nIndex, lpOutput, bUnicode);
387 * Handle system extents here, as we can use user32.dll code to set them.
389 if(wCategory == WTI_DEFSYSCTX)
391 switch(nIndex)
393 case CTX_SYSEXTX:
394 if(lpOutput != NULL)
395 *(LONG*)lpOutput = GetSystemMetrics(SM_CXSCREEN);
396 return sizeof(LONG);
397 case CTX_SYSEXTY:
398 if(lpOutput != NULL)
399 *(LONG*)lpOutput = GetSystemMetrics(SM_CYSCREEN);
400 return sizeof(LONG);
401 /* No action, delegate to X11Drv */
405 if (is_logcontext_category(wCategory) && nIndex == 0)
407 if (lpOutput)
409 LOGCONTEXTW buf;
410 pWTInfoW(wCategory, nIndex, &buf);
412 /* Handle system extents here, as we can use user32.dll code to set them */
413 if(wCategory == WTI_DEFSYSCTX && nIndex == 0)
415 buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN);
416 buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN);
419 if (bUnicode)
420 memcpy(lpOutput, &buf, sizeof(buf));
421 else
422 LOGCONTEXTWtoA(&buf, lpOutput);
425 result = bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA);
427 else if (is_string_field(wCategory, nIndex) && !bUnicode)
429 int size = pWTInfoW(wCategory, nIndex, NULL);
430 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size);
431 pWTInfoW(wCategory, nIndex, buf);
432 result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL);
433 HeapFree(GetProcessHeap(), 0, buf);
435 else
436 result = pWTInfoW(wCategory, nIndex, lpOutput);
438 TRACE("returns %d\n", result);
439 return result;
442 /***********************************************************************
443 * WTInfoA (WINTAB32.20)
445 UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
447 return WTInfoT(wCategory, nIndex, lpOutput, FALSE);
451 /***********************************************************************
452 * WTInfoW (WINTAB32.1020)
454 UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
456 return WTInfoT(wCategory, nIndex, lpOutput, TRUE);
459 /***********************************************************************
460 * WTOpenW (WINTAB32.2021)
462 HCTX WINAPI WTOpenW(HWND hWnd, LPLOGCONTEXTW lpLogCtx, BOOL fEnable)
464 LPOPENCONTEXT newcontext;
466 if (!LoadTablet()) return 0;
468 TRACE("hWnd=%p, lpLogCtx=%p, fEnable=%u\n", hWnd, lpLogCtx, fEnable);
469 DUMPCONTEXT(*lpLogCtx);
471 newcontext = HeapAlloc(GetProcessHeap(), 0 , sizeof(OPENCONTEXT));
472 newcontext->context = *lpLogCtx;
473 newcontext->hwndOwner = hWnd;
474 newcontext->ActiveCursor = -1;
475 newcontext->QueueSize = 10;
476 newcontext->PacketsQueued = 0;
477 newcontext->PacketQueue=HeapAlloc(GetProcessHeap(),0,sizeof(WTPACKET)*10);
479 EnterCriticalSection(&csTablet);
480 newcontext->handle = gTopContext++;
481 newcontext->next = gOpenContexts;
482 gOpenContexts = newcontext;
483 LeaveCriticalSection(&csTablet);
485 pAttachEventQueueToTablet(hWnd);
487 TABLET_PostTabletMessage(newcontext, _WT_CTXOPEN(newcontext->context.lcMsgBase), (WPARAM)newcontext->handle,
488 newcontext->context.lcStatus, TRUE);
490 if (fEnable)
492 newcontext->enabled = TRUE;
493 /* TODO: Add to top of overlap order */
494 newcontext->context.lcStatus = CXS_ONTOP;
496 else
498 newcontext->enabled = FALSE;
499 newcontext->context.lcStatus = CXS_DISABLED;
502 TABLET_PostTabletMessage(newcontext, _WT_CTXOVERLAP(newcontext->context.lcMsgBase),
503 (WPARAM)newcontext->handle,
504 newcontext->context.lcStatus, TRUE);
506 return newcontext->handle;
509 /***********************************************************************
510 * WTOpenA (WINTAB32.21)
512 HCTX WINAPI WTOpenA(HWND hWnd, LPLOGCONTEXTA lpLogCtx, BOOL fEnable)
514 LOGCONTEXTW logCtxW;
516 LOGCONTEXTAtoW(lpLogCtx, &logCtxW);
517 return WTOpenW(hWnd, &logCtxW, fEnable);
520 /***********************************************************************
521 * WTClose (WINTAB32.22)
523 BOOL WINAPI WTClose(HCTX hCtx)
525 LPOPENCONTEXT context,ptr;
527 TRACE("(%p)\n", hCtx);
529 EnterCriticalSection(&csTablet);
531 ptr = context = gOpenContexts;
533 while (context && (context->handle != hCtx))
535 ptr = context;
536 context = context->next;
538 if (!context)
540 LeaveCriticalSection(&csTablet);
541 return TRUE;
544 if (context == gOpenContexts)
545 gOpenContexts = context->next;
546 else
547 ptr->next = context->next;
549 LeaveCriticalSection(&csTablet);
551 TABLET_PostTabletMessage(context, _WT_CTXCLOSE(context->context.lcMsgBase), (WPARAM)context->handle,
552 context->context.lcStatus,TRUE);
554 HeapFree(GetProcessHeap(),0,context->PacketQueue);
555 HeapFree(GetProcessHeap(),0,context);
557 return TRUE;
560 /***********************************************************************
561 * WTPacketsGet (WINTAB32.23)
563 int WINAPI WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
565 int limit;
566 LPOPENCONTEXT context;
567 LPVOID ptr = lpPkts;
569 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
571 if (!hCtx)
572 return 0;
574 EnterCriticalSection(&csTablet);
576 context = TABLET_FindOpenContext(hCtx);
577 if (!context)
579 LeaveCriticalSection(&csTablet);
580 return 0;
583 if (lpPkts != NULL)
584 TABLET_BlankPacketData(context,lpPkts,cMaxPkts);
586 if (context->PacketsQueued == 0)
588 LeaveCriticalSection(&csTablet);
589 return 0;
592 limit = min(cMaxPkts,context->PacketsQueued);
594 if(ptr != NULL)
596 int i = 0;
597 for(i = 0; i < limit; i++)
598 ptr=TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[i]);
602 if (limit < context->PacketsQueued)
604 memmove(context->PacketQueue, &context->PacketQueue[limit],
605 (context->PacketsQueued - (limit))*sizeof(WTPACKET));
607 context->PacketsQueued -= limit;
608 LeaveCriticalSection(&csTablet);
610 TRACE("Copied %i packets\n",limit);
612 return limit;
615 /***********************************************************************
616 * WTPacket (WINTAB32.24)
618 BOOL WINAPI WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)
620 int rc = 0;
621 LPOPENCONTEXT context;
622 LPWTPACKET wtp = NULL;
624 TRACE("(%p, %d, %p)\n", hCtx, wSerial, lpPkt);
626 if (!hCtx)
627 return 0;
629 EnterCriticalSection(&csTablet);
631 context = TABLET_FindOpenContext(hCtx);
632 if (!context)
634 LeaveCriticalSection(&csTablet);
635 return 0;
638 rc = TABLET_FindPacket(context ,wSerial, &wtp);
640 if (rc >= 0)
642 if (lpPkt)
643 TABLET_CopyPacketData(context ,lpPkt, wtp);
645 if ((rc+1) < context->QueueSize)
647 memmove(context->PacketQueue, &context->PacketQueue[rc+1],
648 (context->PacketsQueued - (rc+1))*sizeof(WTPACKET));
650 context->PacketsQueued -= (rc+1);
652 LeaveCriticalSection(&csTablet);
654 TRACE("Returning %i\n",rc+1);
655 return rc+1;
658 /***********************************************************************
659 * WTEnable (WINTAB32.40)
661 BOOL WINAPI WTEnable(HCTX hCtx, BOOL fEnable)
663 LPOPENCONTEXT context;
665 TRACE("hCtx=%p, fEnable=%u\n", hCtx, fEnable);
667 if (!hCtx) return FALSE;
669 EnterCriticalSection(&csTablet);
670 context = TABLET_FindOpenContext(hCtx);
671 if (!context)
673 LeaveCriticalSection(&csTablet);
674 return 0;
677 /* if we want to enable and it is not enabled then */
678 if(fEnable && !context->enabled)
680 context->enabled = TRUE;
681 /* TODO: Add to top of overlap order */
682 context->context.lcStatus = CXS_ONTOP;
683 TABLET_PostTabletMessage(context,
684 _WT_CTXOVERLAP(context->context.lcMsgBase),
685 (WPARAM)context->handle,
686 context->context.lcStatus, TRUE);
688 /* if we want to disable and it is not disabled then */
689 else if (!fEnable && context->enabled)
691 context->enabled = FALSE;
692 /* TODO: Remove from overlap order?? needs a test */
693 context->context.lcStatus = CXS_DISABLED;
694 TABLET_FlushQueue(context);
695 TABLET_PostTabletMessage(context,
696 _WT_CTXOVERLAP(context->context.lcMsgBase),
697 (WPARAM)context->handle,
698 context->context.lcStatus, TRUE);
700 LeaveCriticalSection(&csTablet);
702 return TRUE;
705 /***********************************************************************
706 * WTOverlap (WINTAB32.41)
708 * Move context to top or bottom of overlap order
710 BOOL WINAPI WTOverlap(HCTX hCtx, BOOL fToTop)
712 LPOPENCONTEXT context;
714 TRACE("hCtx=%p, fToTop=%u\n", hCtx, fToTop);
716 if (!hCtx) return FALSE;
718 EnterCriticalSection(&csTablet);
719 context = TABLET_FindOpenContext(hCtx);
720 if (!context)
722 LeaveCriticalSection(&csTablet);
723 return FALSE;
726 /* if we want to send to top and it's not already there */
727 if (fToTop && context->context.lcStatus != CXS_ONTOP)
729 /* TODO: Move context to top of overlap order */
730 FIXME("Not moving context to top of overlap order\n");
731 context->context.lcStatus = CXS_ONTOP;
732 TABLET_PostTabletMessage(context,
733 _WT_CTXOVERLAP(context->context.lcMsgBase),
734 (WPARAM)context->handle,
735 context->context.lcStatus, TRUE);
737 else if (!fToTop)
739 /* TODO: Move context to bottom of overlap order */
740 FIXME("Not moving context to bottom of overlap order\n");
741 context->context.lcStatus = CXS_OBSCURED;
742 TABLET_PostTabletMessage(context,
743 _WT_CTXOVERLAP(context->context.lcMsgBase),
744 (WPARAM)context->handle,
745 context->context.lcStatus, TRUE);
747 LeaveCriticalSection(&csTablet);
749 return TRUE;
752 /***********************************************************************
753 * WTConfig (WINTAB32.61)
755 BOOL WINAPI WTConfig(HCTX hCtx, HWND hWnd)
757 FIXME("(%p, %p): stub\n", hCtx, hWnd);
759 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
761 return FALSE;
764 /***********************************************************************
765 * WTGetA (WINTAB32.61)
767 BOOL WINAPI WTGetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
769 LPOPENCONTEXT context;
771 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
773 if (!hCtx) return 0;
775 EnterCriticalSection(&csTablet);
776 context = TABLET_FindOpenContext(hCtx);
777 if (!context)
779 LeaveCriticalSection(&csTablet);
780 return 0;
783 LOGCONTEXTWtoA(&context->context, lpLogCtx);
784 LeaveCriticalSection(&csTablet);
786 return TRUE;
789 /***********************************************************************
790 * WTGetW (WINTAB32.1061)
792 BOOL WINAPI WTGetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
794 LPOPENCONTEXT context;
796 TRACE("(%p, %p)\n", hCtx, lpLogCtx);
798 if (!hCtx) return 0;
800 EnterCriticalSection(&csTablet);
801 context = TABLET_FindOpenContext(hCtx);
802 if (!context)
804 LeaveCriticalSection(&csTablet);
805 return 0;
808 memmove(lpLogCtx,&context->context,sizeof(LOGCONTEXTW));
809 LeaveCriticalSection(&csTablet);
811 return TRUE;
814 /***********************************************************************
815 * WTSetA (WINTAB32.62)
817 BOOL WINAPI WTSetA(HCTX hCtx, LPLOGCONTEXTA lpLogCtx)
819 LPOPENCONTEXT context;
821 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
823 if (!hCtx || !lpLogCtx) return FALSE;
825 /* TODO: if cur process not owner of hCtx only modify
826 * attribs not locked by owner */
828 EnterCriticalSection(&csTablet);
829 context = TABLET_FindOpenContext(hCtx);
830 if (!context)
832 LeaveCriticalSection(&csTablet);
833 return FALSE;
836 LOGCONTEXTAtoW(lpLogCtx, &context->context);
837 LeaveCriticalSection(&csTablet);
839 return TRUE;
842 /***********************************************************************
843 * WTSetW (WINTAB32.1062)
845 BOOL WINAPI WTSetW(HCTX hCtx, LPLOGCONTEXTW lpLogCtx)
847 LPOPENCONTEXT context;
849 TRACE("hCtx=%p, lpLogCtx=%p\n", hCtx, lpLogCtx);
851 if (!hCtx || !lpLogCtx) return FALSE;
853 /* TODO: if cur process not hCtx owner only modify
854 * attribs not locked by owner */
856 EnterCriticalSection(&csTablet);
857 context = TABLET_FindOpenContext(hCtx);
858 if (!context)
860 LeaveCriticalSection(&csTablet);
861 return FALSE;
864 memmove(&context->context, lpLogCtx, sizeof(LOGCONTEXTW));
865 LeaveCriticalSection(&csTablet);
867 return TRUE;
870 /***********************************************************************
871 * WTExtGet (WINTAB32.63)
873 BOOL WINAPI WTExtGet(HCTX hCtx, UINT wExt, LPVOID lpData)
875 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
877 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
879 return FALSE;
882 /***********************************************************************
883 * WTExtSet (WINTAB32.64)
885 BOOL WINAPI WTExtSet(HCTX hCtx, UINT wExt, LPVOID lpData)
887 FIXME("(%p, %u, %p): stub\n", hCtx, wExt, lpData);
889 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
891 return FALSE;
894 /***********************************************************************
895 * WTSave (WINTAB32.65)
897 BOOL WINAPI WTSave(HCTX hCtx, LPVOID lpSaveInfo)
899 FIXME("(%p, %p): stub\n", hCtx, lpSaveInfo);
901 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
903 return FALSE;
906 /***********************************************************************
907 * WTRestore (WINTAB32.66)
909 HCTX WINAPI WTRestore(HWND hWnd, LPVOID lpSaveInfo, BOOL fEnable)
911 FIXME("(%p, %p, %u): stub\n", hWnd, lpSaveInfo, fEnable);
913 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
915 return 0;
918 /***********************************************************************
919 * WTPacketsPeek (WINTAB32.80)
921 int WINAPI WTPacketsPeek(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)
923 int limit;
924 LPOPENCONTEXT context;
925 LPVOID ptr = lpPkts;
927 TRACE("(%p, %d, %p)\n", hCtx, cMaxPkts, lpPkts);
929 if (!hCtx || !lpPkts) return 0;
931 EnterCriticalSection(&csTablet);
933 context = TABLET_FindOpenContext(hCtx);
935 if (!context || context->PacketsQueued == 0)
937 LeaveCriticalSection(&csTablet);
938 return 0;
941 for (limit = 0; limit < cMaxPkts && limit < context->PacketsQueued; limit++)
942 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[limit]);
944 LeaveCriticalSection(&csTablet);
945 TRACE("Copied %i packets\n",limit);
946 return limit;
949 /***********************************************************************
950 * WTDataGet (WINTAB32.81)
952 int WINAPI WTDataGet(HCTX hCtx, UINT wBegin, UINT wEnd,
953 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
955 LPOPENCONTEXT context;
956 LPVOID ptr = lpPkts;
957 INT bgn = 0;
958 INT end = 0;
959 INT num = 0;
961 TRACE("(%p, %u, %u, %d, %p, %p)\n",
962 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
964 if (!hCtx) return 0;
966 EnterCriticalSection(&csTablet);
968 context = TABLET_FindOpenContext(hCtx);
970 if (!context || context->PacketsQueued == 0)
972 LeaveCriticalSection(&csTablet);
973 return 0;
976 while (bgn < context->PacketsQueued &&
977 context->PacketQueue[bgn].pkSerialNumber != wBegin)
978 bgn++;
980 end = bgn;
981 while (end < context->PacketsQueued &&
982 context->PacketQueue[end].pkSerialNumber != wEnd)
983 end++;
985 if ((bgn == end) && (end == context->PacketsQueued))
987 LeaveCriticalSection(&csTablet);
988 return 0;
991 for (num = bgn; num <= end; num++)
992 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
994 /* remove read packets */
995 if ((end+1) < context->PacketsQueued)
996 memmove( &context->PacketQueue[bgn], &context->PacketQueue[end+1],
997 (context->PacketsQueued - (end+1)) * sizeof (WTPACKET));
999 context->PacketsQueued -= ((end-bgn)+1);
1000 *lpNPkts = ((end-bgn)+1);
1002 LeaveCriticalSection(&csTablet);
1003 TRACE("Copied %i packets\n",*lpNPkts);
1004 return (end - bgn)+1;
1007 /***********************************************************************
1008 * WTDataPeek (WINTAB32.82)
1010 int WINAPI WTDataPeek(HCTX hCtx, UINT wBegin, UINT wEnd,
1011 int cMaxPkts, LPVOID lpPkts, LPINT lpNPkts)
1013 LPOPENCONTEXT context;
1014 LPVOID ptr = lpPkts;
1015 INT bgn = 0;
1016 INT end = 0;
1017 INT num = 0;
1019 TRACE("(%p, %u, %u, %d, %p, %p)\n",
1020 hCtx, wBegin, wEnd, cMaxPkts, lpPkts, lpNPkts);
1022 if (!hCtx || !lpPkts) return 0;
1024 EnterCriticalSection(&csTablet);
1026 context = TABLET_FindOpenContext(hCtx);
1028 if (!context || context->PacketsQueued == 0)
1030 LeaveCriticalSection(&csTablet);
1031 return 0;
1034 while (bgn < context->PacketsQueued &&
1035 context->PacketQueue[bgn].pkSerialNumber != wBegin)
1036 bgn++;
1038 end = bgn;
1039 while (end < context->PacketsQueued &&
1040 context->PacketQueue[end].pkSerialNumber != wEnd)
1041 end++;
1043 if (bgn == context->PacketsQueued || end == context->PacketsQueued)
1045 TRACE("%i %i %i\n", bgn, end, context->PacketsQueued);
1046 LeaveCriticalSection(&csTablet);
1047 return 0;
1050 for (num = bgn; num <= end; num++)
1051 ptr = TABLET_CopyPacketData(context ,ptr, &context->PacketQueue[num]);
1053 *lpNPkts = ((end-bgn)+1);
1054 LeaveCriticalSection(&csTablet);
1056 TRACE("Copied %i packets\n",*lpNPkts);
1057 return (end - bgn)+1;
1060 /***********************************************************************
1061 * WTQueuePacketsEx (WINTAB32.200)
1063 BOOL WINAPI WTQueuePacketsEx(HCTX hCtx, UINT *lpOld, UINT *lpNew)
1065 LPOPENCONTEXT context;
1067 TRACE("(%p, %p, %p)\n", hCtx, lpOld, lpNew);
1069 if (!hCtx) return 0;
1071 EnterCriticalSection(&csTablet);
1073 context = TABLET_FindOpenContext(hCtx);
1075 if (context && context->PacketsQueued)
1077 *lpOld = context->PacketQueue[0].pkSerialNumber;
1078 *lpNew = context->PacketQueue[context->PacketsQueued-1].pkSerialNumber;
1080 else
1082 TRACE("No packets\n");
1083 LeaveCriticalSection(&csTablet);
1084 return FALSE;
1086 LeaveCriticalSection(&csTablet);
1088 return TRUE;
1091 /***********************************************************************
1092 * WTQueueSizeGet (WINTAB32.84)
1094 int WINAPI WTQueueSizeGet(HCTX hCtx)
1096 LPOPENCONTEXT context;
1097 int queueSize = 0;
1099 TRACE("(%p)\n", hCtx);
1101 if (!hCtx) return 0;
1103 EnterCriticalSection(&csTablet);
1104 context = TABLET_FindOpenContext(hCtx);
1105 if (context)
1106 queueSize = context->QueueSize;
1107 LeaveCriticalSection(&csTablet);
1108 return queueSize;
1111 /***********************************************************************
1112 * WTQueueSizeSet (WINTAB32.85)
1114 BOOL WINAPI WTQueueSizeSet(HCTX hCtx, int nPkts)
1116 LPOPENCONTEXT context;
1118 TRACE("(%p, %d)\n", hCtx, nPkts);
1120 if (!hCtx) return 0;
1122 EnterCriticalSection(&csTablet);
1124 context = TABLET_FindOpenContext(hCtx);
1125 if (!context)
1127 LeaveCriticalSection(&csTablet);
1128 return 0;
1131 context->PacketQueue = HeapReAlloc(GetProcessHeap(), 0,
1132 context->PacketQueue, sizeof(WTPACKET)*nPkts);
1134 context->QueueSize = nPkts;
1135 LeaveCriticalSection(&csTablet);
1137 return nPkts;