mouse.c revision 28328
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 *  $Id: mouse.c,v 1.10 1997/08/15 12:32:59 sos Exp $
29 */
30
31#include <stdio.h>
32#include <sys/types.h>
33#include <sys/ioctl.h>
34#include <sys/signal.h>
35#include <machine/console.h>
36#include "vgl.h"
37
38/* prototype for internal function */
39int __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, VGLBitmap *dst, int dstx, int dsty, int width, int hight);
40
41#define X 0xff
42static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
43	X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
44	X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
45	X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
46	X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
47	X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
48	X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
49	X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
50	X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
51	X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
52	0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0,
53	0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0,
54	0,0,0,0,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,0,0,0,0,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};
60static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
61	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62	0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63	0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
64	0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
65	0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
66	0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
67	0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
68	0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0,
69	0,0,0,0,X,X,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,0,X,X,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,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	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};
78#undef X
79static VGLBitmap VGLMouseStdAndMask =
80	{ MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask };
81static VGLBitmap VGLMouseStdOrMask =
82	{ MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask };
83static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
84static byte map[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE];
85static VGLBitmap VGLMouseSave = { MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, map};
86static int VGLMouseVisible = 0;
87static int VGLMouseFrozen = 0;
88static int VGLMouseShown = 0;
89static int VGLMouseXpos = 0;
90static int VGLMouseYpos = 0;
91static int VGLMouseButtons = 0;
92
93void
94VGLMousePointerShow()
95{
96  byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE];
97  VGLBitmap buffer = { 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
122void
123VGLMousePointerHide()
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
142void
143VGLMouseMode(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
159void
160VGLMouseAction(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
179void
180VGLMouseSetImage(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
190void
191VGLMouseSetStdImage()
192{
193  if (VGLMouseShown == VGL_MOUSESHOW)
194    VGLMousePointerHide();
195  VGLMouseAndMask = &VGLMouseStdAndMask;
196  VGLMouseOrMask = &VGLMouseStdOrMask;
197  if (VGLMouseShown == VGL_MOUSESHOW)
198    VGLMousePointerShow();
199}
200
201int
202VGLMouseInit(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
222int
223VGLMouseStatus(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
233int
234VGLMouseFreeze(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
272void
273VGLMouseUnFreeze()
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}
285