/*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991-1997 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "vgl.h" #define X 0xff static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = { X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0, X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0, X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0, X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0, X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0, X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0, X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0, X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, 0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0, 0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0, 0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0, 0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0, 0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0, 0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0, 0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, 0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; #undef X static VGLBitmap VGLMouseStdAndMask = VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask); static VGLBitmap VGLMouseStdOrMask = VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask); static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask; static byte map[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4]; static VGLBitmap VGLMouseSave = VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, map); static int VGLMouseVisible = 0; static int VGLMouseShown = 0; static int VGLMouseXpos = 0; static int VGLMouseYpos = 0; static int VGLMouseButtons = 0; static volatile sig_atomic_t VGLMintpending; static volatile sig_atomic_t VGLMsuppressint; #define INTOFF() (VGLMsuppressint++) #define INTON() do { \ if (--VGLMsuppressint == 0 && VGLMintpending) \ VGLMouseAction(0); \ } while (0) void VGLMousePointerShow() { byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4]; VGLBitmap buffer = VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf); byte crtcidx, crtcval, gdcidx, gdcval; int i, pos, pos1; if (!VGLMouseVisible) { INTOFF(); VGLMouseVisible = 1; crtcidx = inb(0x3c4); crtcval = inb(0x3c5); gdcidx = inb(0x3ce); gdcval = inb(0x3cf); __VGLBitmapCopy(VGLDisplay, VGLMouseXpos, VGLMouseYpos, &VGLMouseSave, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); bcopy(VGLMouseSave.Bitmap, buffer.Bitmap, MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*VGLDisplay->PixelBytes); for (pos = 0; pos < MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++) for (i = 0; i < VGLDisplay->PixelBytes; i++) { pos1 = pos * VGLDisplay->PixelBytes + i; buffer.Bitmap[pos1] = (buffer.Bitmap[pos1] & ~VGLMouseAndMask->Bitmap[pos]) | VGLMouseOrMask->Bitmap[pos]; } __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay, VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); outb(0x3c4, crtcidx); outb(0x3c5, crtcval); outb(0x3ce, gdcidx); outb(0x3cf, gdcval); INTON(); } } void VGLMousePointerHide() { byte crtcidx, crtcval, gdcidx, gdcval; if (VGLMouseVisible) { INTOFF(); VGLMouseVisible = 0; crtcidx = inb(0x3c4); crtcval = inb(0x3c5); gdcidx = inb(0x3ce); gdcval = inb(0x3cf); __VGLBitmapCopy(&VGLMouseSave, 0, 0, VGLDisplay, VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); outb(0x3c4, crtcidx); outb(0x3c5, crtcval); outb(0x3ce, gdcidx); outb(0x3cf, gdcval); INTON(); } } void VGLMouseMode(int mode) { if (mode == VGL_MOUSESHOW) { if (VGLMouseShown == VGL_MOUSEHIDE) { VGLMousePointerShow(); VGLMouseShown = VGL_MOUSESHOW; } } else { if (VGLMouseShown == VGL_MOUSESHOW) { VGLMousePointerHide(); VGLMouseShown = VGL_MOUSEHIDE; } } } void VGLMouseAction(int dummy) { struct mouse_info mouseinfo; if (VGLMsuppressint) { VGLMintpending = 1; return; } again: INTOFF(); VGLMintpending = 0; mouseinfo.operation = MOUSE_GETINFO; ioctl(0, CONS_MOUSECTL, &mouseinfo); if (VGLMouseShown == VGL_MOUSESHOW) VGLMousePointerHide(); VGLMouseXpos = mouseinfo.u.data.x; VGLMouseYpos = mouseinfo.u.data.y; VGLMouseButtons = mouseinfo.u.data.buttons; if (VGLMouseShown == VGL_MOUSESHOW) VGLMousePointerShow(); /* * Loop to handle any new (suppressed) signals. This is INTON() without * recursion. !SA_RESTART prevents recursion in signal handling. So the * maximum recursion is 2 levels. */ VGLMsuppressint = 0; if (VGLMintpending) goto again; } void VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask) { if (VGLMouseShown == VGL_MOUSESHOW) VGLMousePointerHide(); VGLMouseAndMask = AndMask; VGLMouseOrMask = OrMask; if (VGLMouseShown == VGL_MOUSESHOW) VGLMousePointerShow(); } void VGLMouseSetStdImage() { if (VGLMouseShown == VGL_MOUSESHOW) VGLMousePointerHide(); VGLMouseAndMask = &VGLMouseStdAndMask; VGLMouseOrMask = &VGLMouseStdOrMask; if (VGLMouseShown == VGL_MOUSESHOW) VGLMousePointerShow(); } int VGLMouseInit(int mode) { struct mouse_info mouseinfo; int error, i, mask; switch (VGLModeInfo.vi_mem_model) { case V_INFO_MM_PACKED: case V_INFO_MM_PLANAR: mask = 0x0f; break; case V_INFO_MM_VGAX: mask = 0x3f; break; default: mask = 0xff; break; } for (i = 0; i < 256; i++) VGLMouseStdOrMask.Bitmap[i] &= mask; VGLMouseSetStdImage(); mouseinfo.operation = MOUSE_MODE; mouseinfo.u.mode.signal = SIGUSR2; if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo))) return error; signal(SIGUSR2, VGLMouseAction); mouseinfo.operation = MOUSE_GETINFO; ioctl(0, CONS_MOUSECTL, &mouseinfo); VGLMouseXpos = mouseinfo.u.data.x; VGLMouseYpos = mouseinfo.u.data.y; VGLMouseButtons = mouseinfo.u.data.buttons; VGLMouseMode(mode); return 0; } int VGLMouseStatus(int *x, int *y, char *buttons) { INTOFF(); *x = VGLMouseXpos; *y = VGLMouseYpos; *buttons = VGLMouseButtons; INTON(); return VGLMouseShown; } int VGLMouseFreeze(int x, int y, int width, int hight, u_long color) { int i, xstride, ystride; INTOFF(); if (width > 1 || hight > 1 || (color & 0xc0000000) == 0) { /* bitmap */ if (VGLMouseShown == 1) { int overlap; if (x > VGLMouseXpos) overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x; else overlap = (x + width) - VGLMouseXpos; if (overlap > 0) { if (y > VGLMouseYpos) overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y; else overlap = (y + hight) - VGLMouseYpos; if (overlap > 0) VGLMousePointerHide(); } } } else { /* bit */ if (VGLMouseShown && x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE && y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) { xstride = VGLDisplay->PixelBytes; ystride = MOUSE_IMG_SIZE * xstride; if (color & 0x40000000) { /* Get */ color = 0; for (i = xstride - 1; i >= 0; i--) color = (color << 8) | VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+ (x-VGLMouseXpos)*xstride+i]; return 0x40000000 | (color & 0xffffff); } else { /* Set */ color &= 0xffffff; /* discard flag and other garbage */ for (i = 0; i < xstride; i++, color >>= 8) VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+ (x-VGLMouseXpos)*xstride+i] = color; if (VGLMouseAndMask->Bitmap [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) { return 1; } } } } return 0; } void VGLMouseUnFreeze() { if (VGLMouseShown == VGL_MOUSESHOW && !VGLMouseVisible && !VGLMintpending) VGLMousePointerShow(); while (VGLMsuppressint) INTON(); }