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

📄 lib_mouse.c

📁 ncurses 库 可能有用酒用 没用就算了 我觉得还可以用
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************** * Copyright (c) 1998-2004,2005 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-on                 * ****************************************************************************//* * This module is intended to encapsulate ncurses's interface to pointing * devices. * * The primary method used is xterm's internal mouse-tracking facility. * Additional methods depend on the platform: *	Alessandro Rubini's GPM server (Linux) *	sysmouse (FreeBSD) *	special-purpose mouse interface for OS/2 EMX. * * 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.77 2005/09/10 22:58:57 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 *//* use dynamic loader to avoid linkage dependency */#include <dlfcn.h>#ifdef RTLD_NOW#define my_RTLD RTLD_NOW#else#ifdef RTLD_LAZY#define my_RTLD RTLD_LAZY#elsemake an error#endif#endif#endif#endif				/* USE_GPM_SUPPORT */#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)		NCURSES_MOUSE_MASK(x, 001)#define	MASK_PRESS(x)		NCURSES_MOUSE_MASK(x, 002)#define	MASK_CLICK(x)		NCURSES_MOUSE_MASK(x, 004)#define	MASK_DOUBLE_CLICK(x)	NCURSES_MOUSE_MASK(x, 010)#define	MASK_TRIPLE_CLICK(x)	NCURSES_MOUSE_MASK(x, 020)#define	MASK_RESERVED_EVENT(x)	NCURSES_MOUSE_MASK(x, 040)#if NCURSES_MOUSE_VERSION == 1#define BUTTON_CLICKED        (BUTTON1_CLICKED        | BUTTON2_CLICKED        | BUTTON3_CLICKED        | BUTTON4_CLICKED)#define BUTTON_PRESSED        (BUTTON1_PRESSED        | BUTTON2_PRESSED        | BUTTON3_PRESSED        | BUTTON4_PRESSED)#define BUTTON_RELEASED       (BUTTON1_RELEASED       | BUTTON2_RELEASED       | BUTTON3_RELEASED       | BUTTON4_RELEASED)#define BUTTON_DOUBLE_CLICKED (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED)#define BUTTON_TRIPLE_CLICKED (BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED)#define MAX_BUTTONS  4#else#define BUTTON_CLICKED        (BUTTON1_CLICKED        | BUTTON2_CLICKED        | BUTTON3_CLICKED        | BUTTON4_CLICKED        | BUTTON5_CLICKED)#define BUTTON_PRESSED        (BUTTON1_PRESSED        | BUTTON2_PRESSED        | BUTTON3_PRESSED        | BUTTON4_PRESSED        | BUTTON5_PRESSED)#define BUTTON_RELEASED       (BUTTON1_RELEASED       | BUTTON2_RELEASED       | BUTTON3_RELEASED       | BUTTON4_RELEASED       | BUTTON5_RELEASED)#define BUTTON_DOUBLE_CLICKED (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED | BUTTON5_DOUBLE_CLICKED)#define BUTTON_TRIPLE_CLICKED (BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED | BUTTON5_TRIPLE_CLICKED)#define MAX_BUTTONS  5#endif#define INVALID_EVENT	-1#define NORMAL_EVENT	0#if USE_GPM_SUPPORT#ifndef LINT#ifndef LIBGPM_SONAME#define LIBGPM_SONAME "libgpm.so"#endif#define GET_DLSYM(name) (my_##name = (TYPE_##name) dlsym(obj, #name))static Gpm_Connect gpm_connect;typedef int *TYPE_gpm_fd;typedef int (*TYPE_Gpm_Open) (Gpm_Connect *, int);typedef int (*TYPE_Gpm_Close) (void);typedef int (*TYPE_Gpm_GetEvent) (Gpm_Event *);static TYPE_gpm_fd my_gpm_fd;static TYPE_Gpm_Open my_Gpm_Open;static TYPE_Gpm_Close my_Gpm_Close;static TYPE_Gpm_GetEvent my_Gpm_GetEvent;#endif /* LINT */#endif /* USE_GPM_SUPPORT */static 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);}#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;    }}#endif /* USE_SYSMOUSE */static 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%;";}static voidenable_xterm_mouse(int enable){#if USE_EMX_MOUSE    mouse_activated = enable;#else    putp(tparm(SP->_mouse_xtermcap, enable));#endif    SP->_mouse_active = enable;}#if USE_GPM_SUPPORTstatic intallow_gpm_mouse(void){    /* GPM does printf's without checking if stdout is a terminal */    if (isatty(fileno(stdout))) {	char *env = getenv("TERM");	/* GPM checks the beginning of the $TERM variable to decide if	 * it should pass xterm events through.  There is no real advantage	 * in allowing GPM to do this.	 */	if (env == 0 || strncmp(env, "xterm", 5))	    return TRUE;    }    return FALSE;}static boolenable_gpm_mouse(int enable){    bool result;    T((T_CALLED("enable_gpm_mouse(%d)"), enable));    if (enable && !SP->_mouse_active) {	/* 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 = (unsigned short) (~((1 << KG_SHIFT) |						 (1 << KG_SHIFTL) |						 (1 << KG_SHIFTR)));	/*	 * Note: GPM hardcodes \E[?1001s and \E[?1000h during its open.	 * The former is recognized by wscons (SunOS), and the latter by	 * xterm.  Those will not show up in ncurses' traces.	 */	result = (my_Gpm_Open(&gpm_connect, 0) >= 0);	SP->_mouse_active = result;	T(("GPM open %s", result ? "succeeded" : "failed"));    } else {	if (!enable && SP->_mouse_active) {	    /* GPM: close connection to gpm server */	    my_Gpm_Close();	    SP->_mouse_active = FALSE;	    T(("GPM closed"));	}	result = FALSE;    }    returnBool(result);}#endif /* USE_GPM_SUPPORT */static voidinitialize_mousetype(void){    static const char *xterm_kmous = "\033[M";    T((T_CALLED("initialize_mousetype()")));    /* Try gpm first, because gpm may be configured to run in xterm */#if USE_GPM_SUPPORT    if (allow_gpm_mouse()) {	static bool first = TRUE;	static bool found = FALSE;	if (first) {	    void *obj;	    first = FALSE;	    if ((obj = dlopen(LIBGPM_SONAME, my_RTLD)) != 0) {		if (GET_DLSYM(gpm_fd) == 0 ||		    GET_DLSYM(Gpm_Open) == 0 ||		    GET_DLSYM(Gpm_Close) == 0 ||		    GET_DLSYM(Gpm_GetEvent) == 0) {		    T(("GPM initialization failed: %s", dlerror()));		    dlclose(obj);

⌨️ 快捷键说明

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