initial commit
[dos_imgv] / src / mouse.c
1 #include <conio.h>
2 #include <i86.h>
3 #include <dos.h>
4 #include "mouse.h"
5
6 #define EVQ_SIZE        16
7 static struct mouse_event evbuf[EVQ_SIZE];
8 static int evwr, evrd;
9
10 struct mouse_state mouse;
11
12 int init_mouse(void)
13 {
14         if(!_dos_getvect(0x33)) {
15                 mouse.active = 0;
16                 return -1;
17         }
18         return reset_mouse();
19 }
20
21 int reset_mouse(void)
22 {
23         union REGS regs = {0};
24         
25         int386(0x33, &regs, &regs);
26         if(regs.w.ax != 0xffff) {
27                 mouse.active = 0;
28                 return -1;
29         }
30
31         /* read initial mouse state */
32         mouse.active = 1;
33         mouse.visible = 0;
34         mouse.bn = mouse_state(&mouse.x, &mouse.y);
35         mouse.dx = mouse.dy = 0;
36
37         evwr = evrd = 0;        /* reset event queue pointers */
38         return 0;
39 }
40
41 void set_mouse_bounds(int x, int y, int w, int h)
42 {
43         union REGS regs = {0};
44
45         regs.w.ax = 7;
46         regs.w.cx = x;
47         regs.w.dx = x + w - 1;
48         int386(0x33, &regs, &regs);
49
50         regs.w.ax = 8;
51         regs.w.cx = y;
52         regs.w.dx = y + h - 1;
53         int386(0x33, &regs, &regs);
54 }
55
56 void show_mouse(int en)
57 {
58         union REGS regs = {0};
59
60         if(en) {
61                 if(mouse.visible) return;
62
63                 regs.w.ax = 1;
64                 int386(0x33, &regs, &regs);
65         } else {
66                 if(!mouse.visible) return;
67
68                 regs.w.ax = 2;
69                 int386(0x33, &regs, &regs);
70         }
71 }
72
73 void move_mouse(int x, int y)
74 {
75         union REGS regs = {0};
76         regs.w.ax = 4;
77         regs.w.cx = x;
78         regs.w.dx = y;
79         int386(0x33, &regs, &regs);
80 }
81
82 int mouse_state(int *xp, int *yp)
83 {
84         union REGS regs = {0};
85         regs.w.ax = 3;
86         int386(0x33, &regs, &regs);
87
88         if(xp) *xp = regs.w.cx;
89         if(yp) *yp = regs.w.dx;
90         return regs.w.bx;
91 }
92
93 void mouse_delta(int *dx, int *dy)
94 {
95         union REGS regs = {0};
96         regs.w.ax = 0xb;
97         int386(0x33, &regs, &regs);
98
99         *dx = regs.w.cx;
100         *dy = regs.w.dx;
101 }
102
103 int proc_mouse(void)
104 {
105         int x, y, bn, bndelta, bidx, next;
106         int evcount = 0;
107         struct mouse_event *ev;
108
109         bn = mouse_state(&x, &y);
110         mouse.dx = x - mouse.x;
111         mouse.dy = y - mouse.y;
112         mouse.x = x;
113         mouse.y = y;
114
115         if(mouse.dx | mouse.dy) {
116                 next = (evwr + 1) & (EVQ_SIZE - 1);
117                 if(next != evrd) {
118                         ev = evbuf + evwr;
119                         evwr = next;
120                         ev->type = MOUSE_MOTION;
121                         ev->x = x;
122                         ev->y = y;
123                         ev->dx = mouse.dx;
124                         ev->dy = mouse.dy;
125                         evcount++;
126                 }
127         }
128
129         bndelta = bn ^ mouse.bn;
130         mouse.bn = bn;
131         bidx = 0;
132
133         while(bndelta) {
134                 if(bndelta & 1) {
135                         next = (evwr + 1) & (EVQ_SIZE - 1);
136                         if(next != evrd) {
137                                 ev = evbuf + evwr;
138                                 evwr = next;
139                                 ev->type = MOUSE_BUTTON;
140                                 ev->button = bidx;
141                                 ev->state = bn & 1;
142                                 ev->x = x;
143                                 ev->y = y;
144                                 evcount++;
145                         }
146                 }
147                 bn >>= 1;
148                 bndelta >>= 1;
149                 bidx++;
150         }
151
152         return evcount;
153 }
154
155 int next_mouse_event(struct mouse_event *ev)
156 {
157         if(evrd == evwr) return 0;
158
159         *ev = evbuf[evrd];
160         evrd = (evrd + 1) & (EVQ_SIZE - 1);
161         return 1;
162 }