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

📄 key.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
            }
            return ERR;
        }
    } else if (c == ERR){
	/* Maybe we got an incomplete match.
	   This we do only in delay mode, since otherwise
	   xgetch can return ERR at any time. */
	if (seq_append) {
	    pending_keys = seq_buffer;
	    goto pend_send;
	}
	this = NULL;
	return ERR;
    }

    /* Search the key on the root */
    if (!no_delay || this == NULL) {
        this = keys;
        parent = NULL;

        if ((c & 0x80) && use_8th_bit_as_meta) {
            c &= ~0x7f;

	    /* The first sequence defined starts with esc */
	    parent = keys;
	    this = keys->child;
        }
    }
    while (this){
	if (c == this->ch){
	    if (this->child){
		if (!push_char (c)){
		    pending_keys = seq_buffer;
		    goto pend_send;
		}
		parent = this;
		this = this->child;
		if (parent->action == MCKEY_ESCAPE && old_esc_mode) {
		    if (no_delay) {
		        GET_TIME (esctime);
		        if (this == NULL) {
		            /* Shouldn't happen */
		            fprintf (stderr, "Internal error\n");
		            exit (1);
		        }
		        goto nodelay_try_again;
		    }
		    esctime.tv_sec = -1;
		    c = xgetch_second ();
		    if (c == ERR) {
		        pending_keys = seq_append = NULL;
		        this = NULL;
		        return ESC_CHAR;
		    }
		} else {
		    if (no_delay)
		        goto nodelay_try_again;
		    c = xgetch ();
		}
	    } else {
		/* We got a complete match, return and reset search */
		int code;

		pending_keys = seq_append = NULL;
		code = this->code;
		this = NULL;
		return correct_key_code (code);
	    }
	} else {
	    if (this->next)
		this = this->next;
	    else {
	        if (parent != NULL && parent->action == MCKEY_ESCAPE) {
	            /* This is just to save a lot of define_sequences */
	            if (isalpha(c)
			|| (c == '\n') || (c == '\t') || (c == XCTRL('h'))
			|| (c == KEY_BACKSPACE) || (c == '!') || (c == '\r')
			|| c == 127 || c == '+' || c == '-' || c == '\\'
			|| c == '?')
			c = ALT(c);
		    else if (isdigit(c))
	                c = KEY_F (c-'0');
		    else if (c == ' ')
			c = ESC_CHAR;
		    pending_keys = seq_append = NULL;
		    this = NULL;
		    return correct_key_code (c);
		}
		/* Did not find a match or {c} was changed in the if above,
		   so we have to return everything we had skipped
		 */
		push_char (c);
		pending_keys = seq_buffer;
		goto pend_send;
	    }
	}
    }
    this = NULL;
    return correct_key_code (c);
#else
    return ERR;
#endif /* HAVE_X */
}

#ifndef PORT_HAS_FILE_HANDLERS
/* If set timeout is set, then we wait 0.1 seconds, else, we block */
void try_channels (int set_timeout)
{
    struct timeval timeout;
    static fd_set select_set;
    struct timeval *timeptr;
    int v;

    while (1){
	FD_ZERO (&select_set);
	FD_SET  (input_fd, &select_set);	/* Add stdin */
	add_selects (&select_set);

	if (set_timeout){
	    timeout.tv_sec = 0;
	    timeout.tv_usec = 100000;
	    timeptr = &timeout;
	} else
	    timeptr = 0;

	v = select (FD_SETSIZE, &select_set, NULL, NULL, timeptr);
	if (v > 0){
	    check_selects (&select_set);
	    if (FD_ISSET (input_fd, &select_set))
		return;
	}
    }
}

#ifndef HAVE_X
/* Workaround for System V Curses vt100 bug */
static int getch_with_delay (void)
{
    int c;

    /* This routine could be used on systems without mouse support,
       so we need to do the select check :-( */
    while (1){
	if (!pending_keys)
	    try_channels (0);

	/* Try to get a character */
	c = get_key_code (0);
	if (c != ERR)
	    break;
	/* Failed -> wait 0.1 secs and try again */
	try_channels (1);
    }
    /* Success -> return the character */
    return c;
}
#endif /* !HAVE_X */

#ifndef HAVE_LIBGPM
#define gpm_flag 0
#endif
#endif /* !HAVE_FILE_HANDLERS */

extern int max_dirt_limit;

/* Returns a character read from stdin with appropriate interpretation */
/* Also takes care of generated mouse events */
/* Returns EV_MOUSE if it is a mouse event */
/* Returns EV_NONE  if non-blocking or interrupt set and nothing was done */
int get_event (Gpm_Event *event, int redo_event, int block)
{
#ifndef HAVE_X
    int c;
    static int flag;			/* Return value from select */
#ifdef HAVE_LIBGPM
    static Gpm_Event ev;		/* Mouse event */
#endif
    struct timeval timeout;
    struct timeval *time_addr = NULL;
    static int dirty = 3;

    if ((dirty == 3) || is_idle ()){
	mc_refresh ();
	doupdate ();
	dirty = 1;
    } else
	dirty++;

    vfs_timeout_handler ();

    /* Ok, we use (event->x < 0) to signal that the event does not contain
       a suitable position for the mouse, so we can't use show_mouse_pointer
       on it.
    */
    if (event->x > 0){
	show_mouse_pointer (event->x, event->y);
	if (!redo_event)
	    event->x = -1;
    }

    /* Repeat if using mouse */
    while ((xmouse_flag || gpm_flag) && !pending_keys)
    {
	if (xmouse_flag || gpm_flag)
	{
	    FD_ZERO (&select_set);
	    FD_SET  (input_fd, &select_set);
	    add_selects (&select_set);

#ifdef HAVE_LIBGPM
	    if (gpm_flag) {
		FD_SET  (gpm_fd, &select_set);
	    }
#endif

	    if (redo_event){
	        timeout.tv_usec = mou_auto_repeat * 1000;
		timeout.tv_sec = 0;

		time_addr = &timeout;
	    } else {
		int seconds;

		if ((seconds = vfs_timeouts ())){
		    /* the timeout could be improved and actually be
		     * the number of seconds until the next vfs entry
		     * timeouts in the stamp list.
		     */

		    timeout.tv_sec = seconds;
		    timeout.tv_usec = 0;
		    time_addr = &timeout;
		} else
		    time_addr = NULL;
	    }

	    if (!block){
		time_addr = &timeout;
		timeout.tv_sec = 0;
		timeout.tv_usec = 0;
	    }
	    enable_interrupt_key ();
	    flag = select (FD_SETSIZE, &select_set, NULL, NULL, time_addr);
	    disable_interrupt_key ();

	    /* select timed out: it could be for any of the following reasons:
	     * redo_event -> it was because of the MOU_REPEAT handler
	     * !block     -> we did not block in the select call
	     * else       -> 10 second timeout to check the vfs status.
	     */
	    if (flag == 0){
		if (redo_event)
		    return EV_MOUSE;
		if (!block)
		    return EV_NONE;
		vfs_timeout_handler ();
	    }
	    if (flag == -1 && errno == EINTR)
		return EV_NONE;

	    check_selects (&select_set);

	    if (FD_ISSET (input_fd, &select_set))
	        break;
	}
#ifdef HAVE_LIBGPM
	if (gpm_flag && FD_ISSET (gpm_fd, &select_set)){
	    if (gpm_flag){
		Gpm_GetEvent (&ev);
		Gpm_FitEvent (&ev);
	    }
	    *event = ev;
	    return EV_MOUSE;
	}
#endif
    }
#   ifndef HAVE_SLANG
    flag = is_wintouched(stdscr);
    untouchwin (stdscr);
#   endif

    c = block ? getch_with_delay () : get_key_code(1);

#   ifndef HAVE_SLANG
    if (flag)
        touchwin (stdscr);
#   endif

    if (c == MCKEY_MOUSE) { /* Mouse event */
        xmouse_get_event (event);
        return EV_MOUSE;
    }

    return c;
#else
    return EV_NONE;
#endif /* HAVE_X */
}

#ifndef PORT_HAS_GETCH
/* Returns a key press, mouse events are discarded */
int mi_getch ()
{
    Gpm_Event ev;
    int       key;

    ev.x = -1;
    while ((key = get_event (&ev, 0, 1)) == 0)
	;
    return key;
}
#endif

int xgetch_second (void)
{
    fd_set Read_FD_Set;
    int c;
    struct timeval timeout;

    timeout.tv_sec = ESCMODE_TIMEOUT / 1000000;
    timeout.tv_usec = ESCMODE_TIMEOUT % 1000000;
#ifdef BUGGY_CURSES
    wtimeout(stdscr, 500);
#else
    nodelay (stdscr, TRUE);
#endif
    FD_ZERO (&Read_FD_Set);
    FD_SET (input_fd, &Read_FD_Set);
    select (FD_SETSIZE, &Read_FD_Set, NULL, NULL, &timeout);
    c = xgetch ();
#ifdef BUGGY_CURSES
    notimeout (stdscr, TRUE);
#else
    nodelay (stdscr, FALSE);
#endif
    return c;
}

#ifndef HAVE_X
void learn_store_key (char *buffer, char **p, int c)
{
    if (*p - buffer > 253)
        return;
    if (c == ESC_CHAR) {
        *(*p)++ = '\\';
        *(*p)++ = 'e';
    } else if (c < ' ') {
    	*(*p)++ = '^';
    	*(*p)++ = c + 'a' - 1;
    } else if (c == '^') {
    	*(*p)++ = '^';
    	*(*p)++ = '^';
    } else
    	*(*p)++ = (char) c;
}

char *learn_key (void)
{
/* LEARN_TIMEOUT in usec */
#define LEARN_TIMEOUT 200000

    fd_set Read_FD_Set;
    struct timeval endtime;
    struct timeval timeout;
    int c = xgetch ();
    char buffer [256];
    char *p = buffer;

    while (c == ERR)
        c = xgetch (); /* Sanity check, should be unnecessary */
    learn_store_key (buffer, &p, c);
    GET_TIME (endtime);
    endtime.tv_usec += LEARN_TIMEOUT;
    if (endtime.tv_usec > 1000000) {
        endtime.tv_usec -= 1000000;
        endtime.tv_sec++;
    }
#ifdef BUGGY_CURSES
    wtimeout(stdscr, 500);
#else
    nodelay (stdscr, TRUE);
#endif
    for (;;) {
        while ((c = xgetch ()) == ERR) {
            GET_TIME (timeout);
            timeout.tv_usec = endtime.tv_usec - timeout.tv_usec;
            if (timeout.tv_usec < 0)
                timeout.tv_sec++;
            timeout.tv_sec = endtime.tv_sec - timeout.tv_sec;
            if (timeout.tv_sec >= 0 && timeout.tv_usec > 0) {
    		FD_ZERO (&Read_FD_Set);
    		FD_SET (input_fd, &Read_FD_Set);
                select (FD_SETSIZE, &Read_FD_Set, NULL, NULL, &timeout);
            } else
            	break;
        }
        if (c == ERR)
            break;
	learn_store_key (buffer, &p, c);
    }
#ifdef BUGGY_CURSES
    notimeout (stdscr, TRUE);
#else
    nodelay (stdscr, FALSE);
#endif
    *p = 0;
    return strdup (buffer);
}

/* xterm and linux console only: set keypad to numeric or application
   mode. Only in application keypad mode it's possible to distinguish
   the '+' key and the '+' on the keypad ('*' and '-' ditto)*/
void
numeric_keypad_mode (void)
{
    if (console_flag || xterm_flag) {
        fprintf (stdout, "\033>");
        fflush (stdout);
    }
}

void
application_keypad_mode (void)
{
    if (console_flag || xterm_flag) {
        fprintf (stdout, "\033=");
        fflush (stdout);
    }
}

#endif /* !HAVE_X */

/* A function to check if we're idle.
   Currently checks only for key presses.
   We could also check the mouse. */
int is_idle (void)
{
    /* Check for incoming key presses     *
     * If there are any we say we're busy */

    fd_set select_set;
    struct timeval timeout;
    FD_ZERO (&select_set);
    FD_SET (0, &select_set);
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    select (FD_SETSIZE, &select_set, 0, 0, &timeout);
    return ! FD_ISSET (0, &select_set);
}


int get_modifier ()
{
#ifdef __linux__
    unsigned char modifiers;

    modifiers = 6;

    if (ioctl (0, TIOCLINUX, &modifiers) < 0)
	return 0;

    return (int) modifiers;
#else
    return 0;
#endif
}

int ctrl_pressed ()
{
#ifdef __linux__
    if (get_modifier () & CONTROL_PRESSED)
	return 1;
#endif
    return 0;
}

#ifdef HAVE_MAD
#ifndef HAVE_X
void k_dispose (key_def *k)
{
    if (!k)
	return;
    k_dispose (k->child);
    k_dispose (k->next);
    free (k);
}

void s_dispose (SelectList *sel)
{
    if (!sel)
	return;

    s_dispose (sel->next);
    free (sel);
}

void done_key ()
{
    k_dispose (keys);
    s_dispose (select_list);
}

#else

void done_key ()
{
}

#endif /* HAVE_X */
#endif /* HAVE_MAD */

⌨️ 快捷键说明

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