Merge from vendor branch SENDMAIL:
[dragonfly.git] / lib / libvgl / mouse.c
1 /*-
2  * Copyright (c) 1991-1997 Søren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software withough specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD: src/lib/libvgl/mouse.c,v 1.3 1999/11/08 11:37:39 yokota Exp $
29  * $DragonFly: src/lib/libvgl/mouse.c,v 1.2 2003/06/17 04:26:52 dillon Exp $
30  */
31
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/signal.h>
36 #include <machine/console.h>
37 #include "vgl.h"
38
39 #define X 0xff
40 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
41         X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
42         X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
43         X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
44         X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
45         X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
46         X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
47         X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
48         X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
49         X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
50         0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0,
51         0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0,
52         0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
53         0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
54         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
55         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 };
58 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
59         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
60         0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61         0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
62         0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
63         0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
64         0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
65         0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
66         0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0,
67         0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
68         0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
69         0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
70         0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
71         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 };
76 #undef X
77 static VGLBitmap VGLMouseStdAndMask = 
78     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask);
79 static VGLBitmap VGLMouseStdOrMask = 
80     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
81 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
82 static byte map[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE];
83 static VGLBitmap VGLMouseSave = 
84     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, map);
85 static int VGLMouseVisible = 0;
86 static int VGLMouseFrozen = 0;
87 static int VGLMouseShown = 0;
88 static int VGLMouseXpos = 0;
89 static int VGLMouseYpos = 0;
90 static int VGLMouseButtons = 0;
91
92 void
93 VGLMousePointerShow()
94 {
95   byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE];
96   VGLBitmap buffer =
97     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
98   byte crtcidx, crtcval, gdcidx, gdcval;
99   int pos;
100
101   if (!VGLMouseVisible) {
102     VGLMouseVisible = 1;
103     crtcidx = inb(0x3c4);
104     crtcval = inb(0x3c5);
105     gdcidx = inb(0x3ce);
106     gdcval = inb(0x3cf);
107     __VGLBitmapCopy(VGLDisplay, VGLMouseXpos, VGLMouseYpos, 
108                   &VGLMouseSave, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
109     bcopy(VGLMouseSave.Bitmap, buffer.Bitmap, MOUSE_IMG_SIZE*MOUSE_IMG_SIZE);
110     for (pos = 0; pos <  MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++)
111       buffer.Bitmap[pos]=(buffer.Bitmap[pos]&~(VGLMouseAndMask->Bitmap[pos])) |
112                            VGLMouseOrMask->Bitmap[pos];
113     __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay, 
114                   VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
115     outb(0x3c4, crtcidx);
116     outb(0x3c5, crtcval);
117     outb(0x3ce, gdcidx);
118     outb(0x3cf, gdcval);
119   }
120 }
121
122 void
123 VGLMousePointerHide()
124 {
125   byte crtcidx, crtcval, gdcidx, gdcval;
126
127   if (VGLMouseVisible) {
128     VGLMouseVisible = 0;
129     crtcidx = inb(0x3c4);
130     crtcval = inb(0x3c5);
131     gdcidx = inb(0x3ce);
132     gdcval = inb(0x3cf);
133     __VGLBitmapCopy(&VGLMouseSave, 0, 0, VGLDisplay, 
134                   VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
135     outb(0x3c4, crtcidx);
136     outb(0x3c5, crtcval);
137     outb(0x3ce, gdcidx);
138     outb(0x3cf, gdcval);
139   }
140 }
141
142 void
143 VGLMouseMode(int mode)
144 {
145   if (mode == VGL_MOUSESHOW) {
146     if (VGLMouseShown == VGL_MOUSEHIDE) {
147       VGLMousePointerShow();
148       VGLMouseShown = VGL_MOUSESHOW;
149     }
150   }
151   else {
152     if (VGLMouseShown == VGL_MOUSESHOW) {
153       VGLMousePointerHide();
154       VGLMouseShown = VGL_MOUSEHIDE;
155     }
156   }
157 }
158
159 void
160 VGLMouseAction(int dummy)       
161 {
162   struct mouse_info mouseinfo;
163
164   if (VGLMouseFrozen) {
165     VGLMouseFrozen++;
166     return;
167   }
168   mouseinfo.operation = MOUSE_GETINFO;
169   ioctl(0, CONS_MOUSECTL, &mouseinfo);
170   if (VGLMouseShown == VGL_MOUSESHOW)
171     VGLMousePointerHide();
172   VGLMouseXpos = mouseinfo.u.data.x;
173   VGLMouseYpos = mouseinfo.u.data.y;
174   VGLMouseButtons = mouseinfo.u.data.buttons;
175   if (VGLMouseShown == VGL_MOUSESHOW)
176     VGLMousePointerShow();
177 }
178
179 void
180 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
181 {
182   if (VGLMouseShown == VGL_MOUSESHOW)
183     VGLMousePointerHide();
184   VGLMouseAndMask = AndMask;
185   VGLMouseOrMask = OrMask;
186   if (VGLMouseShown == VGL_MOUSESHOW)
187     VGLMousePointerShow();
188 }
189
190 void
191 VGLMouseSetStdImage()
192 {
193   if (VGLMouseShown == VGL_MOUSESHOW)
194     VGLMousePointerHide();
195   VGLMouseAndMask = &VGLMouseStdAndMask;
196   VGLMouseOrMask = &VGLMouseStdOrMask;
197   if (VGLMouseShown == VGL_MOUSESHOW)
198     VGLMousePointerShow();
199 }
200
201 int
202 VGLMouseInit(int mode)
203 {
204   struct mouse_info mouseinfo;
205   int error;
206
207   VGLMouseSetStdImage();
208   mouseinfo.operation = MOUSE_MODE;
209   mouseinfo.u.mode.signal = SIGUSR2;
210   if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo)))
211     return error;
212   signal(SIGUSR2, VGLMouseAction);
213   mouseinfo.operation = MOUSE_GETINFO;
214   ioctl(0, CONS_MOUSECTL, &mouseinfo);
215   VGLMouseXpos = mouseinfo.u.data.x;
216   VGLMouseYpos = mouseinfo.u.data.y;
217   VGLMouseButtons = mouseinfo.u.data.buttons;
218   VGLMouseMode(mode);
219   return 0;
220 }
221
222 int
223 VGLMouseStatus(int *x, int *y, char *buttons)
224 {
225   signal(SIGUSR2, SIG_IGN);
226   *x =  VGLMouseXpos;
227   *y =  VGLMouseYpos;
228   *buttons =  VGLMouseButtons;
229   signal(SIGUSR2, VGLMouseAction);
230   return VGLMouseShown;
231 }
232
233 int
234 VGLMouseFreeze(int x, int y, int width, int hight, byte color)
235 {
236   if (!VGLMouseFrozen) {
237     VGLMouseFrozen = 1;
238     if (width > 1 || hight > 1) {               /* bitmap */
239       if (VGLMouseShown == 1) {
240         int overlap;
241
242         if (x > VGLMouseXpos)
243           overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
244         else
245           overlap = (x + width) - VGLMouseXpos;
246         if (overlap > 0) {
247           if (y > VGLMouseYpos)
248             overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
249           else
250             overlap = (y + hight) - VGLMouseYpos;
251           if (overlap > 0)
252             VGLMousePointerHide();
253         } 
254       }
255     }
256     else {                              /* bit */
257       if (VGLMouseShown &&
258           x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
259           y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) {
260         VGLMouseSave.Bitmap[(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)] =
261           (color);
262         if (VGLMouseAndMask->Bitmap 
263           [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) {
264           return 1;
265         }   
266       }       
267     }
268   }
269   return 0;
270 }
271
272 void
273 VGLMouseUnFreeze()
274 {
275   if (VGLMouseFrozen > 1) {
276     VGLMouseFrozen = 0;
277     VGLMouseAction(0);
278   }
279   else {
280     VGLMouseFrozen = 0;
281     if (VGLMouseShown == VGL_MOUSESHOW && !VGLMouseVisible)
282       VGLMousePointerShow();
283   }
284 }