/* vi: set sw=4 ts=4: */ /* * KON2 - Kanji ON Console - * Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp) * * CCE - Console Chinese Environment - * Copyright (C) 1998-2003 Rui He (rhe@3eti.com) * * 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. * 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. * * 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 TERRENCE R. LAMBERT 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. * */ /* ATTENTION: Hard-coded /dev/sysmouse and MouseSystems for FreeBSD mouse you need to have moused running. Probably it's not a good idea? You can change the code below and use raw device /dev/psm0 and PS2 protocol, it also works(moused not running). */ #include #include #include #include #include #include struct mouseInfo mInfo; int mouseFd = -1; static int pasteButton = MOUSE_RGT; /* default is Right for GGI */ void HandleMouseSelection(void) { static char oldstat; if (mInfo.dx || mInfo.dy) { mInfo.x += mInfo.dx; mInfo.y += mInfo.dy; if (mInfo.x < 0) mInfo.x = 0; else if (mInfo.x > dispInfo.txmax-1) mInfo.x = dispInfo.txmax-1; if (mInfo.y < 0) mInfo.y = 0; else if (mInfo.y > dispInfo.tymax-1) mInfo.y = dispInfo.tymax-1; } if (mInfo.stat & MOUSE_LFT) { if (!(oldstat & MOUSE_LFT)) { mInfo.sx = mInfo.x; mInfo.sy = mInfo.y; TextRefresh(curCon); } else if (mInfo.dx || mInfo.dy) { TextReverse(curCon,mInfo.sx, mInfo.sy, mInfo.x, mInfo.y); TextRefresh(curCon); TextReverse(curCon,mInfo.sx, mInfo.sy, mInfo.x, mInfo.y); } } else if (oldstat & MOUSE_LFT) TextCopy(curCon,mInfo.sx, mInfo.sy, mInfo.x, mInfo.y); if (mInfo.stat & pasteButton && !(oldstat & pasteButton)) TextPaste(curCon); oldstat = mInfo.stat; } #if defined(SUPPORT_MOUSE) #include #include #include "getcap.h" #include "errors.h" #ifdef SUPPORT_GPMMOUSE #include "term.h" /* for VtNum */ #include "gpm.h" static int OpenGpmMouse(int ttyno); static int HandleGpmMouseEvent(int gpm); #endif /* SUPPORT_GPMMOUSE */ static int cFlag; static int headMask; static int headId; static int dataMask; static int pkMax; mtype mouseType = MOUSE_NONE; #define MAX_PK_SIZE 5 struct mouseconf { const char *name; mtype type; int cFlag; int headMask; int headId; int dataMask; int pkMax; } mice[] = { { "Microsoft", MOUSE_MICROSOFT, (CS7|CREAD|CLOCAL|HUPCL), 0x40, 0x40, 0x40, 3 }, { "MouseSystems", MOUSE_MOUSESYSTEMS, (CS8|CSTOPB|CREAD|CLOCAL|HUPCL), 0xf8, 0x80, 0x00, 5 }, { "BusMouse", MOUSE_BUSMOUSE, 0, 0xf8, 0x80, 0x00, 5 }, { "MmSeries", MOUSE_MMSERIES, (CS8|PARENB|PARODD|CREAD|CLOCAL|HUPCL), 0xe0, 0x80, 0x80, 3 }, { "Logitech", MOUSE_LOGITECH, (CS8|CSTOPB|CREAD|CLOCAL|HUPCL), 0xe0, 0x80, 0x80, 3 }, { "PS2", MOUSE_PS2, (CS8|CREAD|CLOCAL|HUPCL), 0xcc, 0x08, 0x00, 3 }, { "None", MOUSE_NONE, 0, 0, 0, 0, 0 }, { NULL, MOUSE_NONE, 0, 0, 0, 0, 0 } }; static int mouseBaud; static int ConfigMouseBaud(const char *config) { int baud; sscanf(config, "%d", &baud); switch (baud) { case 9600: mouseBaud = B9600; break; case 4800: mouseBaud = B4800; break; case 2400: mouseBaud = B2400; break; default: warn("Invalid mouse baud rate %d; set to default (1200)\r\n", baud); case 1200: mouseBaud = B1200; break; } return SUCCESS; } static char *mouseDev; static int ConfigMouseDev(const char *config) { char name[MAX_COLS]; sscanf(config, "%255s", name); if (mouseDev) free(mouseDev); #if defined(__FreeBSD__) /* force to use sysmouse for FreeBSD, good? */ mouseDev = strdup("/dev/sysmouse"); #else mouseDev = strdup(name); #endif return SUCCESS; } static int Config3Buttons(const char *config) { pasteButton = BoolConf(config) ? MOUSE_MID: MOUSE_RGT; return SUCCESS; } static int ConfigMouse(const char *config) { struct mouseconf *p; char name[MAX_COLS]; mouseType = MOUSE_NONE; mInfo.has_mouse = FALSE; #if defined(SUPPORT_GPMMOUSE) && defined(linux) mouseFd = OpenGpmMouse(0); /* 0 will use current active console */ if (mouseFd >= 0) { message("Mouse type: Linux gpm mouse server.\r\n"); mInfo.has_mouse = TRUE; mouseType = MOUSE_GPM; write(0, "\E[?25l\E[?1c", 11); /* disable KD_TEXT mode cursor */ if (isatty(2)) { int nullfd = open("/dev/null", O_RDWR); if (nullfd >= 0) dup2(nullfd, 2); /* just redirect stderr to /dev/null */ } return SUCCESS; /* fail to open it */ } #endif #if defined(__FreeBSD__) /*force to use MouseSystems for FreeBSD */ strcpy(name, "MouseSystems"); #else sscanf(config, "%255s", name); #endif for (p = mice; p->name != NULL; p++) { if (strcasecmp(name, p->name) == 0) { mouseType = p->type; if (mouseType == MOUSE_NONE) return SUCCESS; message("Mouse type `%s', correct? If not, change cce.cfg\r\n", name); mInfo.has_mouse = TRUE; cFlag = p->cFlag; headMask = p->headMask; headId = p->headId; dataMask = p->dataMask; pkMax = p->pkMax; if (mouseType != MOUSE_BUSMOUSE) { DefineCap("MouseBaud", ConfigMouseBaud, "1200"); } DefineCap("MouseDev", ConfigMouseDev, "/dev/mouse"); return SUCCESS; } } warn("Unknown mouse type `%s' ignored; assuming no mouse\r\n", name); return SUCCESS; } static void MouseSetBaud(int mfd, u_short baud, u_short cflag) { struct termios mio; char *cf; tcgetattr(mfd, &mio); mio.c_iflag = IGNBRK | IGNPAR; mio.c_oflag = 0; mio.c_lflag = 0; #ifdef linux mio.c_line = 0; #endif mio.c_cc[VTIME] = 0; mio.c_cc[VMIN] = 1; mio.c_cflag = cflag; cfsetispeed(&mio, baud); cfsetospeed(&mio, baud); tcsetattr(mfd, TCSAFLUSH, &mio); switch(mouseBaud) { case B9600: cf = "*q"; break; case B4800: cf = "*p"; break; case B2400: cf = "*o"; break; case B1200: cf = "*n"; break; default: cf = "*n"; break; } mio.c_cflag = cflag; cfsetispeed(&mio, mouseBaud); cfsetospeed(&mio, mouseBaud); write(mfd, cf, 2); usleep(100000); tcsetattr(mfd, TCSAFLUSH, &mio); } void MouseInit(void) { mInfo.has_mouse = TRUE; DefineCap("Mouse", ConfigMouse, "NONE"); DefineCap("Mouse3Buttons", Config3Buttons, "Off"); } int MouseAttach(void) { int mfd; #ifdef SUPPORT_GPMMOUSE if (mouseType == MOUSE_GPM) { } else #endif { if (!mouseDev || ! *mouseDev) /* why,just for satety */ { mouseDev = NULL; mInfo.has_mouse = FALSE; mouseFd = -1; return -1; } mfd = open(mouseDev, O_RDWR|O_NONBLOCK); if (mfd < 0) { warn("Couldn't open mouse device; mouse disabled\r\n"); free(mouseDev); mouseDev = NULL; mouseFd = -1; mInfo.has_mouse = FALSE; return -1; } if (mouseType != MOUSE_BUSMOUSE) { MouseSetBaud(mfd, B9600, cFlag); MouseSetBaud(mfd, B4800, cFlag); MouseSetBaud(mfd, B2400, cFlag); MouseSetBaud(mfd, B1200, cFlag); if (mouseType == MOUSE_LOGITECH) { write(mfd, "S", 1); MouseSetBaud(mfd, mouseBaud, CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL); } write(mfd, "Q", 1); } mouseFd = mfd; } return(mouseFd); } void MouseDetach(void) { #ifdef SUPPORT_GPMMOUSE if (mouseType == MOUSE_GPM) { } else #endif { if (mouseFd >= 0) close(mouseFd); mouseFd = -1; } } void MouseCleanup(void) { #ifdef SUPPORT_GPMMOUSE if (mouseType == MOUSE_GPM) { Gpm_Close(); write(0, "\E[?25h\E[?0c", 11); /* enable KD_TEXT mode cursor */ } else #endif { if (mouseFd >= 0) close(mouseFd); } mouseFd = -1; } static void MouseAnalyzePacket(u_char *packet) { static int dx, dy; switch (mouseType) { case MOUSE_NONE: return; case MOUSE_MICROSOFT: mInfo.stat = ((packet[0] & 0x20) >> 3) | ((packet[0] & 0x10) >> 4); dx += (char)(((packet[0] & 0x03) << 6) | (packet[1] & 0x3F)); dy += (char)(((packet[0] & 0x0C) << 4) | (packet[2] & 0x3F)); break; case MOUSE_MOUSESYSTEMS: mInfo.stat = (~packet[0]) & 0x07; dx += (char)(packet[1]) + (char)(packet[3]); dy += - ((char)(packet[2]) + (char)(packet[4])); break; case MOUSE_MMSERIES: case MOUSE_LOGITECH: mInfo.stat = packet[0] & 0x07; dx += (packet[0] & 0x10) ? packet[1]: - packet[1]; dy += (packet[0] & 0x08) ? - packet[2]: packet[2]; break; case MOUSE_PS2: mInfo.stat = ((packet[0] & 0x01) << 2) | ((packet[0] & 0x02) >> 1); dx += (char)(packet[1]); dy -= (char)(packet[2]); break; case MOUSE_BUSMOUSE: mInfo.stat = (~packet[0]) & 0x07; dx += (char)packet[1]; dy += - (char)packet[2]; break; } mInfo.dx = dx >> 3; /* FIXME: Is here fixed for width=8 font?? why 3? */ dx -= mInfo.dx << 3; /* save dx % 8 */ mInfo.dy = dy / dispInfo.glineChar; dy -= mInfo.dy * dispInfo.glineChar; mInfo.sw = MOUSE_LIFETIME; HandleMouseSelection(); } static void MouseGetPacket(u_char *buff, int size) { static u_char packet[MAX_PK_SIZE]; static int stat = 0; int n; for (n = 0; n < size; n ++, buff ++) { if (!stat) { if ((*buff & headMask) == headId) { packet[0] = *buff; stat = 1; } continue; } if (mouseType != MOUSE_PS2 && ((*buff & dataMask) || *buff == 0x80)) { stat = 0; continue; } packet[stat] = *buff; stat ++; if (stat == pkMax) { MouseAnalyzePacket(packet); stat = 0; } } } void MouseHandleEvent(int fd) { #ifdef SUPPORT_GPMMOUSE if (mouseType == MOUSE_GPM) HandleGpmMouseEvent(fd); else #endif { int nRead; static u_char buff[256]; nRead = read(fd, buff, sizeof(buff)-1); if (nRead > 0) MouseGetPacket(buff, nRead); } } #ifdef SUPPORT_GPMMOUSE static int OpenGpmMouse(int ttyno) { Gpm_Connect gpmCon; int gpmfd; gpmCon.eventMask = ~0; /* GPM_MOVE|GPM_UP|GPM_DOWN; // get everything */ gpmCon.defaultMask = ~GPM_HARD; /* pass everything unused */ gpmCon.minMod = 0; /* run always */ gpmCon.maxMod = ~0; /* with any modifier */ gpmfd = Gpm_Open(&gpmCon, ttyno == 0 ? VtNum: ttyno); /* 0 for current vc, N to force the vc */ if (gpmfd < 0) { #ifdef DEBUG fprintf(stderr, "Can't open mouse connection at %d\r\n", ttyno); fprintf(stderr, "pid=%d, vc=%d\r\n",gpmCon.pid, gpmCon.vc); #endif return -1; } #ifdef DEBUG fprintf(stderr, "gpmfd=%d pid=%d, vc=%d gpm_fd=%d\r\n", gpmfd, gpmCon.pid, gpmCon.vc, gpm_fd); #endif return gpmfd; } int HandleGpmMouseEvent(int gpm) { Gpm_Event gpmEvent; if (Gpm_GetEvent(&gpmEvent) != 1) { warn("Unable to read a GPM mouse event.\n"); return -1; } if (gpmEvent.type & GPM_UP) /* mouse button up, buttons indicate which is up! */ mInfo.stat &= ~((gpmEvent.buttons & GPM_B_LEFT ? MOUSE_LFT: 0) | (gpmEvent.buttons & GPM_B_MIDDLE ? MOUSE_MID: 0) | (gpmEvent.buttons & GPM_B_RIGHT ? MOUSE_RGT: 0)); else mInfo.stat = (gpmEvent.buttons & GPM_B_LEFT ? MOUSE_LFT: 0) | (gpmEvent.buttons & GPM_B_MIDDLE ? MOUSE_MID: 0) | (gpmEvent.buttons & GPM_B_RIGHT ? MOUSE_RGT: 0); #if 0 mInfo.dx = gpmEvent.x-1 - mInfo.x; mInfo.dy = gpmEvent.y-1 - mInfo.y; /* gpm is 1-based */ #else mInfo.dx = gpmEvent.dx; mInfo.dy = gpmEvent.dy; #endif #ifdef DEBUG fprintf(stderr, "Mouse mInfo: dx=%d dy=%d x=%d y=%d event.x=%d event.y=%d\n", mInfo.dx, mInfo.dy, mInfo.x, mInfo.y, gpmEvent.x, gpmEvent.y); #endif mInfo.sw = MOUSE_LIFETIME; HandleMouseSelection(); return 0; } #endif /* SUPPORT_GPMMOUSE */ #else /* SUPPORT_MOUSE */ void MouseInit(void) { mInfo.has_mouse = FALSE; } void MouseHandleEvent(int fd) { } int MouseAttach(void) { return -1; } void MouseDetach(void) { } void MouseCleanup(void) { } #endif /* SUPPORT_MOUSE */