⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib_mouse.c

📁 ncurses-5.4
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************** * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc.              * *                                                                          * * Permission is hereby granted, free of charge, to any person obtaining a  * * copy of this software and associated documentation files (the            * * "Software"), to deal in the Software without restriction, including      * * without limitation the rights to use, copy, modify, merge, publish,      * * distribute, distribute with modifications, sublicense, and/or sell       * * copies of the Software, and to permit persons to whom the Software is    * * furnished to do so, subject to the following conditions:                 * *                                                                          * * The above copyright notice and this permission notice shall be included  * * in all copies or substantial portions of the Software.                   * *                                                                          * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   * * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    * * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               * *                                                                          * * Except as contained in this notice, the name(s) of the above copyright   * * holders shall not be used in advertising or otherwise to promote the     * * sale, use or other dealings in this Software without prior written       * * authorization.                                                           * ****************************************************************************//**************************************************************************** *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               * *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         * *     and: Thomas E. Dickey 1996-2003                                      * ****************************************************************************//* * This module is intended to encapsulate ncurses's interface to pointing * devices. * * The first method used is xterm's internal mouse-tracking facility. * The second is Alessandro Rubini's GPM server. * * Notes for implementors of new mouse-interface methods: * * The code is logically split into a lower level that accepts event reports * in a device-dependent format and an upper level that parses mouse gestures * and filters events.  The mediating data structure is a circular queue of * MEVENT structures. * * Functionally, the lower level's job is to pick up primitive events and * put them on the circular queue.  This can happen in one of two ways: * either (a) _nc_mouse_event() detects a series of incoming mouse reports * and queues them, or (b) code in lib_getch.c detects the kmous prefix in * the keyboard input stream and calls _nc_mouse_inline to queue up a series * of adjacent mouse reports. * * In either case, _nc_mouse_parse() should be called after the series is * accepted to parse the digested mouse reports (low-level MEVENTs) into * a gesture (a high-level or composite MEVENT). * * Don't be too shy about adding new event types or modifiers, if you can find * room for them in the 32-bit mask.  The API is written so that users get * feedback on which theoretical event types they won't see when they call * mousemask. There's one bit per button (the RESERVED_EVENT bit) not being * used yet, and a couple of bits open at the high end. */#ifdef __EMX__#  include <io.h>#  define  INCL_DOS#  define  INCL_VIO#  define  INCL_KBD#  define  INCL_MOU#  define  INCL_DOSPROCESS#  include <os2.h>		/* Need to include before the others */#endif#include <curses.priv.h>MODULE_ID("$Id: lib_mouse.c,v 1.68 2003/11/08 21:50:50 tom Exp $")#include <term.h>#include <tic.h>#if USE_GPM_SUPPORT#ifndef LINT			/* don't need this for llib-lncurses */#undef buttons			/* term.h defines this, and gpm uses it! */#include <gpm.h>#include <linux/keyboard.h>	/* defines KG_* macros */#endif#endif#if USE_SYSMOUSE#undef buttons			/* symbol conflict in consio.h */#undef mouse_info		/* symbol conflict in consio.h */#include <osreldate.h>#if (__FreeBSD_version >= 400017)#include <sys/consio.h>#include <sys/fbio.h>#else#include <machine/console.h>#endif#endif /* use_SYSMOUSE */#define MY_TRACE TRACE_ICALLS|TRACE_IEVENT#define	MASK_RELEASE(x)		((001 << (6 * ((x) - 1))))#define	MASK_PRESS(x)		((002 << (6 * ((x) - 1))))#define	MASK_CLICK(x)		((004 << (6 * ((x) - 1))))#define	MASK_DOUBLE_CLICK(x)	((010 << (6 * ((x) - 1))))#define	MASK_TRIPLE_CLICK(x)	((020 << (6 * ((x) - 1))))#define	MASK_RESERVED_EVENT(x)	((040 << (6 * ((x) - 1))))#define BUTTON_CLICKED  (BUTTON1_CLICKED  | BUTTON2_CLICKED  | BUTTON3_CLICKED)#define BUTTON_PRESSED  (BUTTON1_PRESSED  | BUTTON2_PRESSED  | BUTTON3_PRESSED)#define BUTTON_RELEASED (BUTTON1_RELEASED | BUTTON2_RELEASED | BUTTON3_RELEASED)#define INVALID_EVENT	-1#define NORMAL_EVENT	0#if USE_GPM_SUPPORT#ifndef LINTstatic Gpm_Connect gpm_connect;#endif#endifstatic mmask_t eventmask;	/* current event mask */static bool _nc_mouse_parse(int);static void _nc_mouse_resume(SCREEN *);static void _nc_mouse_wrap(SCREEN *);/* maintain a circular list of mouse events *//* The definition of the circular list size (EV_MAX), is in curses.priv.h, so * wgetch() may refer to the size and call _nc_mouse_parse() before circular * list overflow. */static MEVENT events[EV_MAX];	/* hold the last mouse event seen */static MEVENT *eventp = events;	/* next free slot in event queue */#undef  NEXT#define NEXT(ep)	((ep == events + EV_MAX - 1) ? events : ep + 1)#undef  PREV#define PREV(ep)	((ep == events) ? events + EV_MAX - 1 : ep - 1)#ifdef TRACEstatic void_trace_slot(const char *tag){    MEVENT *ep;    _tracef(tag);    for (ep = events; ep < events + EV_MAX; ep++)	_tracef("mouse event queue slot %ld = %s",		(long) (ep - events),		_tracemouse(ep));}#endif#if USE_EMX_MOUSE#  define TOP_ROW          0#  define LEFT_COL         0static int mouse_wfd;static int mouse_thread;static int mouse_activated;static char mouse_buttons[] ={0, 1, 3, 2};#  define M_FD(sp) sp->_mouse_fdstatic voidwrite_event(int down, int button, int x, int y){    char buf[6];    unsigned long ignore;    strncpy(buf, key_mouse, 3);	/* should be "\033[M" */    buf[3] = ' ' + (button - 1) + (down ? 0 : 0x40);    buf[4] = ' ' + x - LEFT_COL + 1;    buf[5] = ' ' + y - TOP_ROW + 1;    DosWrite(mouse_wfd, buf, 6, &ignore);}static voidmouse_server(unsigned long ignored GCC_UNUSED){    unsigned short fWait = MOU_WAIT;    /* NOPTRRECT mourt = { 0,0,24,79 }; */    MOUEVENTINFO mouev;    HMOU hmou;    unsigned short mask = MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN;    int nbuttons = 3;    int oldstate = 0;    char err[80];    unsigned long rc;    /* open the handle for the mouse */    if (MouOpen(NULL, &hmou) == 0) {	rc = MouSetEventMask(&mask, hmou);	if (rc) {		/* retry with 2 buttons */	    mask = MOUSE_BN1_DOWN | MOUSE_BN2_DOWN;	    rc = MouSetEventMask(&mask, hmou);	    nbuttons = 2;	}	if (rc == 0 && MouDrawPtr(hmou) == 0) {	    for (;;) {		/* sit and wait on the event queue */		rc = MouReadEventQue(&mouev, &fWait, hmou);		if (rc) {		    sprintf(err, "Error reading mouse queue, rc=%lu.\r\n", rc);		    break;		}		if (!mouse_activated)		    goto finish;		/*		 * OS/2 numbers a 3-button mouse inconsistently from other		 * platforms:		 *      1 = left		 *      2 = right		 *      3 = middle.		 */		if ((mouev.fs ^ oldstate) & MOUSE_BN1_DOWN)		    write_event(mouev.fs & MOUSE_BN1_DOWN,				mouse_buttons[1], mouev.col, mouev.row);		if ((mouev.fs ^ oldstate) & MOUSE_BN2_DOWN)		    write_event(mouev.fs & MOUSE_BN2_DOWN,				mouse_buttons[3], mouev.col, mouev.row);		if ((mouev.fs ^ oldstate) & MOUSE_BN3_DOWN)		    write_event(mouev.fs & MOUSE_BN3_DOWN,				mouse_buttons[2], mouev.col, mouev.row);	      finish:		oldstate = mouev.fs;	    }	} else	    sprintf(err, "Error setting event mask, buttons=%d, rc=%lu.\r\n",		    nbuttons, rc);	DosWrite(2, err, strlen(err), &rc);	MouClose(hmou);    }    DosExit(EXIT_THREAD, 0L);}static voidserver_state(const int state){				/* It would be nice to implement pointer-off and stop looping... */    mouse_activated = state;}#endif /* USE_EMX_MOUSE */#if USE_SYSMOUSEstatic voidhandle_sysmouse(int sig GCC_UNUSED){    struct mouse_info the_mouse;    MEVENT *work;    the_mouse.operation = MOUSE_GETINFO;    if (SP != 0	&& SP->_mouse_fd >= 0	&& SP->_sysmouse_tail < FIFO_SIZE	&& ioctl(SP->_mouse_fd, CONS_MOUSECTL, &the_mouse) != -1) {	if (SP->_sysmouse_head > SP->_sysmouse_tail) {	    SP->_sysmouse_tail = 0;	    SP->_sysmouse_head = 0;	}	work = &(SP->_sysmouse_fifo[SP->_sysmouse_tail]);	memset(work, 0, sizeof(*work));	work->id = NORMAL_EVENT;	/* there's only one mouse... */	SP->_sysmouse_old_buttons = SP->_sysmouse_new_buttons;	SP->_sysmouse_new_buttons = the_mouse.u.data.buttons & 0x7;	if (SP->_sysmouse_new_buttons) {	    if (SP->_sysmouse_new_buttons & 1)		work->bstate |= BUTTON1_PRESSED;	    if (SP->_sysmouse_new_buttons & 2)		work->bstate |= BUTTON2_PRESSED;	    if (SP->_sysmouse_new_buttons & 4)		work->bstate |= BUTTON3_PRESSED;	} else {	    if (SP->_sysmouse_old_buttons & 1)		work->bstate |= BUTTON1_RELEASED;	    if (SP->_sysmouse_old_buttons & 2)		work->bstate |= BUTTON2_RELEASED;	    if (SP->_sysmouse_old_buttons & 4)		work->bstate |= BUTTON3_RELEASED;	}	/* for cosmetic bug in syscons.c on FreeBSD 3.[34] */	the_mouse.operation = MOUSE_HIDE;	ioctl(SP->_mouse_fd, CONS_MOUSECTL, &the_mouse);	the_mouse.operation = MOUSE_SHOW;	ioctl(SP->_mouse_fd, CONS_MOUSECTL, &the_mouse);	/*	 * We're only interested if the button is pressed or released.	 * FIXME: implement continuous event-tracking.	 */	if (SP->_sysmouse_new_buttons != SP->_sysmouse_old_buttons) {	    SP->_sysmouse_tail += 1;	}	work->x = the_mouse.u.data.x / SP->_sysmouse_char_width;	work->y = the_mouse.u.data.y / SP->_sysmouse_char_height;    }}#endifstatic int initialized;static voidinit_xterm_mouse(void){    SP->_mouse_type = M_XTERM;    SP->_mouse_xtermcap = tigetstr("XM");    if (!VALID_STRING(SP->_mouse_xtermcap))	SP->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;";}#if !USE_EMX_MOUSEstatic voidenable_xterm_mouse(int enable){    putp(tparm(SP->_mouse_xtermcap, enable));}#endif /* !USE_EMX_MOUSE */static voidinitialize_mousetype(void){    static const char *xterm_kmous = "\033[M";    /* Try gpm first, because gpm may be configured to run in xterm */#if USE_GPM_SUPPORT    /* GPM does printf's without checking if stdout is a terminal */    if (isatty(fileno(stdout))) {	/* GPM: initialize connection to gpm server */	gpm_connect.eventMask = GPM_DOWN | GPM_UP;	gpm_connect.defaultMask = ~(gpm_connect.eventMask | GPM_HARD);	gpm_connect.minMod = 0;	gpm_connect.maxMod = ~((1 << KG_SHIFT) | (1 << KG_SHIFTL) | (1 << KG_SHIFTR));	if (Gpm_Open(&gpm_connect, 0) >= 0) {	/* returns the file-descriptor */	    SP->_mouse_type = M_GPM;	    SP->_mouse_fd = gpm_fd;	    return;	}    }#endif    /* OS/2 VIO */#if USE_EMX_MOUSE    if (!mouse_thread	&& strstr(cur_term->type.term_names, "xterm") == 0	&& key_mouse) {	int handles[2];	if (pipe(handles) < 0) {	    perror("mouse pipe error");	    return;	} else {	    int rc;	    if (!mouse_buttons[0]) {		char *s = getenv("MOUSE_BUTTONS_123");		mouse_buttons[0] = 1;		if (s && strlen(s) >= 3) {		    mouse_buttons[1] = s[0] - '0';		    mouse_buttons[2] = s[1] - '0';		    mouse_buttons[3] = s[2] - '0';		}	    }	    mouse_wfd = handles[1];	    M_FD(SP) = handles[0];	    /* Needed? */	    setmode(handles[0], O_BINARY);	    setmode(handles[1], O_BINARY);	    /* Do not use CRT functions, we may single-threaded. */	    rc = DosCreateThread((unsigned long *) &mouse_thread,				 mouse_server, 0, 0, 8192);	    if (rc) {		printf("mouse thread error %d=%#x", rc, rc);		return;	    } else {		SP->_mouse_type = M_XTERM;		return;	    }	}    }#endif#if USE_SYSMOUSE    {	struct mouse_info the_mouse;	char *the_device = 0;	if (isatty(SP->_ifd))	    the_device = ttyname(SP->_ifd);	if (the_device == 0)	    the_device = "/dev/tty";	SP->_mouse_fd = open(the_device, O_RDWR);	if (SP->_mouse_fd >= 0) {	    /*	     * sysmouse does not have a usable user interface for obtaining	     * mouse events.  The logical way to proceed (reading data on a	     * stream) only works if one opens the device as root.  Even in	     * that mode, careful examination shows we lose events	     * occasionally.  The interface provided for user programs is to	     * establish a signal handler.  really.	     *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -