Implement function 0xb (Read mouse motion counters) and 0xf (Set
[wine] / dlls / winedos / int33.c
1 /*
2  * DOS interrupt 33h handler
3  */
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "windef.h"
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "winuser.h"
12 #include "miscemu.h"
13 #include "dosexe.h"
14 #include "vga.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(int);
18
19 static struct
20 {
21   DWORD x, y, but;
22   WORD lbcount, rbcount, rlastx, rlasty, llastx, llasty;
23   FARPROC16 callback;
24   WORD callmask;
25   WORD VMPratio, HMPratio, oldx, oldy;
26 } mouse_info;
27
28 /**********************************************************************
29  *          DOSVM_Int33Handler
30  *
31  * Handler for int 33h (MS MOUSE).
32  */
33 void WINAPI DOSVM_Int33Handler( CONTEXT86 *context )
34 {
35   switch (LOWORD(context->Eax)) {
36   case 0x00:
37     TRACE("Reset mouse driver and request status\n");
38     AX_reg(context) = 0xFFFF; /* installed */
39     BX_reg(context) = 3;      /* # of buttons */
40     memset( &mouse_info, 0, sizeof(mouse_info) );
41     /* Set the default mickey/pixel ratio */
42     mouse_info.HMPratio = 8;
43     mouse_info.VMPratio = 16;
44     break;
45   case 0x01:
46     FIXME("Show mouse cursor\n");
47     break;
48   case 0x02:
49     FIXME("Hide mouse cursor\n");
50     break;
51   case 0x03:
52     TRACE("Return mouse position and button status\n");
53     BX_reg(context) = mouse_info.but;
54     CX_reg(context) = mouse_info.x;
55     DX_reg(context) = mouse_info.y;
56     break;
57   case 0x04:
58     FIXME("Position mouse cursor\n");
59     break;
60   case 0x05:
61     TRACE("Return Mouse button press Information for %s mouse button\n",
62           BX_reg(context) ? "right" : "left");
63     if (BX_reg(context)) {
64       BX_reg(context) = mouse_info.rbcount;
65       mouse_info.rbcount = 0;
66       CX_reg(context) = mouse_info.rlastx;
67       DX_reg(context) = mouse_info.rlasty;
68     } else {
69       BX_reg(context) = mouse_info.lbcount;
70       mouse_info.lbcount = 0;
71       CX_reg(context) = mouse_info.llastx;
72       DX_reg(context) = mouse_info.llasty;
73     }
74     AX_reg(context) = mouse_info.but;
75     break;
76   case 0x07:
77     FIXME("Define horizontal mouse cursor range\n");
78     break;
79   case 0x08:
80     FIXME("Define vertical mouse cursor range\n");
81     break;
82   case 0x09:
83     FIXME("Define graphics mouse cursor\n");
84     break;
85   case 0x0A:
86     FIXME("Define text mouse cursor\n");
87     break;
88   case 0x0B:
89     TRACE("Read Mouse motion counters\n");
90     CX_reg(context) = (mouse_info.x - mouse_info.oldx) * (mouse_info.HMPratio / 8);
91     DX_reg(context) = (mouse_info.y - mouse_info.oldy) * (mouse_info.VMPratio / 8);
92     mouse_info.oldx = mouse_info.x;
93     mouse_info.oldy = mouse_info.y;
94     break;
95   case 0x0C:
96     TRACE("Define mouse interrupt subroutine\n");
97     mouse_info.callmask = CX_reg(context);
98     mouse_info.callback = (FARPROC16)MAKESEGPTR(context->SegEs, LOWORD(context->Edx));
99     break;
100   case 0x0F:
101     TRACE("Set mickey/pixel ratio\n");
102     mouse_info.HMPratio = CX_reg(context);
103     mouse_info.VMPratio = DX_reg(context);
104     break;
105   case 0x10:
106     FIXME("Define screen region for update\n");
107     break;
108   default:
109     INT_BARF(context,0x33);
110   }
111 }
112
113 typedef struct {
114   FARPROC16 proc;
115   WORD mask,but,x,y,mx,my;
116 } MCALLDATA;
117
118 static void MouseRelay(CONTEXT86 *context,void *mdata)
119 {
120   MCALLDATA *data = (MCALLDATA *)mdata;
121   CONTEXT86 ctx = *context;
122
123   ctx.Eax   = data->mask;
124   ctx.Ebx   = data->but;
125   ctx.Ecx   = data->x;
126   ctx.Edx   = data->y;
127   ctx.Esi   = data->mx;
128   ctx.Edi   = data->my;
129   ctx.SegCs = SELECTOROF(data->proc);
130   ctx.Eip   = OFFSETOF(data->proc);
131   free(data);
132   DPMI_CallRMProc(&ctx, NULL, 0, 0);
133 }
134
135 void WINAPI DOSVM_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
136 {
137   WORD mask = 0;
138   unsigned Height, Width, SX=1, SY=1;
139
140   if (!VGA_GetMode(&Height,&Width,NULL)) {
141     /* may need to do some coordinate scaling */
142     if (Width) 
143       SX = 640/Width;
144     if (!SX) SX=1;
145   }
146   mouse_info.x = LOWORD(lParam) * SX;
147   mouse_info.y = HIWORD(lParam) * SY;
148   switch (message) {
149   case WM_MOUSEMOVE:
150     mask |= 0x01;
151     break;
152   case WM_LBUTTONDOWN:
153   case WM_LBUTTONDBLCLK:
154     mouse_info.but |= 0x01;
155     mask |= 0x02;
156     mouse_info.llastx = mouse_info.x;
157     mouse_info.llasty = mouse_info.y;
158     mouse_info.lbcount++;
159     break;
160   case WM_LBUTTONUP:
161     mouse_info.but &= ~0x01;
162     mask |= 0x04;
163     break;
164   case WM_RBUTTONDOWN:
165   case WM_RBUTTONDBLCLK:
166     mouse_info.but |= 0x02;
167     mask |= 0x08;
168     mouse_info.rlastx = mouse_info.x;
169     mouse_info.rlasty = mouse_info.y;
170     mouse_info.rbcount++;
171     break;
172   case WM_RBUTTONUP:
173     mouse_info.but &= ~0x02;
174     mask |= 0x10;
175     break;
176   case WM_MBUTTONDOWN:
177   case WM_MBUTTONDBLCLK:
178     mouse_info.but |= 0x04;
179     mask |= 0x20;
180     break;
181   case WM_MBUTTONUP:
182     mouse_info.but &= ~0x04;
183     mask |= 0x40;
184     break;
185   }
186
187   if ((mask & mouse_info.callmask) && mouse_info.callback) {
188     MCALLDATA *data = calloc(1,sizeof(MCALLDATA));
189     data->proc = mouse_info.callback;
190     data->mask = mask & mouse_info.callmask;
191     data->but = mouse_info.but;
192     data->x = mouse_info.x;
193     data->y = mouse_info.y;
194     DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
195   }
196 }