📄 getline.c
字号:
fd_set ufds; /* The set of fds to watch for urgent data */ int max_fd; /* The maximum file-descriptor being watched */#endif};/* * Define the max amount of space needed to store a termcap terminal * description. Unfortunately this has to be done by guesswork, so * there is the potential for buffer overflows if we guess too small. * Fortunately termcap has been replaced by terminfo on most * platforms, and with terminfo this isn't an issue. The value that I * am using here is the conventional value, as recommended by certain * web references. */#ifdef USE_TERMCAP#define TERMCAP_BUF_SIZE 2048#endif/* * Set the size of the string segments used to store terminal capability * strings. */#define CAPMEM_SEGMENT_SIZE 512/* * If no terminal size information is available, substitute the * following vt100 default sizes. */#define GL_DEF_NLINE 24#define GL_DEF_NCOLUMN 80/* * List the signals that we need to catch. In general these are * those that by default terminate or suspend the process, since * in such cases we need to restore terminal settings. */static const struct GlDefSignal { int signo; /* The number of the signal */ unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ GlAfterSignal after; /* What to do after the signal has been delivered */ int errno_value; /* What to set errno to */} gl_signal_list[] = { {SIGABRT, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, {SIGINT, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, {SIGTERM, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, {SIGALRM, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, {SIGCONT, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#if defined(SIGHUP)#ifdef ENOTTY {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, ENOTTY},#else {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR},#endif#endif#if defined(SIGPIPE)#ifdef EPIPE {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, EPIPE},#else {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR},#endif#endif#ifdef SIGPWR {SIGPWR, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#endif#ifdef SIGQUIT {SIGQUIT, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR},#endif#ifdef SIGTSTP {SIGTSTP, GLS_SUSPEND_INPUT, GLS_CONTINUE, 0},#endif#ifdef SIGTTIN {SIGTTIN, GLS_SUSPEND_INPUT, GLS_CONTINUE, 0},#endif#ifdef SIGTTOU {SIGTTOU, GLS_SUSPEND_INPUT, GLS_CONTINUE, 0},#endif#ifdef SIGUSR1 {SIGUSR1, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#endif#ifdef SIGUSR2 {SIGUSR2, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#endif#ifdef SIGVTALRM {SIGVTALRM, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#endif#ifdef SIGWINCH {SIGWINCH, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#endif#ifdef SIGXCPU {SIGXCPU, GLS_RESTORE_ENV, GLS_CONTINUE, 0},#endif};/* * Define file-scope variables for use in signal handlers. */static volatile sig_atomic_t gl_pending_signal = -1;static sigjmp_buf gl_setjmp_buffer;static void gl_signal_handler(int signo);static int gl_check_caught_signal(GetLine *gl);/* * Unfortunately both terminfo and termcap require one to use the tputs() * function to output terminal control characters, and this function * doesn't allow one to specify a file stream. As a result, the following * file-scope variable is used to pass the current output file stream. * This is bad, but there doesn't seem to be any alternative. */#if defined(USE_TERMINFO) || defined(USE_TERMCAP)static FILE *tputs_fp = NULL;#endif/* * Define a tab to be a string of 8 spaces. */#define TAB_WIDTH 8/* * Does the system send us SIGWINCH signals when the terminal size * changes? */#ifdef USE_SIGWINCHstatic int gl_resize_terminal(GetLine *gl, int redisplay);#endif/* * Getline calls this to temporarily override certain signal handlers * of the calling program. */static int gl_override_signal_handlers(GetLine *gl);/* * Getline calls this to restore the signal handlers of the calling * program. */static int gl_restore_signal_handlers(GetLine *gl);/* * Put the terminal into raw input mode, after saving the original * terminal attributes in gl->oldattr. */static int gl_raw_terminal_mode(GetLine *gl);/* * Restore the terminal attributes from gl->oldattr. */static int gl_restore_terminal_attributes(GetLine *gl);/* * Read a line from the user in raw mode. */static int gl_get_input_line(GetLine *gl, const char *start_line, int start_pos, int val);/* * Handle the receipt of the potential start of a new key-sequence from * the user. */static int gl_interpret_char(GetLine *gl, char c);/* * Bind a single control or meta character to an action. */static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c, const char *action);/* * Set up terminal-specific key bindings. */static int gl_bind_terminal_keys(GetLine *gl);/* * Lookup terminal control string and size information. */static int gl_control_strings(GetLine *gl, const char *term);/* * Wrappers around the terminfo and termcap functions that lookup * strings in the terminal information databases. */#ifdef USE_TERMINFOstatic const char *gl_tigetstr(GetLine *gl, const char *name);#elif defined(USE_TERMCAP)static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr);#endif/* * Output a binary string directly to the terminal. */static int gl_output_raw_string(GetLine *gl, const char *string);/* * Output a terminal control sequence. */static int gl_output_control_sequence(GetLine *gl, int nline, const char *string);/* * Output a character or string to the terminal after converting tabs * to spaces and control characters to a caret followed by the modified * character. */static int gl_output_char(GetLine *gl, char c, char pad);static int gl_output_string(GetLine *gl, const char *string, char pad);/* * Delete nc characters starting from the one under the cursor. * Optionally copy the deleted characters to the cut buffer. */static int gl_delete_chars(GetLine *gl, int nc, int cut);/* * Add a character to the line buffer at the current cursor position, * inserting or overwriting according the current mode. */static int gl_add_char_to_line(GetLine *gl, char c);/* * Insert/append a string to the line buffer and terminal at the current * cursor position. */static int gl_add_string_to_line(GetLine *gl, const char *s);/* * Read a single character from the terminal. */static int gl_read_character(GetLine *gl, char *c, int val);/* * Move the terminal cursor n positions to the left or right. */static int gl_terminal_move_cursor(GetLine *gl, int n);/* * Move the terminal cursor to a given position. */static int gl_set_term_curpos(GetLine *gl, int term_curpos);/* * Set the position of the cursor both in the line input buffer and on the * terminal. *//* static int gl_place_cursor(GetLine *gl, int buff_curpos); *//* * Return the terminal cursor position that corresponds to a given * line buffer cursor position. */static int gl_buff_curpos_to_term_curpos(GetLine *gl, int buff_curpos);/* * Return the number of terminal characters needed to display a * given raw character. */static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos);/* * Return the number of terminal characters needed to display a * given substring. */static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, int term_curpos);/* * Return non-zero if 'c' is to be considered part of a word. */static int gl_is_word_char(int c);/* * Read a tecla configuration file. */static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who);/* * Read a tecla configuration string. */static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who);/* * Define the callback function used by _gl_parse_config_line() to * read the next character of a configuration stream. */#define GLC_GETC_FN(fn) int (fn)(void *stream)typedef GLC_GETC_FN(GlcGetcFn);static GLC_GETC_FN(glc_file_getc); /* Read from a file */static GLC_GETC_FN(glc_buff_getc); /* Read from a string *//* * Parse a single configuration command line. */static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, const char *origin, KtBinder who, int *lineno);/* * Bind the actual arrow key bindings to match those of the symbolic * arrow-key bindings. */static int _gl_bind_arrow_keys(GetLine *gl);/* * Copy the binding of the specified symbolic arrow-key binding to * the terminal specific, and default arrow-key key-sequences. */static int _gl_rebind_arrow_key(KeyTab *bindings, const char *name, const char *term_seq, const char *def_seq1, const char *def_seq2);/* * After the gl_read_from_file() action has been used to tell gl_get_line() * to temporarily read input from a file, gl_revert_input() arranges * for input to be reverted to the input stream last registered with * gl_change_terminal(). */static void gl_revert_input(GetLine *gl);/* * Flush unwritten characters to the terminal. */static int gl_flush_output(GetLine *gl);/* * Change the editor style being emulated. */static int gl_change_editor(GetLine *gl, GlEditor editor);/* * Searching in a given direction, return the index of a given (or * read) character in the input line, or the character that precedes * it in the specified search direction. Return -1 if not found. */static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c);/* * Return the buffer index of the nth word ending after the cursor. */static int gl_nth_word_end_forward(GetLine *gl, int n);/* * Return the buffer index of the nth word start after the cursor. */static int gl_nth_word_start_forward(GetLine *gl, int n);/* * Return the buffer index of the nth word start before the cursor. */static int gl_nth_word_start_backward(GetLine *gl, int n);/* * When called when vi command mode is enabled, this function saves the * current line and cursor position for potential restoration later * by the vi undo command. */static void gl_save_for_undo(GetLine *gl);/* * If in vi mode, switch to vi command mode. */static void gl_vi_command_mode(GetLine *gl);/* * In vi mode this is used to delete up to or onto a given or read * character in the input line. Also switch to insert mode if requested * after the deletion. */static int gl_delete_find(GetLine *gl, int count, char c, int forward, int onto, int change);/* * Copy the characters between the cursor and the count'th instance of * a specified (or read) character in the input line, into the cut buffer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -