📄 keyboard.c
字号:
#ifdef subprocesses wait_reading_process_input (0, -1, 1);#else/* Note SIGIO has been undef'd if FIONREAD is missing. */#ifdef SIGIO if (interrupt_input) { sigblockx (SIGIO); set_waiting_for_input (0); while (!kbd_count) sigpausex (SIGIO); clear_waiting_for_input (); sigunblockx (SIGIO); }#else interrupt_input = 0;#endif /* not SIGIO */#endif /* subprocesses */ if (!interrupt_input && !kbd_count) { read_avail_input (0); } }#endif /* not VMS */ } input_pending = --kbd_count > 0; c = *kbd_ptr; /* *kbd_ptr++ would have a timing error. */ kbd_ptr++; /* See kbd_buffer_store_char. */ return (c & (meta_key ? 0377 : 0177)); /* Clean up if sign was extended. */}/* Force an attempt to read input regardless of what FIONREAD says. */force_input_read (){ force_input = 1; detect_input_pending (); force_input = 0;}/* Store into *addr the number of terminal input chars available. Equivalent to ioctl (0, FIONREAD, addr) but works even if FIONREAD does not exist. */static voidget_input_pending (addr) int *addr;{#ifdef VMS /* On VMS, we always have something in the buffer if any input is available. */ /*** It might be simpler to make interrupt_input 1 on VMS ***/ *addr = kbd_count | !NULL (Vquit_flag);#else /* First of all, have we already counted some input? */ *addr = kbd_count | !NULL (Vquit_flag); /* If input is being read as it arrives, and we have none, there is none. */ if (*addr > 0 || (interrupt_input && ! interrupts_deferred && ! force_input)) return;#ifdef FIONREAD if (! force_input) { /* If we can count the input without reading it, do so. */ if (ioctl (0, FIONREAD, addr) < 0) *addr = 0; if (*addr == 0 || read_socket_hook == 0) return; /* If the input consists of window-events, not all of them are necessarily kbd chars. So process all the input and see how many kbd chars we got. */ }#endif#ifdef SIGIO { /* It seems there is a timing error such that a SIGIO can be handled here and cause kbd_count to become nonzero even though raising of SIGIO has already been turned off. */ int mask = sigblock (sigmask (SIGIO)); if (kbd_count == 0) read_avail_input (*addr); sigsetmask (mask); }#else /* If we can't count the input, read it (if any) and see what we got. */ read_avail_input (*addr);#endif *addr = kbd_count | !NULL (Vquit_flag);#endif}/* Read pending any input out of the system and into Emacs. *//* This function is temporary in Emacs 18. It is used only with X windows. X windows always turns on interrupt input if possible, so this function has nothing to do except on systems that don't have SIGIO. And they also don't have FIONREAD. */voidconsume_available_input (){#ifdef SIGIO if (!interrupt_input || interrupts_deferred)#endif read_avail_input (0);}/* Read any terminal input already buffered up by the system into the kbd_buffer, assuming the buffer is currently empty. Never waits. If NREAD is nonzero, assume it contains # chars of raw data waiting. If it is zero, we determine that datum. Input gets into the kbd_buffer either through this function (at main program level) or at interrupt level if input is interrupt-driven. */static voidread_avail_input (nread) int nread;{ /* This function is not used on VMS. */#ifndef VMS char buf[256 * BUFFER_SIZE_FACTOR]; register int i;#ifdef FIONREAD if (! force_input) { if (nread == 0) get_input_pending (&nread); if (nread == 0) return; } if (nread > sizeof buf) nread = sizeof buf; /* Read what is waiting. */ if (read_socket_hook) nread = (*read_socket_hook) (0, buf, nread); else nread = read (0, buf, nread);#else /* no FIONREAD */#ifdef USG fcntl (fileno (stdin), F_SETFL, O_NDELAY); if (read_socket_hook) { nread = (*read_socket_hook) (0, buf, sizeof buf); } else { nread = read (fileno (stdin), buf, sizeof buf); }#ifdef EBADSLT if (nread == -1 && (errno == EAGAIN || errno == EBADSLT))#else if (nread == -1 && errno == EAGAIN)#endif nread = 0; fcntl (fileno (stdin), F_SETFL, 0);#else /* not USG */ you lose#endif /* not USG */#endif /* no FIONREAD */ /* Scan the chars for C-g and store them in kbd_buffer. */ if (kbd_count == 0) kbd_ptr = kbd_buffer; for (i = 0; i < nread; i++) { kbd_buffer_store_char (buf[i]); /* Don't look at input that follows a C-g too closely. This reduces lossage due to autorepeat on C-g. */ if (buf[i] == quit_char) break; }#endif /* not VMS */}#ifdef SIGIO /* for entire page *//* Note SIGIO has been undef'd if FIONREAD is missing. *//* If using interrupt input and some input chars snuck into the buffer before we enabled interrupts, fake an interrupt for them. */gobble_input (){ int nread; if (interrupt_input) { if (ioctl (0, FIONREAD, &nread) < 0) nread = 0; if (nread) { sigholdx (SIGIO); input_available_signal (SIGIO); sigfree (); } }}input_available_signal (signo) int signo;{ unsigned char buf[256 * BUFFER_SIZE_FACTOR]; int nread; register int i; /* Must preserve main program's value of errno. */ int old_errno = errno;#ifdef BSD4_1 extern int select_alarmed;#endif#ifdef USG /* USG systems forget handlers when they are used; must reestablish each time */ signal (signo, input_available_signal);#endif /* USG */#ifdef BSD4_1 sigisheld (SIGIO);#endif if (input_available_clear_word) *input_available_clear_word = 0; while (1) { if (ioctl (0, FIONREAD, &nread) < 0) /* Formerly simply exited the loop, but that sometimes led to a failure of Emacs to terminate. SIGHUP seems appropriate if we can't reach the terminal. */ kill (getpid (), SIGHUP); if (nread <= 0) break;#ifdef BSD4_1 select_alarmed = 1; /* Force the select emulator back to life */#endif if (read_socket_hook) { nread = (*read_socket_hook) (0, buf, sizeof buf); if (!nread) continue; } else { if (nread > sizeof buf) nread = sizeof buf; nread = read (0, buf, nread); } for (i = 0; i < nread; i++) { kbd_buffer_store_char (buf[i]); /* Don't look at input that follows a C-g too closely. This reduces lossage due to autorepeat on C-g. */ if (buf[i] == quit_char) break; } }#ifdef BSD4_1 sigfree ();#endif errno = old_errno;}#endif /* SIGIO */#if 0/* This is turned off because it didn't produce much speedup. *//* Read a single-char key sequence. Do not redisplay. Return 1 if successful, or 0 if what follows is not a single-char key. (In that case, a char has been unread.) This is used instead of read_key_sequence as an optimization just after a direct-updating command is done, since at such times we know that no redisplay is required. */intfast_read_one_key (keybuf) char *keybuf;{ register Lisp_Object map; register int c; register Lisp_Object tem; keys_prompt = 0; /* Read a character, and do not redisplay. */ c = read_command_char (-1); Vquit_flag = Qnil; /* Assume until further notice that we are unlucky and will return zero, so this char will be reread by read_key_sequence. */ unread_command_char = c; if (c < 0 || c >= 0200) return 0; map = current_buffer->keymap; if (!EQ (map, Qnil)) { tem = get_keyelt (access_keymap (map, c)); if (!EQ (tem, Qnil)) return 0; } XSET (map, Lisp_Vector, global_map); tem = !NULL (map) ? get_keyelt (access_keymap (map, c)) : Qnil; read_key_sequence_cmd = tem; /* trace symbols to their function definitions */ while (XTYPE (tem) == Lisp_Symbol && !NULL (tem) && !EQ (tem, Qunbound)) tem = XSYMBOL (tem)->function; /* Is the definition a prefix character? */ if (XTYPE (tem) == Lisp_Vector || (CONSP (tem) && EQ (XCONS (tem)->car, Qkeymap))) return 0; unread_command_char = -1; keybuf[0] = c; return 1;}#endif /* 0 *//* Read a sequence of keys that ends with a non prefix character, and store them in KEYBUF, a buffer of size BUFSIZE. Prompt with PROMPT. Echo starting immediately unless `prompt' is 0. Return the length of the key sequence stored. NODISPLAY nonzero means don't do redisplay before the first character (just for speedup). */intread_key_sequence (keybuf, bufsize, prompt, nodisplay) char *keybuf; int bufsize; unsigned char *prompt; int nodisplay;{ register int i; Lisp_Object nextlocal, nextglobal; register int c, nextc; Lisp_Object local, global; if (FROM_KBD) { if (prompt) echo_prompt (prompt); else if (cursor_in_echo_area) echo_dash (); } nextc = read_command_char (nodisplay ? -1 : !prompt); nextlocal = current_buffer->keymap; XSET (nextglobal, Lisp_Vector, global_map); i = 0; while (!NULL (nextlocal) || !NULL (nextglobal)) { if (i == bufsize) error ("key sequence too long"); if (nextc >= 0) { c = nextc; nextc = -1; } else c = read_command_char (!prompt); Vquit_flag = Qnil; nodisplay = 0; if (c < 0) return 0; if (c >= 0200) { nextc = c & 0177; c = meta_prefix_char; } keybuf[i] = c; global = !NULL (nextglobal) ? get_keyelt (access_keymap (nextglobal, c)) : Qnil; local = !NULL (nextlocal) ? get_keyelt (access_keymap (nextlocal, c)) : Qnil; /* If C is not defined in either keymap and it is an uppercase letter, try corresponding lowercase. */ if (NULL (global) && NULL (local) && UPPERCASEP (c)) { global = !NULL (nextglobal) ? get_keyelt (access_keymap (nextglobal, DOWNCASE (c))) : Qnil; local = !NULL (nextlocal) ? get_keyelt (access_keymap (nextlocal, DOWNCASE (c))) : Qnil; /* If that has worked better that the original char, downcase it permanently. */ if (!NULL (global) || !NULL (local)) { keybuf[i] = c = DOWNCASE (c); } } i++; nextlocal = Qnil; nextglobal = Qnil; read_key_sequence_cmd = !NULL (local) ? local : global; /* trace symbols to their function definitions */ while (XTYPE (global) == Lisp_Symbol && !NULL (global) && !EQ (global, Qunbound)) global = XSYMBOL (global)->function; while (XTYPE (local) == Lisp_Symbol && !NULL (local) && !EQ (local, Qunbound)) local = XSYMBOL (local)->function; /* Are the definitions prefix characters? */ if (XTYPE (local) == Lisp_Vector || (CONSP (local) && EQ (XCONS (local)->car, Qkeymap)) || /* If nextc is set, we are processing a prefix char that represents a meta-bit. Let a global prefix definition override a local non-prefix. This is for minibuffers that redefine Escape for completion. A real Escape gets completion, but Meta bits get ESC-prefix. */ ((NULL (local) || nextc >= 0) && (XTYPE (global) == Lisp_Vector || (CONSP (global) && EQ (XCONS (global)->car, Qkeymap))))) { if (XTYPE (local) == Lisp_Vector || (CONSP (local) && EQ (XCONS (local)->car, Qkeymap))) nextlocal = local; else nextlocal = Qnil; if (XTYPE (global) == Lisp_Vector || (CONSP (global) && EQ (XCONS (global)->car, Qkeymap))) nextglobal = global; else nextglobal = Qnil; } } return i;}DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 1, 0, "Read a sequence of keystrokes and return as a string.\n\The sequence is sufficient to specify a non-prefix command\n\starting from the current local and global keymaps.\n\A C-g typed while in this function is treated like\n\any other character, and quit-flag is not set.\n\One arg, PROMPT, a prompt string or nil, meaning do not prompt specially.") (prompt) Lisp_Object prompt;{ char keybuf[30]; register int i; if (!NULL (prompt)) CHECK_STRING (prompt, 0); QUIT; this_command_key_count = 0; i = read_key_sequence (keybuf, sizeof keybuf, (NULL (prompt)) ? 0 : XSTRING (prompt)->data, 0); return make_string (keybuf, i);}DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 2, 0, "Execute CMD as an editor command.\n\CMD must be a symbol that satisfies the `commandp' predicate.\n\Optional second arg RECORD-FLAG non-nil\n\means unconditionally put this command in the command-history.\n\Otherwise, this is done only if an arg is read using the minibuffer.") (cmd, record) Lisp_Object cmd, record;{ register Lisp_Object final; register Lisp_Object tem; Lisp_Object prefixarg; struct backtrace backtrace; extern int debug_on_next_call; prefixarg = Vprefix_arg, Vprefix_arg = Qnil; Vcurrent_prefix_arg = prefixarg; debug_on_next_call = 0; if (XTYPE (cmd) == Lisp_Symbol) { tem = Fget (cmd, Qdisabled); if (!NULL (tem)) return call0 (Vdisabled_command_hook); } while (1) { final = cmd; while (XTYPE (final) == Lisp_Symbol) { if (EQ (Qunbound, XSYMBOL (final)->function)) Fsymbol_function (final); /* Get an error! */ final = XSYMBOL (final)->function; } if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload))) do_autoload (final, cmd); else break; } if (CONSP (final) || XTYPE (final) == Lisp_Subr) { backtrace.next = backtrace_list; backtrace_list = &backtrace; backtrace.function = &Qcall_interactively; backtrace.args = &cmd; backtrace.nargs = 1; backtrace.evalargs = 0; tem = Fcall_interactively (cmd, record); backtrace_list = backtrace.next; return tem; } if (XTYPE (final) == Lisp_String) { return Fexecute_kbd_macro (final, prefixarg); } return Qnil;}DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command, 1, 1, "P", "Read function name, then read its arguments and call it.") (prefixarg) Lisp_Object prefixarg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -