📄 getline.c
字号:
/* * Copyright (c) 2000, 2001 by Martin C. Shepherd. * * All rights reserved. * * 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, and/or sell copies of the Software, and to permit persons * to whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * 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 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Except as contained in this notice, the name of a copyright holder * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * of the copyright holder. *//* * Standard headers. */#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <setjmp.h>/* * UNIX headers. */#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#ifdef HAVE_SELECT#include <sys/select.h>#include <sys/time.h>#include <sys/types.h>#endif#ifdef __MINGW32__#define sigsetjmp setjmp#define siglongjmp longjmp#define sigjmp_buf jmp_buf#endif/* * The source of terminal control string and size information. * Note that if no terminal information database is available, * ANSI VT100 control sequences are used. */#if defined(USE_TERMINFO)#include <curses.h>#include <term.h>#elif defined(USE_TERMCAP)#if defined(HAVE_TERMCAP_H)#include <termcap.h>#elseextern int tgetent(char *, char *);extern int tputs(char *, int, int (*)(char));extern int tgetnum(char *);extern char *tgetstr(char *, char **);#endif#endif/* * Under Solaris default Curses the output function that tputs takes is * declared to have a char argument. On all other systems and on Solaris * X/Open Curses (Issue 4, Version 2) it expects an int argument (using * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib * selects XPG4v2 Curses on Solaris 2.6 and later). */#if defined USE_TERMINFO || defined USE_TERMCAP#if defined __sun && defined __SVR4 && !defined _XOPEN_CURSEStypedef char TputsType;#elsetypedef int TputsType;#endifstatic int gl_tputs_putchar(TputsType c);#endif/* * POSIX headers. */#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_TERMIOS_H#include <termios.h>#endif/* * Does the system provide the signal and ioctl query facility used * to inform the process of terminal window size changes? */#if defined(SIGWINCH) && defined(TIOCGWINSZ)#define USE_SIGWINCH 1#endif/* * Provide typedefs for standard POSIX structures. */#ifndef __MINGW32__typedef struct sigaction SigAction;typedef struct termios Termios;#endif/* * Local headers. */#include "pathutil.h"#include "libtecla.h"#include "keytab.h"#include "history.h"#include "freelist.h"#include "stringrp.h"#include "getline.h"/* * Enumerate the available editing styles. */typedef enum { GL_EMACS_MODE, /* Emacs style editing */ GL_VI_MODE, /* Vi style editing */ GL_NO_EDITOR /* Fall back to the basic OS-provided editing */} GlEditor;/* * In vi mode, the following datatype is used to implement the * undo command. It records a copy of the input line from before * the command-mode action which edited the input line. */typedef struct { char *line; /* A historical copy of the input line */ int buff_curpos; /* The historical location of the cursor in */ /* line[] when the line was modified. */ int ntotal; /* The number of characters in line[] */ int saved; /* True once a line has been saved after the */ /* last call to gl_interpret_char(). */} ViUndo;/* * In vi mode, the following datatype is used to record information * needed by the vi-repeat-change command. */typedef struct { KtKeyFn *fn; /* The last action function that made a */ /* change to the line. */ int count; /* The repeat count that was passed to the */ /* above command. */ int input_curpos; /* Whenever vi command mode is entered, the */ /* the position at which it was first left */ /* is recorded here. */ int command_curpos; /* Whenever vi command mode is entered, the */ /* the location of the cursor is recorded */ /* here. */ char input_char; /* Commands that call gl_read_character() */ /* record the character here, so that it can */ /* used on repeating the function. */ int saved; /* True if a function has been saved since the */ /* last call to gl_interpret_char(). */ int active; /* True while a function is being repeated. */} ViRepeat;/* * The following datatype is used to encapsulate information specific * to vi mode. */typedef struct { ViUndo undo; /* Information needed to implement the vi */ /* undo command. */ ViRepeat repeat; /* Information needed to implement the vi */ /* repeat command. */ int command; /* True in vi command-mode */ int find_forward; /* True if the last character search was in the */ /* forward direction. */ int find_onto; /* True if the last character search left the */ /* on top of the located character, as opposed */ /* to just before or after it. */ char find_char; /* The last character sought, or '\0' if no */ /* searches have been performed yet. */} ViMode;#ifdef HAVE_SELECT/* * Define a type for recording a file-descriptor callback and its associated * data. */typedef struct { GlFdEventFn *fn; /* The callback function */ void *data; /* Anonymous data to pass to the callback function */} GlFdHandler;/* * A list of nodes of the following type is used to record file-activity * event handlers, but only on systems that have the select() system call. */typedef struct GlFdNode GlFdNode;struct GlFdNode { GlFdNode *next; /* The next in the list of nodes */ int fd; /* The file descriptor being watched */ GlFdHandler rd; /* The callback to call when fd is readable */ GlFdHandler wr; /* The callback to call when fd is writable */ GlFdHandler ur; /* The callback to call when fd has urgent data */};/* * Set the number of the above structures to allocate every time that * the freelist of GlFdNode's becomes exhausted. */#define GLFD_FREELIST_BLOCKING 10/* * Listen for and handle file-descriptor events. */static int gl_event_handler(GetLine *gl);static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, GlFdEvent event);#endif/* * Each signal that gl_get_line() traps is described by a list node * of the following type. */typedef struct GlSignalNode GlSignalNode;struct GlSignalNode { GlSignalNode *next; /* The next signal in the list */ int signo; /* The number of the signal */ sigset_t proc_mask; /* A process mask which only includes signo */#ifndef __MINGW32__ SigAction original; /* The signal disposition of the calling program */ /* for this signal. */#endif unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ GlAfterSignal after; /* What to do after the signal has been handled */ int errno_value; /* What to set errno to */};/* * Set the number of the above structures to allocate every time that * the freelist of GlSignalNode's becomes exhausted. */#define GLS_FREELIST_BLOCKING 30/* * Set the largest key-sequence that can be handled. */#define GL_KEY_MAX 64/* * Define the contents of the GetLine object. * Note that the typedef for this object can be found in libtecla.h. */struct GetLine { GlHistory *glh; /* The line-history buffer */ WordCompletion *cpl; /* String completion resource object */ CplMatchFn(*cpl_fn); /* The tab completion callback function */ void *cpl_data; /* Callback data to pass to cpl_fn() */ ExpandFile *ef; /* ~user/, $envvar and wildcard expansion */ /* resource object. */ StringGroup *capmem; /* Memory for recording terminal capability */ /* strings. */ int input_fd; /* The file descriptor to read on */ int output_fd; /* The file descriptor to write to */ FILE *input_fp; /* A stream wrapper around input_fd */ FILE *output_fp; /* A stream wrapper around output_fd */ FILE *file_fp; /* When input is being temporarily taken from */ /* a file, this is its file-pointer. Otherwise */ /* it is NULL. */ char *term; /* The terminal type specified on the last call */ /* to gl_change_terminal(). */ int is_term; /* True if stdin is a terminal */ int is_net; /* True if the in/out is a network connection */ int net_may_block; /* True if we may block if reading from the net */ int net_read_attempt; /* True if attempt to read from the net */ char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */ int nkey; /* The number of characters in the key sequence */ int user_event_value; /* The user event value code */ size_t linelen; /* The max number of characters per line */ char *line; /* A line-input buffer of allocated size */ /* linelen+2. The extra 2 characters are */ /* reserved for "\n\0". */ char *cutbuf; /* A cut-buffer of the same size as line[] */ const char *prompt; /* The current prompt string */ int prompt_len; /* The length of the prompt string */ int prompt_changed; /* True after a callback changes the prompt */ int prompt_style; /* How the prompt string is displayed */ FreeList *sig_mem; /* Memory for nodes of the signal list */ GlSignalNode *sigs; /* The head of the list of signals */ sigset_t old_signal_set; /* The signal set on entry to gl_get_line() */ sigset_t new_signal_set; /* The set of signals that we are trapping */#ifndef __MINGW32__ Termios oldattr; /* Saved terminal attributes. */#endif KeyTab *bindings; /* A table of key-bindings */ int ntotal; /* The number of characters in gl->line[] */ int buff_curpos; /* The cursor position within gl->line[] */ int term_curpos; /* The cursor position on the terminal */ int buff_mark; /* A marker location in the buffer */ int insert_curpos; /* The cursor position at start of insert */ int insert; /* True in insert mode */ int number; /* If >= 0, a numeric argument is being read */ int endline; /* True to tell gl_get_input_line() to return */ /* the current contents of gl->line[] */ KtKeyFn *current_fn; /* The action function that is currently being */ /* invoked. */ int current_count; /* The repeat count passed to current_fn() */ GlhLineID preload_id; /* When not zero, this should be the ID of a */ /* line in the history buffer for potential */ /* recall. */ int preload_history; /* If true, preload the above history line when */ /* gl_get_input_line() is next called. */ long keyseq_count; /* The number of key sequences entered by the */ /* the user since new_GetLine() was called. */ long last_search; /* The value of oper_count during the last */ /* history search operation. */ GlEditor editor; /* The style of editing, (eg. vi or emacs) */ int silence_bell; /* True if gl_ring_bell() should do nothing. */ ViMode vi; /* Parameters used when editing in vi mode */ const char *left; /* The string that moves the cursor 1 character */ /* left. */ const char *right; /* The string that moves the cursor 1 character */ /* right. */ const char *up; /* The string that moves the cursor 1 character */ /* up. */ const char *down; /* The string that moves the cursor 1 character */ /* down. */ const char *home; /* The string that moves the cursor home */ const char *bol; /* Move cursor to beginning of line */ const char *clear_eol; /* The string that clears from the cursor to */ /* the end of the line. */ const char *clear_eod; /* The string that clears from the cursor to */ /* the end of the display. */ const char *u_arrow; /* The string returned by the up-arrow key */ const char *d_arrow; /* The string returned by the down-arrow key */ const char *l_arrow; /* The string returned by the left-arrow key */ const char *r_arrow; /* The string returned by the right-arrow key */ const char *sound_bell; /* The string needed to ring the terminal bell */ const char *bold; /* Switch to the bold font */ const char *underline; /* Underline subsequent characters */ const char *standout; /* Turn on standout mode */ const char *dim; /* Switch to a dim font */ const char *reverse; /* Turn on reverse video */ const char *blink; /* Switch to a blinking font */ const char *text_attr_off; /* Turn off all text attributes */ int nline; /* The height of the terminal in lines */ int ncolumn; /* The width of the terminal in columns */#ifdef USE_TERMCAP char *tgetent_buf; /* The buffer that is used by tgetent() to */ /* store a terminal description. */ char *tgetstr_buf; /* The buffer that is used by tgetstr() to */ /* store terminal capabilities. */#endif#ifdef USE_TERMINFO const char *left_n; /* The parameter string that moves the cursor */ /* n characters left. */ const char *right_n; /* The parameter string that moves the cursor */ /* n characters right. */#endif char *app_file; /* The pathname of the application-specific */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -