]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libvgl/mouse.c
Fix warnings with lib/libpmc
[FreeBSD/FreeBSD.git] / lib / libvgl / mouse.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1991-1997 Søren Schmidt
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in this position and unchanged.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/signal.h>
38 #include <sys/consio.h>
39 #include <sys/fbio.h>
40 #include "vgl.h"
41
42 #define X 0xff
43 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
44         X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
45         X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
46         X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
47         X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
48         X,X,X,X,X,X,0,0,0,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         X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
51         X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
52         X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
53         0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0,
54         0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0,
55         0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
56         0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
57         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
59         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
60 };
61 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
62         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63         0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64         0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
65         0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
66         0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
67         0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
68         0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
69         0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0,
70         0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
71         0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
72         0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
73         0,0,0,0,0,X,X,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         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
78 };
79 #undef X
80 static VGLBitmap VGLMouseStdAndMask = 
81     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask);
82 static VGLBitmap VGLMouseStdOrMask = 
83     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
84 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
85 static byte map[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
86 static VGLBitmap VGLMouseSave = 
87     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, map);
88 static int VGLMouseVisible = 0;
89 static int VGLMouseShown = 0;
90 static int VGLMouseXpos = 0;
91 static int VGLMouseYpos = 0;
92 static int VGLMouseButtons = 0;
93 static volatile sig_atomic_t VGLMintpending;
94 static volatile sig_atomic_t VGLMsuppressint;
95
96 #define INTOFF()        (VGLMsuppressint++)
97 #define INTON()         do {                                            \
98                                 if (--VGLMsuppressint == 0 && VGLMintpending) \
99                                         VGLMouseAction(0);              \
100                         } while (0)
101
102 void
103 VGLMousePointerShow()
104 {
105   byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
106   VGLBitmap buffer =
107     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
108   byte crtcidx, crtcval, gdcidx, gdcval;
109   int i, pos, pos1;
110
111   if (!VGLMouseVisible) {
112     INTOFF();
113     VGLMouseVisible = 1;
114     crtcidx = inb(0x3c4);
115     crtcval = inb(0x3c5);
116     gdcidx = inb(0x3ce);
117     gdcval = inb(0x3cf);
118     __VGLBitmapCopy(VGLDisplay, VGLMouseXpos, VGLMouseYpos, 
119                   &VGLMouseSave, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
120     bcopy(VGLMouseSave.Bitmap, buffer.Bitmap,
121           MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*VGLDisplay->PixelBytes);
122     for (pos = 0; pos <  MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++)
123       for (i = 0; i < VGLDisplay->PixelBytes; i++) {
124         pos1 = pos * VGLDisplay->PixelBytes + i;
125         buffer.Bitmap[pos1] = (buffer.Bitmap[pos1] &
126                                ~VGLMouseAndMask->Bitmap[pos]) |
127                               VGLMouseOrMask->Bitmap[pos];
128       }
129     __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay, 
130                   VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
131     outb(0x3c4, crtcidx);
132     outb(0x3c5, crtcval);
133     outb(0x3ce, gdcidx);
134     outb(0x3cf, gdcval);
135     INTON();
136   }
137 }
138
139 void
140 VGLMousePointerHide()
141 {
142   byte crtcidx, crtcval, gdcidx, gdcval;
143
144   if (VGLMouseVisible) {
145     INTOFF();
146     VGLMouseVisible = 0;
147     crtcidx = inb(0x3c4);
148     crtcval = inb(0x3c5);
149     gdcidx = inb(0x3ce);
150     gdcval = inb(0x3cf);
151     __VGLBitmapCopy(&VGLMouseSave, 0, 0, VGLDisplay, 
152                   VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
153     outb(0x3c4, crtcidx);
154     outb(0x3c5, crtcval);
155     outb(0x3ce, gdcidx);
156     outb(0x3cf, gdcval);
157     INTON();
158   }
159 }
160
161 void
162 VGLMouseMode(int mode)
163 {
164   if (mode == VGL_MOUSESHOW) {
165     if (VGLMouseShown == VGL_MOUSEHIDE) {
166       VGLMousePointerShow();
167       VGLMouseShown = VGL_MOUSESHOW;
168     }
169   }
170   else {
171     if (VGLMouseShown == VGL_MOUSESHOW) {
172       VGLMousePointerHide();
173       VGLMouseShown = VGL_MOUSEHIDE;
174     }
175   }
176 }
177
178 void
179 VGLMouseAction(int dummy)       
180 {
181   struct mouse_info mouseinfo;
182
183   if (VGLMsuppressint) {
184     VGLMintpending = 1;
185     return;
186   }
187 again:
188   INTOFF();
189   VGLMintpending = 0;
190   mouseinfo.operation = MOUSE_GETINFO;
191   ioctl(0, CONS_MOUSECTL, &mouseinfo);
192   if (VGLMouseShown == VGL_MOUSESHOW)
193     VGLMousePointerHide();
194   VGLMouseXpos = mouseinfo.u.data.x;
195   VGLMouseYpos = mouseinfo.u.data.y;
196   VGLMouseButtons = mouseinfo.u.data.buttons;
197   if (VGLMouseShown == VGL_MOUSESHOW)
198     VGLMousePointerShow();
199
200   /* 
201    * Loop to handle any new (suppressed) signals.  This is INTON() without
202    * recursion.  !SA_RESTART prevents recursion in signal handling.  So the
203    * maximum recursion is 2 levels.
204    */
205   VGLMsuppressint = 0;
206   if (VGLMintpending)
207     goto again;
208 }
209
210 void
211 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
212 {
213   if (VGLMouseShown == VGL_MOUSESHOW)
214     VGLMousePointerHide();
215   VGLMouseAndMask = AndMask;
216   VGLMouseOrMask = OrMask;
217   if (VGLMouseShown == VGL_MOUSESHOW)
218     VGLMousePointerShow();
219 }
220
221 void
222 VGLMouseSetStdImage()
223 {
224   if (VGLMouseShown == VGL_MOUSESHOW)
225     VGLMousePointerHide();
226   VGLMouseAndMask = &VGLMouseStdAndMask;
227   VGLMouseOrMask = &VGLMouseStdOrMask;
228   if (VGLMouseShown == VGL_MOUSESHOW)
229     VGLMousePointerShow();
230 }
231
232 int
233 VGLMouseInit(int mode)
234 {
235   struct mouse_info mouseinfo;
236   int error, i, mask;
237
238   switch (VGLModeInfo.vi_mem_model) {
239   case V_INFO_MM_PACKED:
240   case V_INFO_MM_PLANAR:
241     mask = 0x0f;
242     break;
243   case V_INFO_MM_VGAX:
244     mask = 0x3f;
245     break;
246   default:
247     mask = 0xff;
248     break;
249   }
250   for (i = 0; i < 256; i++)
251     VGLMouseStdOrMask.Bitmap[i] &= mask;
252   VGLMouseSetStdImage();
253   mouseinfo.operation = MOUSE_MODE;
254   mouseinfo.u.mode.signal = SIGUSR2;
255   if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo)))
256     return error;
257   signal(SIGUSR2, VGLMouseAction);
258   mouseinfo.operation = MOUSE_GETINFO;
259   ioctl(0, CONS_MOUSECTL, &mouseinfo);
260   VGLMouseXpos = mouseinfo.u.data.x;
261   VGLMouseYpos = mouseinfo.u.data.y;
262   VGLMouseButtons = mouseinfo.u.data.buttons;
263   VGLMouseMode(mode);
264   return 0;
265 }
266
267 int
268 VGLMouseStatus(int *x, int *y, char *buttons)
269 {
270   INTOFF();
271   *x =  VGLMouseXpos;
272   *y =  VGLMouseYpos;
273   *buttons =  VGLMouseButtons;
274   INTON();
275   return VGLMouseShown;
276 }
277
278 int
279 VGLMouseFreeze(int x, int y, int width, int hight, u_long color)
280 {
281   int i, xstride, ystride;
282
283     INTOFF();
284     if (width > 1 || hight > 1 || (color & 0xc0000000) == 0) { /* bitmap */
285       if (VGLMouseShown == 1) {
286         int overlap;
287
288         if (x > VGLMouseXpos)
289           overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
290         else
291           overlap = (x + width) - VGLMouseXpos;
292         if (overlap > 0) {
293           if (y > VGLMouseYpos)
294             overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
295           else
296             overlap = (y + hight) - VGLMouseYpos;
297           if (overlap > 0)
298             VGLMousePointerHide();
299         } 
300       }
301     }
302     else {                              /* bit */
303       if (VGLMouseShown &&
304           x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
305           y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) {
306         xstride = VGLDisplay->PixelBytes;
307         ystride = MOUSE_IMG_SIZE * xstride;
308         if (color & 0x40000000) {       /* Get */
309           color = 0;
310           for (i = xstride - 1; i >= 0; i--)
311             color = (color << 8) |
312                     VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+
313                                         (x-VGLMouseXpos)*xstride+i];
314           return 0x40000000 | (color & 0xffffff);
315         } else {                        /* Set */
316           color &= 0xffffff;            /* discard flag and other garbage */
317           for (i = 0; i < xstride; i++, color >>= 8)
318             VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+
319                                 (x-VGLMouseXpos)*xstride+i] = color;
320           if (VGLMouseAndMask->Bitmap 
321             [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) {
322             return 1;
323           }   
324         }   
325       }       
326     }
327   return 0;
328 }
329
330 void
331 VGLMouseUnFreeze()
332 {
333   if (VGLMouseShown == VGL_MOUSESHOW && !VGLMouseVisible && !VGLMintpending)
334     VGLMousePointerShow();
335   while (VGLMsuppressint)
336     INTON();
337 }