Implemented a dynamic table of DOS interrupt handlers.
[wine] / msdos / 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 "callback.h"
14 #include "dosexe.h"
15 #include "vga.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(int);
19
20 static struct
21 {
22   DWORD x, y, but;
23   FARPROC16 callback;
24   WORD callmask;
25 } mouse_info;
26
27 /**********************************************************************
28  *          INT_Int33Handler
29  *
30  * Handler for int 33h (MS MOUSE).
31  */
32 void WINAPI INT_Int33Handler( CONTEXT86 *context )
33 {
34   switch (LOWORD(context->Eax)) {
35   case 0x00:
36     TRACE("Reset mouse driver and request status\n");
37     AX_reg(context) = 0xFFFF; /* installed */
38     BX_reg(context) = 3;      /* # of buttons */
39     memset( &mouse_info, 0, sizeof(mouse_info) );
40     break;
41   case 0x01:
42     FIXME("Show mouse cursor\n");
43     break;
44   case 0x02:
45     FIXME("Hide mouse cursor\n");
46     break;
47   case 0x03:
48     TRACE("Return mouse position and button status\n");
49     BX_reg(context) = mouse_info.but;
50     CX_reg(context) = mouse_info.x;
51     DX_reg(context) = mouse_info.y;
52     break;
53   case 0x04:
54     FIXME("Position mouse cursor\n");
55     break;
56   case 0x07:
57     FIXME("Define horizontal mouse cursor range\n");
58     break;
59   case 0x08:
60     FIXME("Define vertical mouse cursor range\n");
61     break;
62   case 0x09:
63     FIXME("Define graphics mouse cursor\n");
64     break;
65   case 0x0A:
66     FIXME("Define text mouse cursor\n");
67     break;
68   case 0x0C:
69     TRACE("Define mouse interrupt subroutine\n");
70     mouse_info.callmask = CX_reg(context);
71     mouse_info.callback = (FARPROC16)MAKESEGPTR(context->SegEs, LOWORD(context->Edx));
72     break;
73   case 0x10:
74     FIXME("Define screen region for update\n");
75     break;
76   default:
77     INT_BARF(context,0x33);
78   }
79 }
80
81 typedef struct {
82   FARPROC16 proc;
83   WORD mask,but,x,y,mx,my;
84 } MCALLDATA;
85
86 static void MouseRelay(CONTEXT86 *context,void *mdata)
87 {
88   MCALLDATA *data = (MCALLDATA *)mdata;
89   CONTEXT86 ctx = *context;
90
91   ctx.Eax   = data->mask;
92   ctx.Ebx   = data->but;
93   ctx.Ecx   = data->x;
94   ctx.Edx   = data->y;
95   ctx.Esi   = data->mx;
96   ctx.Edi   = data->my;
97   ctx.SegCs = SELECTOROF(data->proc);
98   ctx.Eip   = OFFSETOF(data->proc);
99   free(data);
100   DPMI_CallRMProc(&ctx, NULL, 0, 0);
101 }
102
103 void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
104 {
105   WORD mask = 0;
106   unsigned Height, Width, SX=1, SY=1;
107
108   if (!VGA_GetMode(&Height,&Width,NULL)) {
109     /* may need to do some coordinate scaling */
110     SX = 640/Width;
111     if (!SX) SX=1;
112   }
113   mouse_info.x = LOWORD(lParam) * SX;
114   mouse_info.y = HIWORD(lParam) * SY;
115   switch (message) {
116   case WM_MOUSEMOVE:
117     mask |= 0x01;
118     break;
119   case WM_LBUTTONDOWN:
120   case WM_LBUTTONDBLCLK:
121     mouse_info.but |= 0x01;
122     mask |= 0x02;
123     break;
124   case WM_LBUTTONUP:
125     mouse_info.but &= ~0x01;
126     mask |= 0x04;
127     break;
128   case WM_RBUTTONDOWN:
129   case WM_RBUTTONDBLCLK:
130     mouse_info.but |= 0x02;
131     mask |= 0x08;
132     break;
133   case WM_RBUTTONUP:
134     mouse_info.but &= ~0x02;
135     mask |= 0x10;
136     break;
137   case WM_MBUTTONDOWN:
138   case WM_MBUTTONDBLCLK:
139     mouse_info.but |= 0x04;
140     mask |= 0x20;
141     break;
142   case WM_MBUTTONUP:
143     mouse_info.but &= ~0x04;
144     mask |= 0x40;
145     break;
146   }
147
148   if ((mask & mouse_info.callmask) && mouse_info.callback) {
149     MCALLDATA *data = calloc(1,sizeof(MCALLDATA));
150     data->proc = mouse_info.callback;
151     data->mask = mask & mouse_info.callmask;
152     data->but = mouse_info.but;
153     data->x = mouse_info.x;
154     data->y = mouse_info.y;
155     Dosvm.QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
156   }
157 }