1 /*
2  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2012 by Martin C. Shepherd.
3  *
4  * All rights reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, and/or sell copies of the Software, and to permit persons
11  * to whom the Software is furnished to do so, provided that the above
12  * copyright notice(s) and this permission notice appear in all copies of
13  * the Software and that both the above copyright notice(s) and this
14  * permission notice appear in supporting documentation.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
19  * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20  * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
21  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
22  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
23  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  *
26  * Except as contained in this notice, the name of a copyright holder
27  * shall not be used in advertising or otherwise to promote the sale, use
28  * or other dealings in this Software without prior written authorization
29  * of the copyright holder.
30  */
31 
32 /*
33  * Standard headers.
34  */
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <signal.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <ctype.h>
41 #include <setjmp.h>
42 #include <stdarg.h>
43 
44 /*
45  * UNIX headers.
46  */
47 #include <sys/ioctl.h>
48 #ifdef HAVE_SELECT
49 #ifdef HAVE_SYS_SELECT_H
50 #include <sys/select.h>
51 #endif
52 #include <sys/time.h>
53 #include <sys/types.h>
54 #endif
55 
56 /*
57  * Handle the different sources of terminal control string and size
58  * information. Note that if no terminal information database is available,
59  * ANSI VT100 control sequences are used.
60  */
61 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
62 /*
63  * Include curses.h or ncurses/curses.h depending on which is available.
64  */
65 #ifdef HAVE_CURSES_H
66 #include <curses.h>
67 #elif defined(HAVE_NCURSES_CURSES_H)
68 #include <ncurses/curses.h>
69 #endif
70 /*
71  * Include term.h where available.
72  */
73 #if defined(HAVE_TERM_H)
74 #include <term.h>
75 #elif defined(HAVE_NCURSES_TERM_H)
76 #include <ncurses/term.h>
77 #endif
78 /*
79  * When using termcap, include termcap.h on systems that have it.
80  * Otherwise assume that all prototypes are provided by curses.h.
81  */
82 #if defined(USE_TERMCAP) && defined(HAVE_TERMCAP_H)
83 #include <termcap.h>
84 #endif
85 
86 /*
87  * Under Solaris default Curses the output function that tputs takes is
88  * declared to have a char argument. On all other systems and on Solaris
89  * X/Open Curses (Issue 4, Version 2) it expects an int argument (using
90  * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib
91  * selects XPG4v2 Curses on Solaris 2.6 and later).
92  *
93  * Similarly, under Mac OS X, the return value of the tputs output
94  * function is declared as void, whereas it is declared as int on
95  * other systems.
96  */
97 #if defined __sun && defined __SVR4 && !defined _XOPEN_CURSES
98 typedef int TputsRetType;
99 typedef char TputsArgType;              /* int tputs(char c, FILE *fp) */
100 #define TPUTS_RETURNS_VALUE 1
101 #elif defined(__APPLE__) && defined(__MACH__)
102 typedef void TputsRetType;
103 typedef int TputsArgType;               /* void tputs(int c, FILE *fp) */
104 #define TPUTS_RETURNS_VALUE 0
105 #else
106 typedef int TputsRetType;
107 typedef int TputsArgType;               /* int tputs(int c, FILE *fp) */
108 #define TPUTS_RETURNS_VALUE 1
109 #endif
110 
111 /*
112  * Use the above specifications to prototype our tputs callback function.
113  */
114 static TputsRetType gl_tputs_putchar(TputsArgType c);
115 
116 #endif  /* defined(USE_TERMINFO) || defined(USE_TERMCAP) */
117 
118 /*
119  * If the library is being compiled without filesystem access facilities,
120  * ensure that none of the action functions that normally do access the
121  * filesystem are bound by default, and that it they do get bound, that
122  * they don't do anything.
123  */
124 #if WITHOUT_FILE_SYSTEM
125 #define HIDE_FILE_SYSTEM
126 #endif
127 
128 /*
129  * POSIX headers.
130  */
131 #include <unistd.h>
132 #include <fcntl.h>
133 #include <termios.h>
134 
135 /*
136  * Provide typedefs for standard POSIX structures.
137  */
138 typedef struct sigaction SigAction;
139 typedef struct termios Termios;
140 
141 /*
142  * Which flag is used to select non-blocking I/O with fcntl()?
143  */
144 #undef NON_BLOCKING_FLAG
145 #if defined(O_NONBLOCK)
146 #define NON_BLOCKING_FLAG (O_NONBLOCK)
147 #elif defined(O_NDELAY)
148 #define NON_BLOCKING_FLAG (O_NDELAY)
149 #endif
150 
151 /*
152  * What value should we give errno if I/O blocks when it shouldn't.
153  */
154 #undef BLOCKED_ERRNO
155 #if defined(EAGAIN)
156 #define BLOCKED_ERRNO (EAGAIN)
157 #elif defined(EWOULDBLOCK)
158 #define BLOCKED_ERRNO (EWOULDBLOCK)
159 #elif defined(EIO)
160 #define BLOCKED_ERRNO (EIO)
161 #else
162 #define BLOCKED_ERRNO 0
163 #endif
164 
165 /*
166  * Local headers.
167  */
168 #ifndef WITHOUT_FILE_SYSTEM
169 #include "pathutil.h"
170 #endif
171 #include "libtecla.h"
172 #include "keytab.h"
173 #include "getline.h"
174 #include "ioutil.h"
175 #include "history.h"
176 #include "freelist.h"
177 #include "stringrp.h"
178 #include "chrqueue.h"
179 #include "cplmatch.h"
180 #ifndef WITHOUT_FILE_SYSTEM
181 #include "expand.h"
182 #endif
183 #include "errmsg.h"
184 
185 /*
186  * Enumerate the available editing styles.
187  */
188 typedef enum {
189   GL_EMACS_MODE,   /* Emacs style editing */
190   GL_VI_MODE,      /* Vi style editing */
191   GL_NO_EDITOR     /* Fall back to the basic OS-provided editing */
192 } GlEditor;
193 
194 /*
195  * Set the largest key-sequence that can be handled.
196  */
197 #define GL_KEY_MAX 64
198 
199 /*
200  * In vi mode, the following datatype is used to implement the
201  * undo command. It records a copy of the input line from before
202  * the command-mode action which edited the input line.
203  */
204 typedef struct {
205   char *line;        /* A historical copy of the input line */
206   int buff_curpos;   /* The historical location of the cursor in */
207                      /*  line[] when the line was modified. */
208   int ntotal;        /* The number of characters in line[] */
209   int saved;         /* True once a line has been saved after the */
210                      /*  last call to gl_interpret_char(). */
211 } ViUndo;
212 
213 /*
214  * In vi mode, the following datatype is used to record information
215  * needed by the vi-repeat-change command.
216  */
217 typedef struct {
218   KtAction action;           /* The last action function that made a */
219                              /*  change to the line. */
220   int count;                 /* The repeat count that was passed to the */
221                              /*  above command. */
222   int input_curpos;          /* Whenever vi command mode is entered, the */
223                              /*  the position at which it was first left */
224                              /*  is recorded here. */
225   int command_curpos;        /* Whenever vi command mode is entered, the */
226                              /*  the location of the cursor is recorded */
227                              /*  here. */
228   char input_char;           /* Commands that call gl_read_terminal() */
229                              /*  record the character here, so that it can */
230                              /*  used on repeating the function. */
231   int saved;                 /* True if a function has been saved since the */
232                              /*  last call to gl_interpret_char(). */
233   int active;                /* True while a function is being repeated. */
234 } ViRepeat;
235 
236 /*
237  * The following datatype is used to encapsulate information specific
238  * to vi mode.
239  */
240 typedef struct {
241   ViUndo undo;               /* Information needed to implement the vi */
242                              /*  undo command. */
243   ViRepeat repeat;           /* Information needed to implement the vi */
244                              /*  repeat command. */
245   int command;               /* True in vi command-mode */
246   int find_forward;          /* True if the last character search was in the */
247                              /*  forward direction. */
248   int find_onto;             /* True if the last character search left the */
249                              /*  on top of the located character, as opposed */
250                              /*  to just before or after it. */
251   char find_char;            /* The last character sought, or '\0' if no */
252                              /*  searches have been performed yet. */
253 } ViMode;
254 
255 #ifdef HAVE_SELECT
256 /*
257  * Define a type for recording a file-descriptor callback and its associated
258  * data.
259  */
260 typedef struct {
261   GlFdEventFn *fn;   /* The callback function */
262   void *data;        /* Anonymous data to pass to the callback function */
263 } GlFdHandler;
264 
265 /*
266  * A list of nodes of the following type is used to record file-activity
267  * event handlers, but only on systems that have the select() system call.
268  */
269 typedef struct GlFdNode GlFdNode;
270 struct GlFdNode {
271   GlFdNode *next;    /* The next in the list of nodes */
272   int fd;            /* The file descriptor being watched */
273   GlFdHandler rd;    /* The callback to call when fd is readable */
274   GlFdHandler wr;    /* The callback to call when fd is writable */
275   GlFdHandler ur;    /* The callback to call when fd has urgent data */
276 };
277 
278 /*
279  * Set the number of the above structures to allocate every time that
280  * the freelist of GlFdNode's becomes exhausted.
281  */
282 #define GLFD_FREELIST_BLOCKING 10
283 
284 
285 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
286 			      GlFdEvent event);
287 
288 static int gl_call_timeout_handler(GetLine *gl);
289 
290 #endif
291 
292 /*
293  * Each signal that gl_get_line() traps is described by a list node
294  * of the following type.
295  */
296 typedef struct GlSignalNode GlSignalNode;
297 struct GlSignalNode {
298   GlSignalNode *next;  /* The next signal in the list */
299   int signo;           /* The number of the signal */
300   sigset_t proc_mask;  /* A process mask which only includes signo */
301   SigAction original;  /* The signal disposition of the calling program */
302                        /*  for this signal. */
303   unsigned flags;      /* A bitwise union of GlSignalFlags enumerators */
304   GlAfterSignal after; /* What to do after the signal has been handled */
305   int errno_value;     /* What to set errno to */
306 };
307 
308 /*
309  * Set the number of the above structures to allocate every time that
310  * the freelist of GlSignalNode's becomes exhausted.
311  */
312 #define GLS_FREELIST_BLOCKING 30
313 
314 /*
315  * Completion handlers and their callback data are recorded in
316  * nodes of the following type.
317  */
318 typedef struct GlCplCallback GlCplCallback;
319 struct GlCplCallback {
320   CplMatchFn *fn;            /* The completion callback function */
321   void *data;                /* Arbitrary callback data */
322 };
323 
324 /*
325  * The following function is used as the default completion handler when
326  * the filesystem is to be hidden. It simply reports no completions.
327  */
328 #ifdef HIDE_FILE_SYSTEM
329 static CPL_MATCH_FN(gl_no_completions);
330 #endif
331 
332 /*
333  * Specify how many GlCplCallback nodes are added to the GlCplCallback freelist
334  * whenever it becomes exhausted.
335  */
336 #define GL_CPL_FREELIST_BLOCKING 10
337 
338 /*
339  * External action functions and their callback data are recorded in
340  * nodes of the following type.
341  */
342 typedef struct GlExternalAction GlExternalAction;
343 struct GlExternalAction {
344   GlActionFn *fn;          /* The function which implements the action */
345   void *data;              /* Arbitrary callback data */
346 };
347 
348 /*
349  * Specify how many GlExternalAction nodes are added to the
350  * GlExternalAction freelist whenever it becomes exhausted.
351  */
352 #define GL_EXT_ACT_FREELIST_BLOCKING 10
353 
354 /*
355  * Define the contents of the GetLine object.
356  * Note that the typedef for this object can be found in libtecla.h.
357  */
358 struct GetLine {
359   ErrMsg *err;               /* The error-reporting buffer */
360   GlHistory *glh;            /* The line-history buffer */
361   WordCompletion *cpl;       /* String completion resource object */
362   GlCplCallback cplfn;       /* The completion callback */
363 #ifndef WITHOUT_FILE_SYSTEM
364   ExpandFile *ef;            /* ~user/, $envvar and wildcard expansion */
365                              /*  resource object. */
366 #endif
367   StringGroup *capmem;       /* Memory for recording terminal capability */
368                              /*  strings. */
369   GlCharQueue *cq;           /* The terminal output character queue */
370   int input_fd;              /* The file descriptor to read on */
371   int output_fd;             /* The file descriptor to write to */
372   FILE *input_fp;            /* A stream wrapper around input_fd */
373   FILE *output_fp;           /* A stream wrapper around output_fd */
374   FILE *file_fp;             /* When input is being temporarily taken from */
375                              /*  a file, this is its file-pointer. Otherwise */
376                              /*  it is NULL. */
377   char *term;                /* The terminal type specified on the last call */
378                              /*  to gl_change_terminal(). */
379   int is_term;               /* True if stdin is a terminal */
380   GlWriteFn *flush_fn;       /* The function to call to write to the terminal */
381   GlIOMode io_mode;          /* The I/O mode established by gl_io_mode() */
382   int raw_mode;              /* True while the terminal is in raw mode */
383   GlPendingIO pending_io;    /* The type of I/O that is currently pending */
384   GlReturnStatus rtn_status; /* The reason why gl_get_line() returned */
385   int rtn_errno;             /* THe value of errno associated with rtn_status */
386   size_t linelen;            /* The max number of characters per line */
387   char *line;                /* A line-input buffer of allocated size */
388                              /*  linelen+2. The extra 2 characters are */
389                              /*  reserved for "\n\0". */
390   char *cutbuf;              /* A cut-buffer of the same size as line[] */
391   char *prompt;              /* The current prompt string */
392   int prompt_len;            /* The length of the prompt string */
393   int prompt_changed;        /* True after a callback changes the prompt */
394   int prompt_style;          /* How the prompt string is displayed */
395   FreeList *cpl_mem;         /* Memory for GlCplCallback objects */
396   FreeList *ext_act_mem;     /* Memory for GlExternalAction objects */
397   FreeList *sig_mem;         /* Memory for nodes of the signal list */
398   GlSignalNode *sigs;        /* The head of the list of signals */
399   int signals_masked;        /* True between calls to gl_mask_signals() and */
400                              /*  gl_unmask_signals() */
401   int signals_overriden;     /* True between calls to gl_override_signals() */
402                              /*  and gl_restore_signals() */
403   sigset_t all_signal_set;   /* The set of all signals that we are trapping */
404   sigset_t old_signal_set;   /* The set of blocked signals on entry to */
405                              /*  gl_get_line(). */
406   sigset_t use_signal_set;   /* The subset of all_signal_set to unblock */
407                              /*  while waiting for key-strokes */
408   Termios oldattr;           /* Saved terminal attributes. */
409   KeyTab *bindings;          /* A table of key-bindings */
410   int ntotal;                /* The number of characters in gl->line[] */
411   int buff_curpos;           /* The cursor position within gl->line[] */
412   int term_curpos;           /* The cursor position on the terminal */
413   int term_len;              /* The number of terminal characters used to */
414                              /*  display the current input line. */
415   int buff_mark;             /* A marker location in the buffer */
416   int insert_curpos;         /* The cursor position at start of insert */
417   int insert;                /* True in insert mode */
418   int number;                /* If >= 0, a numeric argument is being read */
419   int endline;               /* True to tell gl_get_input_line() to return */
420                              /*  the current contents of gl->line[] */
421   int displayed;             /* True if an input line is currently displayed */
422   int redisplay;             /* If true, the input line will be redrawn */
423                              /*  either after the current action function */
424                              /*  returns, or when gl_get_input_line() */
425                              /*  is next called. */
426   int postpone;              /* _gl_normal_io() sets this flag, to */
427                              /*  postpone any redisplays until */
428                              /*  is next called, to resume line editing. */
429   char keybuf[GL_KEY_MAX+1]; /* A buffer of currently unprocessed key presses */
430   int nbuf;                  /* The number of characters in keybuf[] */
431   int nread;                 /* The number of characters read from keybuf[] */
432   KtAction current_action;   /* The action function that is being invoked */
433   int current_count;         /* The repeat count passed to */
434                              /*  current_acction.fn() */
435   GlhLineID preload_id;      /* When not zero, this should be the ID of a */
436                              /*  line in the history buffer for potential */
437                              /*  recall. */
438   int preload_history;       /* If true, preload the above history line when */
439                              /*  gl_get_input_line() is next called. */
440   long keyseq_count;         /* The number of key sequences entered by the */
441                              /*  the user since new_GetLine() was called. */
442   long last_search;          /* The value of keyseq_count during the last */
443                              /*  history search operation. */
444   GlEditor editor;           /* The style of editing, (eg. vi or emacs) */
445   int silence_bell;          /* True if gl_ring_bell() should do nothing. */
446   int automatic_history;     /* True to automatically archive entered lines */
447                              /*  in the history list. */
448   ViMode vi;                 /* Parameters used when editing in vi mode */
449   const char *left;          /* The string that moves the cursor 1 character */
450                              /*  left. */
451   const char *right;         /* The string that moves the cursor 1 character */
452                              /*  right. */
453   const char *up;            /* The string that moves the cursor 1 character */
454                              /*  up. */
455   const char *down;          /* The string that moves the cursor 1 character */
456                              /*  down. */
457   const char *home;          /* The string that moves the cursor home */
458   const char *bol;           /* Move cursor to beginning of line */
459   const char *clear_eol;     /* The string that clears from the cursor to */
460                              /*  the end of the line. */
461   const char *clear_eod;     /* The string that clears from the cursor to */
462                              /*  the end of the display. */
463   const char *u_arrow;       /* The string returned by the up-arrow key */
464   const char *d_arrow;       /* The string returned by the down-arrow key */
465   const char *l_arrow;       /* The string returned by the left-arrow key */
466   const char *r_arrow;       /* The string returned by the right-arrow key */
467   const char *sound_bell;    /* The string needed to ring the terminal bell */
468   const char *bold;          /* Switch to the bold font */
469   const char *underline;     /* Underline subsequent characters */
470   const char *standout;      /* Turn on standout mode */
471   const char *dim;           /* Switch to a dim font */
472   const char *reverse;       /* Turn on reverse video */
473   const char *blink;         /* Switch to a blinking font */
474   const char *text_attr_off; /* Turn off all text attributes */
475   int nline;                 /* The height of the terminal in lines */
476   int ncolumn;               /* The width of the terminal in columns */
477 #ifdef USE_TERMCAP
478   char *tgetent_buf;         /* The buffer that is used by tgetent() to */
479                              /*  store a terminal description. */
480   char *tgetstr_buf;         /* The buffer that is used by tgetstr() to */
481                              /*  store terminal capabilities. */
482 #endif
483 #ifdef USE_TERMINFO
484   const char *left_n;        /* The parameter string that moves the cursor */
485                              /*  n characters left. */
486   const char *right_n;       /* The parameter string that moves the cursor */
487                              /*  n characters right. */
488 #endif
489   char *app_file;            /* The pathname of the application-specific */
490                              /*  .teclarc configuration file, or NULL. */
491   char *user_file;           /* The pathname of the user-specific */
492                              /*  .teclarc configuration file, or NULL. */
493   int configured;            /* True as soon as any teclarc configuration */
494                              /*  file has been read. */
495   int echo;                  /* True to display the line as it is being */
496                              /*  entered. If 0, only the prompt will be */
497                              /*  displayed, and the line will not be */
498                              /*  archived in the history list. */
499   int last_signal;           /* The last signal that was caught by */
500                              /*  the last call to gl_get_line(), or -1 */
501                              /*  if no signal has been caught yet. */
502 #ifdef HAVE_SELECT
503   FreeList *fd_node_mem;     /* A freelist of GlFdNode structures */
504   GlFdNode *fd_nodes;        /* The list of fd event descriptions */
505   fd_set rfds;               /* The set of fds to watch for readability */
506   fd_set wfds;               /* The set of fds to watch for writability */
507   fd_set ufds;               /* The set of fds to watch for urgent data */
508   int max_fd;                /* The maximum file-descriptor being watched */
509   struct {                   /* Inactivity timeout related data */
510     struct timeval dt;       /* The inactivity timeout when timer.fn() */
511                              /*  isn't 0 */
512     GlTimeoutFn *fn;         /* The application callback to call when */
513                              /*  the inactivity timer expires, or 0 if */
514                              /*  timeouts are not required. */
515     void *data;              /* Application provided data to be passed to */
516                              /*  timer.fn(). */
517   } timer;
518 #endif
519 };
520 
521 /*
522  * Define the max amount of space needed to store a termcap terminal
523  * description. Unfortunately this has to be done by guesswork, so
524  * there is the potential for buffer overflows if we guess too small.
525  * Fortunately termcap has been replaced by terminfo on most
526  * platforms, and with terminfo this isn't an issue. The value that I
527  * am using here is the conventional value, as recommended by certain
528  * web references.
529  */
530 #ifdef USE_TERMCAP
531 #define TERMCAP_BUF_SIZE 2048
532 #endif
533 
534 /*
535  * Set the size of the string segments used to store terminal capability
536  * strings.
537  */
538 #define CAPMEM_SEGMENT_SIZE 512
539 
540 /*
541  * If no terminal size information is available, substitute the
542  * following vt100 default sizes.
543  */
544 #define GL_DEF_NLINE 24
545 #define GL_DEF_NCOLUMN 80
546 
547 /*
548  * Enumerate the attributes needed to classify different types of
549  * signals. These attributes reflect the standard default
550  * characteristics of these signals (according to Richard Steven's
551  * Advanced Programming in the UNIX Environment). Note that these values
552  * are all powers of 2, so that they can be combined in a bitwise union.
553  */
554 typedef enum {
555   GLSA_TERM=1,   /* A signal that terminates processes */
556   GLSA_SUSP=2,   /* A signal that suspends processes */
557   GLSA_CONT=4,   /* A signal that is sent when suspended processes resume */
558   GLSA_IGN=8,    /* A signal that is ignored */
559   GLSA_CORE=16,  /* A signal that generates a core dump */
560   GLSA_HARD=32,  /* A signal generated by a hardware exception */
561   GLSA_SIZE=64   /* A signal indicating terminal size changes */
562 } GlSigAttr;
563 
564 /*
565  * List the signals that we need to catch. In general these are
566  * those that by default terminate or suspend the process, since
567  * in such cases we need to restore terminal settings.
568  */
569 static const struct GlDefSignal {
570   int signo;            /* The number of the signal */
571   unsigned flags;       /* A bitwise union of GlSignalFlags enumerators */
572   GlAfterSignal after;  /* What to do after the signal has been delivered */
573   int attr;             /* The default attributes of this signal, expressed */
574                         /* as a bitwise union of GlSigAttr enumerators */
575   int errno_value;      /* What to set errno to */
576 } gl_signal_list[] = {
577   {SIGABRT,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR},
578   {SIGALRM,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
579   {SIGCONT,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_CONT|GLSA_IGN,  0},
580 #if defined(SIGHUP)
581 #ifdef ENOTTY
582   {SIGHUP,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           ENOTTY},
583 #else
584   {SIGHUP,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
585 #endif
586 #endif
587   {SIGINT,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
588 #if defined(SIGPIPE)
589 #ifdef EPIPE
590   {SIGPIPE,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EPIPE},
591 #else
592   {SIGPIPE,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
593 #endif
594 #endif
595 #ifdef SIGPOLL
596   {SIGPOLL,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
597 #endif
598 #ifdef SIGPWR
599   {SIGPWR,    GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_IGN,            0},
600 #endif
601 #ifdef SIGQUIT
602   {SIGQUIT,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR},
603 #endif
604   {SIGTERM,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
605 #ifdef SIGTSTP
606   {SIGTSTP,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
607 #endif
608 #ifdef SIGTTIN
609   {SIGTTIN,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
610 #endif
611 #ifdef SIGTTOU
612   {SIGTTOU,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
613 #endif
614 #ifdef SIGUSR1
615   {SIGUSR1,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
616 #endif
617 #ifdef SIGUSR2
618   {SIGUSR2,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
619 #endif
620 #ifdef SIGVTALRM
621   {SIGVTALRM, GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
622 #endif
623 #ifdef SIGWINCH
624   {SIGWINCH,  GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_SIZE|GLSA_IGN,  0},
625 #endif
626 #ifdef SIGXCPU
627   {SIGXCPU,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0},
628 #endif
629 #ifdef SIGXFSZ
630   {SIGXFSZ,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0},
631 #endif
632 };
633 
634 /*
635  * Define file-scope variables for use in signal handlers.
636  */
637 static volatile sig_atomic_t gl_pending_signal = -1;
638 static sigjmp_buf gl_setjmp_buffer;
639 
640 static void gl_signal_handler(int signo);
641 
642 static int gl_check_caught_signal(GetLine *gl);
643 
644 /*
645  * Respond to an externally caught process suspension or
646  * termination signal.
647  */
648 static void gl_suspend_process(int signo, GetLine *gl, int ngl);
649 
650 /* Return the default attributes of a given signal */
651 
652 static int gl_classify_signal(int signo);
653 
654 /*
655  * Unfortunately both terminfo and termcap require one to use the tputs()
656  * function to output terminal control characters, and this function
657  * doesn't allow one to specify a file stream. As a result, the following
658  * file-scope variable is used to pass the current output file stream.
659  * This is bad, but there doesn't seem to be any alternative.
660  */
661 static GetLine *tputs_gl = NULL;
662 
663 /*
664  * Define a tab to be a string of 8 spaces.
665  */
666 #define TAB_WIDTH 8
667 
668 /*
669  * Lookup the current size of the terminal.
670  */
671 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline);
672 
673 /*
674  * Getline calls this to temporarily override certain signal handlers
675  * of the calling program.
676  */
677 static int gl_override_signal_handlers(GetLine *gl);
678 
679 /*
680  * Getline calls this to restore the signal handlers of the calling
681  * program.
682  */
683 static int gl_restore_signal_handlers(GetLine *gl);
684 
685 /*
686  * Temporarily block the delivery of all signals that gl_get_line()
687  * is currently configured to trap.
688  */
689 static int gl_mask_signals(GetLine *gl, sigset_t *oldset);
690 
691 /*
692  * Restore the process signal mask that was overriden by a previous
693  * call to gl_mask_signals().
694  */
695 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset);
696 
697 /*
698  * Unblock the signals that gl_get_line() has been configured to catch.
699  */
700 static int gl_catch_signals(GetLine *gl);
701 
702 /*
703  * Return the set of all trappable signals.
704  */
705 static void gl_list_trappable_signals(sigset_t *signals);
706 
707 /*
708  * Put the terminal into raw input mode, after saving the original
709  * terminal attributes in gl->oldattr.
710  */
711 static int gl_raw_terminal_mode(GetLine *gl);
712 
713 /*
714  * Restore the terminal attributes from gl->oldattr.
715  */
716 static int gl_restore_terminal_attributes(GetLine *gl);
717 
718 /*
719  * Switch to non-blocking I/O if possible.
720  */
721 static int gl_nonblocking_io(GetLine *gl, int fd);
722 
723 /*
724  * Switch to blocking I/O if possible.
725  */
726 static int gl_blocking_io(GetLine *gl, int fd);
727 
728 /*
729  * Read a line from the user in raw mode.
730  */
731 static int gl_get_input_line(GetLine *gl, const char *prompt,
732 			     const char *start_line, int start_pos);
733 
734 /*
735  * Query the user for a single character.
736  */
737 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar);
738 
739 /*
740  * Read input from a non-interactive input stream.
741  */
742 static int gl_read_stream_line(GetLine *gl);
743 
744 /*
745  * Read a single character from a non-interactive input stream.
746  */
747 static int gl_read_stream_char(GetLine *gl);
748 
749 /*
750  * Prepare to edit a new line.
751  */
752 static int gl_present_line(GetLine *gl, const char *prompt,
753 			   const char *start_line, int start_pos);
754 
755 /*
756  * Reset all line-editing parameters for a new input line.
757  */
758 static void gl_reset_editor(GetLine *gl);
759 
760 /*
761  * Handle the receipt of the potential start of a new key-sequence from
762  * the user.
763  */
764 static int gl_interpret_char(GetLine *gl, char c);
765 
766 /*
767  * Bind a single control or meta character to an action.
768  */
769 static int gl_bind_control_char(GetLine *gl, KtBinder binder,
770 				char c, const char *action);
771 
772 /*
773  * Set up terminal-specific key bindings.
774  */
775 static int gl_bind_terminal_keys(GetLine *gl);
776 
777 /*
778  * Lookup terminal control string and size information.
779  */
780 static int gl_control_strings(GetLine *gl, const char *term);
781 
782 /*
783  * Wrappers around the terminfo and termcap functions that lookup
784  * strings in the terminal information databases.
785  */
786 #ifdef USE_TERMINFO
787 static const char *gl_tigetstr(GetLine *gl, const char *name);
788 #elif defined(USE_TERMCAP)
789 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr);
790 #endif
791 
792 /*
793  * Output a binary string directly to the terminal.
794  */
795 static int gl_print_raw_string(GetLine *gl, int buffered,
796 			       const char *string, int n);
797 
798 /*
799  * Print an informational message, starting and finishing on new lines.
800  * After the list of strings to be printed, the last argument MUST be
801  * GL_END_INFO.
802  */
803 static int gl_print_info(GetLine *gl, ...);
804 #define GL_END_INFO ((const char *)0)
805 
806 /*
807  * Start a newline and place the cursor at its start.
808  */
809 static int gl_start_newline(GetLine *gl, int buffered);
810 
811 /*
812  * Output a terminal control sequence.
813  */
814 static int gl_print_control_sequence(GetLine *gl, int nline,
815 				     const char *string);
816 
817 /*
818  * Output a character or string to the terminal after converting tabs
819  * to spaces and control characters to a caret followed by the modified
820  * character.
821  */
822 static int gl_print_char(GetLine *gl, char c, char pad);
823 static int gl_print_string(GetLine *gl, const char *string, char pad);
824 
825 /*
826  * Delete nc characters starting from the one under the cursor.
827  * Optionally copy the deleted characters to the cut buffer.
828  */
829 static int gl_delete_chars(GetLine *gl, int nc, int cut);
830 
831 /*
832  * Add a character to the line buffer at the current cursor position,
833  * inserting or overwriting according the current mode.
834  */
835 static int gl_add_char_to_line(GetLine *gl, char c);
836 
837 /*
838  * Insert/append a string to the line buffer and terminal at the current
839  * cursor position.
840  */
841 static int gl_add_string_to_line(GetLine *gl, const char *s);
842 
843 /*
844  * Record a new character in the input-line buffer.
845  */
846 static int gl_buffer_char(GetLine *gl, char c, int bufpos);
847 
848 /*
849  * Record a string in the input-line buffer.
850  */
851 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos);
852 
853 /*
854  * Make way to insert a string in the input-line buffer.
855  */
856 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n);
857 
858 /*
859  * Remove characters from the input-line buffer, and move any characters
860  * that followed them to the start of the vacated space.
861  */
862 static void gl_remove_from_buffer(GetLine *gl, int start, int n);
863 
864 /*
865  * Terminate the input-line buffer after a specified number of characters.
866  */
867 static int gl_truncate_buffer(GetLine *gl, int n);
868 
869 /*
870  * Delete the displayed part of the input line that follows the current
871  * terminal cursor position.
872  */
873 static int gl_truncate_display(GetLine *gl);
874 
875 /*
876  * Accomodate changes to the contents of the input line buffer
877  * that weren't made by the above gl_*buffer functions.
878  */
879 static void gl_update_buffer(GetLine *gl);
880 
881 /*
882  * Read a single character from the terminal.
883  */
884 static int gl_read_terminal(GetLine *gl, int keep, char *c);
885 
886 /*
887  * Discard processed characters from the key-press lookahead buffer.
888  */
889 static void gl_discard_chars(GetLine *gl, int nused);
890 
891 /*
892  * Move the terminal cursor n positions to the left or right.
893  */
894 static int gl_terminal_move_cursor(GetLine *gl, int n);
895 
896 /*
897  * Move the terminal cursor to a given position.
898  */
899 static int gl_set_term_curpos(GetLine *gl, int term_curpos);
900 
901 /*
902  * Set the position of the cursor both in the line input buffer and on the
903  * terminal.
904  */
905 static int gl_place_cursor(GetLine *gl, int buff_curpos);
906 
907 /*
908  * How many characters are needed to write a number as an octal string?
909  */
910 static int gl_octal_width(unsigned num);
911 
912 /*
913  * Return the number of spaces needed to display a tab character at
914  * a given location of the terminal.
915  */
916 static int gl_displayed_tab_width(GetLine *gl, int term_curpos);
917 
918 /*
919  * Return the number of terminal characters needed to display a
920  * given raw character.
921  */
922 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos);
923 
924 /*
925  * Return the number of terminal characters needed to display a
926  * given substring.
927  */
928 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
929 				     int term_curpos);
930 
931 /*
932  * Return non-zero if 'c' is to be considered part of a word.
933  */
934 static int gl_is_word_char(int c);
935 
936 /*
937  * Read a tecla configuration file.
938  */
939 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who);
940 
941 /*
942  * Read a tecla configuration string.
943  */
944 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who);
945 
946 /*
947  * Define the callback function used by _gl_parse_config_line() to
948  * read the next character of a configuration stream.
949  */
950 #define GLC_GETC_FN(fn) int (fn)(void *stream)
951 typedef GLC_GETC_FN(GlcGetcFn);
952 
953 static GLC_GETC_FN(glc_file_getc);  /* Read from a file */
954 static GLC_GETC_FN(glc_buff_getc);  /* Read from a string */
955 
956 /*
957  * Parse a single configuration command line.
958  */
959 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
960 				 const char *origin, KtBinder who, int *lineno);
961 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
962 				  const char *errmsg);
963 
964 /*
965  * Bind the actual arrow key bindings to match those of the symbolic
966  * arrow-key bindings.
967  */
968 static int _gl_bind_arrow_keys(GetLine *gl);
969 
970 /*
971  * Copy the binding of the specified symbolic arrow-key binding to
972  * the terminal specific, and default arrow-key key-sequences.
973  */
974 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
975 				const char *term_seq,
976 				const char *def_seq1,
977 				const char *def_seq2);
978 
979 /*
980  * After the gl_read_from_file() action has been used to tell gl_get_line()
981  * to temporarily read input from a file, gl_revert_input() arranges
982  * for input to be reverted to the input stream last registered with
983  * gl_change_terminal().
984  */
985 static void gl_revert_input(GetLine *gl);
986 
987 /*
988  * Flush unwritten characters to the terminal.
989  */
990 static int gl_flush_output(GetLine *gl);
991 
992 /*
993  * The callback through which all terminal output is routed.
994  * This simply appends characters to a queue buffer, which is
995  * subsequently flushed to the output channel by gl_flush_output().
996  */
997 static GL_WRITE_FN(gl_write_fn);
998 
999 /*
1000  * The callback function which the output character queue object
1001  * calls to transfer characters to the output channel.
1002  */
1003 static GL_WRITE_FN(gl_flush_terminal);
1004 
1005 /*
1006  * Enumerate the possible return statuses of gl_read_input().
1007  */
1008 typedef enum {
1009   GL_READ_OK,      /* A character was read successfully */
1010   GL_READ_ERROR,   /* A read-error occurred */
1011   GL_READ_BLOCKED, /* The read would have blocked the caller */
1012   GL_READ_EOF      /* The end of the current input file was reached */
1013 } GlReadStatus;
1014 
1015 static GlReadStatus gl_read_input(GetLine *gl, char *c);
1016 /*
1017  * Private functions of gl_read_input().
1018  */
1019 static int gl_event_handler(GetLine *gl, int fd);
1020 static GlReadStatus gl_read_unmasked(GetLine *gl, int fd, char *c);
1021 
1022 
1023 /*
1024  * A private function of gl_tty_signals().
1025  */
1026 static int gl_set_tty_signal(int signo, void (*handler)(int));
1027 
1028 /*
1029  * Change the editor style being emulated.
1030  */
1031 static int gl_change_editor(GetLine *gl, GlEditor editor);
1032 
1033 /*
1034  * Searching in a given direction, return the index of a given (or
1035  * read) character in the input line, or the character that precedes
1036  * it in the specified search direction. Return -1 if not found.
1037  */
1038 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c);
1039 
1040 /*
1041  * Return the buffer index of the nth word ending after the cursor.
1042  */
1043 static int gl_nth_word_end_forward(GetLine *gl, int n);
1044 
1045 /*
1046  * Return the buffer index of the nth word start after the cursor.
1047  */
1048 static int gl_nth_word_start_forward(GetLine *gl, int n);
1049 
1050 /*
1051  * Return the buffer index of the nth word start before the cursor.
1052  */
1053 static int gl_nth_word_start_backward(GetLine *gl, int n);
1054 
1055 /*
1056  * When called when vi command mode is enabled, this function saves the
1057  * current line and cursor position for potential restoration later
1058  * by the vi undo command.
1059  */
1060 static void gl_save_for_undo(GetLine *gl);
1061 
1062 /*
1063  * If in vi mode, switch to vi command mode.
1064  */
1065 static void gl_vi_command_mode(GetLine *gl);
1066 
1067 /*
1068  * In vi mode this is used to delete up to or onto a given or read
1069  * character in the input line. Also switch to insert mode if requested
1070  * after the deletion.
1071  */
1072 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
1073 			  int onto, int change);
1074 
1075 /*
1076  * Copy the characters between the cursor and the count'th instance of
1077  * a specified (or read) character in the input line, into the cut buffer.
1078  */
1079 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto);
1080 
1081 /*
1082  * Return the line index of the parenthesis that either matches the one under
1083  * the cursor, or not over a parenthesis character, the index of the next
1084  * close parenthesis. Return -1 if not found.
1085  */
1086 static int gl_index_of_matching_paren(GetLine *gl);
1087 
1088 /*
1089  * Replace a malloc'd string (or NULL), with another malloc'd copy of
1090  * a string (or NULL).
1091  */
1092 static int gl_record_string(char **sptr, const char *string);
1093 
1094 /*
1095  * Enumerate text display attributes as powers of two, suitable for
1096  * use in a bit-mask.
1097  */
1098 typedef enum {
1099   GL_TXT_STANDOUT=1,   /* Display text highlighted */
1100   GL_TXT_UNDERLINE=2,  /* Display text underlined */
1101   GL_TXT_REVERSE=4,    /* Display text with reverse video */
1102   GL_TXT_BLINK=8,      /* Display blinking text */
1103   GL_TXT_DIM=16,       /* Display text in a dim font */
1104   GL_TXT_BOLD=32       /* Display text using a bold font */
1105 } GlTextAttr;
1106 
1107 /*
1108  * Display the prompt regardless of the current visibility mode.
1109  */
1110 static int gl_display_prompt(GetLine *gl);
1111 
1112 /*
1113  * Return the number of characters used by the prompt on the terminal.
1114  */
1115 static int gl_displayed_prompt_width(GetLine *gl);
1116 
1117 /*
1118  * Prepare to return the current input line to the caller of gl_get_line().
1119  */
1120 static int gl_line_ended(GetLine *gl, int newline_char);
1121 
1122 /*
1123  * Arrange for the input line to be redisplayed when the current contents
1124  * of the output queue have been flushed.
1125  */
1126 static void gl_queue_redisplay(GetLine *gl);
1127 
1128 /*
1129  * Erase the displayed representation of the input line, without
1130  * touching the buffered copy.
1131  */
1132 static int gl_erase_line(GetLine *gl);
1133 
1134 /*
1135  * This function is called whenever the input line has been erased.
1136  */
1137 static void gl_line_erased(GetLine *gl);
1138 
1139 /*
1140  * Arrange for the current input line to be discarded.
1141  */
1142 void _gl_abandon_line(GetLine *gl);
1143 
1144 /*
1145  * The following are private internally callable versions of pertinent
1146  * public functions. Unlike their public wrapper functions, they don't
1147  * block signals while running, and assume that their arguments are valid.
1148  * They are designed to be called from places where signals are already
1149  * blocked, and where simple sanity checks have already been applied to
1150  * their arguments.
1151  */
1152 static char *_gl_get_line(GetLine *gl, const char *prompt,
1153 			  const char *start_line, int start_pos);
1154 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar);
1155 static int _gl_read_char(GetLine *gl);
1156 static int _gl_update_size(GetLine *gl);
1157 /*
1158  * Redraw the current input line to account for a change in the terminal
1159  * size. Also install the new size in gl.
1160  */
1161 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline);
1162 
1163 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
1164 			       const char *term);
1165 static int _gl_configure_getline(GetLine *gl, const char *app_string,
1166 				 const char *app_file, const char *user_file);
1167 static int _gl_save_history(GetLine *gl, const char *filename,
1168 			    const char *comment, int max_lines);
1169 static int _gl_load_history(GetLine *gl, const char *filename,
1170 			    const char *comment);
1171 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
1172 			GlFdEventFn *callback, void *data);
1173 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
1174 			      GlTerminalSize *size);
1175 static void _gl_replace_prompt(GetLine *gl, const char *prompt);
1176 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
1177 			   GlAfterSignal after, int errno_value);
1178 static int _gl_raw_io(GetLine *gl, int redisplay);
1179 static int _gl_normal_io(GetLine *gl);
1180 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
1181 				 int list_only, const char *name,
1182 				 const char *keyseq);
1183 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
1184 			       const char *name, const char *keyseq);
1185 static int _gl_io_mode(GetLine *gl, GlIOMode mode);
1186 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline);
1187 static int _gl_append_history(GetLine *gl, const char *line);
1188 
1189 /*
1190  * Reset the completion status and associated errno value in
1191  * gl->rtn_status and gl->rtn_errno.
1192  */
1193 static void gl_clear_status(GetLine *gl);
1194 
1195 /*
1196  * Record a completion status, unless a previous abnormal completion
1197  * status has already been recorded for the current call.
1198  */
1199 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
1200 			     int rtn_errno);
1201 
1202 /*
1203  * Set the maximum length of a line in a user's tecla configuration
1204  * file (not counting comments).
1205  */
1206 #define GL_CONF_BUFLEN 100
1207 
1208 /*
1209  * Set the maximum number of arguments supported by individual commands
1210  * in tecla configuration files.
1211  */
1212 #define GL_CONF_MAXARG 10
1213 
1214 /*
1215  * Prototype the available action functions.
1216  */
1217 static KT_KEY_FN(gl_user_interrupt);
1218 static KT_KEY_FN(gl_abort);
1219 static KT_KEY_FN(gl_suspend);
1220 static KT_KEY_FN(gl_stop_output);
1221 static KT_KEY_FN(gl_start_output);
1222 static KT_KEY_FN(gl_literal_next);
1223 static KT_KEY_FN(gl_cursor_left);
1224 static KT_KEY_FN(gl_cursor_right);
1225 static KT_KEY_FN(gl_insert_mode);
1226 static KT_KEY_FN(gl_beginning_of_line);
1227 static KT_KEY_FN(gl_end_of_line);
1228 static KT_KEY_FN(gl_delete_line);
1229 static KT_KEY_FN(gl_kill_line);
1230 static KT_KEY_FN(gl_forward_word);
1231 static KT_KEY_FN(gl_backward_word);
1232 static KT_KEY_FN(gl_forward_delete_char);
1233 static KT_KEY_FN(gl_backward_delete_char);
1234 static KT_KEY_FN(gl_forward_delete_word);
1235 static KT_KEY_FN(gl_backward_delete_word);
1236 static KT_KEY_FN(gl_delete_refind);
1237 static KT_KEY_FN(gl_delete_invert_refind);
1238 static KT_KEY_FN(gl_delete_to_column);
1239 static KT_KEY_FN(gl_delete_to_parenthesis);
1240 static KT_KEY_FN(gl_forward_delete_find);
1241 static KT_KEY_FN(gl_backward_delete_find);
1242 static KT_KEY_FN(gl_forward_delete_to);
1243 static KT_KEY_FN(gl_backward_delete_to);
1244 static KT_KEY_FN(gl_upcase_word);
1245 static KT_KEY_FN(gl_downcase_word);
1246 static KT_KEY_FN(gl_capitalize_word);
1247 static KT_KEY_FN(gl_redisplay);
1248 static KT_KEY_FN(gl_clear_screen);
1249 static KT_KEY_FN(gl_transpose_chars);
1250 static KT_KEY_FN(gl_set_mark);
1251 static KT_KEY_FN(gl_exchange_point_and_mark);
1252 static KT_KEY_FN(gl_kill_region);
1253 static KT_KEY_FN(gl_copy_region_as_kill);
1254 static KT_KEY_FN(gl_yank);
1255 static KT_KEY_FN(gl_up_history);
1256 static KT_KEY_FN(gl_down_history);
1257 static KT_KEY_FN(gl_history_search_backward);
1258 static KT_KEY_FN(gl_history_re_search_backward);
1259 static KT_KEY_FN(gl_history_search_forward);
1260 static KT_KEY_FN(gl_history_re_search_forward);
1261 static KT_KEY_FN(gl_complete_word);
1262 #ifndef HIDE_FILE_SYSTEM
1263 static KT_KEY_FN(gl_expand_filename);
1264 static KT_KEY_FN(gl_read_from_file);
1265 static KT_KEY_FN(gl_read_init_files);
1266 static KT_KEY_FN(gl_list_glob);
1267 #endif
1268 static KT_KEY_FN(gl_del_char_or_list_or_eof);
1269 static KT_KEY_FN(gl_list_or_eof);
1270 static KT_KEY_FN(gl_beginning_of_history);
1271 static KT_KEY_FN(gl_end_of_history);
1272 static KT_KEY_FN(gl_digit_argument);
1273 static KT_KEY_FN(gl_newline);
1274 static KT_KEY_FN(gl_repeat_history);
1275 static KT_KEY_FN(gl_vi_insert);
1276 static KT_KEY_FN(gl_vi_overwrite);
1277 static KT_KEY_FN(gl_change_case);
1278 static KT_KEY_FN(gl_vi_insert_at_bol);
1279 static KT_KEY_FN(gl_vi_append_at_eol);
1280 static KT_KEY_FN(gl_vi_append);
1281 static KT_KEY_FN(gl_backward_kill_line);
1282 static KT_KEY_FN(gl_goto_column);
1283 static KT_KEY_FN(gl_forward_to_word);
1284 static KT_KEY_FN(gl_vi_replace_char);
1285 static KT_KEY_FN(gl_vi_change_rest_of_line);
1286 static KT_KEY_FN(gl_vi_change_line);
1287 static KT_KEY_FN(gl_vi_change_to_bol);
1288 static KT_KEY_FN(gl_vi_change_refind);
1289 static KT_KEY_FN(gl_vi_change_invert_refind);
1290 static KT_KEY_FN(gl_vi_change_to_column);
1291 static KT_KEY_FN(gl_vi_change_to_parenthesis);
1292 static KT_KEY_FN(gl_vi_forward_change_word);
1293 static KT_KEY_FN(gl_vi_backward_change_word);
1294 static KT_KEY_FN(gl_vi_forward_change_find);
1295 static KT_KEY_FN(gl_vi_backward_change_find);
1296 static KT_KEY_FN(gl_vi_forward_change_to);
1297 static KT_KEY_FN(gl_vi_backward_change_to);
1298 static KT_KEY_FN(gl_vi_forward_change_char);
1299 static KT_KEY_FN(gl_vi_backward_change_char);
1300 static KT_KEY_FN(gl_forward_copy_char);
1301 static KT_KEY_FN(gl_backward_copy_char);
1302 static KT_KEY_FN(gl_forward_find_char);
1303 static KT_KEY_FN(gl_backward_find_char);
1304 static KT_KEY_FN(gl_forward_to_char);
1305 static KT_KEY_FN(gl_backward_to_char);
1306 static KT_KEY_FN(gl_repeat_find_char);
1307 static KT_KEY_FN(gl_invert_refind_char);
1308 static KT_KEY_FN(gl_append_yank);
1309 static KT_KEY_FN(gl_backward_copy_word);
1310 static KT_KEY_FN(gl_forward_copy_word);
1311 static KT_KEY_FN(gl_copy_to_bol);
1312 static KT_KEY_FN(gl_copy_refind);
1313 static KT_KEY_FN(gl_copy_invert_refind);
1314 static KT_KEY_FN(gl_copy_to_column);
1315 static KT_KEY_FN(gl_copy_to_parenthesis);
1316 static KT_KEY_FN(gl_copy_rest_of_line);
1317 static KT_KEY_FN(gl_copy_line);
1318 static KT_KEY_FN(gl_backward_copy_find);
1319 static KT_KEY_FN(gl_forward_copy_find);
1320 static KT_KEY_FN(gl_backward_copy_to);
1321 static KT_KEY_FN(gl_forward_copy_to);
1322 static KT_KEY_FN(gl_vi_undo);
1323 static KT_KEY_FN(gl_emacs_editing_mode);
1324 static KT_KEY_FN(gl_vi_editing_mode);
1325 static KT_KEY_FN(gl_ring_bell);
1326 static KT_KEY_FN(gl_vi_repeat_change);
1327 static KT_KEY_FN(gl_find_parenthesis);
1328 static KT_KEY_FN(gl_list_history);
1329 static KT_KEY_FN(gl_list_completions);
1330 static KT_KEY_FN(gl_run_external_action);
1331 
1332 /*
1333  * Name the available action functions.
1334  */
1335 static const struct {const char *name; KT_KEY_FN(*fn);} gl_actions[] = {
1336   {"user-interrupt",             gl_user_interrupt},
1337   {"abort",                      gl_abort},
1338   {"suspend",                    gl_suspend},
1339   {"stop-output",                gl_stop_output},
1340   {"start-output",               gl_start_output},
1341   {"literal-next",               gl_literal_next},
1342   {"cursor-right",               gl_cursor_right},
1343   {"cursor-left",                gl_cursor_left},
1344   {"insert-mode",                gl_insert_mode},
1345   {"beginning-of-line",          gl_beginning_of_line},
1346   {"end-of-line",                gl_end_of_line},
1347   {"delete-line",                gl_delete_line},
1348   {"kill-line",                  gl_kill_line},
1349   {"forward-word",               gl_forward_word},
1350   {"backward-word",              gl_backward_word},
1351   {"forward-delete-char",        gl_forward_delete_char},
1352   {"backward-delete-char",       gl_backward_delete_char},
1353   {"forward-delete-word",        gl_forward_delete_word},
1354   {"backward-delete-word",       gl_backward_delete_word},
1355   {"delete-refind",              gl_delete_refind},
1356   {"delete-invert-refind",       gl_delete_invert_refind},
1357   {"delete-to-column",           gl_delete_to_column},
1358   {"delete-to-parenthesis",      gl_delete_to_parenthesis},
1359   {"forward-delete-find",        gl_forward_delete_find},
1360   {"backward-delete-find",       gl_backward_delete_find},
1361   {"forward-delete-to",          gl_forward_delete_to},
1362   {"backward-delete-to",         gl_backward_delete_to},
1363   {"upcase-word",                gl_upcase_word},
1364   {"downcase-word",              gl_downcase_word},
1365   {"capitalize-word",            gl_capitalize_word},
1366   {"redisplay",                  gl_redisplay},
1367   {"clear-screen",               gl_clear_screen},
1368   {"transpose-chars",            gl_transpose_chars},
1369   {"set-mark",                   gl_set_mark},
1370   {"exchange-point-and-mark",    gl_exchange_point_and_mark},
1371   {"kill-region",                gl_kill_region},
1372   {"copy-region-as-kill",        gl_copy_region_as_kill},
1373   {"yank",                       gl_yank},
1374   {"up-history",                 gl_up_history},
1375   {"down-history",               gl_down_history},
1376   {"history-search-backward",    gl_history_search_backward},
1377   {"history-re-search-backward", gl_history_re_search_backward},
1378   {"history-search-forward",     gl_history_search_forward},
1379   {"history-re-search-forward",  gl_history_re_search_forward},
1380   {"complete-word",              gl_complete_word},
1381 #ifndef HIDE_FILE_SYSTEM
1382   {"expand-filename",            gl_expand_filename},
1383   {"read-from-file",             gl_read_from_file},
1384   {"read-init-files",            gl_read_init_files},
1385   {"list-glob",                  gl_list_glob},
1386 #endif
1387   {"del-char-or-list-or-eof",    gl_del_char_or_list_or_eof},
1388   {"beginning-of-history",       gl_beginning_of_history},
1389   {"end-of-history",             gl_end_of_history},
1390   {"digit-argument",             gl_digit_argument},
1391   {"newline",                    gl_newline},
1392   {"repeat-history",             gl_repeat_history},
1393   {"vi-insert",                  gl_vi_insert},
1394   {"vi-overwrite",               gl_vi_overwrite},
1395   {"vi-insert-at-bol",           gl_vi_insert_at_bol},
1396   {"vi-append-at-eol",           gl_vi_append_at_eol},
1397   {"vi-append",                  gl_vi_append},
1398   {"change-case",                gl_change_case},
1399   {"backward-kill-line",         gl_backward_kill_line},
1400   {"goto-column",                gl_goto_column},
1401   {"forward-to-word",            gl_forward_to_word},
1402   {"vi-replace-char",            gl_vi_replace_char},
1403   {"vi-change-rest-of-line",     gl_vi_change_rest_of_line},
1404   {"vi-change-line",             gl_vi_change_line},
1405   {"vi-change-to-bol",           gl_vi_change_to_bol},
1406   {"vi-change-refind",           gl_vi_change_refind},
1407   {"vi-change-invert-refind",    gl_vi_change_invert_refind},
1408   {"vi-change-to-column",        gl_vi_change_to_column},
1409   {"vi-change-to-parenthesis",   gl_vi_change_to_parenthesis},
1410   {"forward-copy-char",          gl_forward_copy_char},
1411   {"backward-copy-char",         gl_backward_copy_char},
1412   {"forward-find-char",          gl_forward_find_char},
1413   {"backward-find-char",         gl_backward_find_char},
1414   {"forward-to-char",            gl_forward_to_char},
1415   {"backward-to-char",           gl_backward_to_char},
1416   {"repeat-find-char",           gl_repeat_find_char},
1417   {"invert-refind-char",         gl_invert_refind_char},
1418   {"append-yank",                gl_append_yank},
1419   {"backward-copy-word",         gl_backward_copy_word},
1420   {"forward-copy-word",          gl_forward_copy_word},
1421   {"copy-to-bol",                gl_copy_to_bol},
1422   {"copy-refind",                gl_copy_refind},
1423   {"copy-invert-refind",         gl_copy_invert_refind},
1424   {"copy-to-column",             gl_copy_to_column},
1425   {"copy-to-parenthesis",        gl_copy_to_parenthesis},
1426   {"copy-rest-of-line",          gl_copy_rest_of_line},
1427   {"copy-line",                  gl_copy_line},
1428   {"backward-copy-find",         gl_backward_copy_find},
1429   {"forward-copy-find",          gl_forward_copy_find},
1430   {"backward-copy-to",           gl_backward_copy_to},
1431   {"forward-copy-to",            gl_forward_copy_to},
1432   {"list-or-eof",                gl_list_or_eof},
1433   {"vi-undo",                    gl_vi_undo},
1434   {"vi-backward-change-word",    gl_vi_backward_change_word},
1435   {"vi-forward-change-word",     gl_vi_forward_change_word},
1436   {"vi-backward-change-find",    gl_vi_backward_change_find},
1437   {"vi-forward-change-find",     gl_vi_forward_change_find},
1438   {"vi-backward-change-to",      gl_vi_backward_change_to},
1439   {"vi-forward-change-to",       gl_vi_forward_change_to},
1440   {"vi-backward-change-char",    gl_vi_backward_change_char},
1441   {"vi-forward-change-char",     gl_vi_forward_change_char},
1442   {"emacs-mode",                 gl_emacs_editing_mode},
1443   {"vi-mode",                    gl_vi_editing_mode},
1444   {"ring-bell",                  gl_ring_bell},
1445   {"vi-repeat-change",           gl_vi_repeat_change},
1446   {"find-parenthesis",           gl_find_parenthesis},
1447   {"list-history",               gl_list_history},
1448 };
1449 
1450 /*
1451  * Define the default key-bindings in emacs mode.
1452  */
1453 static const KtKeyBinding gl_emacs_bindings[] = {
1454   {"right",        "cursor-right"},
1455   {"^F",           "cursor-right"},
1456   {"left",         "cursor-left"},
1457   {"^B",           "cursor-left"},
1458   {"M-i",          "insert-mode"},
1459   {"M-I",          "insert-mode"},
1460   {"^A",           "beginning-of-line"},
1461   {"^E",           "end-of-line"},
1462   {"^U",           "delete-line"},
1463   {"^K",           "kill-line"},
1464   {"M-f",          "forward-word"},
1465   {"M-F",          "forward-word"},
1466   {"M-b",          "backward-word"},
1467   {"M-B",          "backward-word"},
1468   {"^D",           "del-char-or-list-or-eof"},
1469   {"^H",           "backward-delete-char"},
1470   {"^?",           "backward-delete-char"},
1471   {"M-d",          "forward-delete-word"},
1472   {"M-D",          "forward-delete-word"},
1473   {"M-^H",         "backward-delete-word"},
1474   {"M-^?",         "backward-delete-word"},
1475   {"M-u",          "upcase-word"},
1476   {"M-U",          "upcase-word"},
1477   {"M-l",          "downcase-word"},
1478   {"M-L",          "downcase-word"},
1479   {"M-c",          "capitalize-word"},
1480   {"M-C",          "capitalize-word"},
1481   {"^R",           "redisplay"},
1482   {"^L",           "clear-screen"},
1483   {"^T",           "transpose-chars"},
1484   {"^@",           "set-mark"},
1485   {"^X^X",         "exchange-point-and-mark"},
1486   {"^W",           "kill-region"},
1487   {"M-w",          "copy-region-as-kill"},
1488   {"M-W",          "copy-region-as-kill"},
1489   {"^Y",           "yank"},
1490   {"^P",           "up-history"},
1491   {"up",           "up-history"},
1492   {"^N",           "down-history"},
1493   {"down",         "down-history"},
1494   {"M-p",          "history-search-backward"},
1495   {"M-P",          "history-search-backward"},
1496   {"M-n",          "history-search-forward"},
1497   {"M-N",          "history-search-forward"},
1498   {"\t",           "complete-word"},
1499 #ifndef HIDE_FILE_SYSTEM
1500   {"^X*",          "expand-filename"},
1501   {"^X^F",         "read-from-file"},
1502   {"^X^R",         "read-init-files"},
1503   {"^Xg",          "list-glob"},
1504   {"^XG",          "list-glob"},
1505 #endif
1506   {"^Xh",          "list-history"},
1507   {"^XH",          "list-history"},
1508   {"M-<",          "beginning-of-history"},
1509   {"M->",          "end-of-history"},
1510   {"M-0",          "digit-argument"},
1511   {"M-1",          "digit-argument"},
1512   {"M-2",          "digit-argument"},
1513   {"M-3",          "digit-argument"},
1514   {"M-4",          "digit-argument"},
1515   {"M-5",          "digit-argument"},
1516   {"M-6",          "digit-argument"},
1517   {"M-7",          "digit-argument"},
1518   {"M-8",          "digit-argument"},
1519   {"M-9",          "digit-argument"},
1520   {"\r",           "newline"},
1521   {"\n",           "newline"},
1522   {"M-o",          "repeat-history"},
1523   {"M-C-v",        "vi-mode"},
1524 };
1525 
1526 /*
1527  * Define the default key-bindings in vi mode. Note that in vi-mode
1528  * meta-key bindings are command-mode bindings. For example M-i first
1529  * switches to command mode if not already in that mode, then moves
1530  * the cursor one position right, as in vi.
1531  */
1532 static const KtKeyBinding gl_vi_bindings[] = {
1533   {"^D",           "list-or-eof"},
1534 #ifndef HIDE_FILE_SYSTEM
1535   {"^G",           "list-glob"},
1536 #endif
1537   {"^H",           "backward-delete-char"},
1538   {"\t",           "complete-word"},
1539   {"\r",           "newline"},
1540   {"\n",           "newline"},
1541   {"^L",           "clear-screen"},
1542   {"^N",           "down-history"},
1543   {"^P",           "up-history"},
1544   {"^R",           "redisplay"},
1545   {"^U",           "backward-kill-line"},
1546   {"^W",           "backward-delete-word"},
1547 #ifndef HIDE_FILE_SYSTEM
1548   {"^X^F",         "read-from-file"},
1549   {"^X^R",         "read-init-files"},
1550   {"^X*",          "expand-filename"},
1551 #endif
1552   {"^?",           "backward-delete-char"},
1553   {"M- ",          "cursor-right"},
1554   {"M-$",          "end-of-line"},
1555 #ifndef HIDE_FILE_SYSTEM
1556   {"M-*",          "expand-filename"},
1557 #endif
1558   {"M-+",          "down-history"},
1559   {"M--",          "up-history"},
1560   {"M-<",          "beginning-of-history"},
1561   {"M->",          "end-of-history"},
1562   {"M-^",          "beginning-of-line"},
1563   {"M-;",          "repeat-find-char"},
1564   {"M-,",          "invert-refind-char"},
1565   {"M-|",          "goto-column"},
1566   {"M-~",          "change-case"},
1567   {"M-.",          "vi-repeat-change"},
1568   {"M-%",          "find-parenthesis"},
1569   {"M-0",          "digit-argument"},
1570   {"M-1",          "digit-argument"},
1571   {"M-2",          "digit-argument"},
1572   {"M-3",          "digit-argument"},
1573   {"M-4",          "digit-argument"},
1574   {"M-5",          "digit-argument"},
1575   {"M-6",          "digit-argument"},
1576   {"M-7",          "digit-argument"},
1577   {"M-8",          "digit-argument"},
1578   {"M-9",          "digit-argument"},
1579   {"M-a",          "vi-append"},
1580   {"M-A",          "vi-append-at-eol"},
1581   {"M-b",          "backward-word"},
1582   {"M-B",          "backward-word"},
1583   {"M-C",          "vi-change-rest-of-line"},
1584   {"M-cb",         "vi-backward-change-word"},
1585   {"M-cB",         "vi-backward-change-word"},
1586   {"M-cc",         "vi-change-line"},
1587   {"M-ce",         "vi-forward-change-word"},
1588   {"M-cE",         "vi-forward-change-word"},
1589   {"M-cw",         "vi-forward-change-word"},
1590   {"M-cW",         "vi-forward-change-word"},
1591   {"M-cF",         "vi-backward-change-find"},
1592   {"M-cf",         "vi-forward-change-find"},
1593   {"M-cT",         "vi-backward-change-to"},
1594   {"M-ct",         "vi-forward-change-to"},
1595   {"M-c;",         "vi-change-refind"},
1596   {"M-c,",         "vi-change-invert-refind"},
1597   {"M-ch",         "vi-backward-change-char"},
1598   {"M-c^H",        "vi-backward-change-char"},
1599   {"M-c^?",        "vi-backward-change-char"},
1600   {"M-cl",         "vi-forward-change-char"},
1601   {"M-c ",         "vi-forward-change-char"},
1602   {"M-c^",         "vi-change-to-bol"},
1603   {"M-c0",         "vi-change-to-bol"},
1604   {"M-c$",         "vi-change-rest-of-line"},
1605   {"M-c|",         "vi-change-to-column"},
1606   {"M-c%",         "vi-change-to-parenthesis"},
1607   {"M-dh",         "backward-delete-char"},
1608   {"M-d^H",        "backward-delete-char"},
1609   {"M-d^?",        "backward-delete-char"},
1610   {"M-dl",         "forward-delete-char"},
1611   {"M-d ",         "forward-delete-char"},
1612   {"M-dd",         "delete-line"},
1613   {"M-db",         "backward-delete-word"},
1614   {"M-dB",         "backward-delete-word"},
1615   {"M-de",         "forward-delete-word"},
1616   {"M-dE",         "forward-delete-word"},
1617   {"M-dw",         "forward-delete-word"},
1618   {"M-dW",         "forward-delete-word"},
1619   {"M-dF",         "backward-delete-find"},
1620   {"M-df",         "forward-delete-find"},
1621   {"M-dT",         "backward-delete-to"},
1622   {"M-dt",         "forward-delete-to"},
1623   {"M-d;",         "delete-refind"},
1624   {"M-d,",         "delete-invert-refind"},
1625   {"M-d^",         "backward-kill-line"},
1626   {"M-d0",         "backward-kill-line"},
1627   {"M-d$",         "kill-line"},
1628   {"M-D",          "kill-line"},
1629   {"M-d|",         "delete-to-column"},
1630   {"M-d%",         "delete-to-parenthesis"},
1631   {"M-e",          "forward-word"},
1632   {"M-E",          "forward-word"},
1633   {"M-f",          "forward-find-char"},
1634   {"M-F",          "backward-find-char"},
1635   {"M--",          "up-history"},
1636   {"M-h",          "cursor-left"},
1637   {"M-H",          "beginning-of-history"},
1638   {"M-i",          "vi-insert"},
1639   {"M-I",          "vi-insert-at-bol"},
1640   {"M-j",          "down-history"},
1641   {"M-J",          "history-search-forward"},
1642   {"M-k",          "up-history"},
1643   {"M-K",          "history-search-backward"},
1644   {"M-l",          "cursor-right"},
1645   {"M-L",          "end-of-history"},
1646   {"M-n",          "history-re-search-forward"},
1647   {"M-N",          "history-re-search-backward"},
1648   {"M-p",          "append-yank"},
1649   {"M-P",          "yank"},
1650   {"M-r",          "vi-replace-char"},
1651   {"M-R",          "vi-overwrite"},
1652   {"M-s",          "vi-forward-change-char"},
1653   {"M-S",          "vi-change-line"},
1654   {"M-t",          "forward-to-char"},
1655   {"M-T",          "backward-to-char"},
1656   {"M-u",          "vi-undo"},
1657   {"M-w",          "forward-to-word"},
1658   {"M-W",          "forward-to-word"},
1659   {"M-x",          "forward-delete-char"},
1660   {"M-X",          "backward-delete-char"},
1661   {"M-yh",         "backward-copy-char"},
1662   {"M-y^H",        "backward-copy-char"},
1663   {"M-y^?",        "backward-copy-char"},
1664   {"M-yl",         "forward-copy-char"},
1665   {"M-y ",         "forward-copy-char"},
1666   {"M-ye",         "forward-copy-word"},
1667   {"M-yE",         "forward-copy-word"},
1668   {"M-yw",         "forward-copy-word"},
1669   {"M-yW",         "forward-copy-word"},
1670   {"M-yb",         "backward-copy-word"},
1671   {"M-yB",         "backward-copy-word"},
1672   {"M-yf",         "forward-copy-find"},
1673   {"M-yF",         "backward-copy-find"},
1674   {"M-yt",         "forward-copy-to"},
1675   {"M-yT",         "backward-copy-to"},
1676   {"M-y;",         "copy-refind"},
1677   {"M-y,",         "copy-invert-refind"},
1678   {"M-y^",         "copy-to-bol"},
1679   {"M-y0",         "copy-to-bol"},
1680   {"M-y$",         "copy-rest-of-line"},
1681   {"M-yy",         "copy-line"},
1682   {"M-Y",          "copy-line"},
1683   {"M-y|",         "copy-to-column"},
1684   {"M-y%",         "copy-to-parenthesis"},
1685   {"M-^E",         "emacs-mode"},
1686   {"M-^H",         "cursor-left"},
1687   {"M-^?",         "cursor-left"},
1688   {"M-^L",         "clear-screen"},
1689   {"M-^N",         "down-history"},
1690   {"M-^P",         "up-history"},
1691   {"M-^R",         "redisplay"},
1692   {"M-^D",         "list-or-eof"},
1693   {"M-\r",         "newline"},
1694   {"M-\t",         "complete-word"},
1695   {"M-\n",         "newline"},
1696 #ifndef HIDE_FILE_SYSTEM
1697   {"M-^X^R",       "read-init-files"},
1698 #endif
1699   {"M-^Xh",        "list-history"},
1700   {"M-^XH",        "list-history"},
1701   {"down",         "down-history"},
1702   {"up",           "up-history"},
1703   {"left",         "cursor-left"},
1704   {"right",        "cursor-right"},
1705 };
1706 
1707 /*.......................................................................
1708  * Create a new GetLine object.
1709  *
1710  * Input:
1711  *  linelen  size_t    The maximum line length to allow for.
1712  *  histlen  size_t    The number of bytes to allocate for recording
1713  *                     a circular buffer of history lines.
1714  * Output:
1715  *  return  GetLine *  The new object, or NULL on error.
1716  */
new_GetLine(size_t linelen,size_t histlen)1717 GetLine *new_GetLine(size_t linelen, size_t histlen)
1718 {
1719   GetLine *gl;  /* The object to be returned */
1720   int i;
1721 /*
1722  * Check the arguments.
1723  */
1724   if(linelen < 10) {
1725     errno = ENOMEM;
1726     return NULL;
1727   };
1728 /*
1729  * Allocate the container.
1730  */
1731   gl = (GetLine *) malloc(sizeof(GetLine));
1732   if(!gl) {
1733     errno = ENOMEM;
1734     return NULL;
1735   };
1736 /*
1737  * Before attempting any operation that might fail, initialize the
1738  * container at least up to the point at which it can safely be passed
1739  * to del_GetLine().
1740  */
1741   gl->err = NULL;
1742   gl->glh = NULL;
1743   gl->cpl = NULL;
1744 #ifndef HIDE_FILE_SYSTEM
1745   gl->cplfn.fn = cpl_file_completions;
1746 #else
1747   gl->cplfn.fn = gl_no_completions;
1748 #endif
1749   gl->cplfn.data = NULL;
1750 #ifndef WITHOUT_FILE_SYSTEM
1751   gl->ef = NULL;
1752 #endif
1753   gl->capmem = NULL;
1754   gl->cq = NULL;
1755   gl->input_fd = -1;
1756   gl->output_fd = -1;
1757   gl->input_fp = NULL;
1758   gl->output_fp = NULL;
1759   gl->file_fp = NULL;
1760   gl->term = NULL;
1761   gl->is_term = 0;
1762   gl->flush_fn = gl_flush_terminal;
1763   gl->io_mode = GL_NORMAL_MODE;
1764   gl->raw_mode = 0;
1765   gl->pending_io = GLP_WRITE;  /* We will start by writing the prompt */
1766   gl_clear_status(gl);
1767   gl->linelen = linelen;
1768   gl->line = NULL;
1769   gl->cutbuf = NULL;
1770   gl->prompt = NULL;
1771   gl->prompt_len = 0;
1772   gl->prompt_changed = 0;
1773   gl->prompt_style = GL_LITERAL_PROMPT;
1774   gl->cpl_mem = NULL;
1775   gl->ext_act_mem = NULL;
1776   gl->sig_mem = NULL;
1777   gl->sigs = NULL;
1778   gl->signals_masked = 0;
1779   gl->signals_overriden = 0;
1780   sigemptyset(&gl->all_signal_set);
1781   sigemptyset(&gl->old_signal_set);
1782   sigemptyset(&gl->use_signal_set);
1783   gl->bindings = NULL;
1784   gl->ntotal = 0;
1785   gl->buff_curpos = 0;
1786   gl->term_curpos = 0;
1787   gl->term_len = 0;
1788   gl->buff_mark = 0;
1789   gl->insert_curpos = 0;
1790   gl->insert = 1;
1791   gl->number = -1;
1792   gl->endline = 1;
1793   gl->displayed = 0;
1794   gl->redisplay = 0;
1795   gl->postpone = 0;
1796   gl->keybuf[0]='\0';
1797   gl->nbuf = 0;
1798   gl->nread = 0;
1799   gl->current_action.fn = 0;
1800   gl->current_action.data = NULL;
1801   gl->current_count = 0;
1802   gl->preload_id = 0;
1803   gl->preload_history = 0;
1804   gl->keyseq_count = 0;
1805   gl->last_search = -1;
1806   gl->editor = GL_EMACS_MODE;
1807   gl->silence_bell = 0;
1808   gl->automatic_history = 1;
1809   gl->vi.undo.line = NULL;
1810   gl->vi.undo.buff_curpos = 0;
1811   gl->vi.undo.ntotal = 0;
1812   gl->vi.undo.saved = 0;
1813   gl->vi.repeat.action.fn = 0;
1814   gl->vi.repeat.action.data = 0;
1815   gl->vi.repeat.count = 0;
1816   gl->vi.repeat.input_curpos = 0;
1817   gl->vi.repeat.command_curpos = 0;
1818   gl->vi.repeat.input_char = '\0';
1819   gl->vi.repeat.saved = 0;
1820   gl->vi.repeat.active = 0;
1821   gl->vi.command = 0;
1822   gl->vi.find_forward = 0;
1823   gl->vi.find_onto = 0;
1824   gl->vi.find_char = '\0';
1825   gl->left = NULL;
1826   gl->right = NULL;
1827   gl->up = NULL;
1828   gl->down = NULL;
1829   gl->home = NULL;
1830   gl->bol = 0;
1831   gl->clear_eol = NULL;
1832   gl->clear_eod = NULL;
1833   gl->u_arrow = NULL;
1834   gl->d_arrow = NULL;
1835   gl->l_arrow = NULL;
1836   gl->r_arrow = NULL;
1837   gl->sound_bell = NULL;
1838   gl->bold = NULL;
1839   gl->underline = NULL;
1840   gl->standout = NULL;
1841   gl->dim = NULL;
1842   gl->reverse = NULL;
1843   gl->blink = NULL;
1844   gl->text_attr_off = NULL;
1845   gl->nline = 0;
1846   gl->ncolumn = 0;
1847 #ifdef USE_TERMINFO
1848   gl->left_n = NULL;
1849   gl->right_n = NULL;
1850 #elif defined(USE_TERMCAP)
1851   gl->tgetent_buf = NULL;
1852   gl->tgetstr_buf = NULL;
1853 #endif
1854   gl->app_file = NULL;
1855   gl->user_file = NULL;
1856   gl->configured = 0;
1857   gl->echo = 1;
1858   gl->last_signal = -1;
1859 #ifdef HAVE_SELECT
1860   gl->fd_node_mem = NULL;
1861   gl->fd_nodes = NULL;
1862   FD_ZERO(&gl->rfds);
1863   FD_ZERO(&gl->wfds);
1864   FD_ZERO(&gl->ufds);
1865   gl->max_fd = 0;
1866   gl->timer.dt.tv_sec = 0;
1867   gl->timer.dt.tv_usec = 0;
1868   gl->timer.fn = 0;
1869   gl->timer.data = NULL;
1870 #endif
1871 /*
1872  * Allocate an error reporting buffer.
1873  */
1874   gl->err = _new_ErrMsg();
1875   if(!gl->err)
1876     return del_GetLine(gl);
1877 /*
1878  * Allocate the history buffer.
1879  */
1880   gl->glh = _new_GlHistory(histlen);
1881   if(!gl->glh)
1882     return del_GetLine(gl);
1883 /*
1884  * Allocate the resource object for file-completion.
1885  */
1886   gl->cpl = new_WordCompletion();
1887   if(!gl->cpl)
1888     return del_GetLine(gl);
1889 /*
1890  * Allocate the resource object for file-completion.
1891  */
1892 #ifndef WITHOUT_FILE_SYSTEM
1893   gl->ef = new_ExpandFile();
1894   if(!gl->ef)
1895     return del_GetLine(gl);
1896 #endif
1897 /*
1898  * Allocate a string-segment memory allocator for use in storing terminal
1899  * capablity strings.
1900  */
1901   gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE);
1902   if(!gl->capmem)
1903     return del_GetLine(gl);
1904 /*
1905  * Allocate the character queue that is used to buffer terminal output.
1906  */
1907   gl->cq = _new_GlCharQueue();
1908   if(!gl->cq)
1909     return del_GetLine(gl);
1910 /*
1911  * Allocate a line buffer, leaving 2 extra characters for the terminating
1912  * '\n' and '\0' characters
1913  */
1914   gl->line = (char *) malloc(linelen + 2);
1915   if(!gl->line) {
1916     errno = ENOMEM;
1917     return del_GetLine(gl);
1918   };
1919 /*
1920  * Start with an empty input line.
1921  */
1922   gl_truncate_buffer(gl, 0);
1923 /*
1924  * Allocate a cut buffer.
1925  */
1926   gl->cutbuf = (char *) malloc(linelen + 2);
1927   if(!gl->cutbuf) {
1928     errno = ENOMEM;
1929     return del_GetLine(gl);
1930   };
1931   gl->cutbuf[0] = '\0';
1932 /*
1933  * Allocate an initial empty prompt.
1934  */
1935   _gl_replace_prompt(gl, NULL);
1936   if(!gl->prompt) {
1937     errno = ENOMEM;
1938     return del_GetLine(gl);
1939   };
1940 /*
1941  * Allocate a vi undo buffer.
1942  */
1943   gl->vi.undo.line = (char *) malloc(linelen + 2);
1944   if(!gl->vi.undo.line) {
1945     errno = ENOMEM;
1946     return del_GetLine(gl);
1947   };
1948   gl->vi.undo.line[0] = '\0';
1949 /*
1950  * Allocate a freelist from which to allocate nodes for the list
1951  * of completion functions.
1952  */
1953   gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING);
1954   if(!gl->cpl_mem)
1955     return del_GetLine(gl);
1956 /*
1957  * Allocate a freelist from which to allocate nodes for the list
1958  * of external action functions.
1959  */
1960   gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction),
1961 				  GL_EXT_ACT_FREELIST_BLOCKING);
1962   if(!gl->ext_act_mem)
1963     return del_GetLine(gl);
1964 /*
1965  * Allocate a freelist from which to allocate nodes for the list
1966  * of signals.
1967  */
1968   gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING);
1969   if(!gl->sig_mem)
1970     return del_GetLine(gl);
1971 /*
1972  * Install initial dispositions for the default list of signals that
1973  * gl_get_line() traps.
1974  */
1975   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
1976     const struct GlDefSignal *sig = gl_signal_list + i;
1977     if(_gl_trap_signal(gl, sig->signo, sig->flags, sig->after,
1978 		       sig->errno_value))
1979       return del_GetLine(gl);
1980   };
1981 /*
1982  * Allocate an empty table of key bindings.
1983  */
1984   gl->bindings = _new_KeyTab();
1985   if(!gl->bindings)
1986     return del_GetLine(gl);
1987 /*
1988  * Define the available actions that can be bound to key sequences.
1989  */
1990   for(i=0; i<sizeof(gl_actions)/sizeof(gl_actions[0]); i++) {
1991     if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn, NULL))
1992       return del_GetLine(gl);
1993   };
1994 /*
1995  * Set up the default bindings.
1996  */
1997   if(gl_change_editor(gl, gl->editor))
1998     return del_GetLine(gl);
1999 /*
2000  * Allocate termcap buffers.
2001  */
2002 #ifdef USE_TERMCAP
2003   gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2004   gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2005   if(!gl->tgetent_buf || !gl->tgetstr_buf) {
2006     errno = ENOMEM;
2007     return del_GetLine(gl);
2008   };
2009 #endif
2010 /*
2011  * Set up for I/O assuming stdin and stdout.
2012  */
2013   if(_gl_change_terminal(gl, stdin, stdout, getenv("TERM")))
2014     return del_GetLine(gl);
2015 /*
2016  * Create a freelist for use in allocating GlFdNode list nodes.
2017  */
2018 #ifdef HAVE_SELECT
2019   gl->fd_node_mem = _new_FreeList(sizeof(GlFdNode), GLFD_FREELIST_BLOCKING);
2020   if(!gl->fd_node_mem)
2021     return del_GetLine(gl);
2022 #endif
2023 /*
2024  * We are done for now.
2025  */
2026   return gl;
2027 }
2028 
2029 /*.......................................................................
2030  * Delete a GetLine object.
2031  *
2032  * Input:
2033  *  gl     GetLine *  The object to be deleted.
2034  * Output:
2035  *  return GetLine *  The deleted object (always NULL).
2036  */
del_GetLine(GetLine * gl)2037 GetLine *del_GetLine(GetLine *gl)
2038 {
2039   if(gl) {
2040 /*
2041  * If the terminal is in raw server mode, reset it.
2042  */
2043     _gl_normal_io(gl);
2044 /*
2045  * Deallocate all objects contained by gl.
2046  */
2047     gl->err = _del_ErrMsg(gl->err);
2048     gl->glh = _del_GlHistory(gl->glh);
2049     gl->cpl = del_WordCompletion(gl->cpl);
2050 #ifndef WITHOUT_FILE_SYSTEM
2051     gl->ef = del_ExpandFile(gl->ef);
2052 #endif
2053     gl->capmem = _del_StringGroup(gl->capmem);
2054     gl->cq = _del_GlCharQueue(gl->cq);
2055     if(gl->file_fp)
2056       fclose(gl->file_fp);
2057     if(gl->term)
2058       free(gl->term);
2059     if(gl->line)
2060       free(gl->line);
2061     if(gl->cutbuf)
2062       free(gl->cutbuf);
2063     if(gl->prompt)
2064       free(gl->prompt);
2065     gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1);
2066     gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1);
2067     gl->sig_mem = _del_FreeList(gl->sig_mem, 1);
2068     gl->sigs = NULL;       /* Already freed by freeing sig_mem */
2069     gl->bindings = _del_KeyTab(gl->bindings);
2070     if(gl->vi.undo.line)
2071       free(gl->vi.undo.line);
2072 #ifdef USE_TERMCAP
2073     if(gl->tgetent_buf)
2074       free(gl->tgetent_buf);
2075     if(gl->tgetstr_buf)
2076       free(gl->tgetstr_buf);
2077 #endif
2078     if(gl->app_file)
2079       free(gl->app_file);
2080     if(gl->user_file)
2081       free(gl->user_file);
2082 #ifdef HAVE_SELECT
2083     gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1);
2084     gl->fd_nodes = NULL;  /* Already freed by freeing gl->fd_node_mem */
2085 #endif
2086 /*
2087  * Delete the now empty container.
2088  */
2089     free(gl);
2090   };
2091   return NULL;
2092 }
2093 
2094 /*.......................................................................
2095  * Bind a control or meta character to an action.
2096  *
2097  * Input:
2098  *  gl         GetLine *  The resource object of this program.
2099  *  binder    KtBinder    The source of the binding.
2100  *  c             char    The control or meta character.
2101  *                        If this is '\0', the call is ignored.
2102  *  action  const char *  The action name to bind the key to.
2103  * Output:
2104  *  return         int    0 - OK.
2105  *                        1 - Error.
2106  */
gl_bind_control_char(GetLine * gl,KtBinder binder,char c,const char * action)2107 static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c,
2108 				const char *action)
2109 {
2110   char keyseq[2];
2111 /*
2112  * Quietly reject binding to the NUL control character, since this
2113  * is an ambiguous prefix of all bindings.
2114  */
2115   if(c == '\0')
2116     return 0;
2117 /*
2118  * Making sure not to bind characters which aren't either control or
2119  * meta characters.
2120  */
2121   if(IS_CTRL_CHAR(c) || IS_META_CHAR(c)) {
2122     keyseq[0] = c;
2123     keyseq[1] = '\0';
2124   } else {
2125     return 0;
2126   };
2127 /*
2128  * Install the binding.
2129  */
2130   if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
2131     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
2132     return 1;
2133   };
2134   return 0;
2135 }
2136 
2137 /*.......................................................................
2138  * Read a line from the user.
2139  *
2140  * Input:
2141  *  gl       GetLine *  A resource object returned by new_GetLine().
2142  *  prompt      char *  The prompt to prefix the line with.
2143  *  start_line  char *  The initial contents of the input line, or NULL
2144  *                      if it should start out empty.
2145  *  start_pos    int    If start_line isn't NULL, this specifies the
2146  *                      index of the character over which the cursor
2147  *                      should initially be positioned within the line.
2148  *                      If you just want it to follow the last character
2149  *                      of the line, send -1.
2150  * Output:
2151  *  return      char *  An internal buffer containing the input line, or
2152  *                      NULL at the end of input. If the line fitted in
2153  *                      the buffer there will be a '\n' newline character
2154  *                      before the terminating '\0'. If it was truncated
2155  *                      there will be no newline character, and the remains
2156  *                      of the line should be retrieved via further calls
2157  *                      to this function.
2158  */
gl_get_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2159 char *gl_get_line(GetLine *gl, const char *prompt,
2160 		  const char *start_line, int start_pos)
2161 {
2162   char *retval;   /* The return value of _gl_get_line() */
2163 /*
2164  * Check the arguments.
2165  */
2166   if(!gl) {
2167     errno = EINVAL;
2168     return NULL;
2169   };
2170 /*
2171  * Temporarily block all of the signals that we have been asked to trap.
2172  */
2173   if(gl_mask_signals(gl, &gl->old_signal_set))
2174     return NULL;
2175 /*
2176  * Perform the command-line editing task.
2177  */
2178   retval = _gl_get_line(gl, prompt, start_line, start_pos);
2179 /*
2180  * Restore the process signal mask to how it was when this function was
2181  * first called.
2182  */
2183   gl_unmask_signals(gl, &gl->old_signal_set);
2184   return retval;
2185 }
2186 
2187 
2188 /*.......................................................................
2189  * This is the main body of the public function gl_get_line().
2190  */
_gl_get_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2191 static char *_gl_get_line(GetLine *gl, const char *prompt,
2192 			  const char *start_line, int start_pos)
2193 {
2194   int waserr = 0;    /* True if an error occurs */
2195 /*
2196  * Assume that this call will successfully complete the input
2197  * line until proven otherwise.
2198  */
2199   gl_clear_status(gl);
2200 /*
2201  * If this is the first call to this function since new_GetLine(),
2202  * complete any postponed configuration.
2203  */
2204   if(!gl->configured) {
2205     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2206     gl->configured = 1;
2207   };
2208 /*
2209  * Before installing our signal handler functions, record the fact
2210  * that there are no pending signals.
2211  */
2212   gl_pending_signal = -1;
2213 /*
2214  * Temporarily override the signal handlers of the calling program,
2215  * so that we can intercept signals that would leave the terminal
2216  * in a bad state.
2217  */
2218   waserr = gl_override_signal_handlers(gl);
2219 /*
2220  * After recording the current terminal settings, switch the terminal
2221  * into raw input mode.
2222  */
2223   waserr = waserr || _gl_raw_io(gl, 1);
2224 /*
2225  * Attempt to read the line. This will require more than one attempt if
2226  * either a current temporary input file is opened by gl_get_input_line()
2227  * or the end of a temporary input file is reached by gl_read_stream_line().
2228  */
2229   while(!waserr) {
2230 /*
2231  * Read a line from a non-interactive stream?
2232  */
2233     if(gl->file_fp || !gl->is_term) {
2234       if(gl_read_stream_line(gl)==0) {
2235 	break;
2236       } else if(gl->file_fp) {
2237 	gl_revert_input(gl);
2238 	gl_record_status(gl, GLR_NEWLINE, 0);
2239       } else {
2240 	waserr = 1;
2241 	break;
2242       };
2243     };
2244 /*
2245  * Read from the terminal? Note that the above if() block may have
2246  * changed gl->file_fp, so it is necessary to retest it here, rather
2247  * than using an else statement.
2248  */
2249     if(!gl->file_fp && gl->is_term) {
2250       if(gl_get_input_line(gl, prompt, start_line, start_pos))
2251 	waserr = 1;
2252       else
2253 	break;
2254     };
2255   };
2256 /*
2257  * If an error occurred, but gl->rtn_status is still set to
2258  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
2259  * leave it at whatever specific value was assigned by the function
2260  * that aborted input. This means that only functions that trap
2261  * non-generic errors have to remember to update gl->rtn_status
2262  * themselves.
2263  */
2264   if(waserr && gl->rtn_status == GLR_NEWLINE)
2265     gl_record_status(gl, GLR_ERROR, errno);
2266 /*
2267  * Restore terminal settings.
2268  */
2269   if(gl->io_mode != GL_SERVER_MODE)
2270     _gl_normal_io(gl);
2271 /*
2272  * Restore the signal handlers.
2273  */
2274   gl_restore_signal_handlers(gl);
2275 /*
2276  * If gl_get_line() gets aborted early, the errno value associated
2277  * with the event that caused this to happen is recorded in
2278  * gl->rtn_errno. Since errno may have been overwritten by cleanup
2279  * functions after this, restore its value to the value that it had
2280  * when the error condition occured, so that the caller can examine it
2281  * to find out what happened.
2282  */
2283   errno = gl->rtn_errno;
2284 /*
2285  * Check the completion status to see how to return.
2286  */
2287   switch(gl->rtn_status) {
2288   case GLR_NEWLINE:    /* Success */
2289     return gl->line;
2290   case GLR_BLOCKED:    /* These events abort the current input line, */
2291   case GLR_SIGNAL:     /*  when in normal blocking I/O mode, but only */
2292   case GLR_TIMEOUT:    /*  temporarily pause line editing when in */
2293   case GLR_FDABORT:    /*  non-blocking server I/O mode. */
2294     if(gl->io_mode != GL_SERVER_MODE)
2295       _gl_abandon_line(gl);
2296     return NULL;
2297   case GLR_ERROR:      /* Unrecoverable errors abort the input line, */
2298   case GLR_EOF:        /*  regardless of the I/O mode. */
2299   default:
2300     _gl_abandon_line(gl);
2301     return NULL;
2302   };
2303 }
2304 
2305 /*.......................................................................
2306  * Read a single character from the user.
2307  *
2308  * Input:
2309  *  gl       GetLine *  A resource object returned by new_GetLine().
2310  *  prompt      char *  The prompt to prefix the line with, or NULL if
2311  *                      no prompt is required.
2312  *  defchar     char    The character to substitute if the
2313  *                      user simply hits return, or '\n' if you don't
2314  *                      need to substitute anything.
2315  * Output:
2316  *  return       int    The character that was read, or EOF if the read
2317  *                      had to be aborted (in which case you can call
2318  *                      gl_return_status() to find out why).
2319  */
gl_query_char(GetLine * gl,const char * prompt,char defchar)2320 int gl_query_char(GetLine *gl, const char *prompt, char defchar)
2321 {
2322   int retval;   /* The return value of _gl_query_char() */
2323 /*
2324  * Check the arguments.
2325  */
2326   if(!gl) {
2327     errno = EINVAL;
2328     return EOF;
2329   };
2330 /*
2331  * Temporarily block all of the signals that we have been asked to trap.
2332  */
2333   if(gl_mask_signals(gl, &gl->old_signal_set))
2334     return EOF;
2335 /*
2336  * Perform the character reading task.
2337  */
2338   retval = _gl_query_char(gl, prompt, defchar);
2339 /*
2340  * Restore the process signal mask to how it was when this function was
2341  * first called.
2342  */
2343   gl_unmask_signals(gl, &gl->old_signal_set);
2344   return retval;
2345 }
2346 
2347 /*.......................................................................
2348  * This is the main body of the public function gl_query_char().
2349  */
_gl_query_char(GetLine * gl,const char * prompt,char defchar)2350 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar)
2351 {
2352   int c = EOF;       /* The character to be returned */
2353   int waserr = 0;    /* True if an error occurs */
2354 /*
2355  * Assume that this call will successfully complete the input operation
2356  * until proven otherwise.
2357  */
2358   gl_clear_status(gl);
2359 /*
2360  * If this is the first call to this function or gl_get_line(),
2361  * since new_GetLine(), complete any postponed configuration.
2362  */
2363   if(!gl->configured) {
2364     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2365     gl->configured = 1;
2366   };
2367 /*
2368  * Before installing our signal handler functions, record the fact
2369  * that there are no pending signals.
2370  */
2371   gl_pending_signal = -1;
2372 /*
2373  * Temporarily override the signal handlers of the calling program,
2374  * so that we can intercept signals that would leave the terminal
2375  * in a bad state.
2376  */
2377   waserr = gl_override_signal_handlers(gl);
2378 /*
2379  * After recording the current terminal settings, switch the terminal
2380  * into raw input mode without redisplaying any partially entered
2381  * input line.
2382  */
2383   waserr = waserr || _gl_raw_io(gl, 0);
2384 /*
2385  * Attempt to read the line. This will require more than one attempt if
2386  * either a current temporary input file is opened by gl_get_input_line()
2387  * or the end of a temporary input file is reached by gl_read_stream_line().
2388  */
2389   while(!waserr) {
2390 /*
2391  * Read a line from a non-interactive stream?
2392  */
2393     if(gl->file_fp || !gl->is_term) {
2394       c = gl_read_stream_char(gl);
2395       if(c != EOF) {            /* Success? */
2396 	if(c=='\n') c = defchar;
2397 	break;
2398       } else if(gl->file_fp) {  /* End of temporary input file? */
2399 	gl_revert_input(gl);
2400 	gl_record_status(gl, GLR_NEWLINE, 0);
2401       } else {                  /* An error? */
2402 	waserr = 1;
2403 	break;
2404       };
2405     };
2406 /*
2407  * Read from the terminal? Note that the above if() block may have
2408  * changed gl->file_fp, so it is necessary to retest it here, rather
2409  * than using an else statement.
2410  */
2411     if(!gl->file_fp && gl->is_term) {
2412       c = gl_get_query_char(gl, prompt, defchar);
2413       if(c==EOF)
2414 	waserr = 1;
2415       else
2416 	break;
2417     };
2418   };
2419 /*
2420  * If an error occurred, but gl->rtn_status is still set to
2421  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
2422  * leave it at whatever specific value was assigned by the function
2423  * that aborted input. This means that only functions that trap
2424  * non-generic errors have to remember to update gl->rtn_status
2425  * themselves.
2426  */
2427   if(waserr && gl->rtn_status == GLR_NEWLINE)
2428     gl_record_status(gl, GLR_ERROR, errno);
2429 /*
2430  * Restore terminal settings.
2431  */
2432   if(gl->io_mode != GL_SERVER_MODE)
2433     _gl_normal_io(gl);
2434 /*
2435  * Restore the signal handlers.
2436  */
2437   gl_restore_signal_handlers(gl);
2438 /*
2439  * If this function gets aborted early, the errno value associated
2440  * with the event that caused this to happen is recorded in
2441  * gl->rtn_errno. Since errno may have been overwritten by cleanup
2442  * functions after this, restore its value to the value that it had
2443  * when the error condition occured, so that the caller can examine it
2444  * to find out what happened.
2445  */
2446   errno = gl->rtn_errno;
2447 /*
2448  * Error conditions are signalled to the caller, by setting the returned
2449  * character to EOF.
2450  */
2451   if(gl->rtn_status != GLR_NEWLINE)
2452     c = EOF;
2453 /*
2454  * In this mode, every character that is read is a completed
2455  * transaction, just like reading a completed input line, so prepare
2456  * for the next input line or character.
2457  */
2458   _gl_abandon_line(gl);
2459 /*
2460  * Return the acquired character.
2461  */
2462   return c;
2463 }
2464 
2465 /*.......................................................................
2466  * Record of the signal handlers of the calling program, so that they
2467  * can be restored later.
2468  *
2469  * Input:
2470  *  gl    GetLine *   The resource object of this library.
2471  * Output:
2472  *  return    int     0 - OK.
2473  *                    1 - Error.
2474  */
gl_override_signal_handlers(GetLine * gl)2475 static int gl_override_signal_handlers(GetLine *gl)
2476 {
2477   GlSignalNode *sig;   /* A node in the list of signals to be caught */
2478 /*
2479  * Set up our signal handler.
2480  */
2481   SigAction act;
2482   act.sa_handler = gl_signal_handler;
2483   memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t));
2484   act.sa_flags = 0;
2485 /*
2486  * Get the subset of the signals that we are supposed to trap that
2487  * should actually be trapped.
2488  */
2489   sigemptyset(&gl->use_signal_set);
2490   for(sig=gl->sigs; sig; sig=sig->next) {
2491 /*
2492  * Trap this signal? If it is blocked by the calling program and we
2493  * haven't been told to unblock it, don't arrange to trap this signal.
2494  */
2495     if(sig->flags & GLS_UNBLOCK_SIG ||
2496        !sigismember(&gl->old_signal_set, sig->signo)) {
2497       if(sigaddset(&gl->use_signal_set, sig->signo) == -1) {
2498 	_err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
2499 	return 1;
2500       };
2501     };
2502   };
2503 /*
2504  * Override the actions of the signals that we are trapping.
2505  */
2506   for(sig=gl->sigs; sig; sig=sig->next) {
2507     if(sigismember(&gl->use_signal_set, sig->signo)) {
2508       sigdelset(&act.sa_mask, sig->signo);
2509       if(sigaction(sig->signo, &act, &sig->original)) {
2510 	_err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2511 	return 1;
2512       };
2513       sigaddset(&act.sa_mask, sig->signo);
2514     };
2515   };
2516 /*
2517  * Record the fact that the application's signal handlers have now
2518  * been overriden.
2519  */
2520   gl->signals_overriden = 1;
2521 /*
2522  * Just in case a SIGWINCH signal was sent to the process while our
2523  * SIGWINCH signal handler wasn't in place, check to see if the terminal
2524  * size needs updating.
2525  */
2526   if(_gl_update_size(gl))
2527     return 1;
2528   return 0;
2529 }
2530 
2531 /*.......................................................................
2532  * Restore the signal handlers of the calling program.
2533  *
2534  * Input:
2535  *  gl     GetLine *  The resource object of this library.
2536  * Output:
2537  *  return     int    0 - OK.
2538  *                    1 - Error.
2539  */
gl_restore_signal_handlers(GetLine * gl)2540 static int gl_restore_signal_handlers(GetLine *gl)
2541 {
2542   GlSignalNode *sig;   /* A node in the list of signals to be caught */
2543 /*
2544  * Restore application signal handlers that were overriden
2545  * by gl_override_signal_handlers().
2546  */
2547   for(sig=gl->sigs; sig; sig=sig->next) {
2548     if(sigismember(&gl->use_signal_set, sig->signo) &&
2549        sigaction(sig->signo, &sig->original, NULL)) {
2550       _err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2551       return 1;
2552     };
2553   };
2554 /*
2555  * Record the fact that the application's signal handlers have now
2556  * been restored.
2557  */
2558   gl->signals_overriden = 0;
2559   return 0;
2560 }
2561 
2562 /*.......................................................................
2563  * This signal handler simply records the fact that a given signal was
2564  * caught in the file-scope gl_pending_signal variable.
2565  */
gl_signal_handler(int signo)2566 static void gl_signal_handler(int signo)
2567 {
2568   gl_pending_signal = signo;
2569   siglongjmp(gl_setjmp_buffer, 1);
2570 }
2571 
2572 /*.......................................................................
2573  * Switch the terminal into raw mode after storing the previous terminal
2574  * settings in gl->attributes.
2575  *
2576  * Input:
2577  *  gl     GetLine *   The resource object of this program.
2578  * Output:
2579  *  return     int     0 - OK.
2580  *                     1 - Error.
2581  */
gl_raw_terminal_mode(GetLine * gl)2582 static int gl_raw_terminal_mode(GetLine *gl)
2583 {
2584   Termios newattr;   /* The new terminal attributes */
2585 /*
2586  * If the terminal is already in raw mode, do nothing.
2587  */
2588   if(gl->raw_mode)
2589     return 0;
2590 /*
2591  * Record the current terminal attributes.
2592  */
2593   if(tcgetattr(gl->input_fd, &gl->oldattr)) {
2594     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
2595     return 1;
2596   };
2597 /*
2598  * This function shouldn't do anything but record the current terminal
2599  * attritubes if editing has been disabled.
2600  */
2601   if(gl->editor == GL_NO_EDITOR)
2602     return 0;
2603 /*
2604  * Modify the existing attributes.
2605  */
2606   newattr = gl->oldattr;
2607 /*
2608  * Turn off local echo, canonical input mode and extended input processing.
2609  */
2610   newattr.c_lflag &= ~(ECHO | ICANON | IEXTEN);
2611 /*
2612  * Don't translate carriage return to newline, turn off input parity
2613  * checking, don't strip off 8th bit, turn off output flow control.
2614  */
2615   newattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP);
2616 /*
2617  * Clear size bits, turn off parity checking, and allow 8-bit characters.
2618  */
2619   newattr.c_cflag &= ~(CSIZE | PARENB);
2620   newattr.c_cflag |= CS8;
2621 /*
2622  * Turn off output processing.
2623  */
2624   newattr.c_oflag &= ~(OPOST);
2625 /*
2626  * Request one byte at a time, without waiting.
2627  */
2628   newattr.c_cc[VMIN] = gl->io_mode==GL_SERVER_MODE ? 0:1;
2629   newattr.c_cc[VTIME] = 0;
2630 /*
2631  * Install the new terminal modes.
2632  */
2633   while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) {
2634     if(errno != EINTR) {
2635       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2636       return 1;
2637     };
2638   };
2639 /*
2640  * Record the new terminal mode.
2641  */
2642   gl->raw_mode = 1;
2643   return 0;
2644 }
2645 
2646 /*.......................................................................
2647  * Restore the terminal attributes recorded in gl->oldattr.
2648  *
2649  * Input:
2650  *  gl     GetLine *   The resource object of this library.
2651  * Output:
2652  *  return     int     0 - OK.
2653  *                     1 - Error.
2654  */
gl_restore_terminal_attributes(GetLine * gl)2655 static int gl_restore_terminal_attributes(GetLine *gl)
2656 {
2657   int waserr = 0;
2658 /*
2659  * If not in raw mode, do nothing.
2660  */
2661   if(!gl->raw_mode)
2662     return 0;
2663 /*
2664  * Before changing the terminal attributes, make sure that all output
2665  * has been passed to the terminal.
2666  */
2667   if(gl_flush_output(gl))
2668     waserr = 1;
2669 /*
2670  * Reset the terminal attributes to the values that they had on
2671  * entry to gl_get_line().
2672  */
2673   while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) {
2674     if(errno != EINTR) {
2675       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2676       waserr = 1;
2677       break;
2678     };
2679   };
2680 /*
2681  * Record the new terminal mode.
2682  */
2683   gl->raw_mode = 0;
2684   return waserr;
2685 }
2686 
2687 /*.......................................................................
2688  * Switch the terminal file descriptor to use non-blocking I/O.
2689  *
2690  * Input:
2691  *  gl         GetLine *  The resource object of gl_get_line().
2692  *  fd             int    The file descriptor to make non-blocking.
2693  */
gl_nonblocking_io(GetLine * gl,int fd)2694 static int gl_nonblocking_io(GetLine *gl, int fd)
2695 {
2696   int fcntl_flags;   /* The new file-descriptor control flags */
2697 /*
2698  * Is non-blocking I/O supported on this system?  Note that even
2699  * without non-blocking I/O, the terminal will probably still act as
2700  * though it was non-blocking, because we also set the terminal
2701  * attributes to return immediately if no input is available and we
2702  * use select() to wait to be able to write. If select() also isn't
2703  * available, then input will probably remain fine, but output could
2704  * block, depending on the behaviour of the terminal driver.
2705  */
2706 #if defined(NON_BLOCKING_FLAG)
2707 /*
2708  * Query the current file-control flags, and add the
2709  * non-blocking I/O flag.
2710  */
2711   fcntl_flags = fcntl(fd, F_GETFL) | NON_BLOCKING_FLAG;
2712 /*
2713  * Install the new control flags.
2714  */
2715   if(fcntl(fd, F_SETFL, fcntl_flags) == -1) {
2716     _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2717     return 1;
2718   };
2719 #endif
2720   return 0;
2721 }
2722 
2723 /*.......................................................................
2724  * Switch to blocking terminal I/O.
2725  *
2726  * Input:
2727  *  gl         GetLine *  The resource object of gl_get_line().
2728  *  fd             int    The file descriptor to make blocking.
2729  */
gl_blocking_io(GetLine * gl,int fd)2730 static int gl_blocking_io(GetLine *gl, int fd)
2731 {
2732   int fcntl_flags;   /* The new file-descriptor control flags */
2733 /*
2734  * Is non-blocking I/O implemented on this system?
2735  */
2736 #if defined(NON_BLOCKING_FLAG)
2737 /*
2738  * Query the current file control flags and remove the non-blocking
2739  * I/O flag.
2740  */
2741   fcntl_flags = fcntl(fd, F_GETFL) & ~NON_BLOCKING_FLAG;
2742 /*
2743  * Install the modified control flags.
2744  */
2745   if(fcntl(fd, F_SETFL, fcntl_flags) == -1) {
2746     _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2747     return 1;
2748   };
2749 #endif
2750   return 0;
2751 }
2752 
2753 /*.......................................................................
2754  * Read a new input line from the user.
2755  *
2756  * Input:
2757  *  gl         GetLine *  The resource object of this library.
2758  *  prompt        char *  The prompt to prefix the line with, or NULL to
2759  *                        use the same prompt that was used by the previous
2760  *                        line.
2761  *  start_line    char *  The initial contents of the input line, or NULL
2762  *                        if it should start out empty.
2763  *  start_pos      int    If start_line isn't NULL, this specifies the
2764  *                        index of the character over which the cursor
2765  *                        should initially be positioned within the line.
2766  *                        If you just want it to follow the last character
2767  *                        of the line, send -1.
2768  * Output:
2769  *  return    int    0 - OK.
2770  *                   1 - Error.
2771  */
gl_get_input_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2772 static int gl_get_input_line(GetLine *gl, const char *prompt,
2773 			     const char *start_line, int start_pos)
2774 {
2775   char c;               /* The character being read */
2776 /*
2777  * Flush any pending output to the terminal.
2778  */
2779   if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2780     return 1;
2781 /*
2782  * Are we starting a new line?
2783  */
2784   if(gl->endline) {
2785 /*
2786  * Delete any incompletely enterred line.
2787  */
2788     if(gl_erase_line(gl))
2789       return 1;
2790 /*
2791  * Display the new line to be edited.
2792  */
2793     if(gl_present_line(gl, prompt, start_line, start_pos))
2794       return 1;
2795   };
2796 /*
2797  * Read one character at a time.
2798  */
2799   while(gl_read_terminal(gl, 1, &c) == 0) {
2800 /*
2801  * Increment the count of the number of key sequences entered.
2802  */
2803     gl->keyseq_count++;
2804 /*
2805  * Interpret the character either as the start of a new key-sequence,
2806  * as a continuation of a repeat count, or as a printable character
2807  * to be added to the line.
2808  */
2809     if(gl_interpret_char(gl, c))
2810       break;
2811 /*
2812  * If we just ran an action function which temporarily asked for
2813  * input to be taken from a file, abort this call.
2814  */
2815     if(gl->file_fp)
2816       return 0;
2817 /*
2818  * Has the line been completed?
2819  */
2820     if(gl->endline)
2821       return gl_line_ended(gl, c);
2822   };
2823 /*
2824  * To get here, gl_read_terminal() must have returned non-zero. See
2825  * whether a signal was caught that requested that the current line
2826  * be returned.
2827  */
2828   if(gl->endline)
2829     return gl_line_ended(gl, '\n');
2830 /*
2831  * If I/O blocked while attempting to get the latest character
2832  * of the key sequence, rewind the key buffer to allow interpretation of
2833  * the current key sequence to be restarted on the next call to this
2834  * function.
2835  */
2836   if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ)
2837     gl->nread = 0;
2838   return 1;
2839 }
2840 
2841 /*.......................................................................
2842  * This is the private function of gl_query_char() that handles
2843  * prompting the user, reading a character from the terminal, and
2844  * displaying what the user entered.
2845  *
2846  * Input:
2847  *  gl         GetLine *  The resource object of this library.
2848  *  prompt        char *  The prompt to prefix the line with.
2849  *  defchar       char    The character to substitute if the
2850  *                        user simply hits return, or '\n' if you don't
2851  *                        need to substitute anything.
2852  * Output:
2853  *  return         int    The character that was read, or EOF if something
2854  *                        prevented a character from being read.
2855  */
gl_get_query_char(GetLine * gl,const char * prompt,int defchar)2856 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar)
2857 {
2858   char c;               /* The character being read */
2859   int retval;           /* The return value of this function */
2860 /*
2861  * Flush any pending output to the terminal.
2862  */
2863   if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2864     return EOF;
2865 /*
2866  * Delete any incompletely entered line.
2867  */
2868   if(gl_erase_line(gl))
2869     return EOF;
2870 /*
2871  * Reset the line input parameters and display the prompt, if any.
2872  */
2873   if(gl_present_line(gl, prompt, NULL, 0))
2874     return EOF;
2875 /*
2876  * Read one character.
2877  */
2878   if(gl_read_terminal(gl, 1, &c) == 0) {
2879 /*
2880  * In this mode, count each character as being a new key-sequence.
2881  */
2882     gl->keyseq_count++;
2883 /*
2884  * Delete the character that was read, from the key-press buffer.
2885  */
2886     gl_discard_chars(gl, gl->nread);
2887 /*
2888  * Convert carriage returns to newlines.
2889  */
2890     if(c == '\r')
2891       c = '\n';
2892 /*
2893  * If the user just hit return, subsitute the default character.
2894  */
2895     if(c == '\n')
2896       c = defchar;
2897 /*
2898  * Display the entered character to the right of the prompt.
2899  */
2900     if(c!='\n') {
2901       if(gl_end_of_line(gl, 1, NULL)==0)
2902 	gl_print_char(gl, c, ' ');
2903     };
2904 /*
2905  * Record the return character, and mark the call as successful.
2906  */
2907     retval = c;
2908     gl_record_status(gl, GLR_NEWLINE, 0);
2909 /*
2910  * Was a signal caught whose disposition is to cause the current input
2911  * line to be returned? If so return a newline character.
2912  */
2913   } else if(gl->endline) {
2914     retval = '\n';
2915     gl_record_status(gl, GLR_NEWLINE, 0);
2916   } else {
2917     retval = EOF;
2918   };
2919 /*
2920  * Start a new line.
2921  */
2922   if(gl_start_newline(gl, 1))
2923     return EOF;
2924 /*
2925  * Attempt to flush any pending output.
2926  */
2927   (void) gl_flush_output(gl);
2928 /*
2929  * Return either the character that was read, or EOF if an error occurred.
2930  */
2931   return retval;
2932 }
2933 
2934 /*.......................................................................
2935  * Add a character to the line buffer at the current cursor position,
2936  * inserting or overwriting according the current mode.
2937  *
2938  * Input:
2939  *  gl   GetLine *   The resource object of this library.
2940  *  c       char     The character to be added.
2941  * Output:
2942  *  return   int     0 - OK.
2943  *                   1 - Insufficient room.
2944  */
gl_add_char_to_line(GetLine * gl,char c)2945 static int gl_add_char_to_line(GetLine *gl, char c)
2946 {
2947 /*
2948  * Keep a record of the current cursor position.
2949  */
2950   int buff_curpos = gl->buff_curpos;
2951   int term_curpos = gl->term_curpos;
2952 /*
2953  * Work out the displayed width of the new character.
2954  */
2955   int width = gl_displayed_char_width(gl, c, term_curpos);
2956 /*
2957  * If we are in insert mode, or at the end of the line,
2958  * check that we can accomodate a new character in the buffer.
2959  * If not, simply return, leaving it up to the calling program
2960  * to check for the absence of a newline character.
2961  */
2962   if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen)
2963     return 0;
2964 /*
2965  * Are we adding characters to the line (ie. inserting or appending)?
2966  */
2967   if(gl->insert || buff_curpos >= gl->ntotal) {
2968 /*
2969  * If inserting, make room for the new character.
2970  */
2971     if(buff_curpos < gl->ntotal)
2972       gl_make_gap_in_buffer(gl, buff_curpos, 1);
2973 /*
2974  * Copy the character into the buffer.
2975  */
2976     gl_buffer_char(gl, c, buff_curpos);
2977     gl->buff_curpos++;
2978 /*
2979  * Redraw the line from the cursor position to the end of the line,
2980  * and move the cursor to just after the added character.
2981  */
2982     if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
2983        gl_set_term_curpos(gl, term_curpos + width))
2984       return 1;
2985 /*
2986  * Are we overwriting an existing character?
2987  */
2988   } else {
2989 /*
2990  * Get the width of the character being overwritten.
2991  */
2992     int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos],
2993 					    term_curpos);
2994 /*
2995  * Overwrite the character in the buffer.
2996  */
2997     gl_buffer_char(gl, c, buff_curpos);
2998 /*
2999  * If we are replacing with a narrower character, we need to
3000  * redraw the terminal string to the end of the line, then
3001  * overwrite the trailing old_width - width characters
3002  * with spaces.
3003  */
3004     if(old_width > width) {
3005       if(gl_print_string(gl, gl->line + buff_curpos, '\0'))
3006 	return 1;
3007 /*
3008  * Clear to the end of the terminal.
3009  */
3010       if(gl_truncate_display(gl))
3011 	return 1;
3012 /*
3013  * Move the cursor to the end of the new character.
3014  */
3015       if(gl_set_term_curpos(gl, term_curpos + width))
3016 	return 1;
3017       gl->buff_curpos++;
3018 /*
3019  * If we are replacing with a wider character, then we will be
3020  * inserting new characters, and thus extending the line.
3021  */
3022     } else if(width > old_width) {
3023 /*
3024  * Redraw the line from the cursor position to the end of the line,
3025  * and move the cursor to just after the added character.
3026  */
3027       if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3028 	 gl_set_term_curpos(gl, term_curpos + width))
3029 	return 1;
3030       gl->buff_curpos++;
3031 /*
3032  * The original and replacement characters have the same width,
3033  * so simply overwrite.
3034  */
3035     } else {
3036 /*
3037  * Copy the character into the buffer.
3038  */
3039       gl_buffer_char(gl, c, buff_curpos);
3040       gl->buff_curpos++;
3041 /*
3042  * Overwrite the original character.
3043  */
3044       if(gl_print_char(gl, c, gl->line[gl->buff_curpos]))
3045 	return 1;
3046     };
3047   };
3048   return 0;
3049 }
3050 
3051 /*.......................................................................
3052  * Insert/append a string to the line buffer and terminal at the current
3053  * cursor position.
3054  *
3055  * Input:
3056  *  gl   GetLine *   The resource object of this library.
3057  *  s       char *   The string to be added.
3058  * Output:
3059  *  return   int     0 - OK.
3060  *                   1 - Insufficient room.
3061  */
gl_add_string_to_line(GetLine * gl,const char * s)3062 static int gl_add_string_to_line(GetLine *gl, const char *s)
3063 {
3064   int buff_slen;   /* The length of the string being added to line[] */
3065   int term_slen;   /* The length of the string being written to the terminal */
3066   int buff_curpos; /* The original value of gl->buff_curpos */
3067   int term_curpos; /* The original value of gl->term_curpos */
3068 /*
3069  * Keep a record of the current cursor position.
3070  */
3071   buff_curpos = gl->buff_curpos;
3072   term_curpos = gl->term_curpos;
3073 /*
3074  * How long is the string to be added?
3075  */
3076   buff_slen = strlen(s);
3077   term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos);
3078 /*
3079  * Check that we can accomodate the string in the buffer.
3080  * If not, simply return, leaving it up to the calling program
3081  * to check for the absence of a newline character.
3082  */
3083   if(gl->ntotal + buff_slen > gl->linelen)
3084     return 0;
3085 /*
3086  * Move the characters that follow the cursor in the buffer by
3087  * buff_slen characters to the right.
3088  */
3089   if(gl->ntotal > gl->buff_curpos)
3090     gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen);
3091 /*
3092  * Copy the string into the buffer.
3093  */
3094   gl_buffer_string(gl, s, buff_slen, gl->buff_curpos);
3095   gl->buff_curpos += buff_slen;
3096 /*
3097  * Write the modified part of the line to the terminal, then move
3098  * the terminal cursor to the end of the displayed input string.
3099  */
3100   if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3101      gl_set_term_curpos(gl, term_curpos + term_slen))
3102     return 1;
3103   return 0;
3104 }
3105 
3106 /*.......................................................................
3107  * Read a single character from the terminal.
3108  *
3109  * Input:
3110  *  gl    GetLine *   The resource object of this library.
3111  *  keep      int     If true, the returned character will be kept in
3112  *                    the input buffer, for potential replays. It should
3113  *                    subsequently be removed from the buffer when the
3114  *                    key sequence that it belongs to has been fully
3115  *                    processed, by calling gl_discard_chars().
3116  * Input/Output:
3117  *  c        char *   The character that is read, is assigned to *c.
3118  * Output:
3119  *  return    int     0 - OK.
3120  *                    1 - Either an I/O error occurred, or a signal was
3121  *                        caught who's disposition is to abort gl_get_line()
3122  *                        or to have gl_get_line() return the current line
3123  *                        as though the user had pressed return. In the
3124  *                        latter case gl->endline will be non-zero.
3125  */
gl_read_terminal(GetLine * gl,int keep,char * c)3126 static int gl_read_terminal(GetLine *gl, int keep, char *c)
3127 {
3128 /*
3129  * Before waiting for a new character to be input, flush unwritten
3130  * characters to the terminal.
3131  */
3132   if(gl_flush_output(gl))
3133     return 1;
3134 /*
3135  * Record the fact that we are about to read from the terminal.
3136  */
3137   gl->pending_io = GLP_READ;
3138 /*
3139  * If there is already an unread character in the buffer,
3140  * return it.
3141  */
3142   if(gl->nread < gl->nbuf) {
3143     *c = gl->keybuf[gl->nread];
3144 /*
3145  * Retain the character in the key buffer, but mark it as having been read?
3146  */
3147     if(keep) {
3148       gl->nread++;
3149 /*
3150  * Completely remove the character from the key buffer?
3151  */
3152     } else {
3153       memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1,
3154 	      gl->nbuf - gl->nread - 1);
3155     };
3156     return 0;
3157   };
3158 /*
3159  * Make sure that there is space in the key buffer for one more character.
3160  * This should always be true if gl_interpret_char() is called for each
3161  * new character added, since it will clear the buffer once it has recognized
3162  * or rejected a key sequence.
3163  */
3164   if(gl->nbuf + 1 > GL_KEY_MAX) {
3165     gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.",
3166 		  GL_END_INFO);
3167     errno = EIO;
3168     return 1;
3169   };
3170 /*
3171  * Read one character from the terminal.
3172  */
3173   switch(gl_read_input(gl, c)) {
3174   case GL_READ_OK:
3175     break;
3176   case GL_READ_BLOCKED:
3177     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
3178     return 1;
3179     break;
3180   default:
3181     return 1;
3182     break;
3183   };
3184 /*
3185  * Append the character to the key buffer?
3186  */
3187   if(keep) {
3188     gl->keybuf[gl->nbuf] = *c;
3189     gl->nread = ++gl->nbuf;
3190   };
3191   return 0;
3192 }
3193 
3194 /*.......................................................................
3195  * Read one or more keypresses from the terminal of an input stream.
3196  *
3197  * Input:
3198  *  gl           GetLine *  The resource object of this module.
3199  *  c               char *  The character that was read is assigned to *c.
3200  * Output:
3201  *  return  GlReadStatus    The completion status of the read operation.
3202  */
gl_read_input(GetLine * gl,char * c)3203 static GlReadStatus gl_read_input(GetLine *gl, char *c)
3204 {
3205 /*
3206  * We may have to repeat the read if window change signals are received.
3207  */
3208   for(;;) {
3209 /*
3210  * Which file descriptor should we read from? Mark this volatile, so
3211  * that siglongjmp() can't clobber it.
3212  */
3213     volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd;
3214 /*
3215  * If the endline flag becomes set, don't wait for another character.
3216  */
3217     if(gl->endline)
3218       return GL_READ_ERROR;
3219 /*
3220  * Since the code in this function can block, trap signals.
3221  */
3222     if(sigsetjmp(gl_setjmp_buffer, 1)==0) {
3223 /*
3224  * Handle the different I/O modes.
3225  */
3226       switch(gl->io_mode) {
3227 /*
3228  * In normal I/O mode, we call the event handler before attempting
3229  * to read, since read() blocks.
3230  */
3231       case GL_NORMAL_MODE:
3232 	if(gl_event_handler(gl, fd))
3233 	  return GL_READ_ERROR;
3234 	return gl_read_unmasked(gl, fd, c);  /* Read one character */
3235 	break;
3236 /*
3237  * In non-blocking server I/O mode, we attempt to read a character,
3238  * and only if this fails, call the event handler to wait for a any
3239  * user-configured timeout and any other user-configured events.  In
3240  * addition, we turn off the fcntl() non-blocking flag when reading
3241  * from the terminal, to work around a bug in Solaris. We can do this
3242  * without causing the read() to block, because when in non-blocking
3243  * server-I/O mode, gl_raw_io() sets the VMIN terminal attribute to 0,
3244  * which tells the terminal driver to return immediately if no
3245  * characters are available to be read.
3246  */
3247       case GL_SERVER_MODE:
3248 	{
3249 	  GlReadStatus status;        /* The return status */
3250 	  if(isatty(fd))              /* If we reading from a terminal, */
3251 	     gl_blocking_io(gl, fd);  /* switch to blocking I/O */
3252 	  status = gl_read_unmasked(gl, fd, c); /* Try reading */
3253 	  if(status == GL_READ_BLOCKED) {       /* Nothing readable yet */
3254 	    if(gl_event_handler(gl, fd))        /* Wait for input */
3255 	      status = GL_READ_ERROR;
3256 	    else
3257 	      status = gl_read_unmasked(gl, fd, c); /* Try reading again */
3258 	  };
3259 	  gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */
3260 	  return status;
3261 	};
3262 	break;
3263       };
3264     };
3265 /*
3266  * To get here, one of the signals that we are trapping must have
3267  * been received. Note that by using sigsetjmp() instead of setjmp()
3268  * the signal mask that was blocking these signals will have been
3269  * reinstated, so we can be sure that no more of these signals will
3270  * be received until we explicitly unblock them again.
3271  *
3272  * First, if non-blocking I/O was temporarily disabled, reinstate it.
3273  */
3274     if(gl->io_mode == GL_SERVER_MODE)
3275       gl_nonblocking_io(gl, fd);
3276 /*
3277  * Now respond to the signal that was caught.
3278  */
3279     if(gl_check_caught_signal(gl))
3280       return GL_READ_ERROR;
3281   };
3282 }
3283 
3284 /*.......................................................................
3285  * This is a private function of gl_read_input(), which unblocks signals
3286  * temporarily while it reads a single character from the specified file
3287  * descriptor.
3288  *
3289  * Input:
3290  *  gl          GetLine *  The resource object of this module.
3291  *  fd              int    The file descriptor to read from.
3292  *  c              char *  The character that was read is assigned to *c.
3293  * Output:
3294  *  return GlReadStatus    The completion status of the read.
3295  */
gl_read_unmasked(GetLine * gl,int fd,char * c)3296 static GlReadStatus gl_read_unmasked(GetLine *gl, int fd, char *c)
3297 {
3298   int nread;  /* The return value of read() */
3299 /*
3300  * Unblock the signals that we are trapping, while waiting for I/O.
3301  */
3302   gl_catch_signals(gl);
3303 /*
3304  * Attempt to read one character from the terminal, restarting the read
3305  * if any signals that we aren't trapping, are received.
3306  */
3307   do {
3308     errno = 0;
3309     nread = read(fd, c, 1);
3310   } while(nread < 0 && errno==EINTR);
3311 /*
3312  * Block all of the signals that we are trapping.
3313  */
3314   gl_mask_signals(gl, NULL);
3315 /*
3316  * Check the completion status of the read.
3317  */
3318   switch(nread) {
3319   case 1:
3320     return GL_READ_OK;
3321   case 0:
3322     return (isatty(fd) || errno != 0) ? GL_READ_BLOCKED : GL_READ_EOF;
3323   default:
3324     return GL_READ_ERROR;
3325   };
3326 }
3327 
3328 /*.......................................................................
3329  * Remove a specified number of characters from the start of the
3330  * key-press lookahead buffer, gl->keybuf[], and arrange for the next
3331  * read to start from the character at the start of the shifted buffer.
3332  *
3333  * Input:
3334  *  gl      GetLine *  The resource object of this module.
3335  *  nused       int    The number of characters to discard from the start
3336  *                     of the buffer.
3337  */
gl_discard_chars(GetLine * gl,int nused)3338 static void gl_discard_chars(GetLine *gl, int nused)
3339 {
3340   int nkeep = gl->nbuf - nused;
3341   if(nkeep > 0) {
3342     memmove(gl->keybuf, gl->keybuf + nused, nkeep);
3343     gl->nbuf = nkeep;
3344     gl->nread = 0;
3345   } else {
3346     gl->nbuf = gl->nread = 0;
3347   };
3348 }
3349 
3350 /*.......................................................................
3351  * This function is called to handle signals caught between calls to
3352  * sigsetjmp() and siglongjmp().
3353  *
3354  * Input:
3355  *  gl      GetLine *   The resource object of this library.
3356  * Output:
3357  *  return      int     0 - Signal handled internally.
3358  *                      1 - Signal requires gl_get_line() to abort.
3359  */
gl_check_caught_signal(GetLine * gl)3360 static int gl_check_caught_signal(GetLine *gl)
3361 {
3362   GlSignalNode *sig;      /* The signal disposition */
3363   SigAction keep_action;  /* The signal disposition of tecla signal handlers */
3364   unsigned flags;         /* The signal processing flags to use */
3365   int signo;              /* The signal to be handled */
3366 /*
3367  * Was no signal caught?
3368  */
3369   if(gl_pending_signal == -1)
3370     return 0;
3371 /*
3372  * Get the signal to be handled.
3373  */
3374   signo = gl_pending_signal;
3375 /*
3376  * Mark the signal as handled. Note that at this point, all of
3377  * the signals that we are trapping are blocked from delivery.
3378  */
3379   gl_pending_signal = -1;
3380 /*
3381  * Record the signal that was caught, so that the user can query it later.
3382  */
3383   gl->last_signal = signo;
3384 /*
3385  * In non-blocking server mode, the application is responsible for
3386  * responding to terminal signals, and we don't want gl_get_line()s
3387  * normal signal handling to clash with this, so whenever a signal
3388  * is caught, we arrange for gl_get_line() to abort and requeue the
3389  * signal while signals are still blocked. If the application
3390  * had the signal unblocked when gl_get_line() was called, the signal
3391  * will be delivered again as soon as gl_get_line() restores the
3392  * process signal mask, just before returning to the application.
3393  * Note that the caller of this function should set gl->pending_io
3394  * to the appropriate choice of GLP_READ and GLP_WRITE, before returning.
3395  */
3396   if(gl->io_mode==GL_SERVER_MODE) {
3397     gl_record_status(gl, GLR_SIGNAL, EINTR);
3398     raise(signo);
3399     return 1;
3400   };
3401 /*
3402  * Lookup the requested disposition of this signal.
3403  */
3404   for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next)
3405     ;
3406   if(!sig)
3407     return 0;
3408 /*
3409  * Get the signal response flags for this signal.
3410  */
3411   flags = sig->flags;
3412 /*
3413  * Only perform terminal-specific actions if the session is interactive.
3414  */
3415   if(gl->is_term) {
3416 /*
3417  * Did we receive a terminal size signal?
3418  */
3419 #ifdef SIGWINCH
3420     if(signo == SIGWINCH && _gl_update_size(gl))
3421       return 1;
3422 #endif
3423 /*
3424  * Start a fresh line?
3425  */
3426     if(flags & GLS_RESTORE_LINE) {
3427       if(gl_start_newline(gl, 0))
3428 	return 1;
3429     };
3430 /*
3431  * Restore terminal settings to how they were before gl_get_line() was
3432  * called?
3433  */
3434     if(flags & GLS_RESTORE_TTY)
3435       gl_restore_terminal_attributes(gl);
3436   };
3437 /*
3438  * Restore signal handlers to how they were before gl_get_line() was
3439  * called? If this hasn't been requested, only reinstate the signal
3440  * handler of the signal that we are handling.
3441  */
3442   if(flags & GLS_RESTORE_SIG) {
3443     gl_restore_signal_handlers(gl);
3444     gl_unmask_signals(gl, &gl->old_signal_set);
3445   } else {
3446     (void) sigaction(sig->signo, &sig->original, &keep_action);
3447     (void) sigprocmask(SIG_UNBLOCK, &sig->proc_mask, NULL);
3448   };
3449 /*
3450  * Forward the signal to the application's signal handler.
3451  */
3452   if(!(flags & GLS_DONT_FORWARD))
3453     raise(signo);
3454 /*
3455  * Reinstate our signal handlers.
3456  */
3457   if(flags & GLS_RESTORE_SIG) {
3458     gl_mask_signals(gl, NULL);
3459     gl_override_signal_handlers(gl);
3460   } else {
3461     (void) sigaction(sig->signo, &keep_action, NULL);
3462     (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL);
3463   };
3464 /*
3465  * Prepare the terminal for continued editing, if this is an interactive
3466  * session.
3467  */
3468   if(gl->is_term) {
3469 /*
3470  * Do we need to reinstate our terminal settings?
3471  */
3472     if(flags & GLS_RESTORE_TTY)
3473       gl_raw_terminal_mode(gl);
3474 /*
3475  * Redraw the line?
3476  */
3477     if(flags & GLS_REDRAW_LINE)
3478       gl_queue_redisplay(gl);
3479   };
3480 /*
3481  * What next?
3482  */
3483   switch(sig->after) {
3484   case GLS_RETURN:
3485     gl_newline(gl, 1, NULL);
3486     return gl->is_term && gl_flush_output(gl);
3487     break;
3488   case GLS_ABORT:
3489     gl_record_status(gl, GLR_SIGNAL, sig->errno_value);
3490     return 1;
3491     break;
3492   case GLS_CONTINUE:
3493     return gl->is_term && gl_flush_output(gl);
3494     break;
3495   };
3496   return 0;
3497 }
3498 
3499 /*.......................................................................
3500  * Get pertinent terminal control strings and the initial terminal size.
3501  *
3502  * Input:
3503  *  gl     GetLine *  The resource object of this library.
3504  *  term      char *  The type of the terminal.
3505  * Output:
3506  *  return     int    0 - OK.
3507  *                    1 - Error.
3508  */
gl_control_strings(GetLine * gl,const char * term)3509 static int gl_control_strings(GetLine *gl, const char *term)
3510 {
3511   int bad_term = 0;   /* True if term is unusable */
3512 /*
3513  * Discard any existing control strings from a previous terminal.
3514  */
3515   gl->left = NULL;
3516   gl->right = NULL;
3517   gl->up = NULL;
3518   gl->down = NULL;
3519   gl->home = NULL;
3520   gl->bol = 0;
3521   gl->clear_eol = NULL;
3522   gl->clear_eod = NULL;
3523   gl->u_arrow = NULL;
3524   gl->d_arrow = NULL;
3525   gl->l_arrow = NULL;
3526   gl->r_arrow = NULL;
3527   gl->sound_bell = NULL;
3528   gl->bold = NULL;
3529   gl->underline = NULL;
3530   gl->standout = NULL;
3531   gl->dim = NULL;
3532   gl->reverse = NULL;
3533   gl->blink = NULL;
3534   gl->text_attr_off = NULL;
3535   gl->nline = 0;
3536   gl->ncolumn = 0;
3537 #ifdef USE_TERMINFO
3538   gl->left_n = NULL;
3539   gl->right_n = NULL;
3540 #endif
3541 /*
3542  * If possible lookup the information in a terminal information
3543  * database.
3544  */
3545 #ifdef USE_TERMINFO
3546   {
3547     int errret;
3548     if(!term || setupterm((char *)term, gl->input_fd, &errret) == ERR) {
3549       bad_term = 1;
3550     } else {
3551       _clr_StringGroup(gl->capmem);
3552       gl->left = gl_tigetstr(gl, "cub1");
3553       gl->right = gl_tigetstr(gl, "cuf1");
3554       gl->up = gl_tigetstr(gl, "cuu1");
3555       gl->down = gl_tigetstr(gl, "cud1");
3556       gl->home = gl_tigetstr(gl, "home");
3557       gl->clear_eol = gl_tigetstr(gl, "el");
3558       gl->clear_eod = gl_tigetstr(gl, "ed");
3559       gl->u_arrow = gl_tigetstr(gl, "kcuu1");
3560       gl->d_arrow = gl_tigetstr(gl, "kcud1");
3561       gl->l_arrow = gl_tigetstr(gl, "kcub1");
3562       gl->r_arrow = gl_tigetstr(gl, "kcuf1");
3563       gl->left_n = gl_tigetstr(gl, "cub");
3564       gl->right_n = gl_tigetstr(gl, "cuf");
3565       gl->sound_bell = gl_tigetstr(gl, "bel");
3566       gl->bold = gl_tigetstr(gl, "bold");
3567       gl->underline = gl_tigetstr(gl, "smul");
3568       gl->standout = gl_tigetstr(gl, "smso");
3569       gl->dim = gl_tigetstr(gl, "dim");
3570       gl->reverse = gl_tigetstr(gl, "rev");
3571       gl->blink = gl_tigetstr(gl, "blink");
3572       gl->text_attr_off = gl_tigetstr(gl, "sgr0");
3573     };
3574   };
3575 #elif defined(USE_TERMCAP)
3576   if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) {
3577     bad_term = 1;
3578   } else {
3579     char *tgetstr_buf_ptr = gl->tgetstr_buf;
3580     _clr_StringGroup(gl->capmem);
3581     gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr);
3582     gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr);
3583     gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr);
3584     gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr);
3585     gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr);
3586     gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr);
3587     gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr);
3588     gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr);
3589     gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr);
3590     gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr);
3591     gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr);
3592     gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr);
3593     gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr);
3594     gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr);
3595     gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr);
3596     gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr);
3597     gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr);
3598     gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr);
3599     gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr);
3600   };
3601 #endif
3602 /*
3603  * Report term being unusable.
3604  */
3605   if(bad_term) {
3606     gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)",
3607 		  "\". Will assume vt100.", GL_END_INFO);
3608   };
3609 /*
3610  * Fill in missing information with ANSI VT100 strings.
3611  */
3612   if(!gl->left)
3613     gl->left = "\b";    /* ^H */
3614   if(!gl->right)
3615     gl->right = GL_ESC_STR "[C";
3616   if(!gl->up)
3617     gl->up = GL_ESC_STR "[A";
3618   if(!gl->down)
3619     gl->down = "\n";
3620   if(!gl->home)
3621     gl->home = GL_ESC_STR "[H";
3622   if(!gl->bol)
3623     gl->bol = "\r";
3624   if(!gl->clear_eol)
3625     gl->clear_eol = GL_ESC_STR "[K";
3626   if(!gl->clear_eod)
3627     gl->clear_eod = GL_ESC_STR "[J";
3628   if(!gl->u_arrow)
3629     gl->u_arrow = GL_ESC_STR "[A";
3630   if(!gl->d_arrow)
3631     gl->d_arrow = GL_ESC_STR "[B";
3632   if(!gl->l_arrow)
3633     gl->l_arrow = GL_ESC_STR "[D";
3634   if(!gl->r_arrow)
3635     gl->r_arrow = GL_ESC_STR "[C";
3636   if(!gl->sound_bell)
3637     gl->sound_bell = "\a";
3638   if(!gl->bold)
3639     gl->bold = GL_ESC_STR "[1m";
3640   if(!gl->underline)
3641     gl->underline = GL_ESC_STR "[4m";
3642   if(!gl->standout)
3643     gl->standout = GL_ESC_STR "[1;7m";
3644   if(!gl->dim)
3645     gl->dim = "";  /* Not available */
3646   if(!gl->reverse)
3647     gl->reverse = GL_ESC_STR "[7m";
3648   if(!gl->blink)
3649     gl->blink = GL_ESC_STR "[5m";
3650   if(!gl->text_attr_off)
3651     gl->text_attr_off = GL_ESC_STR "[m";
3652 /*
3653  * Find out the current terminal size.
3654  */
3655   (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL);
3656   return 0;
3657 }
3658 
3659 #ifdef USE_TERMINFO
3660 /*.......................................................................
3661  * This is a private function of gl_control_strings() used to look up
3662  * a termninal capability string from the terminfo database and make
3663  * a private copy of it.
3664  *
3665  * Input:
3666  *  gl         GetLine *  The resource object of gl_get_line().
3667  *  name    const char *  The name of the terminfo string to look up.
3668  * Output:
3669  *  return  const char *  The local copy of the capability, or NULL
3670  *                        if not available.
3671  */
gl_tigetstr(GetLine * gl,const char * name)3672 static const char *gl_tigetstr(GetLine *gl, const char *name)
3673 {
3674   const char *value = tigetstr((char *)name);
3675   if(!value || value == (char *) -1)
3676     return NULL;
3677   return _sg_store_string(gl->capmem, value, 0);
3678 }
3679 #elif defined(USE_TERMCAP)
3680 /*.......................................................................
3681  * This is a private function of gl_control_strings() used to look up
3682  * a termninal capability string from the termcap database and make
3683  * a private copy of it. Note that some emulations of tgetstr(), such
3684  * as that used by Solaris, ignores the buffer pointer that is past to
3685  * it, so we can't assume that a private copy has been made that won't
3686  * be trashed by another call to gl_control_strings() by another
3687  * GetLine object. So we make what may be a redundant private copy
3688  * of the string in gl->capmem.
3689  *
3690  * Input:
3691  *  gl         GetLine *  The resource object of gl_get_line().
3692  *  name    const char *  The name of the terminfo string to look up.
3693  * Input/Output:
3694  *  bufptr        char ** On input *bufptr points to the location in
3695  *                        gl->tgetstr_buf at which to record the
3696  *                        capability string. On output *bufptr is
3697  *                        incremented over the stored string.
3698  * Output:
3699  *  return  const char *  The local copy of the capability, or NULL
3700  *                        on error.
3701  */
gl_tgetstr(GetLine * gl,const char * name,char ** bufptr)3702 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr)
3703 {
3704   const char *value = tgetstr((char *)name, bufptr);
3705   if(!value || value == (char *) -1)
3706     return NULL;
3707   return _sg_store_string(gl->capmem, value, 0);
3708 }
3709 #endif
3710 
3711 /*.......................................................................
3712  * This is an action function that implements a user interrupt (eg. ^C).
3713  */
KT_KEY_FN(gl_user_interrupt)3714 static KT_KEY_FN(gl_user_interrupt)
3715 {
3716   raise(SIGINT);
3717   return 1;
3718 }
3719 
3720 /*.......................................................................
3721  * This is an action function that implements the abort signal.
3722  */
KT_KEY_FN(gl_abort)3723 static KT_KEY_FN(gl_abort)
3724 {
3725   raise(SIGABRT);
3726   return 1;
3727 }
3728 
3729 /*.......................................................................
3730  * This is an action function that sends a suspend signal (eg. ^Z) to the
3731  * the parent process.
3732  */
KT_KEY_FN(gl_suspend)3733 static KT_KEY_FN(gl_suspend)
3734 {
3735   raise(SIGTSTP);
3736   return 0;
3737 }
3738 
3739 /*.......................................................................
3740  * This is an action function that halts output to the terminal.
3741  */
KT_KEY_FN(gl_stop_output)3742 static KT_KEY_FN(gl_stop_output)
3743 {
3744   tcflow(gl->output_fd, TCOOFF);
3745   return 0;
3746 }
3747 
3748 /*.......................................................................
3749  * This is an action function that resumes halted terminal output.
3750  */
KT_KEY_FN(gl_start_output)3751 static KT_KEY_FN(gl_start_output)
3752 {
3753   tcflow(gl->output_fd, TCOON);
3754   return 0;
3755 }
3756 
3757 /*.......................................................................
3758  * This is an action function that allows the next character to be accepted
3759  * without any interpretation as a special character.
3760  */
KT_KEY_FN(gl_literal_next)3761 static KT_KEY_FN(gl_literal_next)
3762 {
3763   char c;   /* The character to be added to the line */
3764   int i;
3765 /*
3766  * Get the character to be inserted literally.
3767  */
3768   if(gl_read_terminal(gl, 1, &c))
3769     return 1;
3770 /*
3771  * Add the character to the line 'count' times.
3772  */
3773   for(i=0; i<count; i++)
3774     gl_add_char_to_line(gl, c);
3775   return 0;
3776 }
3777 
3778 /*.......................................................................
3779  * Return the width of a tab character at a given position when
3780  * displayed at a given position on the terminal. This is needed
3781  * because the width of tab characters depends on where they are,
3782  * relative to the preceding tab stops.
3783  *
3784  * Input:
3785  *  gl       GetLine *  The resource object of this library.
3786  *  term_curpos  int    The destination terminal location of the character.
3787  * Output:
3788  *  return       int    The number of terminal charaters needed.
3789  */
gl_displayed_tab_width(GetLine * gl,int term_curpos)3790 static int gl_displayed_tab_width(GetLine *gl, int term_curpos)
3791 {
3792   return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH);
3793 }
3794 
3795 /*.......................................................................
3796  * Return the number of characters needed to display a given character
3797  * on the screen. Tab characters require eight spaces, and control
3798  * characters are represented by a caret followed by the modified
3799  * character.
3800  *
3801  * Input:
3802  *  gl       GetLine *  The resource object of this library.
3803  *  c           char    The character to be displayed.
3804  *  term_curpos  int    The destination terminal location of the character.
3805  *                      This is needed because the width of tab characters
3806  *                      depends on where they are, relative to the
3807  *                      preceding tab stops.
3808  * Output:
3809  *  return       int    The number of terminal charaters needed.
3810  */
gl_displayed_char_width(GetLine * gl,char c,int term_curpos)3811 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos)
3812 {
3813   if(c=='\t')
3814     return gl_displayed_tab_width(gl, term_curpos);
3815   if(IS_CTRL_CHAR(c))
3816     return 2;
3817   if(!isprint((int)(unsigned char) c))
3818     return gl_octal_width((int)(unsigned char)c) + 1;
3819   return 1;
3820 }
3821 
3822 
3823 /*.......................................................................
3824  * Work out the length of given string of characters on the terminal.
3825  *
3826  * Input:
3827  *  gl       GetLine *  The resource object of this library.
3828  *  string      char *  The string to be measured.
3829  *  nc           int    The number of characters to be measured, or -1
3830  *                      to measure the whole string.
3831  *  term_curpos  int    The destination terminal location of the character.
3832  *                      This is needed because the width of tab characters
3833  *                      depends on where they are, relative to the
3834  *                      preceding tab stops.
3835  * Output:
3836  *  return       int    The number of displayed characters.
3837  */
gl_displayed_string_width(GetLine * gl,const char * string,int nc,int term_curpos)3838 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
3839 				     int term_curpos)
3840 {
3841   int slen = 0;   /* The displayed number of characters */
3842   int i;
3843 /*
3844  * How many characters are to be measured?
3845  */
3846   if(nc < 0)
3847     nc = strlen(string);
3848 /*
3849  * Add up the length of the displayed string.
3850  */
3851   for(i=0; i<nc; i++)
3852     slen += gl_displayed_char_width(gl, string[i], term_curpos + slen);
3853   return slen;
3854 }
3855 
3856 /*.......................................................................
3857  * Write a string verbatim to the current terminal or output stream.
3858  *
3859  * Note that when async-signal safety is required, the 'buffered'
3860  * argument must be 0, and n must not be -1.
3861  *
3862  * Input:
3863  *  gl         GetLine *  The resource object of the gl_get_line().
3864  *  buffered       int    If true, used buffered I/O when writing to
3865  *                        the terminal. Otherwise use async-signal-safe
3866  *                        unbuffered I/O.
3867  *  string  const char *  The string to be written (this need not be
3868  *                        '\0' terminated unless n<0).
3869  *  n              int    The number of characters to write from the
3870  *                        prefix of string[], or -1 to request that
3871  *                        gl_print_raw_string() use strlen() to figure
3872  *                        out the length.
3873  * Output:
3874  *  return         int    0 - OK.
3875  *                        1 - Error.
3876  */
gl_print_raw_string(GetLine * gl,int buffered,const char * string,int n)3877 static int gl_print_raw_string(GetLine *gl, int buffered,
3878 			       const char *string, int n)
3879 {
3880   GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn;
3881 /*
3882  * Only display output when echoing is turned on.
3883  */
3884   if(gl->echo) {
3885     int ndone = 0;   /* The number of characters written so far */
3886 /*
3887  * When using un-buffered I/O, flush pending output first.
3888  */
3889     if(!buffered) {
3890       if(gl_flush_output(gl))
3891 	return 1;
3892     };
3893 /*
3894  * If no length has been provided, measure the length of the string.
3895  */
3896     if(n < 0)
3897       n = strlen(string);
3898 /*
3899  * Write the string.
3900  */
3901     if(write_fn(gl, string + ndone, n-ndone) != n)
3902       return 1;
3903   };
3904   return 0;
3905 }
3906 
3907 /*.......................................................................
3908  * Output a terminal control sequence. When using terminfo,
3909  * this must be a sequence returned by tgetstr() or tigetstr()
3910  * respectively.
3911  *
3912  * Input:
3913  *  gl     GetLine *   The resource object of this library.
3914  *  nline      int     The number of lines affected by the operation,
3915  *                     or 1 if not relevant.
3916  *  string    char *   The control sequence to be sent.
3917  * Output:
3918  *  return     int     0 - OK.
3919  *                     1 - Error.
3920  */
gl_print_control_sequence(GetLine * gl,int nline,const char * string)3921 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string)
3922 {
3923   int waserr = 0;   /* True if an error occurs */
3924 /*
3925  * Only write characters to the terminal when echoing is enabled.
3926  */
3927   if(gl->echo) {
3928 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3929     tputs_gl = gl;
3930     errno = 0;
3931     tputs((char *)string, nline, gl_tputs_putchar);
3932     waserr = errno != 0;
3933 #else
3934     waserr = gl_print_raw_string(gl, 1, string, -1);
3935 #endif
3936   };
3937   return waserr;
3938 }
3939 
3940 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3941 /*.......................................................................
3942  * The following callback function is called by tputs() to output a raw
3943  * control character to the terminal.
3944  */
gl_tputs_putchar(TputsArgType c)3945 static TputsRetType gl_tputs_putchar(TputsArgType c)
3946 {
3947   char ch = c;
3948 #if TPUTS_RETURNS_VALUE
3949   return gl_print_raw_string(tputs_gl, 1, &ch, 1);
3950 #else
3951   (void) gl_print_raw_string(tputs_gl, 1, &ch, 1);
3952 #endif
3953 }
3954 #endif
3955 
3956 /*.......................................................................
3957  * Move the terminal cursor n characters to the left or right.
3958  *
3959  * Input:
3960  *  gl     GetLine *   The resource object of this program.
3961  *  n          int     number of positions to the right (> 0) or left (< 0).
3962  * Output:
3963  *  return     int     0 - OK.
3964  *                     1 - Error.
3965  */
gl_terminal_move_cursor(GetLine * gl,int n)3966 static int gl_terminal_move_cursor(GetLine *gl, int n)
3967 {
3968   int cur_row, cur_col; /* The current terminal row and column index of */
3969                         /*  the cursor wrt the start of the input line. */
3970   int new_row, new_col; /* The target terminal row and column index of */
3971                         /*  the cursor wrt the start of the input line. */
3972 /*
3973  * Do nothing if the input line isn't currently displayed. In this
3974  * case, the cursor will be moved to the right place when the line
3975  * is next redisplayed.
3976  */
3977   if(!gl->displayed)
3978     return 0;
3979 /*
3980  * How far can we move left?
3981  */
3982   if(gl->term_curpos + n < 0)
3983     n = gl->term_curpos;
3984 /*
3985  * Break down the current and target cursor locations into rows and columns.
3986  */
3987   cur_row = gl->term_curpos / gl->ncolumn;
3988   cur_col = gl->term_curpos % gl->ncolumn;
3989   new_row = (gl->term_curpos + n) / gl->ncolumn;
3990   new_col = (gl->term_curpos + n) % gl->ncolumn;
3991 /*
3992  * Move down to the next line.
3993  */
3994   for(; cur_row < new_row; cur_row++) {
3995     if(gl_print_control_sequence(gl, 1, gl->down))
3996       return 1;
3997   };
3998 /*
3999  * Move up to the previous line.
4000  */
4001   for(; cur_row > new_row; cur_row--) {
4002     if(gl_print_control_sequence(gl, 1, gl->up))
4003       return 1;
4004   };
4005 /*
4006  * Move to the right within the target line?
4007  */
4008   if(cur_col < new_col) {
4009 #ifdef USE_TERMINFO
4010 /*
4011  * Use a parameterized control sequence if it generates less control
4012  * characters (guess based on ANSI terminal termcap entry).
4013  */
4014     if(gl->right_n != NULL && new_col - cur_col > 1) {
4015       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n,
4016            (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4017 	return 1;
4018     } else
4019 #endif
4020     {
4021       for(; cur_col < new_col; cur_col++) {
4022         if(gl_print_control_sequence(gl, 1, gl->right))
4023           return 1;
4024       };
4025     };
4026 /*
4027  * Move to the left within the target line?
4028  */
4029   } else if(cur_col > new_col) {
4030 #ifdef USE_TERMINFO
4031 /*
4032  * Use a parameterized control sequence if it generates less control
4033  * characters (guess based on ANSI terminal termcap entry).
4034  */
4035     if(gl->left_n != NULL && cur_col - new_col > 3) {
4036       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n,
4037            (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4038 	return 1;
4039     } else
4040 #endif
4041     {
4042       for(; cur_col > new_col; cur_col--) {
4043         if(gl_print_control_sequence(gl, 1, gl->left))
4044           return 1;
4045       };
4046     };
4047   }
4048 /*
4049  * Update the recorded position of the terminal cursor.
4050  */
4051   gl->term_curpos += n;
4052   return 0;
4053 }
4054 
4055 /*.......................................................................
4056  * Write a character to the terminal after expanding tabs and control
4057  * characters to their multi-character representations.
4058  *
4059  * Input:
4060  *  gl    GetLine *   The resource object of this program.
4061  *  c        char     The character to be output.
4062  *  pad      char     Many terminals have the irritating feature that
4063  *                    when one writes a character in the last column of
4064  *                    of the terminal, the cursor isn't wrapped to the
4065  *                    start of the next line until one more character
4066  *                    is written. Some terminals don't do this, so
4067  *                    after such a write, we don't know where the
4068  *                    terminal is unless we output an extra character.
4069  *                    This argument specifies the character to write.
4070  *                    If at the end of the input line send '\0' or a
4071  *                    space, and a space will be written. Otherwise,
4072  *                    pass the next character in the input line
4073  *                    following the one being written.
4074  * Output:
4075  *  return    int     0 - OK.
4076  */
gl_print_char(GetLine * gl,char c,char pad)4077 static int gl_print_char(GetLine *gl, char c, char pad)
4078 {
4079   char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */
4080   int nchar;                  /* The number of terminal characters */
4081   int i;
4082 /*
4083  * Check for special characters.
4084  */
4085   if(c == '\t') {
4086 /*
4087  * How many spaces do we need to represent a tab at the current terminal
4088  * column?
4089  */
4090     nchar = gl_displayed_tab_width(gl, gl->term_curpos);
4091 /*
4092  * Compose the tab string.
4093  */
4094     for(i=0; i<nchar; i++)
4095       string[i] = ' ';
4096   } else if(IS_CTRL_CHAR(c)) {
4097     string[0] = '^';
4098     string[1] = CTRL_TO_CHAR(c);
4099     nchar = 2;
4100   } else if(!isprint((int)(unsigned char) c)) {
4101     sprintf(string, "\\%o", (int)(unsigned char)c);
4102     nchar = strlen(string);
4103   } else {
4104     string[0] = c;
4105     nchar = 1;
4106   };
4107 /*
4108  * Terminate the string.
4109  */
4110   string[nchar] = '\0';
4111 /*
4112  * Write the string to the terminal.
4113  */
4114   if(gl_print_raw_string(gl, 1, string, -1))
4115     return 1;
4116 /*
4117  * Except for one exception to be described in a moment, the cursor should
4118  * now have been positioned after the character that was just output.
4119  */
4120   gl->term_curpos += nchar;
4121 /*
4122  * Keep a record of the number of characters in the terminal version
4123  * of the input line.
4124  */
4125   if(gl->term_curpos > gl->term_len)
4126     gl->term_len = gl->term_curpos;
4127 /*
4128  * If the new character ended exactly at the end of a line,
4129  * most terminals won't move the cursor onto the next line until we
4130  * have written a character on the next line, so append an extra
4131  * space then move the cursor back.
4132  */
4133   if(gl->term_curpos % gl->ncolumn == 0) {
4134     int term_curpos = gl->term_curpos;
4135     if(gl_print_char(gl, pad ? pad : ' ', ' ') ||
4136        gl_set_term_curpos(gl, term_curpos))
4137       return 1;
4138   };
4139   return 0;
4140 }
4141 
4142 /*.......................................................................
4143  * Write a string to the terminal after expanding tabs and control
4144  * characters to their multi-character representations.
4145  *
4146  * Input:
4147  *  gl    GetLine *   The resource object of this program.
4148  *  string   char *   The string to be output.
4149  *  pad      char     Many terminals have the irritating feature that
4150  *                    when one writes a character in the last column of
4151  *                    of the terminal, the cursor isn't wrapped to the
4152  *                    start of the next line until one more character
4153  *                    is written. Some terminals don't do this, so
4154  *                    after such a write, we don't know where the
4155  *                    terminal is unless we output an extra character.
4156  *                    This argument specifies the character to write.
4157  *                    If at the end of the input line send '\0' or a
4158  *                    space, and a space will be written. Otherwise,
4159  *                    pass the next character in the input line
4160  *                    following the one being written.
4161  * Output:
4162  *  return    int     0 - OK.
4163  */
gl_print_string(GetLine * gl,const char * string,char pad)4164 static int gl_print_string(GetLine *gl, const char *string, char pad)
4165 {
4166   const char *cptr;   /* A pointer into string[] */
4167   for(cptr=string; *cptr; cptr++) {
4168     char nextc = cptr[1];
4169     if(gl_print_char(gl, *cptr, nextc ? nextc : pad))
4170       return 1;
4171   };
4172   return 0;
4173 }
4174 
4175 /*.......................................................................
4176  * Move the terminal cursor position.
4177  *
4178  * Input:
4179  *  gl      GetLine *  The resource object of this library.
4180  *  term_curpos int    The destination terminal cursor position.
4181  * Output:
4182  *  return      int    0 - OK.
4183  *                     1 - Error.
4184  */
gl_set_term_curpos(GetLine * gl,int term_curpos)4185 static int gl_set_term_curpos(GetLine *gl, int term_curpos)
4186 {
4187   return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos);
4188 }
4189 
4190 /*.......................................................................
4191  * This is an action function that moves the buffer cursor one character
4192  * left, and updates the terminal cursor to match.
4193  */
KT_KEY_FN(gl_cursor_left)4194 static KT_KEY_FN(gl_cursor_left)
4195 {
4196   return gl_place_cursor(gl, gl->buff_curpos - count);
4197 }
4198 
4199 /*.......................................................................
4200  * This is an action function that moves the buffer cursor one character
4201  * right, and updates the terminal cursor to match.
4202  */
KT_KEY_FN(gl_cursor_right)4203 static KT_KEY_FN(gl_cursor_right)
4204 {
4205   return gl_place_cursor(gl, gl->buff_curpos + count);
4206 }
4207 
4208 /*.......................................................................
4209  * This is an action function that toggles between overwrite and insert
4210  * mode.
4211  */
KT_KEY_FN(gl_insert_mode)4212 static KT_KEY_FN(gl_insert_mode)
4213 {
4214   gl->insert = !gl->insert;
4215   return 0;
4216 }
4217 
4218 /*.......................................................................
4219  * This is an action function which moves the cursor to the beginning of
4220  * the line.
4221  */
KT_KEY_FN(gl_beginning_of_line)4222 static KT_KEY_FN(gl_beginning_of_line)
4223 {
4224   return gl_place_cursor(gl, 0);
4225 }
4226 
4227 /*.......................................................................
4228  * This is an action function which moves the cursor to the end of
4229  * the line.
4230  */
KT_KEY_FN(gl_end_of_line)4231 static KT_KEY_FN(gl_end_of_line)
4232 {
4233   return gl_place_cursor(gl, gl->ntotal);
4234 }
4235 
4236 /*.......................................................................
4237  * This is an action function which deletes the entire contents of the
4238  * current line.
4239  */
KT_KEY_FN(gl_delete_line)4240 static KT_KEY_FN(gl_delete_line)
4241 {
4242 /*
4243  * If in vi command mode, preserve the current line for potential
4244  * use by vi-undo.
4245  */
4246   gl_save_for_undo(gl);
4247 /*
4248  * Copy the contents of the line to the cut buffer.
4249  */
4250   strcpy(gl->cutbuf, gl->line);
4251 /*
4252  * Clear the buffer.
4253  */
4254   gl_truncate_buffer(gl, 0);
4255 /*
4256  * Move the terminal cursor to just after the prompt.
4257  */
4258   if(gl_place_cursor(gl, 0))
4259     return 1;
4260 /*
4261  * Clear from the end of the prompt to the end of the terminal.
4262  */
4263   if(gl_truncate_display(gl))
4264     return 1;
4265   return 0;
4266 }
4267 
4268 /*.......................................................................
4269  * This is an action function which deletes all characters between the
4270  * current cursor position and the end of the line.
4271  */
KT_KEY_FN(gl_kill_line)4272 static KT_KEY_FN(gl_kill_line)
4273 {
4274 /*
4275  * If in vi command mode, preserve the current line for potential
4276  * use by vi-undo.
4277  */
4278   gl_save_for_undo(gl);
4279 /*
4280  * Copy the part of the line that is about to be deleted to the cut buffer.
4281  */
4282   strcpy(gl->cutbuf, gl->line + gl->buff_curpos);
4283 /*
4284  * Terminate the buffered line at the current cursor position.
4285  */
4286   gl_truncate_buffer(gl, gl->buff_curpos);
4287 /*
4288  * Clear the part of the line that follows the cursor.
4289  */
4290   if(gl_truncate_display(gl))
4291     return 1;
4292 /*
4293  * Explicitly reset the cursor position to allow vi command mode
4294  * constraints on its position to be set.
4295  */
4296   return gl_place_cursor(gl, gl->buff_curpos);
4297 }
4298 
4299 /*.......................................................................
4300  * This is an action function which deletes all characters between the
4301  * start of the line and the current cursor position.
4302  */
KT_KEY_FN(gl_backward_kill_line)4303 static KT_KEY_FN(gl_backward_kill_line)
4304 {
4305 /*
4306  * How many characters are to be deleted from before the cursor?
4307  */
4308   int nc = gl->buff_curpos - gl->insert_curpos;
4309   if (!nc)
4310     return 0;
4311 /*
4312  * Move the cursor to the start of the line, or in vi input mode,
4313  * the start of the sub-line at which insertion started, and delete
4314  * up to the old cursor position.
4315  */
4316   return gl_place_cursor(gl, gl->insert_curpos) ||
4317          gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command);
4318 }
4319 
4320 /*.......................................................................
4321  * This is an action function which moves the cursor forward by a word.
4322  */
KT_KEY_FN(gl_forward_word)4323 static KT_KEY_FN(gl_forward_word)
4324 {
4325   return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) +
4326 			 (gl->editor==GL_EMACS_MODE));
4327 }
4328 
4329 /*.......................................................................
4330  * This is an action function which moves the cursor forward to the start
4331  * of the next word.
4332  */
KT_KEY_FN(gl_forward_to_word)4333 static KT_KEY_FN(gl_forward_to_word)
4334 {
4335   return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count));
4336 }
4337 
4338 /*.......................................................................
4339  * This is an action function which moves the cursor backward by a word.
4340  */
KT_KEY_FN(gl_backward_word)4341 static KT_KEY_FN(gl_backward_word)
4342 {
4343   return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count));
4344 }
4345 
4346 /*.......................................................................
4347  * Delete one or more characters, starting with the one under the cursor.
4348  *
4349  * Input:
4350  *  gl     GetLine *  The resource object of this library.
4351  *  nc         int    The number of characters to delete.
4352  *  cut        int    If true, copy the characters to the cut buffer.
4353  * Output:
4354  *  return     int    0 - OK.
4355  *                    1 - Error.
4356  */
gl_delete_chars(GetLine * gl,int nc,int cut)4357 static int gl_delete_chars(GetLine *gl, int nc, int cut)
4358 {
4359 /*
4360  * If in vi command mode, preserve the current line for potential
4361  * use by vi-undo.
4362  */
4363   gl_save_for_undo(gl);
4364 /*
4365  * If there are fewer than nc characters following the cursor, limit
4366  * nc to the number available.
4367  */
4368   if(gl->buff_curpos + nc > gl->ntotal)
4369     nc = gl->ntotal - gl->buff_curpos;
4370 /*
4371  * Copy the about to be deleted region to the cut buffer.
4372  */
4373   if(cut) {
4374     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc);
4375     gl->cutbuf[nc] = '\0';
4376   }
4377 /*
4378  * Nothing to delete?
4379  */
4380   if(nc <= 0)
4381     return 0;
4382 /*
4383  * In vi overwrite mode, restore any previously overwritten characters
4384  * from the undo buffer.
4385  */
4386   if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) {
4387 /*
4388  * How many of the characters being deleted can be restored from the
4389  * undo buffer?
4390  */
4391     int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ?
4392       nc : gl->vi.undo.ntotal - gl->buff_curpos;
4393 /*
4394  * Restore any available characters.
4395  */
4396     if(nrestore > 0) {
4397       gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore,
4398 		       gl->buff_curpos);
4399     };
4400 /*
4401  * If their were insufficient characters in the undo buffer, then this
4402  * implies that we are deleting from the end of the line, so we need
4403  * to terminate the line either where the undo buffer ran out, or if
4404  * we are deleting from beyond the end of the undo buffer, at the current
4405  * cursor position.
4406  */
4407     if(nc != nrestore) {
4408       gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ?
4409 			 gl->vi.undo.ntotal : gl->buff_curpos);
4410     };
4411   } else {
4412 /*
4413  * Copy the remaining part of the line back over the deleted characters.
4414  */
4415     gl_remove_from_buffer(gl, gl->buff_curpos, nc);
4416   };
4417 /*
4418  * Redraw the remaining characters following the cursor.
4419  */
4420   if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0'))
4421     return 1;
4422 /*
4423  * Clear to the end of the terminal.
4424  */
4425   if(gl_truncate_display(gl))
4426     return 1;
4427 /*
4428  * Place the cursor at the start of where the deletion was performed.
4429  */
4430   return gl_place_cursor(gl, gl->buff_curpos);
4431 }
4432 
4433 /*.......................................................................
4434  * This is an action function which deletes character(s) under the
4435  * cursor without moving the cursor.
4436  */
KT_KEY_FN(gl_forward_delete_char)4437 static KT_KEY_FN(gl_forward_delete_char)
4438 {
4439 /*
4440  * Delete 'count' characters.
4441  */
4442   return gl_delete_chars(gl, count, gl->vi.command);
4443 }
4444 
4445 /*.......................................................................
4446  * This is an action function which deletes character(s) under the
4447  * cursor and moves the cursor back one character.
4448  */
KT_KEY_FN(gl_backward_delete_char)4449 static KT_KEY_FN(gl_backward_delete_char)
4450 {
4451 /*
4452  * Restrict the deletion count to the number of characters that
4453  * precede the insertion point.
4454  */
4455   if(count > gl->buff_curpos - gl->insert_curpos)
4456     count = gl->buff_curpos - gl->insert_curpos;
4457 /*
4458  * If in vi command mode, preserve the current line for potential
4459  * use by vi-undo.
4460  */
4461   gl_save_for_undo(gl);
4462   return gl_cursor_left(gl, count, NULL) ||
4463     gl_delete_chars(gl, count, gl->vi.command);
4464 }
4465 
4466 /*.......................................................................
4467  * Starting from the cursor position delete to the specified column.
4468  */
KT_KEY_FN(gl_delete_to_column)4469 static KT_KEY_FN(gl_delete_to_column)
4470 {
4471   if (--count >= gl->buff_curpos)
4472     return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL);
4473   else
4474     return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL);
4475 }
4476 
4477 /*.......................................................................
4478  * Starting from the cursor position delete characters to a matching
4479  * parenthesis.
4480  */
KT_KEY_FN(gl_delete_to_parenthesis)4481 static KT_KEY_FN(gl_delete_to_parenthesis)
4482 {
4483   int curpos = gl_index_of_matching_paren(gl);
4484   if(curpos >= 0) {
4485     gl_save_for_undo(gl);
4486     if(curpos >= gl->buff_curpos)
4487       return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL);
4488     else
4489       return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
4490   };
4491   return 0;
4492 }
4493 
4494 /*.......................................................................
4495  * This is an action function which deletes from the cursor to the end
4496  * of the word that the cursor is either in or precedes.
4497  */
KT_KEY_FN(gl_forward_delete_word)4498 static KT_KEY_FN(gl_forward_delete_word)
4499 {
4500 /*
4501  * If in vi command mode, preserve the current line for potential
4502  * use by vi-undo.
4503  */
4504   gl_save_for_undo(gl);
4505 /*
4506  * In emacs mode delete to the end of the word. In vi mode delete to the
4507  * start of the net word.
4508  */
4509   if(gl->editor == GL_EMACS_MODE) {
4510     return gl_delete_chars(gl,
4511 		gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1);
4512   } else {
4513     return gl_delete_chars(gl,
4514 		gl_nth_word_start_forward(gl,count) - gl->buff_curpos,
4515 		gl->vi.command);
4516   };
4517 }
4518 
4519 /*.......................................................................
4520  * This is an action function which deletes the word that precedes the
4521  * cursor.
4522  */
KT_KEY_FN(gl_backward_delete_word)4523 static KT_KEY_FN(gl_backward_delete_word)
4524 {
4525 /*
4526  * Keep a record of the current cursor position.
4527  */
4528   int buff_curpos = gl->buff_curpos;
4529 /*
4530  * If in vi command mode, preserve the current line for potential
4531  * use by vi-undo.
4532  */
4533   gl_save_for_undo(gl);
4534 /*
4535  * Move back 'count' words.
4536  */
4537   if(gl_backward_word(gl, count, NULL))
4538     return 1;
4539 /*
4540  * Delete from the new cursor position to the original one.
4541  */
4542   return gl_delete_chars(gl, buff_curpos - gl->buff_curpos,
4543   			 gl->editor == GL_EMACS_MODE || gl->vi.command);
4544 }
4545 
4546 /*.......................................................................
4547  * Searching in a given direction, delete to the count'th
4548  * instance of a specified or queried character, in the input line.
4549  *
4550  * Input:
4551  *  gl       GetLine *  The getline resource object.
4552  *  count        int    The number of times to search.
4553  *  c           char    The character to be searched for, or '\0' if
4554  *                      the character should be read from the user.
4555  *  forward      int    True if searching forward.
4556  *  onto         int    True if the search should end on top of the
4557  *                      character, false if the search should stop
4558  *                      one character before the character in the
4559  *                      specified search direction.
4560  *  change       int    If true, this function is being called upon
4561  *                      to do a vi change command, in which case the
4562  *                      user will be left in insert mode after the
4563  *                      deletion.
4564  * Output:
4565  *  return       int    0 - OK.
4566  *                      1 - Error.
4567  */
gl_delete_find(GetLine * gl,int count,char c,int forward,int onto,int change)4568 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
4569 			  int onto, int change)
4570 {
4571 /*
4572  * Search for the character, and abort the deletion if not found.
4573  */
4574   int pos = gl_find_char(gl, count, forward, onto, c);
4575   if(pos < 0)
4576     return 0;
4577 /*
4578  * If in vi command mode, preserve the current line for potential
4579  * use by vi-undo.
4580  */
4581   gl_save_for_undo(gl);
4582 /*
4583  * Allow the cursor to be at the end of the line if this is a change
4584  * command.
4585  */
4586   if(change)
4587     gl->vi.command = 0;
4588 /*
4589  * Delete the appropriate span of characters.
4590  */
4591   if(forward) {
4592     if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1))
4593       return 1;
4594   } else {
4595     int buff_curpos = gl->buff_curpos;
4596     if(gl_place_cursor(gl, pos) ||
4597        gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1))
4598       return 1;
4599   };
4600 /*
4601  * If this is a change operation, switch the insert mode.
4602  */
4603   if(change && gl_vi_insert(gl, 0, NULL))
4604     return 1;
4605   return 0;
4606 }
4607 
4608 /*.......................................................................
4609  * This is an action function which deletes forward from the cursor up to and
4610  * including a specified character.
4611  */
KT_KEY_FN(gl_forward_delete_find)4612 static KT_KEY_FN(gl_forward_delete_find)
4613 {
4614   return gl_delete_find(gl, count, '\0', 1, 1, 0);
4615 }
4616 
4617 /*.......................................................................
4618  * This is an action function which deletes backward from the cursor back to
4619  * and including a specified character.
4620  */
KT_KEY_FN(gl_backward_delete_find)4621 static KT_KEY_FN(gl_backward_delete_find)
4622 {
4623   return gl_delete_find(gl, count, '\0', 0, 1, 0);
4624 }
4625 
4626 /*.......................................................................
4627  * This is an action function which deletes forward from the cursor up to but
4628  * not including a specified character.
4629  */
KT_KEY_FN(gl_forward_delete_to)4630 static KT_KEY_FN(gl_forward_delete_to)
4631 {
4632   return gl_delete_find(gl, count, '\0', 1, 0, 0);
4633 }
4634 
4635 /*.......................................................................
4636  * This is an action function which deletes backward from the cursor back to
4637  * but not including a specified character.
4638  */
KT_KEY_FN(gl_backward_delete_to)4639 static KT_KEY_FN(gl_backward_delete_to)
4640 {
4641   return gl_delete_find(gl, count, '\0', 0, 0, 0);
4642 }
4643 
4644 /*.......................................................................
4645  * This is an action function which deletes to a character specified by a
4646  * previous search.
4647  */
KT_KEY_FN(gl_delete_refind)4648 static KT_KEY_FN(gl_delete_refind)
4649 {
4650   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
4651 			gl->vi.find_onto, 0);
4652 }
4653 
4654 /*.......................................................................
4655  * This is an action function which deletes to a character specified by a
4656  * previous search, but in the opposite direction.
4657  */
KT_KEY_FN(gl_delete_invert_refind)4658 static KT_KEY_FN(gl_delete_invert_refind)
4659 {
4660   return gl_delete_find(gl, count, gl->vi.find_char,
4661 			!gl->vi.find_forward, gl->vi.find_onto, 0);
4662 }
4663 
4664 /*.......................................................................
4665  * This is an action function which converts the characters in the word
4666  * following the cursor to upper case.
4667  */
KT_KEY_FN(gl_upcase_word)4668 static KT_KEY_FN(gl_upcase_word)
4669 {
4670 /*
4671  * Locate the count'th word ending after the cursor.
4672  */
4673   int last = gl_nth_word_end_forward(gl, count);
4674 /*
4675  * If in vi command mode, preserve the current line for potential
4676  * use by vi-undo.
4677  */
4678   gl_save_for_undo(gl);
4679 /*
4680  * Upcase characters from the current cursor position to 'last'.
4681  */
4682   while(gl->buff_curpos <= last) {
4683     char *cptr = gl->line + gl->buff_curpos;
4684 /*
4685  * Convert the character to upper case?
4686  */
4687     if(islower((int)(unsigned char) *cptr))
4688       gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos);
4689     gl->buff_curpos++;
4690 /*
4691  * Write the possibly modified character back. Note that for non-modified
4692  * characters we want to do this as well, so as to advance the cursor.
4693  */
4694     if(gl_print_char(gl, *cptr, cptr[1]))
4695       return 1;
4696   };
4697   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4698 }
4699 
4700 /*.......................................................................
4701  * This is an action function which converts the characters in the word
4702  * following the cursor to lower case.
4703  */
KT_KEY_FN(gl_downcase_word)4704 static KT_KEY_FN(gl_downcase_word)
4705 {
4706 /*
4707  * Locate the count'th word ending after the cursor.
4708  */
4709   int last = gl_nth_word_end_forward(gl, count);
4710 /*
4711  * If in vi command mode, preserve the current line for potential
4712  * use by vi-undo.
4713  */
4714   gl_save_for_undo(gl);
4715 /*
4716  * Upcase characters from the current cursor position to 'last'.
4717  */
4718   while(gl->buff_curpos <= last) {
4719     char *cptr = gl->line + gl->buff_curpos;
4720 /*
4721  * Convert the character to upper case?
4722  */
4723     if(isupper((int)(unsigned char) *cptr))
4724       gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos);
4725     gl->buff_curpos++;
4726 /*
4727  * Write the possibly modified character back. Note that for non-modified
4728  * characters we want to do this as well, so as to advance the cursor.
4729  */
4730     if(gl_print_char(gl, *cptr, cptr[1]))
4731       return 1;
4732   };
4733   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4734 }
4735 
4736 /*.......................................................................
4737  * This is an action function which converts the first character of the
4738  * following word to upper case, in order to capitalize the word, and
4739  * leaves the cursor at the end of the word.
4740  */
KT_KEY_FN(gl_capitalize_word)4741 static KT_KEY_FN(gl_capitalize_word)
4742 {
4743   char *cptr;   /* &gl->line[gl->buff_curpos] */
4744   int first;    /* True for the first letter of the word */
4745   int i;
4746 /*
4747  * Keep a record of the current insert mode and the cursor position.
4748  */
4749   int insert = gl->insert;
4750 /*
4751  * If in vi command mode, preserve the current line for potential
4752  * use by vi-undo.
4753  */
4754   gl_save_for_undo(gl);
4755 /*
4756  * We want to overwrite the modified word.
4757  */
4758   gl->insert = 0;
4759 /*
4760  * Capitalize 'count' words.
4761  */
4762   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
4763     int pos = gl->buff_curpos;
4764 /*
4765  * If we are not already within a word, skip to the start of the word.
4766  */
4767     for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr);
4768 	pos++, cptr++)
4769       ;
4770 /*
4771  * Move the cursor to the new position.
4772  */
4773     if(gl_place_cursor(gl, pos))
4774       return 1;
4775 /*
4776  * While searching for the end of the word, change lower case letters
4777  * to upper case.
4778  */
4779     for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr);
4780 	gl->buff_curpos++, cptr++) {
4781 /*
4782  * Convert the character to upper case?
4783  */
4784       if(first) {
4785 	if(islower((int)(unsigned char) *cptr))
4786 	  gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
4787       } else {
4788 	if(isupper((int)(unsigned char) *cptr))
4789 	  gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
4790       };
4791       first = 0;
4792 /*
4793  * Write the possibly modified character back. Note that for non-modified
4794  * characters we want to do this as well, so as to advance the cursor.
4795  */
4796       if(gl_print_char(gl, *cptr, cptr[1]))
4797 	return 1;
4798     };
4799   };
4800 /*
4801  * Restore the insertion mode.
4802  */
4803   gl->insert = insert;
4804   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4805 }
4806 
4807 /*.......................................................................
4808  * This is an action function which redraws the current line.
4809  */
KT_KEY_FN(gl_redisplay)4810 static KT_KEY_FN(gl_redisplay)
4811 {
4812 /*
4813  * Keep a record of the current cursor position.
4814  */
4815   int buff_curpos = gl->buff_curpos;
4816 /*
4817  * Do nothing if there is no line to be redisplayed.
4818  */
4819   if(gl->endline)
4820     return 0;
4821 /*
4822  * Erase the current input line.
4823  */
4824   if(gl_erase_line(gl))
4825     return 1;
4826 /*
4827  * Display the current prompt.
4828  */
4829   if(gl_display_prompt(gl))
4830     return 1;
4831 /*
4832  * Render the part of the line that the user has typed in so far.
4833  */
4834   if(gl_print_string(gl, gl->line, '\0'))
4835     return 1;
4836 /*
4837  * Restore the cursor position.
4838  */
4839   if(gl_place_cursor(gl, buff_curpos))
4840     return 1;
4841 /*
4842  * Mark the redisplay operation as having been completed.
4843  */
4844   gl->redisplay = 0;
4845 /*
4846  * Flush the redisplayed line to the terminal.
4847  */
4848   return gl_flush_output(gl);
4849 }
4850 
4851 /*.......................................................................
4852  * This is an action function which clears the display and redraws the
4853  * input line from the home position.
4854  */
KT_KEY_FN(gl_clear_screen)4855 static KT_KEY_FN(gl_clear_screen)
4856 {
4857 /*
4858  * Home the cursor and clear from there to the end of the display.
4859  */
4860   if(gl_print_control_sequence(gl, gl->nline, gl->home) ||
4861      gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
4862     return 1;
4863 /*
4864  * The input line is no longer displayed.
4865  */
4866   gl_line_erased(gl);
4867 /*
4868  * Arrange for the input line to be redisplayed.
4869  */
4870   gl_queue_redisplay(gl);
4871   return 0;
4872 }
4873 
4874 /*.......................................................................
4875  * This is an action function which swaps the character under the cursor
4876  * with the character to the left of the cursor.
4877  */
KT_KEY_FN(gl_transpose_chars)4878 static KT_KEY_FN(gl_transpose_chars)
4879 {
4880   char from[3];     /* The original string of 2 characters */
4881   char swap[3];     /* The swapped string of two characters */
4882 /*
4883  * If we are at the beginning or end of the line, there aren't two
4884  * characters to swap.
4885  */
4886   if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal)
4887     return 0;
4888 /*
4889  * If in vi command mode, preserve the current line for potential
4890  * use by vi-undo.
4891  */
4892   gl_save_for_undo(gl);
4893 /*
4894  * Get the original and swapped strings of the two characters.
4895  */
4896   from[0] = gl->line[gl->buff_curpos - 1];
4897   from[1] = gl->line[gl->buff_curpos];
4898   from[2] = '\0';
4899   swap[0] = gl->line[gl->buff_curpos];
4900   swap[1] = gl->line[gl->buff_curpos - 1];
4901   swap[2] = '\0';
4902 /*
4903  * Move the cursor to the start of the two characters.
4904  */
4905   if(gl_place_cursor(gl, gl->buff_curpos-1))
4906     return 1;
4907 /*
4908  * Swap the two characters in the buffer.
4909  */
4910   gl_buffer_char(gl, swap[0], gl->buff_curpos);
4911   gl_buffer_char(gl, swap[1], gl->buff_curpos+1);
4912 /*
4913  * If the sum of the displayed width of the two characters
4914  * in their current and final positions is the same, swapping can
4915  * be done by just overwriting with the two swapped characters.
4916  */
4917   if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) ==
4918      gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) {
4919     int insert = gl->insert;
4920     gl->insert = 0;
4921     if(gl_print_char(gl, swap[0], swap[1]) ||
4922        gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2]))
4923       return 1;
4924     gl->insert = insert;
4925 /*
4926  * If the swapped substring has a different displayed size, we need to
4927  * redraw everything after the first of the characters.
4928  */
4929   } else {
4930     if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') ||
4931        gl_truncate_display(gl))
4932       return 1;
4933   };
4934 /*
4935  * Advance the cursor to the character after the swapped pair.
4936  */
4937   return gl_place_cursor(gl, gl->buff_curpos + 2);
4938 }
4939 
4940 /*.......................................................................
4941  * This is an action function which sets a mark at the current cursor
4942  * location.
4943  */
KT_KEY_FN(gl_set_mark)4944 static KT_KEY_FN(gl_set_mark)
4945 {
4946   gl->buff_mark = gl->buff_curpos;
4947   return 0;
4948 }
4949 
4950 /*.......................................................................
4951  * This is an action function which swaps the mark location for the
4952  * cursor location.
4953  */
KT_KEY_FN(gl_exchange_point_and_mark)4954 static KT_KEY_FN(gl_exchange_point_and_mark)
4955 {
4956 /*
4957  * Get the old mark position, and limit to the extent of the input
4958  * line.
4959  */
4960   int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal;
4961 /*
4962  * Make the current cursor position the new mark.
4963  */
4964   gl->buff_mark = gl->buff_curpos;
4965 /*
4966  * Move the cursor to the old mark position.
4967  */
4968   return gl_place_cursor(gl, old_mark);
4969 }
4970 
4971 /*.......................................................................
4972  * This is an action function which deletes the characters between the
4973  * mark and the cursor, recording them in gl->cutbuf for later pasting.
4974  */
KT_KEY_FN(gl_kill_region)4975 static KT_KEY_FN(gl_kill_region)
4976 {
4977 /*
4978  * If in vi command mode, preserve the current line for potential
4979  * use by vi-undo.
4980  */
4981   gl_save_for_undo(gl);
4982 /*
4983  * Limit the mark to be within the line.
4984  */
4985   if(gl->buff_mark > gl->ntotal)
4986     gl->buff_mark = gl->ntotal;
4987 /*
4988  * If there are no characters between the cursor and the mark, simply clear
4989  * the cut buffer.
4990  */
4991   if(gl->buff_mark == gl->buff_curpos) {
4992     gl->cutbuf[0] = '\0';
4993     return 0;
4994   };
4995 /*
4996  * If the mark is before the cursor, swap the cursor and the mark.
4997  */
4998   if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL))
4999     return 1;
5000 /*
5001  * Delete the characters.
5002  */
5003   if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1))
5004     return 1;
5005 /*
5006  * Make the mark the same as the cursor position.
5007  */
5008   gl->buff_mark = gl->buff_curpos;
5009   return 0;
5010 }
5011 
5012 /*.......................................................................
5013  * This is an action function which records the characters between the
5014  * mark and the cursor, in gl->cutbuf for later pasting.
5015  */
KT_KEY_FN(gl_copy_region_as_kill)5016 static KT_KEY_FN(gl_copy_region_as_kill)
5017 {
5018   int ca, cb;  /* The indexes of the first and last characters in the region */
5019   int mark;    /* The position of the mark */
5020 /*
5021  * Get the position of the mark, limiting it to lie within the line.
5022  */
5023   mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark;
5024 /*
5025  * If there are no characters between the cursor and the mark, clear
5026  * the cut buffer.
5027  */
5028   if(mark == gl->buff_curpos) {
5029     gl->cutbuf[0] = '\0';
5030     return 0;
5031   };
5032 /*
5033  * Get the line indexes of the first and last characters in the region.
5034  */
5035   if(mark < gl->buff_curpos) {
5036     ca = mark;
5037     cb = gl->buff_curpos - 1;
5038   } else {
5039     ca = gl->buff_curpos;
5040     cb = mark - 1;
5041   };
5042 /*
5043  * Copy the region to the cut buffer.
5044  */
5045   memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca);
5046   gl->cutbuf[cb + 1 - ca] = '\0';
5047   return 0;
5048 }
5049 
5050 /*.......................................................................
5051  * This is an action function which inserts the contents of the cut
5052  * buffer at the current cursor location.
5053  */
KT_KEY_FN(gl_yank)5054 static KT_KEY_FN(gl_yank)
5055 {
5056   int i;
5057 /*
5058  * Set the mark at the current location.
5059  */
5060   gl->buff_mark = gl->buff_curpos;
5061 /*
5062  * Do nothing else if the cut buffer is empty.
5063  */
5064   if(gl->cutbuf[0] == '\0')
5065     return gl_ring_bell(gl, 1, NULL);
5066 /*
5067  * If in vi command mode, preserve the current line for potential
5068  * use by vi-undo.
5069  */
5070   gl_save_for_undo(gl);
5071 /*
5072  * Insert the string count times.
5073  */
5074   for(i=0; i<count; i++) {
5075     if(gl_add_string_to_line(gl, gl->cutbuf))
5076       return 1;
5077   };
5078 /*
5079  * gl_add_string_to_line() leaves the cursor after the last character that
5080  * was pasted, whereas vi leaves the cursor over the last character pasted.
5081  */
5082   if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL))
5083     return 1;
5084   return 0;
5085 }
5086 
5087 /*.......................................................................
5088  * This is an action function which inserts the contents of the cut
5089  * buffer one character beyond the current cursor location.
5090  */
KT_KEY_FN(gl_append_yank)5091 static KT_KEY_FN(gl_append_yank)
5092 {
5093   int was_command = gl->vi.command;
5094   int i;
5095 /*
5096  * If the cut buffer is empty, ring the terminal bell.
5097  */
5098   if(gl->cutbuf[0] == '\0')
5099     return gl_ring_bell(gl, 1, NULL);
5100 /*
5101  * Set the mark at the current location + 1.
5102  */
5103   gl->buff_mark = gl->buff_curpos + 1;
5104 /*
5105  * If in vi command mode, preserve the current line for potential
5106  * use by vi-undo.
5107  */
5108   gl_save_for_undo(gl);
5109 /*
5110  * Arrange to paste the text in insert mode after the current character.
5111  */
5112   if(gl_vi_append(gl, 0, NULL))
5113     return 1;
5114 /*
5115  * Insert the string count times.
5116  */
5117   for(i=0; i<count; i++) {
5118     if(gl_add_string_to_line(gl, gl->cutbuf))
5119       return 1;
5120   };
5121 /*
5122  * Switch back to command mode if necessary.
5123  */
5124   if(was_command)
5125     gl_vi_command_mode(gl);
5126   return 0;
5127 }
5128 
5129 /*.......................................................................
5130  * Attempt to ask the terminal for its current size. On systems that
5131  * don't support the TIOCWINSZ ioctl() for querying the terminal size,
5132  * the current values of gl->ncolumn and gl->nrow are returned.
5133  *
5134  * Input:
5135  *  gl     GetLine *  The resource object of gl_get_line().
5136  * Input/Output:
5137  *  ncolumn    int *  The number of columns will be assigned to *ncolumn.
5138  *  nline      int *  The number of lines will be assigned to *nline.
5139  */
gl_query_size(GetLine * gl,int * ncolumn,int * nline)5140 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline)
5141 {
5142 #ifdef TIOCGWINSZ
5143 /*
5144  * Query the new terminal window size. Ignore invalid responses.
5145  */
5146   struct winsize size;
5147   if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 &&
5148      size.ws_row > 0 && size.ws_col > 0) {
5149     *ncolumn = size.ws_col;
5150     *nline = size.ws_row;
5151     return;
5152   };
5153 #endif
5154 /*
5155  * Return the existing values.
5156  */
5157   *ncolumn = gl->ncolumn;
5158   *nline = gl->nline;
5159   return;
5160 }
5161 
5162 /*.......................................................................
5163  * Query the size of the terminal, and if it has changed, redraw the
5164  * current input line accordingly.
5165  *
5166  * Input:
5167  *  gl     GetLine *  The resource object of gl_get_line().
5168  * Output:
5169  *  return     int    0 - OK.
5170  *                    1 - Error.
5171  */
_gl_update_size(GetLine * gl)5172 static int _gl_update_size(GetLine *gl)
5173 {
5174   int ncolumn, nline;    /* The new size of the terminal */
5175 /*
5176  * Query the new terminal window size.
5177  */
5178   gl_query_size(gl, &ncolumn, &nline);
5179 /*
5180  * Update gl and the displayed line to fit the new dimensions.
5181  */
5182   return gl_handle_tty_resize(gl, ncolumn, nline);
5183 }
5184 
5185 /*.......................................................................
5186  * Redraw the current input line to account for a change in the terminal
5187  * size. Also install the new size in gl.
5188  *
5189  * Input:
5190  *  gl     GetLine *  The resource object of gl_get_line().
5191  *  ncolumn    int    The new number of columns.
5192  *  nline      int    The new number of lines.
5193  * Output:
5194  *  return     int    0 - OK.
5195  *                    1 - Error.
5196  */
gl_handle_tty_resize(GetLine * gl,int ncolumn,int nline)5197 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline)
5198 {
5199 /*
5200  * If the input device isn't a terminal, just record the new size.
5201  */
5202   if(!gl->is_term) {
5203     gl->nline = nline;
5204     gl->ncolumn = ncolumn;
5205 /*
5206  * Has the size actually changed?
5207  */
5208   } else if(ncolumn != gl->ncolumn || nline != gl->nline) {
5209 /*
5210  * If we are currently editing a line, erase it.
5211  */
5212     if(gl_erase_line(gl))
5213       return 1;
5214 /*
5215  * Update the recorded window size.
5216  */
5217     gl->nline = nline;
5218     gl->ncolumn = ncolumn;
5219 /*
5220  * Arrange for the input line to be redrawn before the next character
5221  * is read from the terminal.
5222  */
5223     gl_queue_redisplay(gl);
5224   };
5225   return 0;
5226 }
5227 
5228 /*.......................................................................
5229  * This is the action function that recalls the previous line in the
5230  * history buffer.
5231  */
KT_KEY_FN(gl_up_history)5232 static KT_KEY_FN(gl_up_history)
5233 {
5234 /*
5235  * In vi mode, switch to command mode, since the user is very
5236  * likely to want to move around newly recalled lines.
5237  */
5238   gl_vi_command_mode(gl);
5239 /*
5240  * Forget any previous recall session.
5241  */
5242   gl->preload_id = 0;
5243 /*
5244  * Record the key sequence number of this search action.
5245  */
5246   gl->last_search = gl->keyseq_count;
5247 /*
5248  * We don't want a search prefix for this function.
5249  */
5250   if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5251     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5252     return 1;
5253   };
5254 /*
5255  * Recall the count'th next older line in the history list. If the first one
5256  * fails we can return since nothing has changed, otherwise we must continue
5257  * and update the line state.
5258  */
5259   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5260     return 0;
5261   while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1))
5262     ;
5263 /*
5264  * Accomodate the new contents of gl->line[].
5265  */
5266   gl_update_buffer(gl);
5267 /*
5268  * Arrange to have the cursor placed at the end of the new line.
5269  */
5270   gl->buff_curpos = gl->ntotal;
5271 /*
5272  * Erase and display the new line.
5273  */
5274   gl_queue_redisplay(gl);
5275   return 0;
5276 }
5277 
5278 /*.......................................................................
5279  * This is the action function that recalls the next line in the
5280  * history buffer.
5281  */
KT_KEY_FN(gl_down_history)5282 static KT_KEY_FN(gl_down_history)
5283 {
5284 /*
5285  * In vi mode, switch to command mode, since the user is very
5286  * likely to want to move around newly recalled lines.
5287  */
5288   gl_vi_command_mode(gl);
5289 /*
5290  * Record the key sequence number of this search action.
5291  */
5292   gl->last_search = gl->keyseq_count;
5293 /*
5294  * If no search is currently in progress continue a previous recall
5295  * session from a previous entered line if possible.
5296  */
5297   if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) {
5298     _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1);
5299     gl->preload_id = 0;
5300   } else {
5301 /*
5302  * We don't want a search prefix for this function.
5303  */
5304     if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5305       _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5306       return 1;
5307     };
5308 /*
5309  * Recall the count'th next newer line in the history list. If the first one
5310  * fails we can return since nothing has changed otherwise we must continue
5311  * and update the line state.
5312  */
5313     if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5314       return 0;
5315     while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1))
5316       ;
5317   };
5318 /*
5319  * Accomodate the new contents of gl->line[].
5320  */
5321   gl_update_buffer(gl);
5322 /*
5323  * Arrange to have the cursor placed at the end of the new line.
5324  */
5325   gl->buff_curpos = gl->ntotal;
5326 /*
5327  * Erase and display the new line.
5328  */
5329   gl_queue_redisplay(gl);
5330   return 0;
5331 }
5332 
5333 /*.......................................................................
5334  * This is the action function that recalls the previous line in the
5335  * history buffer whos prefix matches the characters that currently
5336  * precede the cursor. By setting count=-1, this can be used internally
5337  * to force searching for the prefix used in the last search.
5338  */
KT_KEY_FN(gl_history_search_backward)5339 static KT_KEY_FN(gl_history_search_backward)
5340 {
5341 /*
5342  * In vi mode, switch to command mode, since the user is very
5343  * likely to want to move around newly recalled lines.
5344  */
5345   gl_vi_command_mode(gl);
5346 /*
5347  * Forget any previous recall session.
5348  */
5349   gl->preload_id = 0;
5350 /*
5351  * Record the key sequence number of this search action.
5352  */
5353   gl->last_search = gl->keyseq_count;
5354 /*
5355  * If a prefix search isn't already in progress, replace the search
5356  * prefix to the string that precedes the cursor. In vi command mode
5357  * include the character that is under the cursor in the string.  If
5358  * count<0 keep the previous search prefix regardless, so as to force
5359  * a repeat search even if the last command wasn't a history command.
5360  */
5361   if(count >= 0 && !_glh_search_active(gl->glh) &&
5362      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5363 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5364     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5365     return 1;
5366   };
5367 /*
5368  * Search backwards for a match to the part of the line which precedes the
5369  * cursor.
5370  */
5371   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5372     return 0;
5373 /*
5374  * Accomodate the new contents of gl->line[].
5375  */
5376   gl_update_buffer(gl);
5377 /*
5378  * Arrange to have the cursor placed at the end of the new line.
5379  */
5380   gl->buff_curpos = gl->ntotal;
5381 /*
5382  * Erase and display the new line.
5383  */
5384   gl_queue_redisplay(gl);
5385   return 0;
5386 }
5387 
5388 /*.......................................................................
5389  * This is the action function that recalls the previous line in the
5390  * history buffer who's prefix matches that specified in an earlier call
5391  * to gl_history_search_backward() or gl_history_search_forward().
5392  */
KT_KEY_FN(gl_history_re_search_backward)5393 static KT_KEY_FN(gl_history_re_search_backward)
5394 {
5395   return gl_history_search_backward(gl, -1, NULL);
5396 }
5397 
5398 /*.......................................................................
5399  * This is the action function that recalls the next line in the
5400  * history buffer who's prefix matches that specified in the earlier call
5401  * to gl_history_search_backward) which started the history search.
5402  * By setting count=-1, this can be used internally to force searching
5403  * for the prefix used in the last search.
5404  */
KT_KEY_FN(gl_history_search_forward)5405 static KT_KEY_FN(gl_history_search_forward)
5406 {
5407 /*
5408  * In vi mode, switch to command mode, since the user is very
5409  * likely to want to move around newly recalled lines.
5410  */
5411   gl_vi_command_mode(gl);
5412 /*
5413  * Record the key sequence number of this search action.
5414  */
5415   gl->last_search = gl->keyseq_count;
5416 /*
5417  * If a prefix search isn't already in progress, replace the search
5418  * prefix to the string that precedes the cursor. In vi command mode
5419  * include the character that is under the cursor in the string.  If
5420  * count<0 keep the previous search prefix regardless, so as to force
5421  * a repeat search even if the last command wasn't a history command.
5422  */
5423   if(count >= 0 && !_glh_search_active(gl->glh) &&
5424      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5425 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5426     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5427     return 1;
5428   };
5429 /*
5430  * Search forwards for the next matching line.
5431  */
5432   if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5433     return 0;
5434 /*
5435  * Accomodate the new contents of gl->line[].
5436  */
5437   gl_update_buffer(gl);
5438 /*
5439  * Arrange for the cursor to be placed at the end of the new line.
5440  */
5441   gl->buff_curpos = gl->ntotal;
5442 /*
5443  * Erase and display the new line.
5444  */
5445   gl_queue_redisplay(gl);
5446   return 0;
5447 }
5448 
5449 /*.......................................................................
5450  * This is the action function that recalls the next line in the
5451  * history buffer who's prefix matches that specified in an earlier call
5452  * to gl_history_search_backward() or gl_history_search_forward().
5453  */
KT_KEY_FN(gl_history_re_search_forward)5454 static KT_KEY_FN(gl_history_re_search_forward)
5455 {
5456   return gl_history_search_forward(gl, -1, NULL);
5457 }
5458 
5459 #ifdef HIDE_FILE_SYSTEM
5460 /*.......................................................................
5461  * The following function is used as the default completion handler when
5462  * the filesystem is to be hidden. It simply reports no completions.
5463  */
CPL_MATCH_FN(gl_no_completions)5464 static CPL_MATCH_FN(gl_no_completions)
5465 {
5466   return 0;
5467 }
5468 #endif
5469 
5470 /*.......................................................................
5471  * This is the tab completion function that completes the filename that
5472  * precedes the cursor position. Its callback data argument must be a
5473  * pointer to a GlCplCallback containing the completion callback function
5474  * and its callback data, or NULL to use the builtin filename completer.
5475  */
KT_KEY_FN(gl_complete_word)5476 static KT_KEY_FN(gl_complete_word)
5477 {
5478   CplMatches *matches;    /* The possible completions */
5479   int suffix_len;         /* The length of the completion extension */
5480   int cont_len;           /* The length of any continuation suffix */
5481   int nextra;             /* The number of characters being added to the */
5482                           /*  total length of the line. */
5483   int buff_pos;           /* The buffer index at which the completion is */
5484                           /*  to be inserted. */
5485   int waserr = 0;         /* True after errors */
5486 /*
5487  * Get the container of the completion callback and its callback data.
5488  */
5489   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
5490 /*
5491  * In vi command mode, switch to append mode so that the character under
5492  * the cursor is included in the completion (otherwise people can't
5493  * complete at the end of the line).
5494  */
5495   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5496     return 1;
5497 /*
5498  * Get the cursor position at which the completion is to be inserted.
5499  */
5500   buff_pos = gl->buff_curpos;
5501 /*
5502  * Perform the completion.
5503  */
5504   matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data,
5505 			      cb->fn);
5506 /*
5507  * No matching completions?
5508  */
5509   if(!matches) {
5510     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
5511 /*
5512  * Are there any completions?
5513  */
5514   } else if(matches->nmatch >= 1) {
5515 /*
5516  * If there any ambiguous matches, report them, starting on a new line.
5517  */
5518     if(matches->nmatch > 1 && gl->echo) {
5519       if(_gl_normal_io(gl) ||
5520 	 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
5521 	waserr = 1;
5522     };
5523 /*
5524  * Get the length of the suffix and any continuation suffix to add to it.
5525  */
5526     suffix_len = strlen(matches->suffix);
5527     cont_len = strlen(matches->cont_suffix);
5528 /*
5529  * If there is an unambiguous match, and the continuation suffix ends in
5530  * a newline, strip that newline and arrange to have getline return
5531  * after this action function returns.
5532  */
5533     if(matches->nmatch==1 && cont_len > 0 &&
5534        matches->cont_suffix[cont_len - 1] == '\n') {
5535       cont_len--;
5536       if(gl_newline(gl, 1, NULL))
5537 	waserr = 1;
5538     };
5539 /*
5540  * Work out the number of characters that are to be added.
5541  */
5542     nextra = suffix_len + cont_len;
5543 /*
5544  * Is there anything to be added?
5545  */
5546     if(!waserr && nextra) {
5547 /*
5548  * Will there be space for the expansion in the line buffer?
5549  */
5550       if(gl->ntotal + nextra < gl->linelen) {
5551 /*
5552  * Make room to insert the filename extension.
5553  */
5554 	gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5555 /*
5556  * Insert the filename extension.
5557  */
5558 	gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos);
5559 /*
5560  * Add the terminating characters.
5561  */
5562 	gl_buffer_string(gl, matches->cont_suffix, cont_len,
5563 			 gl->buff_curpos + suffix_len);
5564 /*
5565  * Place the cursor position at the end of the completion.
5566  */
5567 	gl->buff_curpos += nextra;
5568 /*
5569  * If we don't have to redisplay the whole line, redisplay the part
5570  * of the line which follows the original cursor position, and place
5571  * the cursor at the end of the completion.
5572  */
5573 	if(gl->displayed) {
5574 	  if(gl_truncate_display(gl) ||
5575 	     gl_print_string(gl, gl->line + buff_pos, '\0') ||
5576 	     gl_place_cursor(gl, gl->buff_curpos))
5577 	    waserr = 1;
5578 	};
5579       } else {
5580 	(void) gl_print_info(gl,
5581 			     "Insufficient room in line for file completion.",
5582 			     GL_END_INFO);
5583 	waserr = 1;
5584       };
5585     };
5586   };
5587 /*
5588  * If any output had to be written to the terminal, then editing will
5589  * have been suspended, make sure that we are back in raw line editing
5590  * mode before returning.
5591  */
5592   if(_gl_raw_io(gl, 1))
5593     waserr = 1;
5594   return 0;
5595 }
5596 
5597 #ifndef HIDE_FILE_SYSTEM
5598 /*.......................................................................
5599  * This is the function that expands the filename that precedes the
5600  * cursor position. It expands ~user/ expressions, $envvar expressions,
5601  * and wildcards.
5602  */
KT_KEY_FN(gl_expand_filename)5603 static KT_KEY_FN(gl_expand_filename)
5604 {
5605   char *start_path;      /* The pointer to the start of the pathname in */
5606                          /*  gl->line[]. */
5607   FileExpansion *result; /* The results of the filename expansion */
5608   int pathlen;           /* The length of the pathname being expanded */
5609   int length;            /* The number of characters needed to display the */
5610                          /*  expanded files. */
5611   int nextra;            /* The number of characters to be added */
5612   int i,j;
5613 /*
5614  * In vi command mode, switch to append mode so that the character under
5615  * the cursor is included in the completion (otherwise people can't
5616  * complete at the end of the line).
5617  */
5618   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5619     return 1;
5620 /*
5621  * Locate the start of the filename that precedes the cursor position.
5622  */
5623   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5624   if(!start_path)
5625     return 1;
5626 /*
5627  * Get the length of the string that is to be expanded.
5628  */
5629   pathlen = gl->buff_curpos - (start_path - gl->line);
5630 /*
5631  * Attempt to expand it.
5632  */
5633   result = ef_expand_file(gl->ef, start_path, pathlen);
5634 /*
5635  * If there was an error, report the error on a new line.
5636  */
5637   if(!result)
5638     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
5639 /*
5640  * If no files matched, report this as well.
5641  */
5642   if(result->nfile == 0 || !result->exists)
5643     return gl_print_info(gl, "No files match.", GL_END_INFO);
5644 /*
5645  * If in vi command mode, preserve the current line for potential use by
5646  * vi-undo.
5647  */
5648   gl_save_for_undo(gl);
5649 /*
5650  * Work out how much space we will need to display all of the matching
5651  * filenames, taking account of the space that we need to place between
5652  * them, and the number of additional '\' characters needed to escape
5653  * spaces, tabs and backslash characters in the individual filenames.
5654  */
5655   length = 0;
5656   for(i=0; i<result->nfile; i++) {
5657     char *file = result->files[i];
5658     while(*file) {
5659       int c = *file++;
5660       switch(c) {
5661       case ' ': case '\t': case '\\': case '*': case '?': case '[':
5662 	length++;  /* Count extra backslash characters */
5663       };
5664       length++;    /* Count the character itself */
5665     };
5666     length++;      /* Count the space that follows each filename */
5667   };
5668 /*
5669  * Work out the number of characters that are to be added.
5670  */
5671   nextra = length - pathlen;
5672 /*
5673  * Will there be space for the expansion in the line buffer?
5674  */
5675   if(gl->ntotal + nextra >= gl->linelen) {
5676     return gl_print_info(gl, "Insufficient room in line for file expansion.",
5677 			 GL_END_INFO);
5678   } else {
5679 /*
5680  * Do we need to move the part of the line that followed the unexpanded
5681  * filename?
5682  */
5683     if(nextra > 0) {
5684       gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5685     } else if(nextra < 0) {
5686       gl->buff_curpos += nextra;
5687       gl_remove_from_buffer(gl, gl->buff_curpos, -nextra);
5688     };
5689 /*
5690  * Insert the filenames, separated by spaces, and with internal spaces,
5691  * tabs and backslashes escaped with backslashes.
5692  */
5693     for(i=0,j=start_path - gl->line; i<result->nfile; i++) {
5694       char *file = result->files[i];
5695       while(*file) {
5696 	int c = *file++;
5697 	switch(c) {
5698 	case ' ': case '\t': case '\\': case '*': case '?': case '[':
5699 	  gl_buffer_char(gl, '\\', j++);
5700 	};
5701 	gl_buffer_char(gl, c, j++);
5702       };
5703       gl_buffer_char(gl, ' ', j++);
5704     };
5705   };
5706 /*
5707  * Redisplay the part of the line which follows the start of
5708  * the original filename.
5709  */
5710   if(gl_place_cursor(gl, start_path - gl->line) ||
5711      gl_truncate_display(gl) ||
5712      gl_print_string(gl, start_path, start_path[length]))
5713     return 1;
5714 /*
5715  * Move the cursor to the end of the expansion.
5716  */
5717   return gl_place_cursor(gl, (start_path - gl->line) + length);
5718 }
5719 #endif
5720 
5721 #ifndef HIDE_FILE_SYSTEM
5722 /*.......................................................................
5723  * This is the action function that lists glob expansions of the
5724  * filename that precedes the cursor position. It expands ~user/
5725  * expressions, $envvar expressions, and wildcards.
5726  */
KT_KEY_FN(gl_list_glob)5727 static KT_KEY_FN(gl_list_glob)
5728 {
5729   char *start_path;      /* The pointer to the start of the pathname in */
5730                          /*  gl->line[]. */
5731   FileExpansion *result; /* The results of the filename expansion */
5732   int pathlen;           /* The length of the pathname being expanded */
5733 /*
5734  * Locate the start of the filename that precedes the cursor position.
5735  */
5736   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5737   if(!start_path)
5738     return 1;
5739 /*
5740  * Get the length of the string that is to be expanded.
5741  */
5742   pathlen = gl->buff_curpos - (start_path - gl->line);
5743 /*
5744  * Attempt to expand it.
5745  */
5746   result = ef_expand_file(gl->ef, start_path, pathlen);
5747 /*
5748  * If there was an error, report it.
5749  */
5750   if(!result) {
5751     return gl_print_info(gl,  ef_last_error(gl->ef), GL_END_INFO);
5752 /*
5753  * If no files matched, report this as well.
5754  */
5755   } else if(result->nfile == 0 || !result->exists) {
5756     return gl_print_info(gl, "No files match.", GL_END_INFO);
5757 /*
5758  * List the matching expansions.
5759  */
5760   } else if(gl->echo) {
5761     if(gl_start_newline(gl, 1) ||
5762        _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn))
5763       return 1;
5764     gl_queue_redisplay(gl);
5765   };
5766   return 0;
5767 }
5768 #endif
5769 
5770 /*.......................................................................
5771  * Return non-zero if a character should be considered a part of a word.
5772  *
5773  * Input:
5774  *  c       int  The character to be tested.
5775  * Output:
5776  *  return  int  True if the character should be considered part of a word.
5777  */
gl_is_word_char(int c)5778 static int gl_is_word_char(int c)
5779 {
5780   return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL;
5781 }
5782 
5783 /*.......................................................................
5784  * Override the builtin file-completion callback that is bound to the
5785  * "complete_word" action function.
5786  *
5787  * Input:
5788  *  gl            GetLine *  The resource object of the command-line input
5789  *                           module.
5790  *  data             void *  This is passed to match_fn() whenever it is
5791  *                           called. It could, for example, point to a
5792  *                           symbol table where match_fn() could look
5793  *                           for possible completions.
5794  *  match_fn   CplMatchFn *  The function that will identify the prefix
5795  *                           to be completed from the input line, and
5796  *                           report matching symbols.
5797  * Output:
5798  *  return            int    0 - OK.
5799  *                           1 - Error.
5800  */
gl_customize_completion(GetLine * gl,void * data,CplMatchFn * match_fn)5801 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn)
5802 {
5803   sigset_t oldset; /* The signals that were blocked on entry to this function */
5804 /*
5805  * Check the arguments.
5806  */
5807   if(!gl || !match_fn) {
5808     if(gl)
5809       _err_record_msg(gl->err, "NULL argument", END_ERR_MSG);
5810     errno = EINVAL;
5811     return 1;
5812   };
5813 /*
5814  * Temporarily block all signals.
5815  */
5816   gl_mask_signals(gl, &oldset);
5817 /*
5818  * Record the new completion function and its callback data.
5819  */
5820   gl->cplfn.fn = match_fn;
5821   gl->cplfn.data = data;
5822 /*
5823  * Restore the process signal mask before returning.
5824  */
5825   gl_unmask_signals(gl, &oldset);
5826   return 0;
5827 }
5828 
5829 /*.......................................................................
5830  * Change the terminal (or stream) that getline interacts with.
5831  *
5832  * Input:
5833  *  gl            GetLine *  The resource object of the command-line input
5834  *                           module.
5835  *  input_fp         FILE *  The stdio stream to read from.
5836  *  output_fp        FILE *  The stdio stream to write to.
5837  *  term             char *  The terminal type. This can be NULL if
5838  *                           either or both of input_fp and output_fp don't
5839  *                           refer to a terminal. Otherwise it should refer
5840  *                           to an entry in the terminal information database.
5841  * Output:
5842  *  return            int    0 - OK.
5843  *                           1 - Error.
5844  */
gl_change_terminal(GetLine * gl,FILE * input_fp,FILE * output_fp,const char * term)5845 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5846 		       const char *term)
5847 {
5848   sigset_t oldset; /* The signals that were blocked on entry to this function */
5849   int status;      /* The return status of _gl_change_terminal() */
5850 /*
5851  * Check the arguments.
5852  */
5853   if(!gl) {
5854     errno = EINVAL;
5855     return 1;
5856   };
5857 /*
5858  * Block all signals.
5859  */
5860   if(gl_mask_signals(gl, &oldset))
5861     return 1;
5862 /*
5863  * Execute the private body of the function while signals are blocked.
5864  */
5865   status = _gl_change_terminal(gl, input_fp, output_fp, term);
5866 /*
5867  * Restore the process signal mask.
5868  */
5869   gl_unmask_signals(gl, &oldset);
5870   return status;
5871 }
5872 
5873 /*.......................................................................
5874  * This is the private body of the gl_change_terminal() function. It
5875  * assumes that the caller has checked its arguments and blocked the
5876  * delivery of signals.
5877  */
_gl_change_terminal(GetLine * gl,FILE * input_fp,FILE * output_fp,const char * term)5878 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5879 			       const char *term)
5880 {
5881   int is_term = 0;   /* True if both input_fd and output_fd are associated */
5882                      /*  with a terminal. */
5883 /*
5884  * Require that input_fp and output_fp both be valid.
5885  */
5886   if(!input_fp || !output_fp) {
5887     gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).",
5888 		  GL_END_INFO);
5889     return 1;
5890   };
5891 /*
5892  * Are we displacing an existing terminal (as opposed to setting the
5893  * initial terminal)?
5894  */
5895   if(gl->input_fd >= 0) {
5896 /*
5897  * Make sure to leave the previous terminal in a usable state.
5898  */
5899     if(_gl_normal_io(gl))
5900       return 1;
5901 /*
5902  * Remove the displaced terminal from the list of fds to watch.
5903  */
5904 #ifdef HAVE_SELECT
5905     FD_CLR(gl->input_fd, &gl->rfds);
5906 #endif
5907   };
5908 /*
5909  * Record the file descriptors and streams.
5910  */
5911   gl->input_fp = input_fp;
5912   gl->input_fd = fileno(input_fp);
5913   gl->output_fp = output_fp;
5914   gl->output_fd = fileno(output_fp);
5915 /*
5916  * If needed, expand the record of the maximum file-descriptor that might
5917  * need to be monitored with select().
5918  */
5919 #ifdef HAVE_SELECT
5920   if(gl->input_fd > gl->max_fd)
5921     gl->max_fd = gl->input_fd;
5922 #endif
5923 /*
5924  * Disable terminal interaction until we have enough info to interact
5925  * with the terminal.
5926  */
5927   gl->is_term = 0;
5928 /*
5929  * For terminal editing, we need both output_fd and input_fd to refer to
5930  * a terminal. While we can't verify that they both point to the same
5931  * terminal, we can verify that they point to terminals. If the user
5932  * sets the TERM environment variable to "dumb", treat a terminal as
5933  * a non-interactive I/O stream.
5934  */
5935   is_term = (isatty(gl->input_fd) && isatty(gl->output_fd)) &&
5936     !(term && strcmp(term, "dumb")==0);
5937 /*
5938  * If we are interacting with a terminal and no terminal type has been
5939  * specified, treat it as a generic ANSI terminal.
5940  */
5941   if(is_term && !term)
5942     term = "ansi";
5943 /*
5944  * Make a copy of the terminal type string.
5945  */
5946   if(term != gl->term) {
5947 /*
5948  * Delete any old terminal type string.
5949  */
5950     if(gl->term) {
5951       free(gl->term);
5952       gl->term = NULL;
5953     };
5954 /*
5955  * Make a copy of the new terminal-type string, if any.
5956  */
5957     if(term) {
5958       gl->term = (char *) malloc(strlen(term)+1);
5959       if(gl->term)
5960 	strcpy(gl->term, term);
5961     };
5962   };
5963 /*
5964  * Clear any terminal-specific key bindings that were taken from the
5965  * settings of the last terminal.
5966  */
5967   _kt_clear_bindings(gl->bindings, KTB_TERM);
5968 /*
5969  * If we have a terminal install new bindings for it.
5970  */
5971   if(is_term) {
5972 /*
5973  * Get the current settings of the terminal.
5974  */
5975     if(tcgetattr(gl->input_fd, &gl->oldattr)) {
5976       _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
5977       return 1;
5978     };
5979 /*
5980  * If we don't set this now, gl_control_strings() won't know
5981  * that it is talking to a terminal.
5982  */
5983     gl->is_term = 1;
5984 /*
5985  * Lookup the terminal control string and size information.
5986  */
5987     if(gl_control_strings(gl, term)) {
5988       gl->is_term = 0;
5989       return 1;
5990     };
5991 /*
5992  * Bind terminal-specific keys.
5993  */
5994     if(gl_bind_terminal_keys(gl))
5995       return 1;
5996   };
5997 /*
5998  * Assume that the caller has given us a terminal in a sane state.
5999  */
6000   gl->io_mode = GL_NORMAL_MODE;
6001 /*
6002  * Switch into the currently configured I/O mode.
6003  */
6004   if(_gl_io_mode(gl, gl->io_mode))
6005     return 1;
6006   return 0;
6007 }
6008 
6009 /*.......................................................................
6010  * Set up terminal-specific key bindings.
6011  *
6012  * Input:
6013  *  gl            GetLine *  The resource object of the command-line input
6014  *                           module.
6015  * Output:
6016  *  return            int    0 - OK.
6017  *                           1 - Error.
6018  */
gl_bind_terminal_keys(GetLine * gl)6019 static int gl_bind_terminal_keys(GetLine *gl)
6020 {
6021 /*
6022  * Install key-bindings for the special terminal characters.
6023  */
6024   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR],
6025 			  "user-interrupt") ||
6026      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") ||
6027      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend"))
6028     return 1;
6029 /*
6030  * In vi-mode, arrange for the above characters to be seen in command
6031  * mode.
6032  */
6033   if(gl->editor == GL_VI_MODE) {
6034     if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]),
6035 			    "user-interrupt") ||
6036        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]),
6037 			    "abort") ||
6038        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]),
6039 			    "suspend"))
6040       return 1;
6041   };
6042 /*
6043  * Non-universal special keys.
6044  */
6045 #ifdef VLNEXT
6046   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT],
6047 			  "literal-next"))
6048     return 1;
6049 #else
6050   if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) {
6051     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6052     return 1;
6053   };
6054 #endif
6055 /*
6056  * Bind action functions to the terminal-specific arrow keys
6057  * looked up by gl_control_strings().
6058  */
6059   if(_gl_bind_arrow_keys(gl))
6060     return 1;
6061   return 0;
6062 }
6063 
6064 /*.......................................................................
6065  * This function is normally bound to control-D. When it is invoked within
6066  * a line it deletes the character which follows the cursor. When invoked
6067  * at the end of the line it lists possible file completions, and when
6068  * invoked on an empty line it causes gl_get_line() to return EOF. This
6069  * function emulates the one that is normally bound to control-D by tcsh.
6070  */
KT_KEY_FN(gl_del_char_or_list_or_eof)6071 static KT_KEY_FN(gl_del_char_or_list_or_eof)
6072 {
6073 /*
6074  * If we have an empty line arrange to return EOF.
6075  */
6076   if(gl->ntotal < 1) {
6077     gl_record_status(gl, GLR_EOF, 0);
6078     return 1;
6079 /*
6080  * If we are at the end of the line list possible completions.
6081  */
6082   } else if(gl->buff_curpos >= gl->ntotal) {
6083     return gl_list_completions(gl, 1, NULL);
6084 /*
6085  * Within the line delete the character that follows the cursor.
6086  */
6087   } else {
6088 /*
6089  * If in vi command mode, first preserve the current line for potential use
6090  * by vi-undo.
6091  */
6092     gl_save_for_undo(gl);
6093 /*
6094  * Delete 'count' characters.
6095  */
6096     return gl_forward_delete_char(gl, count, NULL);
6097   };
6098 }
6099 
6100 /*.......................................................................
6101  * This function is normally bound to control-D in vi mode. When it is
6102  * invoked within a line it lists possible file completions, and when
6103  * invoked on an empty line it causes gl_get_line() to return EOF. This
6104  * function emulates the one that is normally bound to control-D by tcsh.
6105  */
KT_KEY_FN(gl_list_or_eof)6106 static KT_KEY_FN(gl_list_or_eof)
6107 {
6108 /*
6109  * If we have an empty line arrange to return EOF.
6110  */
6111   if(gl->ntotal < 1) {
6112     gl_record_status(gl, GLR_EOF, 0);
6113     return 1;
6114 /*
6115  * Otherwise list possible completions.
6116  */
6117   } else {
6118     return gl_list_completions(gl, 1, NULL);
6119   };
6120 }
6121 
6122 /*.......................................................................
6123  * List possible completions of the word that precedes the cursor. The
6124  * callback data argument must either be NULL to select the default
6125  * file completion callback, or be a GlCplCallback object containing the
6126  * completion callback function to call.
6127  */
KT_KEY_FN(gl_list_completions)6128 static KT_KEY_FN(gl_list_completions)
6129 {
6130   int waserr = 0;   /* True after errors */
6131 /*
6132  * Get the container of the completion callback and its callback data.
6133  */
6134   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
6135 /*
6136  * Get the list of possible completions.
6137  */
6138   CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos,
6139 					  cb->data, cb->fn);
6140 /*
6141  * No matching completions?
6142  */
6143   if(!matches) {
6144     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
6145 /*
6146  * List the matches.
6147  */
6148   } else if(matches->nmatch > 0 && gl->echo) {
6149     if(_gl_normal_io(gl) ||
6150        _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
6151       waserr = 1;
6152   };
6153 /*
6154  * If any output had to be written to the terminal, then editing will
6155  * have been suspended, make sure that we are back in raw line editing
6156  * mode before returning.
6157  */
6158   if(_gl_raw_io(gl, 1))
6159     waserr = 1;
6160   return waserr;
6161 }
6162 
6163 /*.......................................................................
6164  * Where the user has used the symbolic arrow-key names to specify
6165  * arrow key bindings, bind the specified action functions to the default
6166  * and terminal specific arrow key sequences.
6167  *
6168  * Input:
6169  *  gl     GetLine *   The getline resource object.
6170  * Output:
6171  *  return     int     0 - OK.
6172  *                     1 - Error.
6173  */
_gl_bind_arrow_keys(GetLine * gl)6174 static int _gl_bind_arrow_keys(GetLine *gl)
6175 {
6176 /*
6177  * Process each of the arrow keys.
6178  */
6179   if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") ||
6180      _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") ||
6181      _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") ||
6182      _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC"))
6183     return 1;
6184   return 0;
6185 }
6186 
6187 /*.......................................................................
6188  * Lookup the action function of a symbolic arrow-key binding, and bind
6189  * it to the terminal-specific and default arrow-key sequences. Note that
6190  * we don't trust the terminal-specified key sequences to be correct.
6191  * The main reason for this is that on some machines the xterm terminfo
6192  * entry is for hardware X-terminals, rather than xterm terminal emulators
6193  * and the two terminal types emit different character sequences when the
6194  * their cursor keys are pressed. As a result we also supply a couple
6195  * of default key sequences.
6196  *
6197  * Input:
6198  *  gl          GetLine *   The resource object of gl_get_line().
6199  *  name           char *   The symbolic name of the arrow key.
6200  *  term_seq       char *   The terminal-specific arrow-key sequence.
6201  *  def_seq1       char *   The first default arrow-key sequence.
6202  *  def_seq2       char *   The second arrow-key sequence.
6203  * Output:
6204  *  return          int     0 - OK.
6205  *                          1 - Error.
6206  */
_gl_rebind_arrow_key(GetLine * gl,const char * name,const char * term_seq,const char * def_seq1,const char * def_seq2)6207 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
6208 				const char *term_seq, const char *def_seq1,
6209 				const char *def_seq2)
6210 {
6211   KeySym *keysym;  /* The binding-table entry matching the arrow-key name */
6212   int nsym;        /* The number of ambiguous matches */
6213 /*
6214  * Lookup the key binding for the symbolic name of the arrow key. This
6215  * will either be the default action, or a user provided one.
6216  */
6217   if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym)
6218      == KT_EXACT_MATCH) {
6219 /*
6220  * Get the action function.
6221  */
6222     KtAction *action = keysym->actions + keysym->binder;
6223     KtKeyFn *fn = action->fn;
6224     void *data = action->data;
6225 /*
6226  * Bind this to each of the specified key sequences.
6227  */
6228     if((term_seq &&
6229 	_kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) ||
6230        (def_seq1 &&
6231 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) ||
6232        (def_seq2 &&
6233 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) {
6234       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6235       return 1;
6236     };
6237   };
6238   return 0;
6239 }
6240 
6241 /*.......................................................................
6242  * Read getline configuration information from a given file.
6243  *
6244  * Input:
6245  *  gl           GetLine *  The getline resource object.
6246  *  filename  const char *  The name of the file to read configuration
6247  *                          information from. The contents of this file
6248  *                          are as described in the gl_get_line(3) man
6249  *                          page for the default ~/.teclarc configuration
6250  *                          file.
6251  *  who         KtBinder    Who bindings are to be installed for.
6252  * Output:
6253  *  return           int    0 - OK.
6254  *                          1 - Irrecoverable error.
6255  */
_gl_read_config_file(GetLine * gl,const char * filename,KtBinder who)6256 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who)
6257 {
6258 /*
6259  * If filesystem access is to be excluded, configuration files can't
6260  * be read.
6261  */
6262 #ifdef WITHOUT_FILE_SYSTEM
6263   _err_record_msg(gl->err,
6264 		  "Can't read configuration files without filesystem access",
6265 		  END_ERR_MSG);
6266   errno = EINVAL;
6267   return 1;
6268 #else
6269   FileExpansion *expansion; /* The expansion of the filename */
6270   FILE *fp;                 /* The opened file */
6271   int waserr = 0;           /* True if an error occurred while reading */
6272   int lineno = 1;           /* The line number being processed */
6273 /*
6274  * Check the arguments.
6275  */
6276   if(!gl || !filename) {
6277     if(gl)
6278       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6279     errno = EINVAL;
6280     return 1;
6281   };
6282 /*
6283  * Expand the filename.
6284  */
6285   expansion = ef_expand_file(gl->ef, filename, -1);
6286   if(!expansion) {
6287     gl_print_info(gl, "Unable to expand ", filename, " (",
6288 		  ef_last_error(gl->ef), ").", GL_END_INFO);
6289     return 1;
6290   };
6291 /*
6292  * Attempt to open the file.
6293  */
6294   fp = fopen(expansion->files[0], "r");
6295 /*
6296  * It isn't an error for there to be no configuration file.
6297  */
6298   if(!fp)
6299     return 0;
6300 /*
6301  * Parse the contents of the file.
6302  */
6303   while(!waserr && !feof(fp))
6304     waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who,
6305 				   &lineno);
6306 /*
6307  * Bind action functions to the terminal-specific arrow keys.
6308  */
6309   if(_gl_bind_arrow_keys(gl))
6310     return 1;
6311 /*
6312  * Clean up.
6313  */
6314   (void) fclose(fp);
6315   return waserr;
6316 #endif
6317 }
6318 
6319 /*.......................................................................
6320  * Read GetLine configuration information from a string. The contents of
6321  * the string are the same as those described in the gl_get_line(3)
6322  * man page for the contents of the ~/.teclarc configuration file.
6323  */
_gl_read_config_string(GetLine * gl,const char * buffer,KtBinder who)6324 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who)
6325 {
6326   const char *bptr;         /* A pointer into buffer[] */
6327   int waserr = 0;           /* True if an error occurred while reading */
6328   int lineno = 1;           /* The line number being processed */
6329 /*
6330  * Check the arguments.
6331  */
6332   if(!gl || !buffer) {
6333     if(gl)
6334       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6335     errno = EINVAL;
6336     return 1;
6337   };
6338 /*
6339  * Get a pointer to the start of the buffer.
6340  */
6341   bptr = buffer;
6342 /*
6343  * Parse the contents of the buffer.
6344  */
6345   while(!waserr && *bptr)
6346     waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno);
6347 /*
6348  * Bind action functions to the terminal-specific arrow keys.
6349  */
6350   if(_gl_bind_arrow_keys(gl))
6351     return 1;
6352   return waserr;
6353 }
6354 
6355 /*.......................................................................
6356  * Parse the next line of a getline configuration file.
6357  *
6358  * Input:
6359  *  gl         GetLine *  The getline resource object.
6360  *  stream        void *  The pointer representing the stream to be read
6361  *                        by getc_fn().
6362  *  getc_fn  GlcGetcFn *  A callback function which when called with
6363  *                       'stream' as its argument, returns the next
6364  *                        unread character from the stream.
6365  *  origin  const char *  The name of the entity being read (eg. a
6366  *                        file name).
6367  *  who       KtBinder    Who bindings are to be installed for.
6368  * Input/Output:
6369  *  lineno         int *  The line number being processed is to be
6370  *                        maintained in *lineno.
6371  * Output:
6372  *  return         int    0 - OK.
6373  *                        1 - Irrecoverable error.
6374  */
_gl_parse_config_line(GetLine * gl,void * stream,GlcGetcFn * getc_fn,const char * origin,KtBinder who,int * lineno)6375 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
6376 				 const char *origin, KtBinder who, int *lineno)
6377 {
6378   char buffer[GL_CONF_BUFLEN+1];  /* The input line buffer */
6379   char *argv[GL_CONF_MAXARG];     /* The argument list */
6380   int argc = 0;                   /* The number of arguments in argv[] */
6381   int c;                          /* A character from the file */
6382   int escaped = 0;                /* True if the next character is escaped */
6383   int i;
6384 /*
6385  * Skip spaces and tabs.
6386  */
6387   do c = getc_fn(stream); while(c==' ' || c=='\t');
6388 /*
6389  * Comments extend to the end of the line.
6390  */
6391   if(c=='#')
6392     do c = getc_fn(stream); while(c != '\n' && c != EOF);
6393 /*
6394  * Ignore empty lines.
6395  */
6396   if(c=='\n' || c==EOF) {
6397     (*lineno)++;
6398     return 0;
6399   };
6400 /*
6401  * Record the buffer location of the start of the first argument.
6402  */
6403   argv[argc] = buffer;
6404 /*
6405  * Read the rest of the line, stopping early if a comment is seen, or
6406  * the buffer overflows, and replacing sequences of spaces with a
6407  * '\0', and recording the thus terminated string as an argument.
6408  */
6409   i = 0;
6410   while(i<GL_CONF_BUFLEN) {
6411 /*
6412  * Did we hit the end of the latest argument?
6413  */
6414     if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) {
6415 /*
6416  * Terminate the argument.
6417  */
6418       buffer[i++] = '\0';
6419       argc++;
6420 /*
6421  * Skip spaces and tabs.
6422  */
6423       while(c==' ' || c=='\t')
6424 	c = getc_fn(stream);
6425 /*
6426  * If we hit the end of the line, or the start of a comment, exit the loop.
6427  */
6428       if(c==EOF || c=='\n' || c=='#')
6429 	break;
6430 /*
6431  * Start recording the next argument.
6432  */
6433       if(argc >= GL_CONF_MAXARG) {
6434 	gl_report_config_error(gl, origin, *lineno, "Too many arguments.");
6435 	do c = getc_fn(stream); while(c!='\n' && c!=EOF);  /* Skip past eol */
6436 	return 0;
6437       };
6438       argv[argc] = buffer + i;
6439 /*
6440  * The next character was preceded by spaces, so it isn't escaped.
6441  */
6442       escaped = 0;
6443     } else {
6444 /*
6445  * If we hit an unescaped backslash, this means that we should arrange
6446  * to treat the next character like a simple alphabetical character.
6447  */
6448       if(c=='\\' && !escaped) {
6449 	escaped = 1;
6450 /*
6451  * Splice lines where the newline is escaped.
6452  */
6453       } else if(c=='\n' && escaped) {
6454 	(*lineno)++;
6455 /*
6456  * Record a normal character, preserving any preceding backslash.
6457  */
6458       } else {
6459 	if(escaped)
6460 	  buffer[i++] = '\\';
6461 	if(i>=GL_CONF_BUFLEN)
6462 	  break;
6463 	escaped = 0;
6464 	buffer[i++] = c;
6465       };
6466 /*
6467  * Get the next character.
6468  */
6469       c = getc_fn(stream);
6470     };
6471   };
6472 /*
6473  * Did the buffer overflow?
6474  */
6475   if(i>=GL_CONF_BUFLEN) {
6476     gl_report_config_error(gl, origin, *lineno, "Line too long.");
6477     return 0;
6478   };
6479 /*
6480  * The first argument should be a command name.
6481  */
6482   if(strcmp(argv[0], "bind") == 0) {
6483     const char *action = NULL; /* A NULL action removes a keybinding */
6484     const char *keyseq = NULL;
6485     switch(argc) {
6486     case 3:
6487       action = argv[2];
6488     case 2:              /* Note the intentional fallthrough */
6489       keyseq = argv[1];
6490 /*
6491  * Attempt to record the new keybinding.
6492  */
6493       if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) {
6494 	gl_report_config_error(gl, origin, *lineno,
6495 			       _kt_last_error(gl->bindings));
6496       };
6497       break;
6498     default:
6499       gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments.");
6500     };
6501   } else if(strcmp(argv[0], "edit-mode") == 0) {
6502     if(argc == 2 && strcmp(argv[1], "emacs") == 0) {
6503       gl_change_editor(gl, GL_EMACS_MODE);
6504     } else if(argc == 2 && strcmp(argv[1], "vi") == 0) {
6505       gl_change_editor(gl, GL_VI_MODE);
6506     } else if(argc == 2 && strcmp(argv[1], "none") == 0) {
6507       gl_change_editor(gl, GL_NO_EDITOR);
6508     } else {
6509       gl_report_config_error(gl, origin, *lineno,
6510 			     "The argument of editor should be vi or emacs.");
6511     };
6512   } else if(strcmp(argv[0], "nobeep") == 0) {
6513     gl->silence_bell = 1;
6514   } else {
6515     gl_report_config_error(gl, origin, *lineno, "Unknown command name.");
6516   };
6517 /*
6518  * Skip any trailing comment.
6519  */
6520   while(c != '\n' && c != EOF)
6521     c = getc_fn(stream);
6522   (*lineno)++;
6523   return 0;
6524 }
6525 
6526 /*.......................................................................
6527  * This is a private function of _gl_parse_config_line() which prints
6528  * out an error message about the contents of the line, prefixed by the
6529  * name of the origin of the line and its line number.
6530  *
6531  * Input:
6532  *  gl         GetLine *  The resource object of gl_get_line().
6533  *  origin  const char *  The name of the entity being read (eg. a
6534  *                        file name).
6535  *  lineno         int    The line number at which the error occurred.
6536  *  errmsg  const char *  The error message.
6537  * Output:
6538  *  return         int    0 - OK.
6539  *                        1 - Error.
6540  */
gl_report_config_error(GetLine * gl,const char * origin,int lineno,const char * errmsg)6541 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
6542 				  const char *errmsg)
6543 {
6544   char lnum[20];   /* A buffer in which to render a single integer */
6545 /*
6546  * Convert the line number into a string.
6547  */
6548   sprintf(lnum, "%d", lineno);
6549 /*
6550  * Have the string printed on the terminal.
6551  */
6552   return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO);
6553 }
6554 
6555 /*.......................................................................
6556  * This is the _gl_parse_config_line() callback function which reads the
6557  * next character from a configuration file.
6558  */
GLC_GETC_FN(glc_file_getc)6559 static GLC_GETC_FN(glc_file_getc)
6560 {
6561   return fgetc((FILE *) stream);
6562 }
6563 
6564 /*.......................................................................
6565  * This is the _gl_parse_config_line() callback function which reads the
6566  * next character from a buffer. Its stream argument is a pointer to a
6567  * variable which is, in turn, a pointer into the buffer being read from.
6568  */
GLC_GETC_FN(glc_buff_getc)6569 static GLC_GETC_FN(glc_buff_getc)
6570 {
6571   const char **lptr = (char const **) stream;
6572   return **lptr ? *(*lptr)++ : EOF;
6573 }
6574 
6575 #ifndef HIDE_FILE_SYSTEM
6576 /*.......................................................................
6577  * When this action is triggered, it arranges to temporarily read command
6578  * lines from the regular file whos name precedes the cursor.
6579  * The current line is first discarded.
6580  */
KT_KEY_FN(gl_read_from_file)6581 static KT_KEY_FN(gl_read_from_file)
6582 {
6583   char *start_path;       /* The pointer to the start of the pathname in */
6584                           /*  gl->line[]. */
6585   FileExpansion *result;  /* The results of the filename expansion */
6586   int pathlen;            /* The length of the pathname being expanded */
6587 /*
6588  * Locate the start of the filename that precedes the cursor position.
6589  */
6590   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
6591   if(!start_path)
6592     return 1;
6593 /*
6594  * Get the length of the pathname string.
6595  */
6596   pathlen = gl->buff_curpos - (start_path - gl->line);
6597 /*
6598  * Attempt to expand the pathname.
6599  */
6600   result = ef_expand_file(gl->ef, start_path, pathlen);
6601 /*
6602  * If there was an error, report the error on a new line.
6603  */
6604   if(!result) {
6605     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
6606 /*
6607  * If no files matched, report this as well.
6608  */
6609   } else if(result->nfile == 0 || !result->exists) {
6610     return gl_print_info(gl, "No files match.", GL_END_INFO);
6611 /*
6612  * Complain if more than one file matches.
6613  */
6614   } else if(result->nfile > 1) {
6615     return gl_print_info(gl, "More than one file matches.", GL_END_INFO);
6616 /*
6617  * Disallow input from anything but normal files. In principle we could
6618  * also support input from named pipes. Terminal files would be a problem
6619  * since we wouldn't know the terminal type, and other types of files
6620  * might cause the library to lock up.
6621  */
6622   } else if(!_pu_path_is_file(result->files[0])) {
6623     return gl_print_info(gl, "Not a normal file.", GL_END_INFO);
6624   } else {
6625 /*
6626  * Attempt to open and install the specified file for reading.
6627  */
6628     gl->file_fp = fopen(result->files[0], "r");
6629     if(!gl->file_fp) {
6630       return gl_print_info(gl, "Unable to open: ", result->files[0],
6631 			   GL_END_INFO);
6632     };
6633 /*
6634  * If needed, expand the record of the maximum file-descriptor that might
6635  * need to be monitored with select().
6636  */
6637 #ifdef HAVE_SELECT
6638     if(fileno(gl->file_fp) > gl->max_fd)
6639       gl->max_fd = fileno(gl->file_fp);
6640 #endif
6641 /*
6642  * Is non-blocking I/O needed?
6643  */
6644     if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE &&
6645        gl_nonblocking_io(gl, fileno(gl->file_fp))) {
6646       gl_revert_input(gl);
6647       return gl_print_info(gl, "Can't read file %s with non-blocking I/O",
6648 			   result->files[0]);
6649     };
6650 /*
6651  * Inform the user what is happening.
6652  */
6653     if(gl_print_info(gl, "<Taking input from ", result->files[0], ">",
6654 		     GL_END_INFO))
6655       return 1;
6656   };
6657   return 0;
6658 }
6659 #endif
6660 
6661 /*.......................................................................
6662  * Close any temporary file that is being used for input.
6663  *
6664  * Input:
6665  *  gl     GetLine *  The getline resource object.
6666  */
gl_revert_input(GetLine * gl)6667 static void gl_revert_input(GetLine *gl)
6668 {
6669   if(gl->file_fp)
6670     fclose(gl->file_fp);
6671   gl->file_fp = NULL;
6672   gl->endline = 1;
6673 }
6674 
6675 /*.......................................................................
6676  * This is the action function that recalls the oldest line in the
6677  * history buffer.
6678  */
KT_KEY_FN(gl_beginning_of_history)6679 static KT_KEY_FN(gl_beginning_of_history)
6680 {
6681 /*
6682  * In vi mode, switch to command mode, since the user is very
6683  * likely to want to move around newly recalled lines.
6684  */
6685   gl_vi_command_mode(gl);
6686 /*
6687  * Forget any previous recall session.
6688  */
6689   gl->preload_id = 0;
6690 /*
6691  * Record the key sequence number of this search action.
6692  */
6693   gl->last_search = gl->keyseq_count;
6694 /*
6695  * Recall the next oldest line in the history list.
6696  */
6697   if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6698     return 0;
6699 /*
6700  * Accomodate the new contents of gl->line[].
6701  */
6702   gl_update_buffer(gl);
6703 /*
6704  * Arrange to have the cursor placed at the end of the new line.
6705  */
6706   gl->buff_curpos = gl->ntotal;
6707 /*
6708  * Erase and display the new line.
6709  */
6710   gl_queue_redisplay(gl);
6711   return 0;
6712 }
6713 
6714 /*.......................................................................
6715  * If a history session is currently in progress, this action function
6716  * recalls the line that was being edited when the session started. If
6717  * no history session is in progress, it does nothing.
6718  */
KT_KEY_FN(gl_end_of_history)6719 static KT_KEY_FN(gl_end_of_history)
6720 {
6721 /*
6722  * In vi mode, switch to command mode, since the user is very
6723  * likely to want to move around newly recalled lines.
6724  */
6725   gl_vi_command_mode(gl);
6726 /*
6727  * Forget any previous recall session.
6728  */
6729   gl->preload_id = 0;
6730 /*
6731  * Record the key sequence number of this search action.
6732  */
6733   gl->last_search = gl->keyseq_count;
6734 /*
6735  * Recall the next oldest line in the history list.
6736  */
6737   if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6738     return 0;
6739 /*
6740  * Accomodate the new contents of gl->line[].
6741  */
6742   gl_update_buffer(gl);
6743 /*
6744  * Arrange to have the cursor placed at the end of the new line.
6745  */
6746   gl->buff_curpos = gl->ntotal;
6747 /*
6748  * Erase and display the new line.
6749  */
6750   gl_queue_redisplay(gl);
6751   return 0;
6752 }
6753 
6754 /*.......................................................................
6755  * This action function is treated specially, in that its count argument
6756  * is set to the end keystroke of the keysequence that activated it.
6757  * It accumulates a numeric argument, adding one digit on each call in
6758  * which the last keystroke was a numeric digit.
6759  */
KT_KEY_FN(gl_digit_argument)6760 static KT_KEY_FN(gl_digit_argument)
6761 {
6762 /*
6763  * Was the last keystroke a digit?
6764  */
6765   int is_digit = isdigit((int)(unsigned char) count);
6766 /*
6767  * In vi command mode, a lone '0' means goto-start-of-line.
6768  */
6769   if(gl->vi.command && gl->number < 0 && count == '0')
6770     return gl_beginning_of_line(gl, count, NULL);
6771 /*
6772  * Are we starting to accumulate a new number?
6773  */
6774   if(gl->number < 0 || !is_digit)
6775     gl->number = 0;
6776 /*
6777  * Was the last keystroke a digit?
6778  */
6779   if(is_digit) {
6780 /*
6781  * Read the numeric value of the digit, without assuming ASCII.
6782  */
6783     int n;
6784     char s[2]; s[0] = count; s[1] = '\0';
6785     n = atoi(s);
6786 /*
6787  * Append the new digit.
6788  */
6789     gl->number = gl->number * 10 + n;
6790   };
6791   return 0;
6792 }
6793 
6794 /*.......................................................................
6795  * The newline action function sets gl->endline to tell
6796  * gl_get_input_line() that the line is now complete.
6797  */
KT_KEY_FN(gl_newline)6798 static KT_KEY_FN(gl_newline)
6799 {
6800   GlhLineID id;    /* The last history line recalled while entering this line */
6801 /*
6802  * Flag the line as ended.
6803  */
6804   gl->endline = 1;
6805 /*
6806  * Record the next position in the history buffer, for potential
6807  * recall by an action function on the next call to gl_get_line().
6808  */
6809   id = _glh_line_id(gl->glh, 1);
6810   if(id)
6811     gl->preload_id = id;
6812   return 0;
6813 }
6814 
6815 /*.......................................................................
6816  * The 'repeat' action function sets gl->endline to tell
6817  * gl_get_input_line() that the line is now complete, and records the
6818  * ID of the next history line in gl->preload_id so that the next call
6819  * to gl_get_input_line() will preload the line with that history line.
6820  */
KT_KEY_FN(gl_repeat_history)6821 static KT_KEY_FN(gl_repeat_history)
6822 {
6823   gl->endline = 1;
6824   gl->preload_id = _glh_line_id(gl->glh, 1);
6825   gl->preload_history = 1;
6826   return 0;
6827 }
6828 
6829 /*.......................................................................
6830  * Flush unwritten characters to the terminal.
6831  *
6832  * Input:
6833  *  gl     GetLine *  The getline resource object.
6834  * Output:
6835  *  return     int    0 - OK.
6836  *                    1 - Either an error occured, or the output
6837  *                        blocked and non-blocking I/O is being used.
6838  *                        See gl->rtn_status for details.
6839  */
gl_flush_output(GetLine * gl)6840 static int gl_flush_output(GetLine *gl)
6841 {
6842 /*
6843  * Record the fact that we are about to write to the terminal.
6844  */
6845   gl->pending_io = GLP_WRITE;
6846 /*
6847  * Attempt to flush the output to the terminal.
6848  */
6849   errno = 0;
6850   switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) {
6851   case GLQ_FLUSH_DONE:
6852     return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL);
6853     break;
6854   case GLQ_FLUSH_AGAIN:      /* Output blocked */
6855     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
6856     return 1;
6857     break;
6858   default:                   /* Abort the line if an error occurs */
6859     gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno);
6860     return 1;
6861     break;
6862   };
6863 }
6864 
6865 /*.......................................................................
6866  * This is the callback which _glq_flush_queue() uses to write buffered
6867  * characters to the terminal.
6868  */
GL_WRITE_FN(gl_flush_terminal)6869 static GL_WRITE_FN(gl_flush_terminal)
6870 {
6871   int ndone = 0;    /* The number of characters written so far */
6872 /*
6873  * Get the line-editor resource object.
6874  */
6875   GetLine *gl = (GetLine *) data;
6876 /*
6877  * Transfer the latest array of characters to stdio.
6878  */
6879   while(ndone < n) {
6880     int nnew = write(gl->output_fd, s, n-ndone);
6881 /*
6882  * If the write was successful, add to the recorded number of bytes
6883  * that have now been written.
6884  */
6885     if(nnew > 0) {
6886       ndone += nnew;
6887 /*
6888  * If a signal interrupted the call, restart the write(), since all of
6889  * the signals that gl_get_line() has been told to watch for are
6890  * currently blocked.
6891  */
6892     } else if(errno == EINTR) {
6893       continue;
6894 /*
6895  * If we managed to write something before an I/O error occurred, or
6896  * output blocked before anything was written, report the number of
6897  * bytes that were successfully written before this happened.
6898  */
6899     } else if(ndone > 0
6900 #if defined(EAGAIN)
6901 	      || errno==EAGAIN
6902 #endif
6903 #if defined(EWOULDBLOCK)
6904 	      || errno==EWOULDBLOCK
6905 #endif
6906 	      ) {
6907       return ndone;
6908 
6909 /*
6910  * To get here, an error must have occurred before anything new could
6911  * be written.
6912  */
6913     } else {
6914       return -1;
6915     };
6916   };
6917 /*
6918  * To get here, we must have successfully written the number of
6919  * bytes that was specified.
6920  */
6921   return n;
6922 }
6923 
6924 /*.......................................................................
6925  * Change the style of editing to emulate a given editor.
6926  *
6927  * Input:
6928  *  gl       GetLine *  The getline resource object.
6929  *  editor  GlEditor    The type of editor to emulate.
6930  * Output:
6931  *  return       int    0 - OK.
6932  *                      1 - Error.
6933  */
gl_change_editor(GetLine * gl,GlEditor editor)6934 static int gl_change_editor(GetLine *gl, GlEditor editor)
6935 {
6936 /*
6937  * Install the default key-bindings of the requested editor.
6938  */
6939   switch(editor) {
6940   case GL_EMACS_MODE:
6941     _kt_clear_bindings(gl->bindings, KTB_NORM);
6942     _kt_clear_bindings(gl->bindings, KTB_TERM);
6943     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings,
6944 		   sizeof(gl_emacs_bindings)/sizeof(gl_emacs_bindings[0]));
6945     break;
6946   case GL_VI_MODE:
6947     _kt_clear_bindings(gl->bindings, KTB_NORM);
6948     _kt_clear_bindings(gl->bindings, KTB_TERM);
6949     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings,
6950 			    sizeof(gl_vi_bindings)/sizeof(gl_vi_bindings[0]));
6951     break;
6952   case GL_NO_EDITOR:
6953     break;
6954   default:
6955     _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG);
6956     errno = EINVAL;
6957     return 1;
6958   };
6959 /*
6960  * Record the new editing mode.
6961  */
6962   gl->editor = editor;
6963   gl->vi.command = 0;     /* Start in input mode */
6964   gl->insert_curpos = 0;
6965 /*
6966  * Reinstate terminal-specific bindings.
6967  */
6968   if(gl->editor != GL_NO_EDITOR && gl->input_fp)
6969     (void) gl_bind_terminal_keys(gl);
6970   return 0;
6971 }
6972 
6973 /*.......................................................................
6974  * This is an action function that switches to editing using emacs bindings
6975  */
KT_KEY_FN(gl_emacs_editing_mode)6976 static KT_KEY_FN(gl_emacs_editing_mode)
6977 {
6978   return gl_change_editor(gl, GL_EMACS_MODE);
6979 }
6980 
6981 /*.......................................................................
6982  * This is an action function that switches to editing using vi bindings
6983  */
KT_KEY_FN(gl_vi_editing_mode)6984 static KT_KEY_FN(gl_vi_editing_mode)
6985 {
6986   return gl_change_editor(gl, GL_VI_MODE);
6987 }
6988 
6989 /*.......................................................................
6990  * This is the action function that switches to insert mode.
6991  */
KT_KEY_FN(gl_vi_insert)6992 static KT_KEY_FN(gl_vi_insert)
6993 {
6994 /*
6995  * If in vi command mode, preserve the current line for potential
6996  * use by vi-undo.
6997  */
6998   gl_save_for_undo(gl);
6999 /*
7000  * Switch to vi insert mode.
7001  */
7002   gl->insert = 1;
7003   gl->vi.command = 0;
7004   gl->insert_curpos = gl->buff_curpos;
7005   return 0;
7006 }
7007 
7008 /*.......................................................................
7009  * This is an action function that switches to overwrite mode.
7010  */
KT_KEY_FN(gl_vi_overwrite)7011 static KT_KEY_FN(gl_vi_overwrite)
7012 {
7013 /*
7014  * If in vi command mode, preserve the current line for potential
7015  * use by vi-undo.
7016  */
7017   gl_save_for_undo(gl);
7018 /*
7019  * Switch to vi overwrite mode.
7020  */
7021   gl->insert = 0;
7022   gl->vi.command = 0;
7023   gl->insert_curpos = gl->buff_curpos;
7024   return 0;
7025 }
7026 
7027 /*.......................................................................
7028  * This action function toggles the case of the character under the
7029  * cursor.
7030  */
KT_KEY_FN(gl_change_case)7031 static KT_KEY_FN(gl_change_case)
7032 {
7033   int i;
7034 /*
7035  * Keep a record of the current insert mode and the cursor position.
7036  */
7037   int insert = gl->insert;
7038 /*
7039  * If in vi command mode, preserve the current line for potential
7040  * use by vi-undo.
7041  */
7042   gl_save_for_undo(gl);
7043 /*
7044  * We want to overwrite the modified word.
7045  */
7046   gl->insert = 0;
7047 /*
7048  * Toggle the case of 'count' characters.
7049  */
7050   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
7051     char *cptr = gl->line + gl->buff_curpos++;
7052 /*
7053  * Convert the character to upper case?
7054  */
7055     if(islower((int)(unsigned char) *cptr))
7056       gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
7057     else if(isupper((int)(unsigned char) *cptr))
7058       gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
7059 /*
7060  * Write the possibly modified character back. Note that for non-modified
7061  * characters we want to do this as well, so as to advance the cursor.
7062  */
7063       if(gl_print_char(gl, *cptr, cptr[1]))
7064 	return 1;
7065   };
7066 /*
7067  * Restore the insertion mode.
7068  */
7069   gl->insert = insert;
7070   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7071 }
7072 
7073 /*.......................................................................
7074  * This is the action function which implements the vi-style action which
7075  * moves the cursor to the start of the line, then switches to insert mode.
7076  */
KT_KEY_FN(gl_vi_insert_at_bol)7077 static KT_KEY_FN(gl_vi_insert_at_bol)
7078 {
7079   gl_save_for_undo(gl);
7080   return gl_beginning_of_line(gl, 0, NULL) ||
7081          gl_vi_insert(gl, 0, NULL);
7082 
7083 }
7084 
7085 /*.......................................................................
7086  * This is the action function which implements the vi-style action which
7087  * moves the cursor to the end of the line, then switches to insert mode
7088  * to allow text to be appended to the line.
7089  */
KT_KEY_FN(gl_vi_append_at_eol)7090 static KT_KEY_FN(gl_vi_append_at_eol)
7091 {
7092   gl_save_for_undo(gl);
7093   gl->vi.command = 0;	/* Allow cursor at EOL */
7094   return gl_end_of_line(gl, 0, NULL) ||
7095          gl_vi_insert(gl, 0, NULL);
7096 }
7097 
7098 /*.......................................................................
7099  * This is the action function which implements the vi-style action which
7100  * moves the cursor to right one then switches to insert mode, thus
7101  * allowing text to be appended after the next character.
7102  */
KT_KEY_FN(gl_vi_append)7103 static KT_KEY_FN(gl_vi_append)
7104 {
7105   gl_save_for_undo(gl);
7106   gl->vi.command = 0;	/* Allow cursor at EOL */
7107   return gl_cursor_right(gl, 1, NULL) ||
7108          gl_vi_insert(gl, 0, NULL);
7109 }
7110 
7111 /*.......................................................................
7112  * This action function moves the cursor to the column specified by the
7113  * numeric argument. Column indexes start at 1.
7114  */
KT_KEY_FN(gl_goto_column)7115 static KT_KEY_FN(gl_goto_column)
7116 {
7117   return gl_place_cursor(gl, count - 1);
7118 }
7119 
7120 /*.......................................................................
7121  * Starting with the character under the cursor, replace 'count'
7122  * characters with the next character that the user types.
7123  */
KT_KEY_FN(gl_vi_replace_char)7124 static KT_KEY_FN(gl_vi_replace_char)
7125 {
7126   char c;  /* The replacement character */
7127   int i;
7128 /*
7129  * Keep a record of the current insert mode.
7130  */
7131   int insert = gl->insert;
7132 /*
7133  * Get the replacement character.
7134  */
7135   if(gl->vi.repeat.active) {
7136     c = gl->vi.repeat.input_char;
7137   } else {
7138     if(gl_read_terminal(gl, 1, &c))
7139       return 1;
7140     gl->vi.repeat.input_char = c;
7141   };
7142 /*
7143  * Are there 'count' characters to be replaced?
7144  */
7145   if(gl->ntotal - gl->buff_curpos >= count) {
7146 /*
7147  * If in vi command mode, preserve the current line for potential
7148  * use by vi-undo.
7149  */
7150     gl_save_for_undo(gl);
7151 /*
7152  * Temporarily switch to overwrite mode.
7153  */
7154     gl->insert = 0;
7155 /*
7156  * Overwrite the current character plus count-1 subsequent characters
7157  * with the replacement character.
7158  */
7159     for(i=0; i<count; i++)
7160       gl_add_char_to_line(gl, c);
7161 /*
7162  * Restore the original insert/overwrite mode.
7163  */
7164     gl->insert = insert;
7165   };
7166   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7167 }
7168 
7169 /*.......................................................................
7170  * This is an action function which changes all characters between the
7171  * current cursor position and the end of the line.
7172  */
KT_KEY_FN(gl_vi_change_rest_of_line)7173 static KT_KEY_FN(gl_vi_change_rest_of_line)
7174 {
7175   gl_save_for_undo(gl);
7176   gl->vi.command = 0;	/* Allow cursor at EOL */
7177   return gl_kill_line(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7178 }
7179 
7180 /*.......................................................................
7181  * This is an action function which changes all characters between the
7182  * start of the line and the current cursor position.
7183  */
KT_KEY_FN(gl_vi_change_to_bol)7184 static KT_KEY_FN(gl_vi_change_to_bol)
7185 {
7186   return gl_backward_kill_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7187 }
7188 
7189 /*.......................................................................
7190  * This is an action function which deletes the entire contents of the
7191  * current line and switches to insert mode.
7192  */
KT_KEY_FN(gl_vi_change_line)7193 static KT_KEY_FN(gl_vi_change_line)
7194 {
7195   return gl_delete_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7196 }
7197 
7198 /*.......................................................................
7199  * Starting from the cursor position and looking towards the end of the
7200  * line, copy 'count' characters to the cut buffer.
7201  */
KT_KEY_FN(gl_forward_copy_char)7202 static KT_KEY_FN(gl_forward_copy_char)
7203 {
7204 /*
7205  * Limit the count to the number of characters available.
7206  */
7207   if(gl->buff_curpos + count >= gl->ntotal)
7208     count = gl->ntotal - gl->buff_curpos;
7209   if(count < 0)
7210     count = 0;
7211 /*
7212  * Copy the characters to the cut buffer.
7213  */
7214   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7215   gl->cutbuf[count] = '\0';
7216   return 0;
7217 }
7218 
7219 /*.......................................................................
7220  * Starting from the character before the cursor position and looking
7221  * backwards towards the start of the line, copy 'count' characters to
7222  * the cut buffer.
7223  */
KT_KEY_FN(gl_backward_copy_char)7224 static KT_KEY_FN(gl_backward_copy_char)
7225 {
7226 /*
7227  * Limit the count to the number of characters available.
7228  */
7229   if(count > gl->buff_curpos)
7230     count = gl->buff_curpos;
7231   if(count < 0)
7232     count = 0;
7233   gl_place_cursor(gl, gl->buff_curpos - count);
7234 /*
7235  * Copy the characters to the cut buffer.
7236  */
7237   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7238   gl->cutbuf[count] = '\0';
7239   return 0;
7240 }
7241 
7242 /*.......................................................................
7243  * Starting from the cursor position copy to the specified column into the
7244  * cut buffer.
7245  */
KT_KEY_FN(gl_copy_to_column)7246 static KT_KEY_FN(gl_copy_to_column)
7247 {
7248   if (--count >= gl->buff_curpos)
7249     return gl_forward_copy_char(gl, count - gl->buff_curpos, NULL);
7250   else
7251     return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL);
7252 }
7253 
7254 /*.......................................................................
7255  * Starting from the cursor position copy characters up to a matching
7256  * parenthesis into the cut buffer.
7257  */
KT_KEY_FN(gl_copy_to_parenthesis)7258 static KT_KEY_FN(gl_copy_to_parenthesis)
7259 {
7260   int curpos = gl_index_of_matching_paren(gl);
7261   if(curpos >= 0) {
7262     gl_save_for_undo(gl);
7263     if(curpos >= gl->buff_curpos)
7264       return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1, NULL);
7265     else
7266       return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
7267   };
7268   return 0;
7269 }
7270 
7271 /*.......................................................................
7272  * Starting from the cursor position copy the rest of the line into the
7273  * cut buffer.
7274  */
KT_KEY_FN(gl_copy_rest_of_line)7275 static KT_KEY_FN(gl_copy_rest_of_line)
7276 {
7277 /*
7278  * Copy the characters to the cut buffer.
7279  */
7280   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos);
7281   gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0';
7282   return 0;
7283 }
7284 
7285 /*.......................................................................
7286  * Copy from the beginning of the line to the cursor position into the
7287  * cut buffer.
7288  */
KT_KEY_FN(gl_copy_to_bol)7289 static KT_KEY_FN(gl_copy_to_bol)
7290 {
7291 /*
7292  * Copy the characters to the cut buffer.
7293  */
7294   memcpy(gl->cutbuf, gl->line, gl->buff_curpos);
7295   gl->cutbuf[gl->buff_curpos] = '\0';
7296   gl_place_cursor(gl, 0);
7297   return 0;
7298 }
7299 
7300 /*.......................................................................
7301  * Copy the entire line into the cut buffer.
7302  */
KT_KEY_FN(gl_copy_line)7303 static KT_KEY_FN(gl_copy_line)
7304 {
7305 /*
7306  * Copy the characters to the cut buffer.
7307  */
7308   memcpy(gl->cutbuf, gl->line, gl->ntotal);
7309   gl->cutbuf[gl->ntotal] = '\0';
7310   return 0;
7311 }
7312 
7313 /*.......................................................................
7314  * Search forwards for the next character that the user enters.
7315  */
KT_KEY_FN(gl_forward_find_char)7316 static KT_KEY_FN(gl_forward_find_char)
7317 {
7318   int pos = gl_find_char(gl, count, 1, 1, '\0');
7319   return pos >= 0 && gl_place_cursor(gl, pos);
7320 }
7321 
7322 /*.......................................................................
7323  * Search backwards for the next character that the user enters.
7324  */
KT_KEY_FN(gl_backward_find_char)7325 static KT_KEY_FN(gl_backward_find_char)
7326 {
7327   int pos = gl_find_char(gl, count, 0, 1, '\0');
7328   return pos >= 0 && gl_place_cursor(gl, pos);
7329 }
7330 
7331 /*.......................................................................
7332  * Search forwards for the next character that the user enters. Move up to,
7333  * but not onto, the found character.
7334  */
KT_KEY_FN(gl_forward_to_char)7335 static KT_KEY_FN(gl_forward_to_char)
7336 {
7337   int pos = gl_find_char(gl, count, 1, 0, '\0');
7338   return pos >= 0 && gl_place_cursor(gl, pos);
7339 }
7340 
7341 /*.......................................................................
7342  * Search backwards for the next character that the user enters. Move back to,
7343  * but not onto, the found character.
7344  */
KT_KEY_FN(gl_backward_to_char)7345 static KT_KEY_FN(gl_backward_to_char)
7346 {
7347   int pos = gl_find_char(gl, count, 0, 0, '\0');
7348   return pos >= 0 && gl_place_cursor(gl, pos);
7349 }
7350 
7351 /*.......................................................................
7352  * Searching in a given direction, return the index of a given (or
7353  * read) character in the input line, or the character that precedes
7354  * it in the specified search direction. Return -1 if not found.
7355  *
7356  * Input:
7357  *  gl       GetLine *  The getline resource object.
7358  *  count        int    The number of times to search.
7359  *  forward      int    True if searching forward.
7360  *  onto         int    True if the search should end on top of the
7361  *                      character, false if the search should stop
7362  *                      one character before the character in the
7363  *                      specified search direction.
7364  *  c           char    The character to be sought, or '\0' if the
7365  *                      character should be read from the user.
7366  * Output:
7367  *  return       int    The index of the character in gl->line[], or
7368  *                      -1 if not found.
7369  */
gl_find_char(GetLine * gl,int count,int forward,int onto,char c)7370 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c)
7371 {
7372   int pos;     /* The index reached in searching the input line */
7373   int i;
7374 /*
7375  * Get a character from the user?
7376  */
7377   if(!c) {
7378 /*
7379  * If we are in the process of repeating a previous change command, substitute
7380  * the last find character.
7381  */
7382     if(gl->vi.repeat.active) {
7383       c = gl->vi.find_char;
7384     } else {
7385       if(gl_read_terminal(gl, 1, &c))
7386 	return -1;
7387 /*
7388  * Record the details of the new search, for use by repeat finds.
7389  */
7390       gl->vi.find_forward = forward;
7391       gl->vi.find_onto = onto;
7392       gl->vi.find_char = c;
7393     };
7394   };
7395 /*
7396  * Which direction should we search?
7397  */
7398   if(forward) {
7399 /*
7400  * Search forwards 'count' times for the character, starting with the
7401  * character that follows the cursor.
7402  */
7403     for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) {
7404 /*
7405  * Advance past the last match (or past the current cursor position
7406  * on the first search).
7407  */
7408       pos++;
7409 /*
7410  * Search for the next instance of c.
7411  */
7412       for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++)
7413 	;
7414     };
7415 /*
7416  * If the character was found and we have been requested to return the
7417  * position of the character that precedes the desired character, then
7418  * we have gone one character too far.
7419  */
7420     if(!onto && pos<gl->ntotal)
7421       pos--;
7422   } else {
7423 /*
7424  * Search backwards 'count' times for the character, starting with the
7425  * character that precedes the cursor.
7426  */
7427     for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) {
7428 /*
7429  * Step back one from the last match (or from the current cursor
7430  * position on the first search).
7431  */
7432       pos--;
7433 /*
7434  * Search for the next instance of c.
7435  */
7436       for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--)
7437 	;
7438     };
7439 /*
7440  * If the character was found and we have been requested to return the
7441  * position of the character that precedes the desired character, then
7442  * we have gone one character too far.
7443  */
7444     if(!onto && pos>=gl->insert_curpos)
7445       pos++;
7446   };
7447 /*
7448  * If found, return the cursor position of the count'th match.
7449  * Otherwise ring the terminal bell.
7450  */
7451   if(pos >= gl->insert_curpos && pos < gl->ntotal) {
7452     return pos;
7453   } else {
7454     (void) gl_ring_bell(gl, 1, NULL);
7455     return -1;
7456   }
7457 }
7458 
7459 /*.......................................................................
7460  * Repeat the last character search in the same direction as the last
7461  * search.
7462  */
KT_KEY_FN(gl_repeat_find_char)7463 static KT_KEY_FN(gl_repeat_find_char)
7464 {
7465   int pos = gl->vi.find_char ?
7466     gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto,
7467 		 gl->vi.find_char) : -1;
7468   return pos >= 0 && gl_place_cursor(gl, pos);
7469 }
7470 
7471 /*.......................................................................
7472  * Repeat the last character search in the opposite direction as the last
7473  * search.
7474  */
KT_KEY_FN(gl_invert_refind_char)7475 static KT_KEY_FN(gl_invert_refind_char)
7476 {
7477   int pos = gl->vi.find_char ?
7478     gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto,
7479 		 gl->vi.find_char) : -1;
7480   return pos >= 0 && gl_place_cursor(gl, pos);
7481 }
7482 
7483 /*.......................................................................
7484  * Search forward from the current position of the cursor for 'count'
7485  * word endings, returning the index of the last one found, or the end of
7486  * the line if there were less than 'count' words.
7487  *
7488  * Input:
7489  *  gl       GetLine *  The getline resource object.
7490  *  n            int    The number of word boundaries to search for.
7491  * Output:
7492  *  return       int    The buffer index of the located position.
7493  */
gl_nth_word_end_forward(GetLine * gl,int n)7494 static int gl_nth_word_end_forward(GetLine *gl, int n)
7495 {
7496   int bufpos;   /* The buffer index being checked. */
7497   int i;
7498 /*
7499  * In order to guarantee forward motion to the next word ending,
7500  * we need to start from one position to the right of the cursor
7501  * position, since this may already be at the end of a word.
7502  */
7503   bufpos = gl->buff_curpos + 1;
7504 /*
7505  * If we are at the end of the line, return the index of the last
7506  * real character on the line. Note that this will be -1 if the line
7507  * is empty.
7508  */
7509   if(bufpos >= gl->ntotal)
7510     return gl->ntotal - 1;
7511 /*
7512  * Search 'n' times, unless the end of the input line is reached first.
7513  */
7514   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7515 /*
7516  * If we are not already within a word, skip to the start of the next word.
7517  */
7518     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7519 	bufpos++)
7520       ;
7521 /*
7522  * Find the end of the next word.
7523  */
7524     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7525 	bufpos++)
7526       ;
7527   };
7528 /*
7529  * We will have overshot.
7530  */
7531   return bufpos > 0 ? bufpos-1 : bufpos;
7532 }
7533 
7534 /*.......................................................................
7535  * Search forward from the current position of the cursor for 'count'
7536  * word starts, returning the index of the last one found, or the end of
7537  * the line if there were less than 'count' words.
7538  *
7539  * Input:
7540  *  gl       GetLine *  The getline resource object.
7541  *  n            int    The number of word boundaries to search for.
7542  * Output:
7543  *  return       int    The buffer index of the located position.
7544  */
gl_nth_word_start_forward(GetLine * gl,int n)7545 static int gl_nth_word_start_forward(GetLine *gl, int n)
7546 {
7547   int bufpos;   /* The buffer index being checked. */
7548   int i;
7549 /*
7550  * Get the current cursor position.
7551  */
7552   bufpos = gl->buff_curpos;
7553 /*
7554  * Search 'n' times, unless the end of the input line is reached first.
7555  */
7556   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7557 /*
7558  * Find the end of the current word.
7559  */
7560     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7561 	bufpos++)
7562       ;
7563 /*
7564  * Skip to the start of the next word.
7565  */
7566     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7567 	bufpos++)
7568       ;
7569   };
7570   return bufpos;
7571 }
7572 
7573 /*.......................................................................
7574  * Search backward from the current position of the cursor for 'count'
7575  * word starts, returning the index of the last one found, or the start
7576  * of the line if there were less than 'count' words.
7577  *
7578  * Input:
7579  *  gl       GetLine *  The getline resource object.
7580  *  n            int    The number of word boundaries to search for.
7581  * Output:
7582  *  return       int    The buffer index of the located position.
7583  */
gl_nth_word_start_backward(GetLine * gl,int n)7584 static int gl_nth_word_start_backward(GetLine *gl, int n)
7585 {
7586   int bufpos;   /* The buffer index being checked. */
7587   int i;
7588 /*
7589  * Get the current cursor position.
7590  */
7591   bufpos = gl->buff_curpos;
7592 /*
7593  * Search 'n' times, unless the beginning of the input line (or vi insertion
7594  * point) is reached first.
7595  */
7596   for(i=0; i<n && bufpos > gl->insert_curpos; i++) {
7597 /*
7598  * Starting one character back from the last search, so as not to keep
7599  * settling on the same word-start, search backwards until finding a
7600  * word character.
7601  */
7602     while(--bufpos >= gl->insert_curpos &&
7603           !gl_is_word_char((int)gl->line[bufpos]))
7604       ;
7605 /*
7606  * Find the start of the word.
7607  */
7608     while(--bufpos >= gl->insert_curpos &&
7609           gl_is_word_char((int)gl->line[bufpos]))
7610       ;
7611 /*
7612  * We will have gone one character too far.
7613  */
7614     bufpos++;
7615   };
7616   return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos;
7617 }
7618 
7619 /*.......................................................................
7620  * Copy one or more words into the cut buffer without moving the cursor
7621  * or deleting text.
7622  */
KT_KEY_FN(gl_forward_copy_word)7623 static KT_KEY_FN(gl_forward_copy_word)
7624 {
7625 /*
7626  * Find the location of the count'th start or end of a word
7627  * after the cursor, depending on whether in emacs or vi mode.
7628  */
7629   int next = gl->editor == GL_EMACS_MODE ?
7630     gl_nth_word_end_forward(gl, count) :
7631     gl_nth_word_start_forward(gl, count);
7632 /*
7633  * How many characters are to be copied into the cut buffer?
7634  */
7635   int n = next - gl->buff_curpos;
7636 /*
7637  * Copy the specified segment and terminate the string.
7638  */
7639   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7640   gl->cutbuf[n] = '\0';
7641   return 0;
7642 }
7643 
7644 /*.......................................................................
7645  * Copy one or more words preceding the cursor into the cut buffer,
7646  * without moving the cursor or deleting text.
7647  */
KT_KEY_FN(gl_backward_copy_word)7648 static KT_KEY_FN(gl_backward_copy_word)
7649 {
7650 /*
7651  * Find the location of the count'th start of word before the cursor.
7652  */
7653   int next = gl_nth_word_start_backward(gl, count);
7654 /*
7655  * How many characters are to be copied into the cut buffer?
7656  */
7657   int n = gl->buff_curpos - next;
7658   gl_place_cursor(gl, next);
7659 /*
7660  * Copy the specified segment and terminate the string.
7661  */
7662   memcpy(gl->cutbuf, gl->line + next, n);
7663   gl->cutbuf[n] = '\0';
7664   return 0;
7665 }
7666 
7667 /*.......................................................................
7668  * Copy the characters between the cursor and the count'th instance of
7669  * a specified character in the input line, into the cut buffer.
7670  *
7671  * Input:
7672  *  gl       GetLine *  The getline resource object.
7673  *  count        int    The number of times to search.
7674  *  c           char    The character to be searched for, or '\0' if
7675  *                      the character should be read from the user.
7676  *  forward      int    True if searching forward.
7677  *  onto         int    True if the search should end on top of the
7678  *                      character, false if the search should stop
7679  *                      one character before the character in the
7680  *                      specified search direction.
7681  * Output:
7682  *  return       int    0 - OK.
7683  *                      1 - Error.
7684  *
7685  */
gl_copy_find(GetLine * gl,int count,char c,int forward,int onto)7686 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto)
7687 {
7688   int n;  /* The number of characters in the cut buffer */
7689 /*
7690  * Search for the character, and abort the operation if not found.
7691  */
7692   int pos = gl_find_char(gl, count, forward, onto, c);
7693   if(pos < 0)
7694     return 0;
7695 /*
7696  * Copy the specified segment.
7697  */
7698   if(forward) {
7699     n = pos + 1 - gl->buff_curpos;
7700     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7701   } else {
7702     n = gl->buff_curpos - pos;
7703     memcpy(gl->cutbuf, gl->line + pos, n);
7704     if(gl->editor == GL_VI_MODE)
7705       gl_place_cursor(gl, pos);
7706   }
7707 /*
7708  * Terminate the copy.
7709  */
7710   gl->cutbuf[n] = '\0';
7711   return 0;
7712 }
7713 
7714 /*.......................................................................
7715  * Copy a section up to and including a specified character into the cut
7716  * buffer without moving the cursor or deleting text.
7717  */
KT_KEY_FN(gl_forward_copy_find)7718 static KT_KEY_FN(gl_forward_copy_find)
7719 {
7720   return gl_copy_find(gl, count, '\0', 1, 1);
7721 }
7722 
7723 /*.......................................................................
7724  * Copy a section back to and including a specified character into the cut
7725  * buffer without moving the cursor or deleting text.
7726  */
KT_KEY_FN(gl_backward_copy_find)7727 static KT_KEY_FN(gl_backward_copy_find)
7728 {
7729   return gl_copy_find(gl, count, '\0', 0, 1);
7730 }
7731 
7732 /*.......................................................................
7733  * Copy a section up to and not including a specified character into the cut
7734  * buffer without moving the cursor or deleting text.
7735  */
KT_KEY_FN(gl_forward_copy_to)7736 static KT_KEY_FN(gl_forward_copy_to)
7737 {
7738   return gl_copy_find(gl, count, '\0', 1, 0);
7739 }
7740 
7741 /*.......................................................................
7742  * Copy a section back to and not including a specified character into the cut
7743  * buffer without moving the cursor or deleting text.
7744  */
KT_KEY_FN(gl_backward_copy_to)7745 static KT_KEY_FN(gl_backward_copy_to)
7746 {
7747   return gl_copy_find(gl, count, '\0', 0, 0);
7748 }
7749 
7750 /*.......................................................................
7751  * Copy to a character specified in a previous search into the cut
7752  * buffer without moving the cursor or deleting text.
7753  */
KT_KEY_FN(gl_copy_refind)7754 static KT_KEY_FN(gl_copy_refind)
7755 {
7756   return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7757 		      gl->vi.find_onto);
7758 }
7759 
7760 /*.......................................................................
7761  * Copy to a character specified in a previous search, but in the opposite
7762  * direction, into the cut buffer without moving the cursor or deleting text.
7763  */
KT_KEY_FN(gl_copy_invert_refind)7764 static KT_KEY_FN(gl_copy_invert_refind)
7765 {
7766   return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7767 		      gl->vi.find_onto);
7768 }
7769 
7770 /*.......................................................................
7771  * Set the position of the cursor in the line input buffer and the
7772  * terminal.
7773  *
7774  * Input:
7775  *  gl       GetLine *  The getline resource object.
7776  *  buff_curpos  int    The new buffer cursor position.
7777  * Output:
7778  *  return       int    0 - OK.
7779  *                      1 - Error.
7780  */
gl_place_cursor(GetLine * gl,int buff_curpos)7781 static int gl_place_cursor(GetLine *gl, int buff_curpos)
7782 {
7783 /*
7784  * Don't allow the cursor position to go out of the bounds of the input
7785  * line.
7786  */
7787   if(buff_curpos >= gl->ntotal)
7788     buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal;
7789   if(buff_curpos < 0)
7790     buff_curpos = 0;
7791 /*
7792  * Record the new buffer position.
7793  */
7794   gl->buff_curpos = buff_curpos;
7795 /*
7796  * Move the terminal cursor to the corresponding character.
7797  */
7798   return gl_set_term_curpos(gl, gl->prompt_len +
7799     gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len));
7800 }
7801 
7802 /*.......................................................................
7803  * In vi command mode, this function saves the current line to the
7804  * historical buffer needed by the undo command. In emacs mode it does
7805  * nothing. In order to allow action functions to call other action
7806  * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before
7807  * invoking an action, and thereafter once any call to this function
7808  * has set it to 1, further calls are ignored.
7809  *
7810  * Input:
7811  *  gl       GetLine *  The getline resource object.
7812  */
gl_save_for_undo(GetLine * gl)7813 static void gl_save_for_undo(GetLine *gl)
7814 {
7815   if(gl->vi.command && !gl->vi.undo.saved) {
7816     strcpy(gl->vi.undo.line, gl->line);
7817     gl->vi.undo.buff_curpos = gl->buff_curpos;
7818     gl->vi.undo.ntotal = gl->ntotal;
7819     gl->vi.undo.saved = 1;
7820   };
7821   if(gl->vi.command && !gl->vi.repeat.saved &&
7822      gl->current_action.fn != gl_vi_repeat_change) {
7823     gl->vi.repeat.action = gl->current_action;
7824     gl->vi.repeat.count = gl->current_count;
7825     gl->vi.repeat.saved = 1;
7826   };
7827   return;
7828 }
7829 
7830 /*.......................................................................
7831  * In vi mode, restore the line to the way it was before the last command
7832  * mode operation, storing the current line in the buffer so that the
7833  * undo operation itself can subsequently be undone.
7834  */
KT_KEY_FN(gl_vi_undo)7835 static KT_KEY_FN(gl_vi_undo)
7836 {
7837 /*
7838  * Get pointers into the two lines.
7839  */
7840   char *undo_ptr = gl->vi.undo.line;
7841   char *line_ptr = gl->line;
7842 /*
7843  * Swap the characters of the two buffers up to the length of the shortest
7844  * line.
7845  */
7846   while(*undo_ptr && *line_ptr) {
7847     char c = *undo_ptr;
7848     *undo_ptr++ = *line_ptr;
7849     *line_ptr++ = c;
7850   };
7851 /*
7852  * Copy the rest directly.
7853  */
7854   if(gl->ntotal > gl->vi.undo.ntotal) {
7855     strcpy(undo_ptr, line_ptr);
7856     *line_ptr = '\0';
7857   } else {
7858     strcpy(line_ptr, undo_ptr);
7859     *undo_ptr = '\0';
7860   };
7861 /*
7862  * Record the length of the stored string.
7863  */
7864   gl->vi.undo.ntotal = gl->ntotal;
7865 /*
7866  * Accomodate the new contents of gl->line[].
7867  */
7868   gl_update_buffer(gl);
7869 /*
7870  * Set both cursor positions to the leftmost of the saved and current
7871  * cursor positions to emulate what vi does.
7872  */
7873   if(gl->buff_curpos < gl->vi.undo.buff_curpos)
7874     gl->vi.undo.buff_curpos = gl->buff_curpos;
7875   else
7876     gl->buff_curpos = gl->vi.undo.buff_curpos;
7877 /*
7878  * Since we have bipassed calling gl_save_for_undo(), record repeat
7879  * information inline.
7880  */
7881   gl->vi.repeat.action.fn = gl_vi_undo;
7882   gl->vi.repeat.action.data = NULL;
7883   gl->vi.repeat.count = 1;
7884 /*
7885  * Display the restored line.
7886  */
7887   gl_queue_redisplay(gl);
7888   return 0;
7889 }
7890 
7891 /*.......................................................................
7892  * Delete the following word and leave the user in vi insert mode.
7893  */
KT_KEY_FN(gl_vi_forward_change_word)7894 static KT_KEY_FN(gl_vi_forward_change_word)
7895 {
7896   gl_save_for_undo(gl);
7897   gl->vi.command = 0;	/* Allow cursor at EOL */
7898   return gl_forward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7899 }
7900 
7901 /*.......................................................................
7902  * Delete the preceding word and leave the user in vi insert mode.
7903  */
KT_KEY_FN(gl_vi_backward_change_word)7904 static KT_KEY_FN(gl_vi_backward_change_word)
7905 {
7906   return gl_backward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7907 }
7908 
7909 /*.......................................................................
7910  * Delete the following section and leave the user in vi insert mode.
7911  */
KT_KEY_FN(gl_vi_forward_change_find)7912 static KT_KEY_FN(gl_vi_forward_change_find)
7913 {
7914   return gl_delete_find(gl, count, '\0', 1, 1, 1);
7915 }
7916 
7917 /*.......................................................................
7918  * Delete the preceding section and leave the user in vi insert mode.
7919  */
KT_KEY_FN(gl_vi_backward_change_find)7920 static KT_KEY_FN(gl_vi_backward_change_find)
7921 {
7922   return gl_delete_find(gl, count, '\0', 0, 1, 1);
7923 }
7924 
7925 /*.......................................................................
7926  * Delete the following section and leave the user in vi insert mode.
7927  */
KT_KEY_FN(gl_vi_forward_change_to)7928 static KT_KEY_FN(gl_vi_forward_change_to)
7929 {
7930   return gl_delete_find(gl, count, '\0', 1, 0, 1);
7931 }
7932 
7933 /*.......................................................................
7934  * Delete the preceding section and leave the user in vi insert mode.
7935  */
KT_KEY_FN(gl_vi_backward_change_to)7936 static KT_KEY_FN(gl_vi_backward_change_to)
7937 {
7938   return gl_delete_find(gl, count, '\0', 0, 0, 1);
7939 }
7940 
7941 /*.......................................................................
7942  * Delete to a character specified by a previous search and leave the user
7943  * in vi insert mode.
7944  */
KT_KEY_FN(gl_vi_change_refind)7945 static KT_KEY_FN(gl_vi_change_refind)
7946 {
7947   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7948 			gl->vi.find_onto, 1);
7949 }
7950 
7951 /*.......................................................................
7952  * Delete to a character specified by a previous search, but in the opposite
7953  * direction, and leave the user in vi insert mode.
7954  */
KT_KEY_FN(gl_vi_change_invert_refind)7955 static KT_KEY_FN(gl_vi_change_invert_refind)
7956 {
7957   return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7958 			gl->vi.find_onto, 1);
7959 }
7960 
7961 /*.......................................................................
7962  * Delete the following character and leave the user in vi insert mode.
7963  */
KT_KEY_FN(gl_vi_forward_change_char)7964 static KT_KEY_FN(gl_vi_forward_change_char)
7965 {
7966   gl_save_for_undo(gl);
7967   gl->vi.command = 0;	/* Allow cursor at EOL */
7968   return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0, NULL);
7969 }
7970 
7971 /*.......................................................................
7972  * Delete the preceding character and leave the user in vi insert mode.
7973  */
KT_KEY_FN(gl_vi_backward_change_char)7974 static KT_KEY_FN(gl_vi_backward_change_char)
7975 {
7976   return gl_backward_delete_char(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7977 }
7978 
7979 /*.......................................................................
7980  * Starting from the cursor position change characters to the specified column.
7981  */
KT_KEY_FN(gl_vi_change_to_column)7982 static KT_KEY_FN(gl_vi_change_to_column)
7983 {
7984   if (--count >= gl->buff_curpos)
7985     return gl_vi_forward_change_char(gl, count - gl->buff_curpos, NULL);
7986   else
7987     return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL);
7988 }
7989 
7990 /*.......................................................................
7991  * Starting from the cursor position change characters to a matching
7992  * parenthesis.
7993  */
KT_KEY_FN(gl_vi_change_to_parenthesis)7994 static KT_KEY_FN(gl_vi_change_to_parenthesis)
7995 {
7996   int curpos = gl_index_of_matching_paren(gl);
7997   if(curpos >= 0) {
7998     gl_save_for_undo(gl);
7999     if(curpos >= gl->buff_curpos)
8000       return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1, NULL);
8001     else
8002       return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1,
8003 					NULL);
8004   };
8005   return 0;
8006 }
8007 
8008 /*.......................................................................
8009  * If in vi mode, switch to vi command mode.
8010  *
8011  * Input:
8012  *  gl       GetLine *  The getline resource object.
8013  */
gl_vi_command_mode(GetLine * gl)8014 static void gl_vi_command_mode(GetLine *gl)
8015 {
8016   if(gl->editor == GL_VI_MODE && !gl->vi.command) {
8017     gl->insert = 1;
8018     gl->vi.command = 1;
8019     gl->vi.repeat.input_curpos = gl->insert_curpos;
8020     gl->vi.repeat.command_curpos = gl->buff_curpos;
8021     gl->insert_curpos = 0;	 /* unrestrict left motion boundary */
8022     gl_cursor_left(gl, 1, NULL); /* Vi moves 1 left on entering command mode */
8023   };
8024 }
8025 
8026 /*.......................................................................
8027  * This is an action function which rings the terminal bell.
8028  */
KT_KEY_FN(gl_ring_bell)8029 static KT_KEY_FN(gl_ring_bell)
8030 {
8031   return gl->silence_bell ? 0 :
8032     gl_print_control_sequence(gl, 1, gl->sound_bell);
8033 }
8034 
8035 /*.......................................................................
8036  * This is the action function which implements the vi-repeat-change
8037  * action.
8038  */
KT_KEY_FN(gl_vi_repeat_change)8039 static KT_KEY_FN(gl_vi_repeat_change)
8040 {
8041   int status;   /* The return status of the repeated action function */
8042   int i;
8043 /*
8044  * Nothing to repeat?
8045  */
8046   if(!gl->vi.repeat.action.fn)
8047     return gl_ring_bell(gl, 1, NULL);
8048 /*
8049  * Provide a way for action functions to know whether they are being
8050  * called by us.
8051  */
8052   gl->vi.repeat.active = 1;
8053 /*
8054  * Re-run the recorded function.
8055  */
8056   status = gl->vi.repeat.action.fn(gl, gl->vi.repeat.count,
8057 				   gl->vi.repeat.action.data);
8058 /*
8059  * Mark the repeat as completed.
8060  */
8061   gl->vi.repeat.active = 0;
8062 /*
8063  * Is we are repeating a function that has just switched to input
8064  * mode to allow the user to type, re-enter the text that the user
8065  * previously entered.
8066  */
8067   if(status==0 && !gl->vi.command) {
8068 /*
8069  * Make sure that the current line has been saved.
8070  */
8071     gl_save_for_undo(gl);
8072 /*
8073  * Repeat a previous insertion or overwrite?
8074  */
8075     if(gl->vi.repeat.input_curpos >= 0 &&
8076        gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos &&
8077        gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) {
8078 /*
8079  * Using the current line which is saved in the undo buffer, plus
8080  * the range of characters therein, as recorded by gl_vi_command_mode(),
8081  * add the characters that the user previously entered, to the input
8082  * line.
8083  */
8084       for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) {
8085 	if(gl_add_char_to_line(gl, gl->vi.undo.line[i]))
8086 	  return 1;
8087       };
8088     };
8089 /*
8090  * Switch back to command mode, now that the insertion has been repeated.
8091  */
8092     gl_vi_command_mode(gl);
8093   };
8094   return status;
8095 }
8096 
8097 /*.......................................................................
8098  * If the cursor is currently over a parenthesis character, return the
8099  * index of its matching parenthesis. If not currently over a parenthesis
8100  * character, return the next close parenthesis character to the right of
8101  * the cursor. If the respective parenthesis character isn't found,
8102  * ring the terminal bell and return -1.
8103  *
8104  * Input:
8105  *  gl       GetLine *  The getline resource object.
8106  * Output:
8107  *  return       int    Either the index of the matching parenthesis,
8108  *                      or -1 if not found.
8109  */
gl_index_of_matching_paren(GetLine * gl)8110 static int gl_index_of_matching_paren(GetLine *gl)
8111 {
8112   int i;
8113 /*
8114  * List the recognized parentheses, and their matches.
8115  */
8116   const char *o_paren = "([{";
8117   const char *c_paren = ")]}";
8118   const char *cptr;
8119 /*
8120  * Get the character that is currently under the cursor.
8121  */
8122   char c = gl->line[gl->buff_curpos];
8123 /*
8124  * If the character under the cursor is an open parenthesis, look forward
8125  * for the matching close parenthesis.
8126  */
8127   if((cptr=strchr(o_paren, c))) {
8128     char match = c_paren[cptr - o_paren];
8129     int matches_needed = 1;
8130     for(i=gl->buff_curpos+1; i<gl->ntotal; i++) {
8131       if(gl->line[i] == c)
8132 	matches_needed++;
8133       else if(gl->line[i] == match && --matches_needed==0)
8134 	return i;
8135     };
8136 /*
8137  * If the character under the cursor is an close parenthesis, look forward
8138  * for the matching open parenthesis.
8139  */
8140   } else if((cptr=strchr(c_paren, c))) {
8141     char match = o_paren[cptr - c_paren];
8142     int matches_needed = 1;
8143     for(i=gl->buff_curpos-1; i>=0; i--) {
8144       if(gl->line[i] == c)
8145 	matches_needed++;
8146       else if(gl->line[i] == match && --matches_needed==0)
8147 	return i;
8148     };
8149 /*
8150  * If not currently over a parenthesis character, search forwards for
8151  * the first close parenthesis (this is what the vi % binding does).
8152  */
8153   } else {
8154     for(i=gl->buff_curpos+1; i<gl->ntotal; i++)
8155       if(strchr(c_paren, gl->line[i]) != NULL)
8156 	return i;
8157   };
8158 /*
8159  * Not found.
8160  */
8161   (void) gl_ring_bell(gl, 1, NULL);
8162   return -1;
8163 }
8164 
8165 /*.......................................................................
8166  * If the cursor is currently over a parenthesis character, this action
8167  * function moves the cursor to its matching parenthesis.
8168  */
KT_KEY_FN(gl_find_parenthesis)8169 static KT_KEY_FN(gl_find_parenthesis)
8170 {
8171   int curpos = gl_index_of_matching_paren(gl);
8172   if(curpos >= 0)
8173     return gl_place_cursor(gl, curpos);
8174   return 0;
8175 }
8176 
8177 /*.......................................................................
8178  * Handle the receipt of the potential start of a new key-sequence from
8179  * the user.
8180  *
8181  * Input:
8182  *  gl      GetLine *   The resource object of this library.
8183  *  first_char char     The first character of the sequence.
8184  * Output:
8185  *  return      int     0 - OK.
8186  *                      1 - Error.
8187  */
gl_interpret_char(GetLine * gl,char first_char)8188 static int gl_interpret_char(GetLine *gl, char first_char)
8189 {
8190   char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */
8191   int nkey=0;                /* The number of characters in the key sequence */
8192   int count;                 /* The repeat count of an action function */
8193   int ret;                   /* The return value of an action function */
8194   int i;
8195 /*
8196  * Get the first character.
8197  */
8198   char c = first_char;
8199 /*
8200  * If editing is disabled, just add newly entered characters to the
8201  * input line buffer, and watch for the end of the line.
8202  */
8203   if(gl->editor == GL_NO_EDITOR) {
8204     gl_discard_chars(gl, 1);
8205     if(gl->ntotal >= gl->linelen)
8206       return 0;
8207     if(c == '\n' || c == '\r')
8208       return gl_newline(gl, 1, NULL);
8209     gl_buffer_char(gl, c, gl->ntotal);
8210     return 0;
8211   };
8212 /*
8213  * If the user is in the process of specifying a repeat count and the
8214  * new character is a digit, increment the repeat count accordingly.
8215  */
8216   if(gl->number >= 0 && isdigit((int)(unsigned char) c)) {
8217     gl_discard_chars(gl, 1);
8218     return gl_digit_argument(gl, c, NULL);
8219 /*
8220  * In vi command mode, all key-sequences entered need to be
8221  * either implicitly or explicitly prefixed with an escape character.
8222  */
8223   } else if(gl->vi.command && c != GL_ESC_CHAR) {
8224     keyseq[nkey++] = GL_ESC_CHAR;
8225 /*
8226  * If the first character of the sequence is a printable character,
8227  * then to avoid confusion with the special "up", "down", "left"
8228  * or "right" cursor key bindings, we need to prefix the
8229  * printable character with a backslash escape before looking it up.
8230  */
8231   } else if(!IS_META_CHAR(c) && !IS_CTRL_CHAR(c)) {
8232     keyseq[nkey++] = '\\';
8233   };
8234 /*
8235  * Compose a potentially multiple key-sequence in gl->keyseq.
8236  */
8237   while(nkey < GL_KEY_MAX) {
8238     KtAction *action; /* An action function */
8239     KeySym *keysym;   /* The symbol-table entry of a key-sequence */
8240     int nsym;         /* The number of ambiguously matching key-sequences */
8241 /*
8242  * If the character is an unprintable meta character, split it
8243  * into two characters, an escape character and the character
8244  * that was modified by the meta key.
8245  */
8246     if(IS_META_CHAR(c)) {
8247       keyseq[nkey++] = GL_ESC_CHAR;
8248       c = META_TO_CHAR(c);
8249       continue;
8250     };
8251 /*
8252  * Append the latest character to the key sequence.
8253  */
8254     keyseq[nkey++] = c;
8255 /*
8256  * When doing vi-style editing, an escape at the beginning of any binding
8257  * switches to command mode.
8258  */
8259     if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command)
8260       gl_vi_command_mode(gl);
8261 /*
8262  * Lookup the key sequence.
8263  */
8264     switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &keysym, &nsym)) {
8265     case KT_EXACT_MATCH:
8266 /*
8267  * Get the matching action function.
8268  */
8269       action = keysym->actions + keysym->binder;
8270 /*
8271  * Get the repeat count, passing the last keystroke if executing the
8272  * digit-argument action.
8273  */
8274       if(action->fn == gl_digit_argument) {
8275 	count = c;
8276       } else {
8277 	count = gl->number >= 0 ? gl->number : 1;
8278       };
8279 /*
8280  * Record the function that is being invoked.
8281  */
8282       gl->current_action = *action;
8283       gl->current_count = count;
8284 /*
8285  * Mark the current line as not yet preserved for use by the vi undo command.
8286  */
8287       gl->vi.undo.saved = 0;
8288       gl->vi.repeat.saved = 0;
8289 /*
8290  * Execute the action function. Note the action function can tell
8291  * whether the provided repeat count was defaulted or specified
8292  * explicitly by looking at whether gl->number is -1 or not. If
8293  * it is negative, then no repeat count was specified by the user.
8294  */
8295       ret = action->fn(gl, count, action->data);
8296 /*
8297  * In server mode, the action will return immediately if it tries to
8298  * read input from the terminal, and no input is currently available.
8299  * If this happens, abort. Note that gl_get_input_line() will rewind
8300  * the read-ahead buffer to allow the next call to redo the function
8301  * from scratch.
8302  */
8303       if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ)
8304 	return 1;
8305 /*
8306  * Discard the now processed characters from the key sequence buffer.
8307  */
8308       gl_discard_chars(gl, gl->nread);
8309 /*
8310  * If the latest action function wasn't a history action, cancel any
8311  * current history search.
8312  */
8313       if(gl->last_search != gl->keyseq_count)
8314 	_glh_cancel_search(gl->glh);
8315 /*
8316  * Reset the repeat count after running action functions.
8317  */
8318       if(action->fn != gl_digit_argument)
8319 	gl->number = -1;
8320       return ret ? 1 : 0;
8321       break;
8322     case KT_AMBIG_MATCH:    /* Ambiguous match - so read the next character */
8323       if(gl_read_terminal(gl, 1, &c))
8324 	return 1;
8325       break;
8326     case KT_NO_MATCH:
8327 /*
8328  * If the first character looked like it might be a prefix of a key-sequence
8329  * but it turned out not to be, ring the bell to tell the user that it
8330  * wasn't recognised.
8331  */
8332       if(keyseq[0] != '\\' && keyseq[0] != '\t') {
8333 	gl_ring_bell(gl, 1, NULL);
8334       } else {
8335 /*
8336  * The user typed a single printable character that doesn't match
8337  * the start of any keysequence, so add it to the line in accordance
8338  * with the current repeat count.
8339  */
8340 	count = gl->number >= 0 ? gl->number : 1;
8341 	for(i=0; i<count; i++)
8342 	  gl_add_char_to_line(gl, first_char);
8343 	gl->number = -1;
8344       };
8345       gl_discard_chars(gl, 1);
8346       _glh_cancel_search(gl->glh);
8347       return 0;
8348       break;
8349     case KT_BAD_MATCH:
8350       gl_ring_bell(gl, 1, NULL);
8351       gl_discard_chars(gl, gl->nread);
8352       _glh_cancel_search(gl->glh);
8353       return 1;
8354       break;
8355     };
8356   };
8357 /*
8358  * If the key sequence was too long to match, ring the bell, then
8359  * discard the first character, so that the next attempt to match a
8360  * key-sequence continues with the next key press. In practice this
8361  * shouldn't happen, since one isn't allowed to bind action functions
8362  * to keysequences that are longer than GL_KEY_MAX.
8363  */
8364   gl_ring_bell(gl, 1, NULL);
8365   gl_discard_chars(gl, 1);
8366   return 0;
8367 }
8368 
8369 /*.......................................................................
8370  * Configure the application and/or user-specific behavior of
8371  * gl_get_line().
8372  *
8373  * Note that calling this function between calling new_GetLine() and
8374  * the first call to gl_get_line(), disables the otherwise automatic
8375  * reading of ~/.teclarc on the first call to gl_get_line().
8376  *
8377  * Input:
8378  *  gl             GetLine *  The resource object of this library.
8379  *  app_string  const char *  Either NULL, or a string containing one
8380  *                            or more .teclarc command lines, separated
8381  *                            by newline characters. This can be used to
8382  *                            establish an application-specific
8383  *                            configuration, without the need for an external
8384  *                            file. This is particularly useful in embedded
8385  *                            environments where there is no filesystem.
8386  *  app_file    const char *  Either NULL, or the pathname of an
8387  *                            application-specific .teclarc file. The
8388  *                            contents of this file, if provided, are
8389  *                            read after the contents of app_string[].
8390  *  user_file   const char *  Either NULL, or the pathname of a
8391  *                            user-specific .teclarc file. Except in
8392  *                            embedded applications, this should
8393  *                            usually be "~/.teclarc".
8394  * Output:
8395  *  return             int    0 - OK.
8396  *                            1 - Bad argument(s).
8397  */
gl_configure_getline(GetLine * gl,const char * app_string,const char * app_file,const char * user_file)8398 int gl_configure_getline(GetLine *gl, const char *app_string,
8399 			 const char *app_file, const char *user_file)
8400 {
8401   sigset_t oldset; /* The signals that were blocked on entry to this function */
8402   int status;      /* The return status of _gl_configure_getline() */
8403 /*
8404  * Check the arguments.
8405  */
8406   if(!gl) {
8407     errno = EINVAL;
8408     return 1;
8409   };
8410 /*
8411  * Block all signals.
8412  */
8413   if(gl_mask_signals(gl, &oldset))
8414     return 1;
8415 /*
8416  * Execute the private body of the function while signals are blocked.
8417  */
8418   status = _gl_configure_getline(gl, app_string, app_file, user_file);
8419 /*
8420  * Restore the process signal mask.
8421  */
8422   gl_unmask_signals(gl, &oldset);
8423   return status;
8424 }
8425 
8426 /*.......................................................................
8427  * This is the private body of the gl_configure_getline() function. It
8428  * assumes that the caller has checked its arguments and blocked the
8429  * delivery of signals.
8430  */
_gl_configure_getline(GetLine * gl,const char * app_string,const char * app_file,const char * user_file)8431 static int _gl_configure_getline(GetLine *gl, const char *app_string,
8432 				 const char *app_file, const char *user_file)
8433 {
8434 /*
8435  * Mark getline as having been explicitly configured.
8436  */
8437   gl->configured = 1;
8438 /*
8439  * Start by parsing the configuration string, if provided.
8440  */
8441   if(app_string)
8442     (void) _gl_read_config_string(gl, app_string, KTB_NORM);
8443 /*
8444  * Now parse the application-specific configuration file, if provided.
8445  */
8446   if(app_file)
8447     (void) _gl_read_config_file(gl, app_file, KTB_NORM);
8448 /*
8449  * Finally, parse the user-specific configuration file, if provided.
8450  */
8451   if(user_file)
8452     (void) _gl_read_config_file(gl, user_file, KTB_USER);
8453 /*
8454  * Record the names of the configuration files to allow them to
8455  * be re-read if requested at a later time.
8456  */
8457   if(gl_record_string(&gl->app_file, app_file) ||
8458      gl_record_string(&gl->user_file, user_file)) {
8459     errno = ENOMEM;
8460     _err_record_msg(gl->err,
8461 	   "Insufficient memory to record tecla configuration file names",
8462 	   END_ERR_MSG);
8463     return 1;
8464   };
8465   return 0;
8466 }
8467 
8468 /*.......................................................................
8469  * Replace a malloc'd string (or NULL), with another malloc'd copy of
8470  * a string (or NULL).
8471  *
8472  * Input:
8473  *  sptr          char **  On input if *sptr!=NULL, *sptr will be
8474  *                         free'd and *sptr will be set to NULL. Then,
8475  *                         on output, if string!=NULL a malloc'd copy
8476  *                         of this string will be assigned to *sptr.
8477  *  string  const char *   The string to be copied, or NULL to simply
8478  *                         discard any existing string.
8479  * Output:
8480  *  return         int     0 - OK.
8481  *                         1 - Malloc failure (no error message is generated).
8482  */
gl_record_string(char ** sptr,const char * string)8483 static int gl_record_string(char **sptr, const char *string)
8484 {
8485 /*
8486  * If the original string is the same string, don't do anything.
8487  */
8488   if(*sptr == string || (*sptr && string && strcmp(*sptr, string)==0))
8489     return 0;
8490 /*
8491  * Discard any existing cached string.
8492  */
8493   if(*sptr) {
8494     free(*sptr);
8495     *sptr = NULL;
8496   };
8497 /*
8498  * Allocate memory for a copy of the specified string.
8499  */
8500   if(string) {
8501     *sptr = (char *) malloc(strlen(string) + 1);
8502     if(!*sptr)
8503       return 1;
8504 /*
8505  * Copy the string.
8506  */
8507     strcpy(*sptr, string);
8508   };
8509   return 0;
8510 }
8511 
8512 #ifndef HIDE_FILE_SYSTEM
8513 /*.......................................................................
8514  * Re-read any application-specific and user-specific files previously
8515  * specified via the gl_configure_getline() function.
8516  */
KT_KEY_FN(gl_read_init_files)8517 static KT_KEY_FN(gl_read_init_files)
8518 {
8519   return _gl_configure_getline(gl, NULL, gl->app_file, gl->user_file);
8520 }
8521 #endif
8522 
8523 /*.......................................................................
8524  * Save the contents of the history buffer to a given new file.
8525  *
8526  * Input:
8527  *  gl             GetLine *  The resource object of this library.
8528  *  filename    const char *  The name of the new file to write to.
8529  *  comment     const char *  Extra information such as timestamps will
8530  *                            be recorded on a line started with this
8531  *                            string, the idea being that the file can
8532  *                            double as a command file. Specify "" if
8533  *                            you don't care.
8534  *  max_lines          int    The maximum number of lines to save, or -1
8535  *                            to save all of the lines in the history
8536  *                            list.
8537  * Output:
8538  *  return             int     0 - OK.
8539  *                             1 - Error.
8540  */
gl_save_history(GetLine * gl,const char * filename,const char * comment,int max_lines)8541 int gl_save_history(GetLine *gl, const char *filename, const char *comment,
8542 		    int max_lines)
8543 {
8544   sigset_t oldset; /* The signals that were blocked on entry to this function */
8545   int status;      /* The return status of _gl_save_history() */
8546 /*
8547  * Check the arguments.
8548  */
8549   if(!gl || !filename || !comment) {
8550     if(gl)
8551       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8552     errno = EINVAL;
8553     return 1;
8554   };
8555 /*
8556  * Block all signals.
8557  */
8558   if(gl_mask_signals(gl, &oldset))
8559     return 1;
8560 /*
8561  * Execute the private body of the function while signals are blocked.
8562  */
8563   status = _gl_save_history(gl, filename, comment, max_lines);
8564 /*
8565  * Restore the process signal mask.
8566  */
8567   gl_unmask_signals(gl, &oldset);
8568   return status;
8569 }
8570 
8571 /*.......................................................................
8572  * This is the private body of the gl_save_history() function. It
8573  * assumes that the caller has checked its arguments and blocked the
8574  * delivery of signals.
8575  */
_gl_save_history(GetLine * gl,const char * filename,const char * comment,int max_lines)8576 static int _gl_save_history(GetLine *gl, const char *filename,
8577 			    const char *comment, int max_lines)
8578 {
8579 /*
8580  * If filesystem access is to be excluded, then history files can't
8581  * be written.
8582  */
8583 #ifdef WITHOUT_FILE_SYSTEM
8584   _err_record_msg(gl->err, "Can't save history without filesystem access",
8585 		  END_ERR_MSG);
8586   errno = EINVAL;
8587   return 1;
8588 #else
8589   FileExpansion *expansion; /* The expansion of the filename */
8590 /*
8591  * Expand the filename.
8592  */
8593   expansion = ef_expand_file(gl->ef, filename, -1);
8594   if(!expansion) {
8595     gl_print_info(gl, "Unable to expand ", filename, " (",
8596 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8597     return 1;
8598   };
8599 /*
8600  * Attempt to save to the specified file.
8601  */
8602   if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) {
8603     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8604     return 1;
8605   };
8606   return 0;
8607 #endif
8608 }
8609 
8610 /*.......................................................................
8611  * Restore the contents of the history buffer from a given new file.
8612  *
8613  * Input:
8614  *  gl             GetLine *  The resource object of this library.
8615  *  filename    const char *  The name of the new file to write to.
8616  *  comment     const char *  This must be the same string that was
8617  *                            passed to gl_save_history() when the file
8618  *                            was written.
8619  * Output:
8620  *  return             int     0 - OK.
8621  *                             1 - Error.
8622  */
gl_load_history(GetLine * gl,const char * filename,const char * comment)8623 int gl_load_history(GetLine *gl, const char *filename, const char *comment)
8624 {
8625   sigset_t oldset; /* The signals that were blocked on entry to this function */
8626   int status;      /* The return status of _gl_load_history() */
8627 /*
8628  * Check the arguments.
8629  */
8630   if(!gl || !filename || !comment) {
8631     if(gl)
8632       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8633     errno = EINVAL;
8634     return 1;
8635   };
8636 /*
8637  * Block all signals.
8638  */
8639   if(gl_mask_signals(gl, &oldset))
8640     return 1;
8641 /*
8642  * Execute the private body of the function while signals are blocked.
8643  */
8644   status = _gl_load_history(gl, filename, comment);
8645 /*
8646  * Restore the process signal mask.
8647  */
8648   gl_unmask_signals(gl, &oldset);
8649   return status;
8650 }
8651 
8652 /*.......................................................................
8653  * This is the private body of the gl_load_history() function. It
8654  * assumes that the caller has checked its arguments and blocked the
8655  * delivery of signals.
8656  */
_gl_load_history(GetLine * gl,const char * filename,const char * comment)8657 static int _gl_load_history(GetLine *gl, const char *filename,
8658 			    const char *comment)
8659 {
8660 /*
8661  * If filesystem access is to be excluded, then history files can't
8662  * be read.
8663  */
8664 #ifdef WITHOUT_FILE_SYSTEM
8665   _err_record_msg(gl->err, "Can't load history without filesystem access",
8666 		  END_ERR_MSG);
8667   errno = EINVAL;
8668   return 1;
8669 #else
8670   FileExpansion *expansion; /* The expansion of the filename */
8671 /*
8672  * Expand the filename.
8673  */
8674   expansion = ef_expand_file(gl->ef, filename, -1);
8675   if(!expansion) {
8676     gl_print_info(gl, "Unable to expand ", filename, " (",
8677 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8678     return 1;
8679   };
8680 /*
8681  * Attempt to load from the specified file.
8682  */
8683   if(_glh_load_history(gl->glh, expansion->files[0], comment,
8684 		       gl->cutbuf, gl->linelen+1)) {
8685     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8686     gl->cutbuf[0] = '\0';
8687     return 1;
8688   };
8689   gl->cutbuf[0] = '\0';
8690   return 0;
8691 #endif
8692 }
8693 
8694 /*.......................................................................
8695  * Where possible, register a function and associated data to be called
8696  * whenever a specified event is seen on a file descriptor.
8697  *
8698  * Input:
8699  *  gl            GetLine *  The resource object of the command-line input
8700  *                           module.
8701  *  fd                int    The file descriptor to watch.
8702  *  event       GlFdEvent    The type of activity to watch for.
8703  *  callback  GlFdEventFn *  The function to call when the specified
8704  *                           event occurs. Setting this to 0 removes
8705  *                           any existing callback.
8706  *  data             void *  A pointer to arbitrary data to pass to the
8707  *                           callback function.
8708  * Output:
8709  *  return            int    0 - OK.
8710  *                           1 - Either gl==NULL, or this facility isn't
8711  *                               available on the the host system
8712  *                               (ie. select() isn't available). No
8713  *                               error message is generated in the latter
8714  *                               case.
8715  */
gl_watch_fd(GetLine * gl,int fd,GlFdEvent event,GlFdEventFn * callback,void * data)8716 int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8717 		GlFdEventFn *callback, void *data)
8718 {
8719   sigset_t oldset; /* The signals that were blocked on entry to this function */
8720   int status;      /* The return status of _gl_watch_fd() */
8721 /*
8722  * Check the arguments.
8723  */
8724   if(!gl) {
8725     errno = EINVAL;
8726     return 1;
8727   };
8728   if(fd < 0) {
8729     _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG);
8730     errno = EINVAL;
8731     return 1;
8732   };
8733 /*
8734  * Block all signals.
8735  */
8736   if(gl_mask_signals(gl, &oldset))
8737     return 1;
8738 /*
8739  * Execute the private body of the function while signals are blocked.
8740  */
8741   status = _gl_watch_fd(gl, fd, event, callback, data);
8742 /*
8743  * Restore the process signal mask.
8744  */
8745   gl_unmask_signals(gl, &oldset);
8746   return status;
8747 }
8748 
8749 /*.......................................................................
8750  * This is the private body of the gl_watch_fd() function. It
8751  * assumes that the caller has checked its arguments and blocked the
8752  * delivery of signals.
8753  */
_gl_watch_fd(GetLine * gl,int fd,GlFdEvent event,GlFdEventFn * callback,void * data)8754 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8755 			GlFdEventFn *callback, void *data)
8756 #if !defined(HAVE_SELECT)
8757 {return 1;}               /* The facility isn't supported on this system */
8758 #else
8759 {
8760   GlFdNode *prev;  /* The node that precedes 'node' in gl->fd_nodes */
8761   GlFdNode *node;  /* The file-descriptor node being checked */
8762 /*
8763  * Search the list of already registered fd activity nodes for the specified
8764  * file descriptor.
8765  */
8766   for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd;
8767       prev=node, node=node->next)
8768     ;
8769 /*
8770  * Hasn't a node been allocated for this fd yet?
8771  */
8772   if(!node) {
8773 /*
8774  * If there is no callback to record, just ignore the call.
8775  */
8776     if(!callback)
8777       return 0;
8778 /*
8779  * Allocate the new node.
8780  */
8781     node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem);
8782     if(!node) {
8783       errno = ENOMEM;
8784       _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG);
8785       return 1;
8786     };
8787 /*
8788  * Prepend the node to the list.
8789  */
8790     node->next = gl->fd_nodes;
8791     gl->fd_nodes = node;
8792 /*
8793  * Initialize the node.
8794  */
8795     node->fd = fd;
8796     node->rd.fn = 0;
8797     node->rd.data = NULL;
8798     node->ur = node->wr = node->rd;
8799   };
8800 /*
8801  * Record the new callback.
8802  */
8803   switch(event) {
8804   case GLFD_READ:
8805     node->rd.fn = callback;
8806     node->rd.data = data;
8807     if(callback)
8808       FD_SET(fd, &gl->rfds);
8809     else
8810       FD_CLR(fd, &gl->rfds);
8811     break;
8812   case GLFD_WRITE:
8813     node->wr.fn = callback;
8814     node->wr.data = data;
8815     if(callback)
8816       FD_SET(fd, &gl->wfds);
8817     else
8818       FD_CLR(fd, &gl->wfds);
8819     break;
8820   case GLFD_URGENT:
8821     node->ur.fn = callback;
8822     node->ur.data = data;
8823     if(callback)
8824       FD_SET(fd, &gl->ufds);
8825     else
8826       FD_CLR(fd, &gl->ufds);
8827     break;
8828   };
8829 /*
8830  * Keep a record of the largest file descriptor being watched.
8831  */
8832   if(fd > gl->max_fd)
8833     gl->max_fd = fd;
8834 /*
8835  * If we are deleting an existing callback, also delete the parent
8836  * activity node if no callbacks are registered to the fd anymore.
8837  */
8838   if(!callback) {
8839     if(!node->rd.fn && !node->wr.fn && !node->ur.fn) {
8840       if(prev)
8841 	prev->next = node->next;
8842       else
8843 	gl->fd_nodes = node->next;
8844       node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node);
8845     };
8846   };
8847   return 0;
8848 }
8849 #endif
8850 
8851 /*.......................................................................
8852  * On systems with the select() system call, the gl_inactivity_timeout()
8853  * function provides the option of setting (or cancelling) an
8854  * inactivity timeout. Inactivity, in this case, refers both to
8855  * terminal input received from the user, and to I/O on any file
8856  * descriptors registered by calls to gl_watch_fd(). If at any time,
8857  * no activity is seen for the requested time period, the specified
8858  * timeout callback function is called. On returning, this callback
8859  * returns a code which tells gl_get_line() what to do next. Note that
8860  * each call to gl_inactivity_timeout() replaces any previously installed
8861  * timeout callback, and that specifying a callback of 0, turns off
8862  * inactivity timing.
8863  *
8864  * Beware that although the timeout argument includes a nano-second
8865  * component, few computer clocks presently have resolutions finer
8866  * than a few milliseconds, so asking for less than a few milliseconds
8867  * is equivalent to zero on a lot of systems.
8868  *
8869  * Input:
8870  *  gl            GetLine *  The resource object of the command-line input
8871  *                           module.
8872  *  callback  GlTimeoutFn *  The function to call when the inactivity
8873  *                           timeout is exceeded. To turn off
8874  *                           inactivity timeouts altogether, send 0.
8875  *  data             void *  A pointer to arbitrary data to pass to the
8876  *                           callback function.
8877  *  sec     unsigned long    The number of whole seconds in the timeout.
8878  *  nsec    unsigned long    The fractional number of seconds in the
8879  *                           timeout, expressed in nano-seconds (see
8880  *                           the caveat above).
8881  * Output:
8882  *  return            int    0 - OK.
8883  *                           1 - Either gl==NULL, or this facility isn't
8884  *                               available on the the host system
8885  *                               (ie. select() isn't available). No
8886  *                               error message is generated in the latter
8887  *                               case.
8888  */
gl_inactivity_timeout(GetLine * gl,GlTimeoutFn * timeout_fn,void * data,unsigned long sec,unsigned long nsec)8889 int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data,
8890 		   unsigned long sec, unsigned long nsec)
8891 #if !defined(HAVE_SELECT)
8892 {return 1;}               /* The facility isn't supported on this system */
8893 #else
8894 {
8895   sigset_t oldset; /* The signals that were blocked on entry to this function */
8896 /*
8897  * Check the arguments.
8898  */
8899   if(!gl) {
8900     errno = EINVAL;
8901     return 1;
8902   };
8903 /*
8904  * Block all signals.
8905  */
8906   if(gl_mask_signals(gl, &oldset))
8907     return 1;
8908 /*
8909  * Install a new timeout?
8910  */
8911   if(timeout_fn) {
8912     gl->timer.dt.tv_sec = sec;
8913     gl->timer.dt.tv_usec = nsec / 1000;
8914     gl->timer.fn = timeout_fn;
8915     gl->timer.data = data;
8916   } else {
8917     gl->timer.fn = 0;
8918     gl->timer.data = NULL;
8919   };
8920 /*
8921  * Restore the process signal mask.
8922  */
8923   gl_unmask_signals(gl, &oldset);
8924   return 0;
8925 }
8926 #endif
8927 
8928 /*.......................................................................
8929  * When select() is available, this is a private function of
8930  * gl_read_input() which responds to file-descriptor events registered by
8931  * the caller. Note that it assumes that it is being called from within
8932  * gl_read_input()'s sigsetjump() clause.
8933  *
8934  * Input:
8935  *  gl    GetLine *  The resource object of this module.
8936  *  fd        int    The file descriptor to be watched for user input.
8937  * Output:
8938  *  return    int    0 - OK.
8939  *                   1 - An error occurred.
8940  */
gl_event_handler(GetLine * gl,int fd)8941 static int gl_event_handler(GetLine *gl, int fd)
8942 #if !defined(HAVE_SELECT)
8943 {return 0;}
8944 #else
8945 {
8946 /*
8947  * Set up a zero-second timeout.
8948  */
8949   struct timeval zero;
8950   zero.tv_sec = zero.tv_usec = 0;
8951 /*
8952  * If at any time no external callbacks remain, quit the loop return,
8953  * so that we can simply wait in read(). This is designed as an
8954  * optimization for when no callbacks have been registered on entry to
8955  * this function, but since callbacks can delete themselves, it can
8956  * also help later.
8957  */
8958   while(gl->fd_nodes || gl->timer.fn) {
8959     int nready;   /* The number of file descriptors that are ready for I/O */
8960 /*
8961  * Get the set of descriptors to be watched.
8962  */
8963     fd_set rfds = gl->rfds;
8964     fd_set wfds = gl->wfds;
8965     fd_set ufds = gl->ufds;
8966 /*
8967  * Get the appropriate timeout.
8968  */
8969     struct timeval dt = gl->timer.fn ? gl->timer.dt : zero;
8970 /*
8971  * Add the specified user-input file descriptor tot he set that is to
8972  * be watched.
8973  */
8974     FD_SET(fd, &rfds);
8975 /*
8976  * Unblock the signals that we are watching, while select is blocked
8977  * waiting for I/O.
8978  */
8979     gl_catch_signals(gl);
8980 /*
8981  * Wait for activity on any of the file descriptors.
8982  */
8983     nready = select(gl->max_fd+1, &rfds, &wfds, &ufds,
8984 	    (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL);
8985 /*
8986  * We don't want to do a longjmp in the middle of a callback that
8987  * might be modifying global or heap data, so block all the signals
8988  * that we are trapping before executing callback functions. Note that
8989  * the caller will unblock them again when it needs to, so there is
8990  * no need to undo this before returning.
8991  */
8992     gl_mask_signals(gl, NULL);
8993 /*
8994  * If select() returns but none of the file descriptors are reported
8995  * to have activity, then select() timed out.
8996  */
8997     if(nready == 0) {
8998 /*
8999  * Note that in non-blocking server mode, the inactivity timer is used
9000  * to allow I/O to block for a specified amount of time, so in this
9001  * mode we return the postponed blocked status when an abort is
9002  * requested.
9003  */
9004       if(gl_call_timeout_handler(gl)) {
9005 	return 1;
9006       } else if(gl->io_mode == GL_SERVER_MODE) {
9007 	gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
9008 	return 1;
9009       };
9010 /*
9011  * If nready < 0, this means an error occurred.
9012  */
9013     } else if(nready < 0) {
9014       if(errno != EINTR) {
9015 	gl_record_status(gl, GLR_ERROR, errno);
9016 	return 1;
9017       };
9018 /*
9019  * If the user-input file descriptor has data available, return.
9020  */
9021     } else if(FD_ISSET(fd, &rfds)) {
9022       return 0;
9023 /*
9024  * Check for activity on any of the file descriptors registered by the
9025  * calling application, and call the associated callback functions.
9026  */
9027     } else {
9028       GlFdNode *node;   /* The fd event node being checked */
9029 /*
9030  * Search the list for the file descriptor that caused select() to return.
9031  */
9032       for(node=gl->fd_nodes; node; node=node->next) {
9033 /*
9034  * Is there urgent out of band data waiting to be read on fd?
9035  */
9036 	if(node->ur.fn && FD_ISSET(node->fd, &ufds)) {
9037 	  if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT))
9038 	    return 1;
9039 	  break;  /* The callback may have changed the list of nodes */
9040 /*
9041  * Is the fd readable?
9042  */
9043 	} else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) {
9044 	  if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ))
9045 	    return 1;
9046 	  break;  /* The callback may have changed the list of nodes */
9047 /*
9048  * Is the fd writable?
9049  */
9050 	} else if(node->wr.fn && FD_ISSET(node->fd, &wfds)) {
9051 	  if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE))
9052 	    return 1;
9053 	  break;  /* The callback may have changed the list of nodes */
9054 	};
9055       };
9056     };
9057 /*
9058  * Just in case the above event handlers asked for the input line to
9059  * be redrawn, flush any pending output.
9060  */
9061     if(gl_flush_output(gl))
9062       return 1;
9063   };
9064   return 0;
9065 #endif
9066 }
9067 
9068 #if defined(HAVE_SELECT)
9069 /*.......................................................................
9070  * This is a private function of gl_event_handler(), used to call a
9071  * file-descriptor callback.
9072  *
9073  * Input:
9074  *  gl       GetLine *  The resource object of gl_get_line().
9075  *  gfh  GlFdHandler *  The I/O handler.
9076  *  fd           int    The file-descriptor being reported.
9077  *  event  GlFdEvent    The I/O event being reported.
9078  * Output:
9079  *  return       int    0 - OK.
9080  *                      1 - Error.
9081  */
9082 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
9083 			      GlFdEvent event)
9084 {
9085   Termios attr;       /* The terminal attributes */
9086   int waserr = 0;     /* True after any error */
9087 /*
9088  * Re-enable conversion of newline characters to carriage-return/linefeed,
9089  * so that the callback can write to the terminal without having to do
9090  * anything special.
9091  */
9092   if(tcgetattr(gl->input_fd, &attr)) {
9093     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9094     return 1;
9095   };
9096   attr.c_oflag |= OPOST;
9097   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9098     if(errno != EINTR) {
9099       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9100       return 1;
9101     };
9102   };
9103 /*
9104  * Invoke the application's callback function.
9105  */
9106   switch(gfh->fn(gl, gfh->data, fd, event)) {
9107   default:
9108   case GLFD_ABORT:
9109     gl_record_status(gl, GLR_FDABORT, 0);
9110     waserr = 1;
9111     break;
9112   case GLFD_REFRESH:
9113     gl_queue_redisplay(gl);
9114     break;
9115   case GLFD_CONTINUE:
9116     break;
9117   };
9118 /*
9119  * If the callback function called gl_normal_io(), restore raw mode,
9120  * and queue a redisplay of the input line.
9121  */
9122   if(!gl->raw_mode)
9123     waserr = waserr || _gl_raw_io(gl, 1);
9124 /*
9125  * Disable conversion of newline characters to carriage-return/linefeed.
9126  */
9127   attr.c_oflag &= ~(OPOST);
9128   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9129     if(errno != EINTR) {
9130       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9131       return 1;
9132     };
9133   };
9134   return waserr;
9135 }
9136 
9137 /*.......................................................................
9138  * This is a private function of gl_event_handler(), used to call a
9139  * inactivity timer callbacks.
9140  *
9141  * Input:
9142  *  gl       GetLine *  The resource object of gl_get_line().
9143  * Output:
9144  *  return       int    0 - OK.
9145  *                      1 - Error.
9146  */
9147 static int gl_call_timeout_handler(GetLine *gl)
9148 {
9149   Termios attr;       /* The terminal attributes */
9150   int waserr = 0;     /* True after any error */
9151 /*
9152  * Make sure that there is an inactivity timeout callback.
9153  */
9154   if(!gl->timer.fn)
9155     return 0;
9156 /*
9157  * Re-enable conversion of newline characters to carriage-return/linefeed,
9158  * so that the callback can write to the terminal without having to do
9159  * anything special.
9160  */
9161   if(tcgetattr(gl->input_fd, &attr)) {
9162     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9163     return 1;
9164   };
9165   attr.c_oflag |= OPOST;
9166   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9167     if(errno != EINTR) {
9168       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9169       return 1;
9170     };
9171   };
9172 /*
9173  * Invoke the application's callback function.
9174  */
9175   switch(gl->timer.fn(gl, gl->timer.data)) {
9176   default:
9177   case GLTO_ABORT:
9178     gl_record_status(gl, GLR_TIMEOUT, 0);
9179     waserr = 1;
9180     break;
9181   case GLTO_REFRESH:
9182     gl_queue_redisplay(gl);
9183     break;
9184   case GLTO_CONTINUE:
9185     break;
9186   };
9187 /*
9188  * If the callback function called gl_normal_io(), restore raw mode,
9189  * and queue a redisplay of the input line.
9190  */
9191   if(!gl->raw_mode)
9192     waserr = waserr || _gl_raw_io(gl, 1);
9193 /*
9194  * Disable conversion of newline characters to carriage-return/linefeed.
9195  */
9196   attr.c_oflag &= ~(OPOST);
9197   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9198     if(errno != EINTR) {
9199       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9200       return 1;
9201     };
9202   };
9203   return waserr;
9204 }
9205 #endif  /* HAVE_SELECT */
9206 
9207 /*.......................................................................
9208  * Switch history groups. History groups represent separate history
9209  * lists recorded within a single history buffer. Different groups
9210  * are distinguished by integer identifiers chosen by the calling
9211  * appplicaton. Initially new_GetLine() sets the group identifier to
9212  * 0. Whenever a new line is appended to the history list, the current
9213  * group identifier is recorded with it, and history lookups only
9214  * consider lines marked with the current group identifier.
9215  *
9216  * Input:
9217  *  gl      GetLine *  The resource object of gl_get_line().
9218  *  id     unsigned    The new history group identifier.
9219  * Output:
9220  *  return      int    0 - OK.
9221  *                     1 - Error.
9222  */
9223 int gl_group_history(GetLine *gl, unsigned id)
9224 {
9225   sigset_t oldset; /* The signals that were blocked on entry to this function */
9226   int status;      /* The return status of this function */
9227 /*
9228  * Check the arguments.
9229  */
9230   if(!gl) {
9231     errno = EINVAL;
9232     return 1;
9233   };
9234 /*
9235  * Block all signals while we install the new configuration.
9236  */
9237   if(gl_mask_signals(gl, &oldset))
9238     return 1;
9239 /*
9240  * If the group isn't being changed, do nothing.
9241  */
9242   if(_glh_get_group(gl->glh) == id) {
9243     status = 0;
9244 /*
9245  * Establish the new group.
9246  */
9247   } else if(_glh_set_group(gl->glh, id)) {
9248     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9249     status = 1;
9250 /*
9251  * Prevent history information from the previous group being
9252  * inappropriately used by the next call to gl_get_line().
9253  */
9254   } else {
9255     gl->preload_history = 0;
9256     gl->last_search = -1;
9257     status = 0;
9258   };
9259 /*
9260  * Restore the process signal mask.
9261  */
9262   gl_unmask_signals(gl, &oldset);
9263   return status;
9264 }
9265 
9266 /*.......................................................................
9267  * Display the contents of the history list.
9268  *
9269  * Input:
9270  *  gl      GetLine *  The resource object of gl_get_line().
9271  *  fp         FILE *  The stdio output stream to write to.
9272  *  fmt  const char *  A format string. This containing characters to be
9273  *                     written verbatim, plus any of the following
9274  *                     format directives:
9275  *                       %D  -  The date, formatted like 2001-11-20
9276  *                       %T  -  The time of day, formatted like 23:59:59
9277  *                       %N  -  The sequential entry number of the
9278  *                              line in the history buffer.
9279  *                       %G  -  The number of the history group that
9280  *                              the line belongs to.
9281  *                       %%  -  A literal % character.
9282  *                       %H  -  The history line itself.
9283  *                     Note that a '\n' newline character is not
9284  *                     appended by default.
9285  *  all_groups  int    If true, display history lines from all
9286  *                     history groups. Otherwise only display
9287  *                     those of the current history group.
9288  *  max_lines   int    If max_lines is < 0, all available lines
9289  *                     are displayed. Otherwise only the most
9290  *                     recent max_lines lines will be displayed.
9291  * Output:
9292  *  return      int    0 - OK.
9293  *                     1 - Error.
9294  */
9295 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups,
9296 		    int max_lines)
9297 {
9298   sigset_t oldset; /* The signals that were blocked on entry to this function */
9299   int status;      /* The return status of this function */
9300 /*
9301  * Check the arguments.
9302  */
9303   if(!gl || !fp || !fmt) {
9304     if(gl)
9305       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
9306     errno = EINVAL;
9307     return 1;
9308   };
9309 /*
9310  * Block all signals.
9311  */
9312   if(gl_mask_signals(gl, &oldset))
9313     return 1;
9314 /*
9315  * Display the specified history group(s) while signals are blocked.
9316  */
9317   status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups,
9318 			     max_lines) || fflush(fp)==EOF;
9319   if(!status)
9320     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9321 /*
9322  * Restore the process signal mask.
9323  */
9324   gl_unmask_signals(gl, &oldset);
9325   return status;
9326 }
9327 
9328 /*.......................................................................
9329  * Update if necessary, and return the current size of the terminal.
9330  *
9331  * Input:
9332  *  gl            GetLine *  The resource object of gl_get_line().
9333  *  def_ncolumn       int    If the number of columns in the terminal
9334  *                           can't be determined, substitute this number.
9335  *  def_nline         int    If the number of lines in the terminal can't
9336  *                           be determined, substitute this number.
9337  * Output:
9338  *  return GlTerminalSize    The current terminal size.
9339  */
9340 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline)
9341 {
9342   GlTerminalSize size;  /* The object to be returned */
9343   sigset_t oldset;      /* The signals that were blocked on entry */
9344                         /*  to this function */
9345 /*
9346  * Block all signals while accessing gl.
9347  */
9348   gl_mask_signals(gl, &oldset);
9349 /*
9350  * Lookup/configure the terminal size.
9351  */
9352   _gl_terminal_size(gl, def_ncolumn, def_nline, &size);
9353 /*
9354  * Restore the process signal mask before returning.
9355  */
9356   gl_unmask_signals(gl, &oldset);
9357   return size;
9358 }
9359 
9360 /*.......................................................................
9361  * This is the private body of the gl_terminal_size() function. It
9362  * assumes that the caller has checked its arguments and blocked the
9363  * delivery of signals.
9364  */
9365 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
9366 			      GlTerminalSize *size)
9367 {
9368   const char *env;      /* The value of an environment variable */
9369   int n;                /* A number read from env[] */
9370 /*
9371  * Set the number of lines and columns to non-sensical values so that
9372  * we know later if they have been set.
9373  */
9374   gl->nline = 0;
9375   gl->ncolumn = 0;
9376 /*
9377  * Are we reading from a terminal?
9378  */
9379   if(gl->is_term) {
9380 /*
9381  * Ask the terminal directly if possible.
9382  */
9383     gl_query_size(gl, &gl->ncolumn, &gl->nline);
9384 /*
9385  * If gl_query_size() couldn't ask the terminal, it will have
9386  * left gl->nrow and gl->ncolumn unchanged. If these values haven't
9387  * been changed from their initial values of zero, we need to find
9388  * a different method to get the terminal size.
9389  *
9390  * If the number of lines isn't known yet, first see if the
9391  * LINES environment ariable exists and specifies a believable number.
9392  * If this doesn't work, look up the default size in the terminal
9393  * information database.
9394  */
9395     if(gl->nline < 1) {
9396       if((env = getenv("LINES")) && (n=atoi(env)) > 0)
9397 	gl->nline = n;
9398 #ifdef USE_TERMINFO
9399       else
9400 	gl->nline = tigetnum((char *)"lines");
9401 #elif defined(USE_TERMCAP)
9402       else
9403         gl->nline = tgetnum("li");
9404 #endif
9405     };
9406 /*
9407  * If the number of lines isn't known yet, first see if the COLUMNS
9408  * environment ariable exists and specifies a believable number.  If
9409  * this doesn't work, look up the default size in the terminal
9410  * information database.
9411  */
9412     if(gl->ncolumn < 1) {
9413       if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0)
9414 	gl->ncolumn = n;
9415 #ifdef USE_TERMINFO
9416       else
9417 	gl->ncolumn = tigetnum((char *)"cols");
9418 #elif defined(USE_TERMCAP)
9419       else
9420 	gl->ncolumn = tgetnum("co");
9421 #endif
9422     };
9423   };
9424 /*
9425  * If we still haven't been able to acquire reasonable values, substitute
9426  * the default values specified by the caller.
9427  */
9428   if(gl->nline <= 0)
9429     gl->nline = def_nline;
9430   if(gl->ncolumn <= 0)
9431     gl->ncolumn = def_ncolumn;
9432 /*
9433  * Copy the new size into the return value.
9434  */
9435   if(size) {
9436     size->nline = gl->nline;
9437     size->ncolumn = gl->ncolumn;
9438   };
9439   return;
9440 }
9441 
9442 /*.......................................................................
9443  * Resize or delete the history buffer.
9444  *
9445  * Input:
9446  *  gl      GetLine *  The resource object of gl_get_line().
9447  *  bufsize  size_t    The number of bytes in the history buffer, or 0
9448  *                     to delete the buffer completely.
9449  * Output:
9450  *  return      int    0 - OK.
9451  *                     1 - Insufficient memory (the previous buffer
9452  *                         will have been retained). No error message
9453  *                         will be displayed.
9454  */
9455 int gl_resize_history(GetLine *gl, size_t bufsize)
9456 {
9457   sigset_t oldset; /* The signals that were blocked on entry to this function */
9458   int status;      /* The return status of this function */
9459 /*
9460  * Check the arguments.
9461  */
9462   if(!gl)
9463     return 1;
9464 /*
9465  * Block all signals while modifying the contents of gl.
9466  */
9467   if(gl_mask_signals(gl, &oldset))
9468     return 1;
9469 /*
9470  * Perform the resize while signals are blocked.
9471  */
9472   status = _glh_resize_history(gl->glh, bufsize);
9473   if(status)
9474     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9475 /*
9476  * Restore the process signal mask before returning.
9477  */
9478   gl_unmask_signals(gl, &oldset);
9479   return status;
9480 }
9481 
9482 /*.......................................................................
9483  * Set an upper limit to the number of lines that can be recorded in the
9484  * history list, or remove a previously specified limit.
9485  *
9486  * Input:
9487  *  gl      GetLine *  The resource object of gl_get_line().
9488  *  max_lines   int    The maximum number of lines to allow, or -1 to
9489  *                     cancel a previous limit and allow as many lines
9490  *                     as will fit in the current history buffer size.
9491  */
9492 void gl_limit_history(GetLine *gl, int max_lines)
9493 {
9494   if(gl) {
9495     sigset_t oldset; /* The signals that were blocked on entry to this block */
9496 /*
9497  * Temporarily block all signals.
9498  */
9499     gl_mask_signals(gl, &oldset);
9500 /*
9501  * Apply the limit while signals are blocked.
9502  */
9503     _glh_limit_history(gl->glh, max_lines);
9504 /*
9505  * Restore the process signal mask before returning.
9506  */
9507     gl_unmask_signals(gl, &oldset);
9508   };
9509 }
9510 
9511 /*.......................................................................
9512  * Discard either all historical lines, or just those associated with the
9513  * current history group.
9514  *
9515  * Input:
9516  *  gl      GetLine *  The resource object of gl_get_line().
9517  *  all_groups  int    If true, clear all of the history. If false,
9518  *                     clear only the stored lines associated with the
9519  *                     currently selected history group.
9520  */
9521 void gl_clear_history(GetLine *gl, int all_groups)
9522 {
9523   if(gl) {
9524     sigset_t oldset; /* The signals that were blocked on entry to this block */
9525 /*
9526  * Temporarily block all signals.
9527  */
9528     gl_mask_signals(gl, &oldset);
9529 /*
9530  * Clear the history buffer while signals are blocked.
9531  */
9532     _glh_clear_history(gl->glh, all_groups);
9533 /*
9534  * Restore the process signal mask before returning.
9535  */
9536     gl_unmask_signals(gl, &oldset);
9537   };
9538 }
9539 
9540 /*.......................................................................
9541  * Temporarily enable or disable the gl_get_line() history mechanism.
9542  *
9543  * Input:
9544  *  gl      GetLine *  The resource object of gl_get_line().
9545  *  enable      int    If true, turn on the history mechanism. If
9546  *                     false, disable it.
9547  */
9548 void gl_toggle_history(GetLine *gl, int enable)
9549 {
9550   if(gl) {
9551     sigset_t oldset; /* The signals that were blocked on entry to this block */
9552 /*
9553  * Temporarily block all signals.
9554  */
9555     gl_mask_signals(gl, &oldset);
9556 /*
9557  * Change the history recording mode while signals are blocked.
9558  */
9559     _glh_toggle_history(gl->glh, enable);
9560 /*
9561  * Restore the process signal mask before returning.
9562  */
9563     gl_unmask_signals(gl, &oldset);
9564   };
9565 }
9566 
9567 /*.......................................................................
9568  * Lookup a history line by its sequential number of entry in the
9569  * history buffer.
9570  *
9571  * Input:
9572  *  gl            GetLine *  The resource object of gl_get_line().
9573  *  id      unsigned long    The identification number of the line to
9574  *                           be returned, where 0 denotes the first line
9575  *                           that was entered in the history list, and
9576  *                           each subsequently added line has a number
9577  *                           one greater than the previous one. For
9578  *                           the range of lines currently in the list,
9579  *                           see the gl_range_of_history() function.
9580  * Input/Output:
9581  *  line    GlHistoryLine *  A pointer to the variable in which to
9582  *                           return the details of the line.
9583  * Output:
9584  *  return            int    0 - The line is no longer in the history
9585  *                               list, and *line has not been changed.
9586  *                           1 - The requested line can be found in
9587  *                               *line. Note that line->line is part
9588  *                               of the history buffer, so a
9589  *                               private copy should be made if you
9590  *                               wish to use it after subsequent calls
9591  *                               to any functions that take *gl as an
9592  *                               argument.
9593  */
9594 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line)
9595 {
9596   sigset_t oldset; /* The signals that were blocked on entry to this function */
9597   int status;      /* The return status of this function */
9598 /*
9599  * Check the arguments.
9600  */
9601   if(!gl)
9602     return 0;
9603 /*
9604  * Block all signals while modifying the contents of gl.
9605  */
9606   if(gl_mask_signals(gl, &oldset))
9607     return 1;
9608 /*
9609  * Perform the lookup while signals are blocked.
9610  */
9611   status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line,
9612 			       &line->group, &line->timestamp);
9613   if(status)
9614     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9615 /*
9616  * Restore the process signal mask before returning.
9617  */
9618   gl_unmask_signals(gl, &oldset);
9619   return status;
9620 }
9621 
9622 /*.......................................................................
9623  * Query the state of the history list. Note that any of the input/output
9624  * pointers can be specified as NULL.
9625  *
9626  * Input:
9627  *  gl            GetLine *  The resource object of gl_get_line().
9628  * Input/Output:
9629  *  state  GlHistoryState *  A pointer to the variable in which to record
9630  *                           the return values.
9631  */
9632 void gl_state_of_history(GetLine *gl, GlHistoryState *state)
9633 {
9634   if(gl && state) {
9635     sigset_t oldset; /* The signals that were blocked on entry to this block */
9636 /*
9637  * Temporarily block all signals.
9638  */
9639     gl_mask_signals(gl, &oldset);
9640 /*
9641  * Lookup the status while signals are blocked.
9642  */
9643     _glh_state_of_history(gl->glh, &state->enabled, &state->group,
9644 			  &state->max_lines);
9645 /*
9646  * Restore the process signal mask before returning.
9647  */
9648     gl_unmask_signals(gl, &oldset);
9649   };
9650 }
9651 
9652 /*.......................................................................
9653  * Query the number and range of lines in the history buffer.
9654  *
9655  * Input:
9656  *  gl            GetLine *  The resource object of gl_get_line().
9657  *  range  GlHistoryRange *  A pointer to the variable in which to record
9658  *                           the return values. If range->nline=0, the
9659  *                           range of lines will be given as 0-0.
9660  */
9661 void gl_range_of_history(GetLine *gl, GlHistoryRange *range)
9662 {
9663   if(gl && range) {
9664     sigset_t oldset; /* The signals that were blocked on entry to this block */
9665 /*
9666  * Temporarily block all signals.
9667  */
9668     gl_mask_signals(gl, &oldset);
9669 /*
9670  * Lookup the information while signals are blocked.
9671  */
9672     _glh_range_of_history(gl->glh, &range->oldest, &range->newest,
9673 			  &range->nlines);
9674 /*
9675  * Restore the process signal mask before returning.
9676  */
9677     gl_unmask_signals(gl, &oldset);
9678   };
9679 }
9680 
9681 /*.......................................................................
9682  * Return the size of the history buffer and the amount of the
9683  * buffer that is currently in use.
9684  *
9685  * Input:
9686  *  gl         GetLine *  The gl_get_line() resource object.
9687  * Input/Output:
9688  *  GlHistorySize size *  A pointer to the variable in which to return
9689  *                        the results.
9690  */
9691 void gl_size_of_history(GetLine *gl, GlHistorySize *size)
9692 {
9693   if(gl && size) {
9694     sigset_t oldset; /* The signals that were blocked on entry to this block */
9695 /*
9696  * Temporarily block all signals.
9697  */
9698     gl_mask_signals(gl, &oldset);
9699 /*
9700  * Lookup the information while signals are blocked.
9701  */
9702     _glh_size_of_history(gl->glh, &size->size, &size->used);
9703 /*
9704  * Restore the process signal mask before returning.
9705  */
9706     gl_unmask_signals(gl, &oldset);
9707   };
9708 }
9709 
9710 /*.......................................................................
9711  * This is the action function that lists the contents of the history
9712  * list.
9713  */
9714 static KT_KEY_FN(gl_list_history)
9715 {
9716 /*
9717  * Start a new line.
9718  */
9719   if(gl_start_newline(gl, 1))
9720     return 1;
9721 /*
9722  * List history lines that belong to the current group.
9723  */
9724   _glh_show_history(gl->glh, gl_write_fn, gl, "%N  %T   %H\r\n", 0,
9725 		    count<=1 ? -1 : count);
9726 /*
9727  * Arrange for the input line to be redisplayed.
9728  */
9729   gl_queue_redisplay(gl);
9730   return 0;
9731 }
9732 
9733 /*.......................................................................
9734  * Specify whether text that users type should be displayed or hidden.
9735  * In the latter case, only the prompt is displayed, and the final
9736  * input line is not archived in the history list.
9737  *
9738  * Input:
9739  *  gl         GetLine *  The gl_get_line() resource object.
9740  *  enable         int     0 - Disable echoing.
9741  *                         1 - Enable echoing.
9742  *                        -1 - Just query the mode without changing it.
9743  * Output:
9744  *  return         int    The echoing disposition that was in effect
9745  *                        before this function was called:
9746  *                         0 - Echoing was disabled.
9747  *                         1 - Echoing was enabled.
9748  */
9749 int gl_echo_mode(GetLine *gl, int enable)
9750 {
9751   if(gl) {
9752     sigset_t oldset; /* The signals that were blocked on entry to this block */
9753     int was_echoing; /* The echoing disposition on entry to this function */
9754 /*
9755  * Temporarily block all signals.
9756  */
9757     gl_mask_signals(gl, &oldset);
9758 /*
9759  * Install the new disposition while signals are blocked.
9760  */
9761     was_echoing = gl->echo;
9762     if(enable >= 0)
9763       gl->echo = enable;
9764 /*
9765  * Restore the process signal mask before returning.
9766  */
9767     gl_unmask_signals(gl, &oldset);
9768 /*
9769  * Return the original echoing disposition.
9770  */
9771     return was_echoing;
9772   };
9773   return 1;
9774 }
9775 
9776 /*.......................................................................
9777  * Display the prompt.
9778  *
9779  * Input:
9780  *  gl         GetLine *  The resource object of gl_get_line().
9781  * Output:
9782  *  return         int    0 - OK.
9783  *                        1 - Error.
9784  */
9785 static int gl_display_prompt(GetLine *gl)
9786 {
9787   const char *pptr;       /* A pointer into gl->prompt[] */
9788   unsigned old_attr=0;    /* The current text display attributes */
9789   unsigned new_attr=0;    /* The requested text display attributes */
9790 /*
9791  * Temporarily switch to echoing output characters.
9792  */
9793   int kept_echo = gl->echo;
9794   gl->echo = 1;
9795 /*
9796  * In case the screen got messed up, send a carriage return to
9797  * put the cursor at the beginning of the current terminal line.
9798  */
9799   if(gl_print_control_sequence(gl, 1, gl->bol))
9800     return 1;
9801 /*
9802  * Mark the line as partially displayed.
9803  */
9804   gl->displayed = 1;
9805 /*
9806  * Write the prompt, using the currently selected prompt style.
9807  */
9808   switch(gl->prompt_style) {
9809   case GL_LITERAL_PROMPT:
9810     if(gl_print_string(gl, gl->prompt, '\0'))
9811       return 1;
9812     break;
9813   case GL_FORMAT_PROMPT:
9814     for(pptr=gl->prompt; *pptr; pptr++) {
9815 /*
9816  * Does the latest character appear to be the start of a directive?
9817  */
9818       if(*pptr == '%') {
9819 /*
9820  * Check for and act on attribute changing directives.
9821  */
9822 	switch(pptr[1]) {
9823 /*
9824  * Add or remove a text attribute from the new set of attributes.
9825  * If you add or remove a directive from this list, be sure to update
9826  * the equivalent list of directives in gl_displayed_prompt_width().
9827  */
9828 	case 'B': case 'U': case 'S': case 'P': case 'F': case 'V':
9829 	case 'b': case 'u': case 's': case 'p': case 'f': case 'v':
9830 	  switch(*++pptr) {
9831 	  case 'B':           /* Switch to a bold font */
9832 	    new_attr |= GL_TXT_BOLD;
9833 	    break;
9834 	  case 'b':           /* Switch to a non-bold font */
9835 	    new_attr &= ~GL_TXT_BOLD;
9836 	    break;
9837 	  case 'U':           /* Start underlining */
9838 	    new_attr |= GL_TXT_UNDERLINE;
9839 	    break;
9840 	  case 'u':           /* Stop underlining */
9841 	    new_attr &= ~GL_TXT_UNDERLINE;
9842 	    break;
9843 	  case 'S':           /* Start highlighting */
9844 	    new_attr |= GL_TXT_STANDOUT;
9845 	    break;
9846 	  case 's':           /* Stop highlighting */
9847 	    new_attr &= ~GL_TXT_STANDOUT;
9848 	    break;
9849 	  case 'P':           /* Switch to a pale font */
9850 	    new_attr |= GL_TXT_DIM;
9851 	    break;
9852 	  case 'p':           /* Switch to a non-pale font */
9853 	    new_attr &= ~GL_TXT_DIM;
9854 	    break;
9855 	  case 'F':           /* Switch to a flashing font */
9856 	    new_attr |= GL_TXT_BLINK;
9857 	    break;
9858 	  case 'f':           /* Switch to a steady font */
9859 	    new_attr &= ~GL_TXT_BLINK;
9860 	    break;
9861 	  case 'V':           /* Switch to reverse video */
9862 	    new_attr |= GL_TXT_REVERSE;
9863 	    break;
9864 	  case 'v':           /* Switch out of reverse video */
9865 	    new_attr &= ~GL_TXT_REVERSE;
9866 	    break;
9867 	  };
9868 	  continue;
9869 /*
9870  * A literal % is represented by %%. Skip the leading %.
9871  */
9872 	case '%':
9873 	  pptr++;
9874 	  break;
9875 	};
9876       };
9877 /*
9878  * Many terminals, when asked to turn off a single text attribute, turn
9879  * them all off, so the portable way to turn one off individually is to
9880  * explicitly turn them all off, then specify those that we want from
9881  * scratch.
9882  */
9883       if(old_attr & ~new_attr) {
9884 	if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9885 	  return 1;
9886 	old_attr = 0;
9887       };
9888 /*
9889  * Install new text attributes?
9890  */
9891       if(new_attr != old_attr) {
9892 	if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) &&
9893 	   gl_print_control_sequence(gl, 1, gl->bold))
9894 	  return 1;
9895 	if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) &&
9896 	   gl_print_control_sequence(gl, 1, gl->underline))
9897 	  return 1;
9898 	if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) &&
9899 	   gl_print_control_sequence(gl, 1, gl->standout))
9900 	  return 1;
9901 	if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) &&
9902 	   gl_print_control_sequence(gl, 1, gl->dim))
9903 	  return 1;
9904 	if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) &&
9905 	   gl_print_control_sequence(gl, 1, gl->reverse))
9906 	  return 1;
9907 	if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) &&
9908 	   gl_print_control_sequence(gl, 1, gl->blink))
9909 	  return 1;
9910 	old_attr = new_attr;
9911       };
9912 /*
9913  * Display the latest character.
9914  */
9915       if(gl_print_char(gl, *pptr, pptr[1]))
9916 	return 1;
9917     };
9918 /*
9919  * Turn off all text attributes now that we have finished drawing
9920  * the prompt.
9921  */
9922     if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9923       return 1;
9924     break;
9925   };
9926 /*
9927  * Restore the original echo mode.
9928  */
9929   gl->echo = kept_echo;
9930 /*
9931  * The prompt has now been displayed at least once.
9932  */
9933   gl->prompt_changed = 0;
9934   return 0;
9935 }
9936 
9937 /*.......................................................................
9938  * This function can be called from gl_get_line() callbacks to have
9939  * the prompt changed when they return. It has no effect if gl_get_line()
9940  * is not currently being invoked.
9941  *
9942  * Input:
9943  *  gl         GetLine *  The resource object of gl_get_line().
9944  *  prompt  const char *  The new prompt.
9945  */
9946 void gl_replace_prompt(GetLine *gl, const char *prompt)
9947 {
9948   if(gl) {
9949     sigset_t oldset; /* The signals that were blocked on entry to this block */
9950 /*
9951  * Temporarily block all signals.
9952  */
9953     gl_mask_signals(gl, &oldset);
9954 /*
9955  * Replace the prompt.
9956  */
9957     _gl_replace_prompt(gl, prompt);
9958 /*
9959  * Restore the process signal mask before returning.
9960  */
9961     gl_unmask_signals(gl, &oldset);
9962   };
9963 }
9964 
9965 /*.......................................................................
9966  * This is the private body of the gl_replace_prompt() function. It
9967  * assumes that the caller has checked its arguments and blocked the
9968  * delivery of signals.
9969  */
9970 static void _gl_replace_prompt(GetLine *gl, const char *prompt)
9971 {
9972 /*
9973  * Substitute an empty prompt?
9974  */
9975   if(!prompt)
9976     prompt = "";
9977 /*
9978  * Gaurd against aliasing between prompt and gl->prompt.
9979  */
9980   if(gl->prompt != prompt) {
9981 /*
9982  * Get the length of the new prompt string.
9983  */
9984     size_t slen = strlen(prompt);
9985 /*
9986  * If needed, allocate a new buffer for the prompt string.
9987  */
9988     if(!gl->prompt || slen > strlen(gl->prompt)) {
9989       size_t size = sizeof(char) * (slen + 1);
9990       char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size);
9991       if(!new_prompt)
9992 	return;
9993       gl->prompt = new_prompt;
9994     };
9995 /*
9996  * Make a copy of the new prompt.
9997  */
9998     strcpy(gl->prompt, prompt);
9999   };
10000 /*
10001  * Record the statistics of the new prompt.
10002  */
10003   gl->prompt_len = gl_displayed_prompt_width(gl);
10004   gl->prompt_changed = 1;
10005   gl_queue_redisplay(gl);
10006   return;
10007 }
10008 
10009 /*.......................................................................
10010  * Work out the length of the current prompt on the terminal, according
10011  * to the current prompt formatting style.
10012  *
10013  * Input:
10014  *  gl       GetLine *  The resource object of this library.
10015  * Output:
10016  *  return       int    The number of displayed characters.
10017  */
10018 static int gl_displayed_prompt_width(GetLine *gl)
10019 {
10020   int slen=0;         /* The displayed number of characters */
10021   const char *pptr;   /* A pointer into prompt[] */
10022 /*
10023  * The length differs according to the prompt display style.
10024  */
10025   switch(gl->prompt_style) {
10026   case GL_LITERAL_PROMPT:
10027     return gl_displayed_string_width(gl, gl->prompt, -1, 0);
10028     break;
10029   case GL_FORMAT_PROMPT:
10030 /*
10031  * Add up the length of the displayed string, while filtering out
10032  * attribute directives.
10033  */
10034     for(pptr=gl->prompt; *pptr; pptr++) {
10035 /*
10036  * Does the latest character appear to be the start of a directive?
10037  */
10038       if(*pptr == '%') {
10039 /*
10040  * Check for and skip attribute changing directives.
10041  */
10042 	switch(pptr[1]) {
10043 	case 'B': case 'U': case 'S': case 'P': case 'F': case 'V':
10044 	case 'b': case 'u': case 's': case 'p': case 'f': case 'v':
10045 	  pptr++;
10046 	  continue;
10047 /*
10048  * A literal % is represented by %%. Skip the leading %.
10049  */
10050 	case '%':
10051 	  pptr++;
10052 	  break;
10053 	};
10054       };
10055       slen += gl_displayed_char_width(gl, *pptr, slen);
10056     };
10057     break;
10058   };
10059   return slen;
10060 }
10061 
10062 /*.......................................................................
10063  * Specify whether to heed text attribute directives within prompt
10064  * strings.
10065  *
10066  * Input:
10067  *  gl           GetLine *  The resource object of gl_get_line().
10068  *  style  GlPromptStyle    The style of prompt (see the definition of
10069  *                          GlPromptStyle in libtecla.h for details).
10070  */
10071 void gl_prompt_style(GetLine *gl, GlPromptStyle style)
10072 {
10073   if(gl) {
10074     sigset_t oldset; /* The signals that were blocked on entry to this block */
10075 /*
10076  * Temporarily block all signals.
10077  */
10078     gl_mask_signals(gl, &oldset);
10079 /*
10080  * Install the new style in gl while signals are blocked.
10081  */
10082     if(style != gl->prompt_style) {
10083       gl->prompt_style = style;
10084       gl->prompt_len = gl_displayed_prompt_width(gl);
10085       gl->prompt_changed = 1;
10086       gl_queue_redisplay(gl);
10087     };
10088 /*
10089  * Restore the process signal mask before returning.
10090  */
10091     gl_unmask_signals(gl, &oldset);
10092   };
10093 }
10094 
10095 /*.......................................................................
10096  * Tell gl_get_line() how to respond to a given signal. This can be used
10097  * both to override the default responses to signals that gl_get_line()
10098  * normally catches and to add new signals to the list that are to be
10099  * caught.
10100  *
10101  * Input:
10102  *  gl           GetLine *  The resource object of gl_get_line().
10103  *  signo            int    The number of the signal to be caught.
10104  *  flags       unsigned    A bitwise union of GlSignalFlags enumerators.
10105  *  after  GlAfterSignal    What to do after the application's signal
10106  *                          handler has been called.
10107  *  errno_value      int    The value to set errno to.
10108  * Output:
10109  *  return           int    0 - OK.
10110  *                          1 - Error.
10111  */
10112 int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10113 		   GlAfterSignal after, int errno_value)
10114 {
10115   sigset_t oldset; /* The signals that were blocked on entry to this function */
10116   int status;      /* The return status of this function */
10117 /*
10118  * Check the arguments.
10119  */
10120   if(!gl) {
10121     errno = EINVAL;
10122     return 1;
10123   };
10124 /*
10125  * Block all signals while modifying the contents of gl.
10126  */
10127   if(gl_mask_signals(gl, &oldset))
10128     return 1;
10129 /*
10130  * Perform the modification while signals are blocked.
10131  */
10132   status = _gl_trap_signal(gl, signo, flags, after, errno_value);
10133 /*
10134  * Restore the process signal mask before returning.
10135  */
10136   gl_unmask_signals(gl, &oldset);
10137   return status;
10138 }
10139 
10140 /*.......................................................................
10141  * This is the private body of the gl_trap_signal() function. It
10142  * assumes that the caller has checked its arguments and blocked the
10143  * delivery of signals.
10144  */
10145 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10146 			   GlAfterSignal after, int errno_value)
10147 {
10148   GlSignalNode *sig;
10149 /*
10150  * Complain if an attempt is made to trap untrappable signals.
10151  * These would otherwise cause errors later in gl_mask_signals().
10152  */
10153   if(0
10154 #ifdef SIGKILL
10155      || signo==SIGKILL
10156 #endif
10157 #ifdef SIGBLOCK
10158      || signo==SIGBLOCK
10159 #endif
10160      ) {
10161     return 1;
10162   };
10163 /*
10164  * See if the signal has already been registered.
10165  */
10166   for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next)
10167     ;
10168 /*
10169  * If the signal hasn't already been registered, allocate a node for
10170  * it.
10171  */
10172   if(!sig) {
10173     sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem);
10174     if(!sig)
10175       return 1;
10176 /*
10177  * Add the new node to the head of the list.
10178  */
10179     sig->next = gl->sigs;
10180     gl->sigs = sig;
10181 /*
10182  * Record the signal number.
10183  */
10184     sig->signo = signo;
10185 /*
10186  * Create a signal set that includes just this signal.
10187  */
10188     sigemptyset(&sig->proc_mask);
10189     if(sigaddset(&sig->proc_mask, signo) == -1) {
10190       _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
10191       sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10192       return 1;
10193     };
10194 /*
10195  * Add the signal to the bit-mask of signals being trapped.
10196  */
10197     sigaddset(&gl->all_signal_set, signo);
10198   };
10199 /*
10200  * Record the new signal attributes.
10201  */
10202   sig->flags = flags;
10203   sig->after = after;
10204   sig->errno_value = errno_value;
10205   return 0;
10206 }
10207 
10208 /*.......................................................................
10209  * Remove a signal from the list of signals that gl_get_line() traps.
10210  *
10211  * Input:
10212  *  gl           GetLine *  The resource object of gl_get_line().
10213  *  signo            int    The number of the signal to be ignored.
10214  * Output:
10215  *  return           int    0 - OK.
10216  *                          1 - Error.
10217  */
10218 int gl_ignore_signal(GetLine *gl, int signo)
10219 {
10220   GlSignalNode *sig;  /* The gl->sigs list node of the specified signal */
10221   GlSignalNode *prev; /* The node that precedes sig in the list */
10222   sigset_t oldset;    /* The signals that were blocked on entry to this */
10223                       /*  function. */
10224 /*
10225  * Check the arguments.
10226  */
10227   if(!gl) {
10228     errno = EINVAL;
10229     return 1;
10230   };
10231 /*
10232  * Block all signals while modifying the contents of gl.
10233  */
10234   if(gl_mask_signals(gl, &oldset))
10235     return 1;
10236 /*
10237  * Find the node of the gl->sigs list which records the disposition
10238  * of the specified signal.
10239  */
10240   for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo;
10241       prev=sig,sig=sig->next)
10242     ;
10243   if(sig) {
10244 /*
10245  * Remove the node from the list.
10246  */
10247     if(prev)
10248       prev->next = sig->next;
10249     else
10250       gl->sigs = sig->next;
10251 /*
10252  * Return the node to the freelist.
10253  */
10254     sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10255 /*
10256  * Remove the signal from the bit-mask union of signals being trapped.
10257  */
10258     sigdelset(&gl->all_signal_set, signo);
10259   };
10260 /*
10261  * Restore the process signal mask before returning.
10262  */
10263   gl_unmask_signals(gl, &oldset);
10264   return 0;
10265 }
10266 
10267 /*.......................................................................
10268  * This function is called when an input line has been completed. It
10269  * appends the specified newline character, terminates the line,
10270  * records the line in the history buffer if appropriate, and positions
10271  * the terminal cursor at the start of the next line.
10272  *
10273  * Input:
10274  *  gl           GetLine *  The resource object of gl_get_line().
10275  *  newline_char     int    The newline character to add to the end
10276  *                          of the line.
10277  * Output:
10278  *  return           int    0 - OK.
10279  *                          1 - Error.
10280  */
10281 static int gl_line_ended(GetLine *gl, int newline_char)
10282 {
10283 /*
10284  * If the newline character is printable, display it at the end of
10285  * the line, and add it to the input line buffer.
10286  */
10287   if(isprint((int)(unsigned char) newline_char)) {
10288     if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char))
10289       return 1;
10290   } else {
10291 /*
10292  * Otherwise just append a newline character to the input line buffer.
10293  */
10294     newline_char = '\n';
10295     gl_buffer_char(gl, newline_char, gl->ntotal);
10296   };
10297 /*
10298  * Add the line to the history buffer if it was entered with a
10299  * newline character.
10300  */
10301   if(gl->echo && gl->automatic_history && newline_char=='\n')
10302     (void) _gl_append_history(gl, gl->line);
10303 /*
10304  * Except when depending on the system-provided line editing, start a new
10305  * line after the end of the line that has just been entered.
10306  */
10307   if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1))
10308     return 1;
10309 /*
10310  * Record the successful return status.
10311  */
10312   gl_record_status(gl, GLR_NEWLINE, 0);
10313 /*
10314  * Attempt to flush any pending output.
10315  */
10316   (void) gl_flush_output(gl);
10317 /*
10318  * The next call to gl_get_line() will write the prompt for a new line
10319  * (or continue the above flush if incomplete), so if we manage to
10320  * flush the terminal now, report that we are waiting to write to the
10321  * terminal.
10322  */
10323   gl->pending_io = GLP_WRITE;
10324   return 0;
10325 }
10326 
10327 /*.......................................................................
10328  * Return the last signal that was caught by the most recent call to
10329  * gl_get_line(), or -1 if no signals were caught. This is useful if
10330  * gl_get_line() returns errno=EINTR and you need to find out what signal
10331  * caused it to abort.
10332  *
10333  * Input:
10334  *  gl           GetLine *  The resource object of gl_get_line().
10335  * Output:
10336  *  return           int    The last signal caught by the most recent
10337  *                          call to gl_get_line(), or -1 if no signals
10338  *                          were caught.
10339  */
10340 int gl_last_signal(GetLine *gl)
10341 {
10342   int signo = -1;   /* The requested signal number */
10343   if(gl) {
10344     sigset_t oldset; /* The signals that were blocked on entry to this block */
10345 /*
10346  * Temporarily block all signals.
10347  */
10348     gl_mask_signals(gl, &oldset);
10349 /*
10350  * Access gl now that signals are blocked.
10351  */
10352     signo = gl->last_signal;
10353 /*
10354  * Restore the process signal mask before returning.
10355  */
10356     gl_unmask_signals(gl, &oldset);
10357   };
10358   return signo;
10359 }
10360 
10361 /*.......................................................................
10362  * Prepare to edit a new line.
10363  *
10364  * Input:
10365  *  gl         GetLine *  The resource object of this library.
10366  *  prompt        char *  The prompt to prefix the line with, or NULL to
10367  *                        use the same prompt that was used by the previous
10368  *                        line.
10369  *  start_line    char *  The initial contents of the input line, or NULL
10370  *                        if it should start out empty.
10371  *  start_pos      int    If start_line isn't NULL, this specifies the
10372  *                        index of the character over which the cursor
10373  *                        should initially be positioned within the line.
10374  *                        If you just want it to follow the last character
10375  *                        of the line, send -1.
10376  * Output:
10377  *  return    int    0 - OK.
10378  *                   1 - Error.
10379  */
10380 static int gl_present_line(GetLine *gl, const char *prompt,
10381 			   const char *start_line, int start_pos)
10382 {
10383 /*
10384  * Prepare the line-editing properties for a new editing session.
10385  */
10386   gl_reset_editor(gl);
10387 /*
10388  * Record the new prompt and its displayed width.
10389  */
10390   if(prompt)
10391     _gl_replace_prompt(gl, prompt);
10392 /*
10393  * Reset the history search pointers.
10394  */
10395   if(_glh_cancel_search(gl->glh)) {
10396     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
10397     return 1;
10398   };
10399 /*
10400  * If the previous line was entered via the repeat-history action,
10401  * preload the specified history line.
10402  */
10403   if(gl->preload_history) {
10404     gl->preload_history = 0;
10405     if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) {
10406       gl_update_buffer(gl);          /* Compute gl->ntotal etc.. */
10407       gl->buff_curpos = gl->ntotal;
10408     } else {
10409       gl_truncate_buffer(gl, 0);
10410     };
10411     gl->preload_id = 0;
10412 /*
10413  * Present a specified initial line?
10414  */
10415   } else if(start_line) {
10416     char *cptr;      /* A pointer into gl->line[] */
10417 /*
10418  * Measure the length of the starting line.
10419  */
10420     int start_len = strlen(start_line);
10421 /*
10422  * If the length of the line is greater than the available space,
10423  * truncate it.
10424  */
10425     if(start_len > gl->linelen)
10426       start_len = gl->linelen;
10427 /*
10428  * Load the line into the buffer.
10429  */
10430     if(start_line != gl->line) {
10431       gl_truncate_buffer(gl, 0);
10432       gl_buffer_string(gl, start_line, start_len, 0);
10433     };
10434 /*
10435  * Strip off any trailing newline and carriage return characters.
10436  */
10437     for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line &&
10438 	(*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--)
10439       ;
10440     gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal);
10441 /*
10442  * Where should the cursor be placed within the line?
10443  */
10444     if(start_pos < 0 || start_pos > gl->ntotal) {
10445       if(gl_place_cursor(gl, gl->ntotal))
10446 	return 1;
10447     } else {
10448       if(gl_place_cursor(gl, start_pos))
10449 	return 1;
10450     };
10451 /*
10452  * Clear the input line?
10453  */
10454   } else {
10455     gl_truncate_buffer(gl, 0);
10456   };
10457 /*
10458  * Arrange for the line to be displayed by gl_flush_output().
10459  */
10460   gl_queue_redisplay(gl);
10461 /*
10462  * Update the display.
10463  */
10464   return gl_flush_output(gl);
10465 }
10466 
10467 /*.......................................................................
10468  * Reset all line-editing parameters for a new editing session. Note
10469  * that this does not empty the input line, since that would prevent a
10470  * gl_get_line() caller from specifying the returned line buffer as
10471  * the start_line argument of the next call to gl_get_line().
10472  *
10473  * Input:
10474  *  gl      GetLine *  The line editor resource object.
10475  */
10476 static void gl_reset_editor(GetLine *gl)
10477 {
10478 /*
10479  * Warning: Don't clear gl->line[] and gl->ntotal here (see above).
10480  */
10481   gl->buff_curpos = 0;
10482   gl->term_curpos = 0;
10483   gl->term_len = 0;
10484   gl->insert_curpos = 0;
10485   gl->number = -1;
10486   gl->displayed = 0;
10487   gl->endline = 0;
10488   gl->redisplay = 0;
10489   gl->postpone = 0;
10490   gl->nbuf = 0;
10491   gl->nread = 0;
10492   gl->vi.command = 0;
10493   gl->vi.undo.line[0] = '\0';
10494   gl->vi.undo.ntotal = 0;
10495   gl->vi.undo.buff_curpos = 0;
10496   gl->vi.repeat.action.fn = 0;
10497   gl->vi.repeat.action.data = 0;
10498   gl->last_signal = -1;
10499 }
10500 
10501 /*.......................................................................
10502  * Print an informational message to the terminal, after starting a new
10503  * line.
10504  *
10505  * Input:
10506  *  gl      GetLine *  The line editor resource object.
10507  *  ...  const char *  Zero or more strings to be printed.
10508  *  ...        void *  The last argument must always be GL_END_INFO.
10509  * Output:
10510  *  return      int    0 - OK.
10511  *                     1 - Error.
10512  */
10513 static int gl_print_info(GetLine *gl, ...)
10514 {
10515   va_list ap;     /* The variable argument list */
10516   const char *s;  /* The string being printed */
10517   int waserr = 0; /* True after an error */
10518 /*
10519  * Only display output when echoing is on.
10520  */
10521   if(gl->echo) {
10522 /*
10523  * Skip to the start of the next empty line before displaying the message.
10524  */
10525     if(gl_start_newline(gl, 1))
10526       return 1;
10527 /*
10528  * Display the list of provided messages.
10529  */
10530     va_start(ap, gl);
10531     while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO)
10532       waserr = gl_print_raw_string(gl, 1, s, -1);
10533     va_end(ap);
10534 /*
10535  * Start a newline.
10536  */
10537     waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1);
10538 /*
10539  * Arrange for the input line to be redrawn.
10540  */
10541     gl_queue_redisplay(gl);
10542   };
10543   return waserr;
10544 }
10545 
10546 /*.......................................................................
10547  * Go to the start of the next empty line, ready to output miscellaneous
10548  * text to the screen.
10549  *
10550  * Note that when async-signal safety is required, the 'buffered'
10551  * argument must be 0.
10552  *
10553  * Input:
10554  *  gl          GetLine *  The line editor resource object.
10555  *  buffered        int    If true, used buffered I/O when writing to
10556  *                         the terminal. Otherwise use async-signal-safe
10557  *                         unbuffered I/O.
10558  * Output:
10559  *  return          int    0 - OK.
10560  *                         1 - Error.
10561  */
10562 static int gl_start_newline(GetLine *gl, int buffered)
10563 {
10564   int waserr = 0;  /* True after any I/O error */
10565 /*
10566  * Move the cursor to the start of the terminal line that follows the
10567  * last line of the partially enterred line. In order that this
10568  * function remain async-signal safe when write_fn is signal safe, we
10569  * can't call our normal output functions, since they call tputs(),
10570  * who's signal saftey isn't defined. Fortunately, we can simply use
10571  * \r and \n to move the cursor to the right place.
10572  */
10573   if(gl->displayed) {   /* Is an input line currently displayed? */
10574 /*
10575  * On which terminal lines are the cursor and the last character of the
10576  * input line?
10577  */
10578     int curs_line = gl->term_curpos / gl->ncolumn;
10579     int last_line = gl->term_len / gl->ncolumn;
10580 /*
10581  * Move the cursor to the start of the line that follows the last
10582  * terminal line that is occupied by the input line.
10583  */
10584     for( ; curs_line < last_line + 1; curs_line++)
10585       waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1);
10586     waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1);
10587 /*
10588  * Mark the line as no longer displayed.
10589  */
10590     gl_line_erased(gl);
10591   };
10592   return waserr;
10593 }
10594 
10595 /*.......................................................................
10596  * The callback through which all terminal output is routed.
10597  * This simply appends characters to a queue buffer, which is
10598  * subsequently flushed to the output channel by gl_flush_output().
10599  *
10600  * Input:
10601  *  data     void *  The pointer to a GetLine line editor resource object
10602  *                   cast to (void *).
10603  *  s  const char *  The string to be written.
10604  *  n         int    The number of characters to write from s[].
10605  * Output:
10606  *  return    int    The number of characters written. This will always
10607  *                   be equal to 'n' unless an error occurs.
10608  */
10609 static GL_WRITE_FN(gl_write_fn)
10610 {
10611   GetLine *gl = (GetLine *) data;
10612   int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl);
10613   if(ndone != n)
10614     _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG);
10615   return ndone;
10616 }
10617 
10618 /*.......................................................................
10619  * Ask gl_get_line() what caused it to return.
10620  *
10621  * Input:
10622  *  gl             GetLine *  The line editor resource object.
10623  * Output:
10624  *  return  GlReturnStatus    The return status of the last call to
10625  *                            gl_get_line().
10626  */
10627 GlReturnStatus gl_return_status(GetLine *gl)
10628 {
10629   GlReturnStatus rtn_status = GLR_ERROR;   /* The requested status */
10630   if(gl) {
10631     sigset_t oldset; /* The signals that were blocked on entry to this block */
10632 /*
10633  * Temporarily block all signals.
10634  */
10635     gl_mask_signals(gl, &oldset);
10636 /*
10637  * Access gl while signals are blocked.
10638  */
10639     rtn_status = gl->rtn_status;
10640 /*
10641  * Restore the process signal mask before returning.
10642  */
10643     gl_unmask_signals(gl, &oldset);
10644   };
10645   return rtn_status;
10646 }
10647 
10648 /*.......................................................................
10649  * In non-blocking server-I/O mode, this function should be called
10650  * from the application's external event loop to see what type of
10651  * terminal I/O is being waited for by gl_get_line(), and thus what
10652  * direction of I/O to wait for with select() or poll().
10653  *
10654  * Input:
10655  *  gl          GetLine *  The resource object of gl_get_line().
10656  * Output:
10657  *  return  GlPendingIO    The type of pending I/O being waited for.
10658  */
10659 GlPendingIO gl_pending_io(GetLine *gl)
10660 {
10661   GlPendingIO pending_io = GLP_WRITE;   /* The requested information */
10662   if(gl) {
10663     sigset_t oldset; /* The signals that were blocked on entry to this block */
10664 /*
10665  * Temporarily block all signals.
10666  */
10667     gl_mask_signals(gl, &oldset);
10668 /*
10669  * Access gl while signals are blocked.
10670  */
10671     pending_io = gl->pending_io;
10672 /*
10673  * Restore the process signal mask before returning.
10674  */
10675     gl_unmask_signals(gl, &oldset);
10676   };
10677   return pending_io;
10678 }
10679 
10680 /*.......................................................................
10681  * In server mode, this function configures the terminal for non-blocking
10682  * raw terminal I/O. In normal I/O mode it does nothing.
10683  *
10684  * Callers of this function must be careful to trap all signals that
10685  * terminate or suspend the program, and call gl_normal_io()
10686  * from the corresponding signal handlers in order to restore the
10687  * terminal to its original settings before the program is terminated
10688  * or suspended. They should also trap the SIGCONT signal to detect
10689  * when the program resumes, and ensure that its signal handler
10690  * call gl_raw_io() to redisplay the line and resume editing.
10691  *
10692  * This function is async signal safe.
10693  *
10694  * Input:
10695  *  gl      GetLine *  The line editor resource object.
10696  * Output:
10697  *  return      int    0 - OK.
10698  *                     1 - Error.
10699  */
10700 int gl_raw_io(GetLine *gl)
10701 {
10702   sigset_t oldset; /* The signals that were blocked on entry to this function */
10703   int status;      /* The return status of _gl_raw_io() */
10704 /*
10705  * Check the arguments.
10706  */
10707   if(!gl) {
10708     errno = EINVAL;
10709     return 1;
10710   };
10711 /*
10712  * Block all signals.
10713  */
10714   if(gl_mask_signals(gl, &oldset))
10715     return 1;
10716 /*
10717  * Don't allow applications to switch into raw mode unless in server mode.
10718  */
10719   if(gl->io_mode != GL_SERVER_MODE) {
10720     _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode",
10721 		    END_ERR_MSG);
10722     errno = EPERM;
10723     status = 1;
10724   } else {
10725 /*
10726  * Execute the private body of the function while signals are blocked.
10727  */
10728     status = _gl_raw_io(gl, 1);
10729   };
10730 /*
10731  * Restore the process signal mask.
10732  */
10733   gl_unmask_signals(gl, &oldset);
10734   return status;
10735 }
10736 
10737 /*.......................................................................
10738  * This is the private body of the public function, gl_raw_io().
10739  * It assumes that the caller has checked its arguments and blocked the
10740  * delivery of signals.
10741  *
10742  * This function is async signal safe.
10743  */
10744 static int _gl_raw_io(GetLine *gl, int redisplay)
10745 {
10746 /*
10747  * If we are already in the correct mode, do nothing.
10748  */
10749   if(gl->raw_mode)
10750     return 0;
10751 /*
10752  * Switch the terminal to raw mode.
10753  */
10754   if(gl->is_term && gl_raw_terminal_mode(gl))
10755     return 1;
10756 /*
10757  * Switch to non-blocking I/O mode?
10758  */
10759   if(gl->io_mode==GL_SERVER_MODE &&
10760      (gl_nonblocking_io(gl, gl->input_fd) ||
10761       gl_nonblocking_io(gl, gl->output_fd) ||
10762       (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) {
10763     if(gl->is_term)
10764       gl_restore_terminal_attributes(gl);
10765     return 1;
10766   };
10767 /*
10768  * If an input line is being entered, arrange for it to be
10769  * displayed.
10770  */
10771   if(redisplay) {
10772     gl->postpone = 0;
10773     gl_queue_redisplay(gl);
10774   };
10775   return 0;
10776 }
10777 
10778 /*.......................................................................
10779  * Restore the terminal to the state that it had when
10780  * gl_raw_io() was last called. After calling
10781  * gl_raw_io(), this function must be called before
10782  * terminating or suspending the program, and before attempting other
10783  * uses of the terminal from within the program. See gl_raw_io()
10784  * for more details.
10785  *
10786  * Input:
10787  *  gl      GetLine *  The line editor resource object.
10788  * Output:
10789  *  return      int    0 - OK.
10790  *                     1 - Error.
10791  */
10792 int gl_normal_io(GetLine *gl)
10793 {
10794   sigset_t oldset; /* The signals that were blocked on entry to this function */
10795   int status;      /* The return status of _gl_normal_io() */
10796 /*
10797  * Check the arguments.
10798  */
10799   if(!gl) {
10800     errno = EINVAL;
10801     return 1;
10802   };
10803 /*
10804  * Block all signals.
10805  */
10806   if(gl_mask_signals(gl, &oldset))
10807     return 1;
10808 /*
10809  * Execute the private body of the function while signals are blocked.
10810  */
10811   status = _gl_normal_io(gl);
10812 /*
10813  * Restore the process signal mask.
10814  */
10815   gl_unmask_signals(gl, &oldset);
10816   return status;
10817 }
10818 
10819 /*.......................................................................
10820  * This is the private body of the public function, gl_normal_io().
10821  * It assumes that the caller has checked its arguments and blocked the
10822  * delivery of signals.
10823  */
10824 static int _gl_normal_io(GetLine *gl)
10825 {
10826 /*
10827  * If we are already in normal mode, do nothing.
10828  */
10829   if(!gl->raw_mode)
10830     return 0;
10831 /*
10832  * Postpone subsequent redisplays until after _gl_raw_io(gl, 1)
10833  * is next called.
10834  */
10835   gl->postpone = 1;
10836 /*
10837  * Switch back to blocking I/O. Note that this is essential to do
10838  * here, because when using non-blocking I/O, the terminal output
10839  * buffering code can't always make room for new output without calling
10840  * malloc(), and a call to malloc() would mean that this function
10841  * couldn't safely be called from signal handlers.
10842  */
10843   if(gl->io_mode==GL_SERVER_MODE &&
10844      (gl_blocking_io(gl, gl->input_fd) ||
10845       gl_blocking_io(gl, gl->output_fd) ||
10846       (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp)))))
10847     return 1;
10848 /*
10849  * Move the cursor to the next empty terminal line. Note that
10850  * unbuffered I/O is requested, to ensure that gl_start_newline() be
10851  * async-signal-safe.
10852  */
10853   if(gl->is_term && gl_start_newline(gl, 0))
10854     return 1;
10855 /*
10856  * Switch the terminal to normal mode.
10857  */
10858   if(gl->is_term && gl_restore_terminal_attributes(gl)) {
10859 /*
10860  * On error, revert to non-blocking I/O if needed, so that on failure
10861  * we remain in raw mode.
10862  */
10863     if(gl->io_mode==GL_SERVER_MODE) {
10864       gl_nonblocking_io(gl, gl->input_fd);
10865       gl_nonblocking_io(gl, gl->output_fd);
10866       if(gl->file_fp)
10867 	gl_nonblocking_io(gl, fileno(gl->file_fp));
10868     };
10869     return 1;
10870   };
10871   return 0;
10872 }
10873 
10874 /*.......................................................................
10875  * This function allows you to install an additional completion
10876  * action, or to change the completion function of an existing
10877  * one. This should be called before the first call to gl_get_line()
10878  * so that the name of the action be defined before the user's
10879  * configuration file is read.
10880  *
10881  * Input:
10882  *  gl            GetLine *  The resource object of the command-line input
10883  *                           module.
10884  *  data             void *  This is passed to match_fn() whenever it is
10885  *                           called. It could, for example, point to a
10886  *                           symbol table that match_fn() would look up
10887  *                           matches in.
10888  *  match_fn   CplMatchFn *  The function that will identify the prefix
10889  *                           to be completed from the input line, and
10890  *                           report matching symbols.
10891  *  list_only         int    If non-zero, install an action that only lists
10892  *                           possible completions, rather than attempting
10893  *                           to perform the completion.
10894  *  name       const char *  The name with which users can refer to the
10895  *                           binding in tecla configuration files.
10896  *  keyseq     const char *  Either NULL, or a key sequence with which
10897  *                           to invoke the binding. This should be
10898  *                           specified in the same manner as key-sequences
10899  *                           in tecla configuration files (eg. "M-^I").
10900  * Output:
10901  *  return            int    0 - OK.
10902  *                           1 - Error.
10903  */
10904 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10905 			 int list_only, const char *name, const char *keyseq)
10906 {
10907   sigset_t oldset; /* The signals that were blocked on entry to this function */
10908   int status;      /* The return status of _gl_completion_action() */
10909 /*
10910  * Check the arguments.
10911  */
10912   if(!gl || !name || !match_fn) {
10913     errno = EINVAL;
10914     return 1;
10915   };
10916 /*
10917  * Block all signals.
10918  */
10919   if(gl_mask_signals(gl, &oldset))
10920     return 1;
10921 /*
10922  * Install the new action while signals are blocked.
10923  */
10924   status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq);
10925 /*
10926  * Restore the process signal mask.
10927  */
10928   gl_unmask_signals(gl, &oldset);
10929   return status;
10930 }
10931 
10932 /*.......................................................................
10933  * This is the private body of the public function, gl_completion_action().
10934  * It assumes that the caller has checked its arguments and blocked the
10935  * delivery of signals.
10936  */
10937 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10938 				 int list_only, const char *name,
10939 				 const char *keyseq)
10940 {
10941   KtKeyFn *current_fn;      /* An existing action function */
10942   void *current_data;       /* The action-function callback data */
10943 /*
10944  * Which action function is desired?
10945  */
10946   KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word;
10947 /*
10948  * Is there already an action of the specified name?
10949  */
10950   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
10951 /*
10952  * If the action has the same type as the one being requested,
10953  * simply change the contents of its GlCplCallback callback data.
10954  */
10955     if(current_fn == action_fn) {
10956       GlCplCallback *cb = (GlCplCallback *) current_data;
10957       cb->fn = match_fn;
10958       cb->data = data;
10959     } else {
10960       errno = EINVAL;
10961       _err_record_msg(gl->err,
10962         "Illegal attempt to change the type of an existing completion action",
10963         END_ERR_MSG);
10964       return 1;
10965     };
10966 /*
10967  * No existing action has the specified name.
10968  */
10969   } else {
10970 /*
10971  * Allocate a new GlCplCallback callback object.
10972  */
10973     GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem);
10974     if(!cb) {
10975       errno = ENOMEM;
10976       _err_record_msg(gl->err, "Insufficient memory to add completion action",
10977 		      END_ERR_MSG);
10978       return 1;
10979     };
10980 /*
10981  * Record the completion callback data.
10982  */
10983     cb->fn = match_fn;
10984     cb->data = data;
10985 /*
10986  * Attempt to register the new action.
10987  */
10988     if(_kt_set_action(gl->bindings, name, action_fn, cb)) {
10989       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10990       _del_FreeListNode(gl->cpl_mem, (void *) cb);
10991       return 1;
10992     };
10993   };
10994 /*
10995  * Bind the action to a given key-sequence?
10996  */
10997   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
10998     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10999     return 1;
11000   };
11001   return 0;
11002 }
11003 
11004 /*.......................................................................
11005  * Register an application-provided function as an action function.
11006  * This should preferably be called before the first call to gl_get_line()
11007  * so that the name of the action becomes defined before the user's
11008  * configuration file is read.
11009  *
11010  * Input:
11011  *  gl            GetLine *  The resource object of the command-line input
11012  *                           module.
11013  *  data             void *  Arbitrary application-specific callback
11014  *                           data to be passed to the callback
11015  *                           function, fn().
11016  *  fn         GlActionFn *  The application-specific function that
11017  *                           implements the action. This will be invoked
11018  *                           whenever the user presses any
11019  *                           key-sequence which is bound to this action.
11020  *  name       const char *  The name with which users can refer to the
11021  *                           binding in tecla configuration files.
11022  *  keyseq     const char *  The key sequence with which to invoke
11023  *                           the binding. This should be specified in the
11024  *                           same manner as key-sequences in tecla
11025  *                           configuration files (eg. "M-^I").
11026  * Output:
11027  *  return            int    0 - OK.
11028  *                           1 - Error.
11029  */
11030 int gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11031                        const char *name, const char *keyseq)
11032 {
11033   sigset_t oldset; /* The signals that were blocked on entry to this function */
11034   int status;      /* The return status of _gl_register_action() */
11035 /*
11036  * Check the arguments.
11037  */
11038   if(!gl || !name || !fn) {
11039     errno = EINVAL;
11040     return 1;
11041   };
11042 /*
11043  * Block all signals.
11044  */
11045   if(gl_mask_signals(gl, &oldset))
11046     return 1;
11047 /*
11048  * Install the new action while signals are blocked.
11049  */
11050   status = _gl_register_action(gl, data, fn, name, keyseq);
11051 /*
11052  * Restore the process signal mask.
11053  */
11054   gl_unmask_signals(gl, &oldset);
11055   return status;
11056 }
11057 
11058 /*.......................................................................
11059  * This is the private body of the public function, gl_register_action().
11060  * It assumes that the caller has checked its arguments and blocked the
11061  * delivery of signals.
11062  */
11063 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11064 			       const char *name, const char *keyseq)
11065 {
11066   KtKeyFn *current_fn;      /* An existing action function */
11067   void *current_data;       /* The action-function callback data */
11068 /*
11069  * Get the action function which actually runs the application-provided
11070  * function.
11071  */
11072   KtKeyFn *action_fn = gl_run_external_action;
11073 /*
11074  * Is there already an action of the specified name?
11075  */
11076   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
11077 /*
11078  * If the action has the same type as the one being requested,
11079  * simply change the contents of its GlCplCallback callback data.
11080  */
11081     if(current_fn == action_fn) {
11082       GlExternalAction *a = (GlExternalAction *) current_data;
11083       a->fn = fn;
11084       a->data = data;
11085     } else {
11086       errno = EINVAL;
11087       _err_record_msg(gl->err,
11088         "Illegal attempt to change the type of an existing action",
11089 		      END_ERR_MSG);
11090       return 1;
11091     };
11092 /*
11093  * No existing action has the specified name.
11094  */
11095   } else {
11096 /*
11097  * Allocate a new GlCplCallback callback object.
11098  */
11099     GlExternalAction *a =
11100       (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem);
11101     if(!a) {
11102       errno = ENOMEM;
11103       _err_record_msg(gl->err, "Insufficient memory to add completion action",
11104 		      END_ERR_MSG);
11105       return 1;
11106     };
11107 /*
11108  * Record the completion callback data.
11109  */
11110     a->fn = fn;
11111     a->data = data;
11112 /*
11113  * Attempt to register the new action.
11114  */
11115     if(_kt_set_action(gl->bindings, name, action_fn, a)) {
11116       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11117       _del_FreeListNode(gl->cpl_mem, (void *) a);
11118       return 1;
11119     };
11120   };
11121 /*
11122  * Bind the action to a given key-sequence?
11123  */
11124   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
11125     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11126     return 1;
11127   };
11128   return 0;
11129 }
11130 
11131 /*.......................................................................
11132  * Invoke an action function previously registered by a call to
11133  * gl_register_action().
11134  */
11135 static KT_KEY_FN(gl_run_external_action)
11136 {
11137   GlAfterAction status;  /* The return value of the action function */
11138 /*
11139  * Get the container of the action function and associated callback data.
11140  */
11141   GlExternalAction *a = (GlExternalAction *) data;
11142 /*
11143  * Invoke the action function.
11144  */
11145   status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line);
11146 /*
11147  * If the callback took us out of raw (possibly non-blocking) input
11148  * mode, restore this mode, and queue a redisplay of the input line.
11149  */
11150   if(_gl_raw_io(gl, 1))
11151     return 1;
11152 /*
11153  * Finally, check to see what the action function wants us to do next.
11154  */
11155   switch(status) {
11156   default:
11157   case GLA_ABORT:
11158     gl_record_status(gl, GLR_ERROR, errno);
11159     return 1;
11160     break;
11161   case GLA_RETURN:
11162     return gl_newline(gl, 1, NULL);
11163     break;
11164   case GLA_CONTINUE:
11165     break;
11166   };
11167   return 0;
11168 }
11169 
11170 /*.......................................................................
11171  * In server-I/O mode the terminal is left in raw mode between calls
11172  * to gl_get_line(), so it is necessary for the application to install
11173  * terminal restoring signal handlers for signals that could terminate
11174  * or suspend the process, plus a terminal reconfiguration handler to
11175  * be called when a process resumption signal is received, and finally
11176  * a handler to be called when a terminal-resize signal is received.
11177  *
11178  * Since there are many signals that by default terminate or suspend
11179  * processes, and different systems support different sub-sets of
11180  * these signals, this function provides a convenient wrapper around
11181  * sigaction() for assigning the specified handlers to all appropriate
11182  * signals. It also arranges that when any one of these signals is
11183  * being handled, all other catchable signals are blocked. This is
11184  * necessary so that the specified signal handlers can safely call
11185  * gl_raw_io(), gl_normal_io() and gl_update_size() without
11186  * reentrancy issues.
11187  *
11188  * Input:
11189  *  term_handler  void (*)(int)  The signal handler to invoke when
11190  *                               a process-terminating signal is
11191  *                               received.
11192  *  susp_handler  void (*)(int)  The signal handler to invoke when
11193  *                               a process-suspending signal is
11194  *                               received.
11195  *  cont_handler  void (*)(int)  The signal handler to invoke when
11196  *                               a process-resumption signal is
11197  *                               received (ie. SIGCONT).
11198  *  size_handler  void (*)(int)  The signal handler to invoke when
11199  *                               a terminal-resize signal (ie. SIGWINCH)
11200  *                               is received.
11201  * Output:
11202  *  return                  int  0 - OK.
11203  *                               1 - Error.
11204  */
11205 int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int),
11206 		   void (*cont_handler)(int), void (*size_handler)(int))
11207 {
11208   int i;
11209 /*
11210  * Search for signals of the specified classes, and assign the
11211  * associated signal handler to them.
11212  */
11213   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11214     const struct GlDefSignal *sig = gl_signal_list + i;
11215     if(sig->attr & GLSA_SUSP) {
11216       if(gl_set_tty_signal(sig->signo, susp_handler))
11217 	return 1;
11218     } else if(sig->attr & GLSA_TERM) {
11219       if(gl_set_tty_signal(sig->signo, term_handler))
11220 	return 1;
11221     } else if(sig->attr & GLSA_CONT) {
11222       if(gl_set_tty_signal(sig->signo, cont_handler))
11223 	return 1;
11224     } else if(sig->attr & GLSA_SIZE) {
11225       if(gl_set_tty_signal(sig->signo, size_handler))
11226 	return 1;
11227     };
11228   };
11229   return 0;
11230 }
11231 
11232 /*.......................................................................
11233  * This is a private function of gl_tty_signals(). It installs a given
11234  * signal handler, and arranges that when that signal handler is being
11235  * invoked other signals are blocked. The latter is important to allow
11236  * functions like gl_normal_io(), gl_raw_io() and gl_update_size()
11237  * to be called from signal handlers.
11238  *
11239  * Input:
11240  *  signo     int           The signal to be trapped.
11241  *  handler  void (*)(int)  The signal handler to assign to the signal.
11242  */
11243 static int gl_set_tty_signal(int signo, void (*handler)(int))
11244 {
11245   SigAction act;   /* The signal handler configuation */
11246 /*
11247  * Arrange to block all trappable signals except the one that is being
11248  * assigned (the trapped signal will be blocked automatically by the
11249  * system).
11250  */
11251   gl_list_trappable_signals(&act.sa_mask);
11252   sigdelset(&act.sa_mask, signo);
11253 /*
11254  * Assign the signal handler.
11255  */
11256   act.sa_handler = handler;
11257 /*
11258  * There is only one portable signal handling flag, and it isn't
11259  * relevant to us, so don't specify any flags.
11260  */
11261   act.sa_flags = 0;
11262 /*
11263  * Register the signal handler.
11264  */
11265   if(sigaction(signo, &act, NULL))
11266     return 1;
11267   return 0;
11268 }
11269 
11270 /*.......................................................................
11271  * Display a left-justified string over multiple terminal lines,
11272  * taking account of the current width of the terminal. Optional
11273  * indentation and an optional prefix string can be specified to be
11274  * displayed at the start of each new terminal line used. Similarly,
11275  * an optional suffix can be specified to be displayed at the end of
11276  * each terminal line.  If needed, a single paragraph can be broken
11277  * across multiple calls.  Note that literal newlines in the input
11278  * string can be used to force a newline at any point and that you
11279  * should use this feature to explicitly end all paragraphs, including
11280  * at the end of the last string that you write. Note that when a new
11281  * line is started between two words that are separated by spaces,
11282  * those spaces are not output, whereas when a new line is started
11283  * because a newline character was found in the string, only the
11284  * spaces before the newline character are discarded.
11285  *
11286  * Input:
11287  *  gl         GetLine *  The resource object of gl_get_line().
11288  *  indentation    int    The number of spaces of indentation to write
11289  *                        at the beginning of each new terminal line.
11290  *  prefix  const char *  An optional prefix string to write after the
11291  *                        indentation margin at the start of each new
11292  *                        terminal line. You can specify NULL if no
11293  *                        prefix is required.
11294  *  suffix  const char *  An optional suffix string to draw at the end
11295  *                        of the terminal line. Spaces will be added
11296  *                        where necessary to ensure that the suffix ends
11297  *                        in the last column of the terminal line. If
11298  *                        no suffix is desired, specify NULL.
11299  *  fill_char      int    The padding character to use when indenting
11300  *                        the line or padding up to the suffix.
11301  *  def_width      int    If the terminal width isn't known, such as when
11302  *                        writing to a pipe or redirecting to a file,
11303  *                        this number specifies what width to assume.
11304  *  start          int    The number of characters already written to
11305  *                        the start of the current terminal line. This
11306  *                        is primarily used to allow individual
11307  *                        paragraphs to be written over multiple calls
11308  *                        to this function, but can also be used to
11309  *                        allow you to start the first line of a
11310  *                        paragraph with a different prefix or
11311  *                        indentation than those specified above.
11312  *  string  const char *  The string to be written.
11313  * Output:
11314  *  return         int    On error -1 is returned. Otherwise the
11315  *                        return value is the terminal column index at
11316  *                        which the cursor was left after writing the
11317  *                        final word in the string. Successful return
11318  *                        values can thus be passed verbatim to the
11319  *                        'start' arguments of subsequent calls to
11320  *                        gl_display_text() to allow the printing of a
11321  *                        paragraph to be broken across multiple calls
11322  *                        to gl_display_text().
11323  */
11324 int gl_display_text(GetLine *gl, int indentation, const char *prefix,
11325 		    const char *suffix, int fill_char,
11326 		    int def_width, int start, const char *string)
11327 {
11328   sigset_t oldset; /* The signals that were blocked on entry to this function */
11329   int status;      /* The return status of _gl_completion_action() */
11330 /*
11331  * Check the arguments?
11332  */
11333   if(!gl || !string) {
11334     errno = EINVAL;
11335     return -1;
11336   };
11337 /*
11338  * Block all signals.
11339  */
11340   if(gl_mask_signals(gl, &oldset))
11341     return -1;
11342 /*
11343  * Display the text while signals are blocked.
11344  */
11345   status = _io_display_text(_io_write_stdio, gl->output_fp, indentation,
11346 			    prefix, suffix, fill_char,
11347 			    gl->ncolumn > 0 ? gl->ncolumn : def_width,
11348 			    start, string);
11349 /*
11350  * Restore the process signal mask.
11351  */
11352   gl_unmask_signals(gl, &oldset);
11353   return status;
11354 }
11355 
11356 /*.......................................................................
11357  * Block all of the signals that we are currently trapping.
11358  *
11359  * Input:
11360  *  gl       GetLine *   The resource object of gl_get_line().
11361  * Input/Output:
11362  *  oldset   sigset_t *   The superseded process signal mask
11363  *                        will be return in *oldset unless oldset is
11364  *                        NULL.
11365  * Output:
11366  *  return        int     0 - OK.
11367  *                        1 - Error.
11368  */
11369 static int gl_mask_signals(GetLine *gl, sigset_t *oldset)
11370 {
11371 /*
11372  * Block all signals in all_signal_set, along with any others that are
11373  * already blocked by the application.
11374  */
11375   if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) {
11376     gl->signals_masked = 1;
11377     return 0;
11378   };
11379 /*
11380  * On error attempt to query the current process signal mask, so
11381  * that oldset be the correct process signal mask to restore later
11382  * if the caller of this function ignores the error return value.
11383  */
11384   if(oldset)
11385     (void) sigprocmask(SIG_SETMASK, NULL, oldset);
11386   gl->signals_masked = 0;
11387   return 1;
11388 }
11389 
11390 /*.......................................................................
11391  * Restore a process signal mask that was previously returned via the
11392  * oldset argument of gl_mask_signals().
11393  *
11394  * Input:
11395  *  gl        GetLine *   The resource object of gl_get_line().
11396  * Input/Output:
11397  *  oldset   sigset_t *   The process signal mask to be restored.
11398  * Output:
11399  *  return        int     0 - OK.
11400  *                        1 - Error.
11401  */
11402 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset)
11403 {
11404   gl->signals_masked = 0;
11405   return sigprocmask(SIG_SETMASK, oldset, NULL) < 0;
11406 }
11407 
11408 /*.......................................................................
11409  * Arrange to temporarily catch the signals marked in gl->use_signal_set.
11410  *
11411  * Input:
11412  *  gl        GetLine *   The resource object of gl_get_line().
11413  * Output:
11414  *  return        int     0 - OK.
11415  *                        1 - Error.
11416  */
11417 static int gl_catch_signals(GetLine *gl)
11418 {
11419   return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0;
11420 }
11421 
11422 /*.......................................................................
11423  * Select the I/O mode to be used by gl_get_line().
11424  *
11425  * Input:
11426  *  gl         GetLine *  The resource object of gl_get_line().
11427  *  mode      GlIOMode    The I/O mode to establish.
11428  * Output:
11429  *  return         int    0 - OK.
11430  *                        1 - Error.
11431  */
11432 int gl_io_mode(GetLine *gl, GlIOMode mode)
11433 {
11434   sigset_t oldset; /* The signals that were blocked on entry to this function */
11435   int status;      /* The return status of _gl_io_mode() */
11436 /*
11437  * Check the arguments.
11438  */
11439   if(!gl) {
11440     errno = EINVAL;
11441     return 1;
11442   };
11443 /*
11444  * Check that the requested mode is known.
11445  */
11446   switch(mode) {
11447   case GL_NORMAL_MODE:
11448   case GL_SERVER_MODE:
11449     break;
11450   default:
11451     errno = EINVAL;
11452     _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.",
11453 		    END_ERR_MSG);
11454     return 1;
11455   };
11456 /*
11457  * Block all signals.
11458  */
11459   if(gl_mask_signals(gl, &oldset))
11460     return 1;
11461 /*
11462  * Invoke the private body of this function.
11463  */
11464   status = _gl_io_mode(gl, mode);
11465 /*
11466  * Restore the process signal mask.
11467  */
11468   gl_unmask_signals(gl, &oldset);
11469   return status;
11470 }
11471 
11472 /*.......................................................................
11473  * This is the private body of the public function, gl_io_mode().
11474  * It assumes that the caller has checked its arguments and blocked the
11475  * delivery of signals.
11476  */
11477 static int _gl_io_mode(GetLine *gl, GlIOMode mode)
11478 {
11479 /*
11480  * Are we already in the specified mode?
11481  */
11482   if(mode == gl->io_mode)
11483     return 0;
11484 /*
11485  * First revert to normal I/O in the current I/O mode.
11486  */
11487   _gl_normal_io(gl);
11488 /*
11489  * Record the new mode.
11490  */
11491   gl->io_mode = mode;
11492 /*
11493  * Perform any actions needed by the new mode.
11494  */
11495   if(mode==GL_SERVER_MODE) {
11496     if(_gl_raw_io(gl, 1))
11497       return 1;
11498   };
11499   return 0;
11500 }
11501 
11502 /*.......................................................................
11503  * Return extra information (ie. in addition to that provided by errno)
11504  * about the last error to occur in either gl_get_line() or its
11505  * associated public functions.
11506  *
11507  * Input:
11508  *  gl         GetLine *  The resource object of gl_get_line().
11509  * Input/Output:
11510  *  buff          char *  An optional output buffer. Note that if the
11511  *                        calling application calls any gl_*()
11512  *                        functions from signal handlers, it should
11513  *                        provide a buffer here, so that a copy of
11514  *                        the latest error message can safely be made
11515  *                        while signals are blocked.
11516  *  n           size_t    The allocated size of buff[].
11517  * Output:
11518  *  return  const char *  A pointer to the error message. This will
11519  *                        be the buff argument, unless buff==NULL, in
11520  *                        which case it will be a pointer to an
11521  *                        internal error buffer. In the latter case,
11522  *                        note that the contents of the returned buffer
11523  *                        will change on subsequent calls to any gl_*()
11524  *                        functions.
11525  */
11526 const char *gl_error_message(GetLine *gl, char *buff, size_t n)
11527 {
11528   if(!gl) {
11529     static const char *msg = "NULL GetLine argument";
11530     if(buff) {
11531       strncpy(buff, msg, n);
11532       buff[n-1] = '\0';
11533     } else {
11534       return msg;
11535     };
11536   } else if(buff) {
11537     sigset_t oldset; /* The signals that were blocked on entry to this block */
11538 /*
11539  * Temporarily block all signals.
11540  */
11541     gl_mask_signals(gl, &oldset);
11542 /*
11543  * Copy the error message into the specified buffer.
11544  */
11545     if(buff && n > 0) {
11546       strncpy(buff, _err_get_msg(gl->err), n);
11547       buff[n-1] = '\0';
11548     };
11549 /*
11550  * Restore the process signal mask before returning.
11551  */
11552     gl_unmask_signals(gl, &oldset);
11553   } else {
11554     return _err_get_msg(gl->err);
11555   };
11556   return buff;
11557 }
11558 
11559 /*.......................................................................
11560  * Return the signal mask used by gl_get_line(). This is the set of
11561  * signals that gl_get_line() is currently configured to trap.
11562  *
11563  * Input:
11564  *  gl         GetLine *  The resource object of gl_get_line().
11565  * Input/Output:
11566  *  set       sigset_t *  The set of signals will be returned in *set,
11567  *                        in the form of a signal process mask, as
11568  *                        used by sigaction(), sigprocmask(),
11569  *                        sigpending(), sigsuspend(), sigsetjmp() and
11570  *                        other standard POSIX signal-aware
11571  *                        functions.
11572  * Output:
11573  *  return         int    0 - OK.
11574  *                        1 - Error (examine errno for reason).
11575  */
11576 int gl_list_signals(GetLine *gl, sigset_t *set)
11577 {
11578 /*
11579  * Check the arguments.
11580  */
11581   if(!gl || !set) {
11582     if(gl)
11583       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
11584     errno = EINVAL;
11585     return 1;
11586   };
11587 /*
11588  * Copy the signal mask into *set.
11589  */
11590   memcpy(set, &gl->all_signal_set, sizeof(*set));
11591   return 0;
11592 }
11593 
11594 /*.......................................................................
11595  * By default, gl_get_line() doesn't trap signals that are blocked
11596  * when it is called. This default can be changed either on a
11597  * per-signal basis by calling gl_trap_signal(), or on a global basis
11598  * by calling this function. What this function does is add the
11599  * GLS_UNBLOCK_SIG flag to all signals that are currently configured
11600  * to be trapped by gl_get_line(), such that when subsequent calls to
11601  * gl_get_line() wait for I/O, these signals are temporarily
11602  * unblocked. This behavior is useful in non-blocking server-I/O mode,
11603  * where it is used to avoid race conditions related to handling these
11604  * signals externally to gl_get_line(). See the demonstration code in
11605  * demo3.c, or the gl_handle_signal() man page for further
11606  * information.
11607  *
11608  * Input:
11609  *  gl         GetLine *   The resource object of gl_get_line().
11610  */
11611 void gl_catch_blocked(GetLine *gl)
11612 {
11613   sigset_t oldset;    /* The process signal mask to restore */
11614   GlSignalNode *sig;  /* A signal node in gl->sigs */
11615 /*
11616  * Check the arguments.
11617  */
11618   if(!gl) {
11619     errno = EINVAL;
11620     return;
11621   };
11622 /*
11623  * Temporarily block all signals while we modify the contents of gl.
11624  */
11625   gl_mask_signals(gl, &oldset);
11626 /*
11627  * Add the GLS_UNBLOCK_SIG flag to all configured signals.
11628  */
11629   for(sig=gl->sigs; sig; sig=sig->next)
11630     sig->flags |= GLS_UNBLOCK_SIG;
11631 /*
11632  * Restore the process signal mask that was superseded by the call
11633  * to gl_mask_signals().
11634  */
11635   gl_unmask_signals(gl, &oldset);
11636   return;
11637 }
11638 
11639 /*.......................................................................
11640  * Respond to signals who's default effects have important
11641  * consequences to gl_get_line(). This is intended for use in
11642  * non-blocking server mode, where the external event loop is
11643  * responsible for catching signals. Signals that are handled include
11644  * those that by default terminate or suspend the process, and the
11645  * signal that indicates that the terminal size has changed. Note that
11646  * this function is not signal safe and should thus not be called from
11647  * a signal handler itself. See the gl_io_mode() man page for how it
11648  * should be used.
11649  *
11650  * In the case of signals that by default terminate or suspend
11651  * processes, command-line editing will be suspended, the terminal
11652  * returned to a usable state, then the default disposition of the
11653  * signal restored and the signal resent, in order to suspend or
11654  * terminate the process.  If the process subsequently resumes,
11655  * command-line editing is resumed.
11656  *
11657  * In the case of signals that indicate that the terminal has been
11658  * resized, the new size will be queried, and any input line that is
11659  * being edited will be redrawn to fit the new dimensions of the
11660  * terminal.
11661  *
11662  * Input:
11663  *  signo    int    The number of the signal to respond to.
11664  *  gl   GetLine *  The first element of an array of 'ngl' GetLine
11665  *                  objects.
11666  *  ngl      int    The number of elements in the gl[] array. Normally
11667  *                  this will be one.
11668  */
11669 void gl_handle_signal(int signo, GetLine *gl, int ngl)
11670 {
11671   int attr;             /* The attributes of the specified signal */
11672   sigset_t all_signals; /* The set of trappable signals */
11673   sigset_t oldset;      /* The process signal mask to restore */
11674   int i;
11675 /*
11676  * NULL operation?
11677  */
11678   if(ngl < 1 || !gl)
11679     return;
11680 /*
11681  * Look up the default attributes of the specified signal.
11682  */
11683   attr = gl_classify_signal(signo);
11684 /*
11685  * If the signal isn't known, we are done.
11686  */
11687   if(!attr)
11688     return;
11689 /*
11690  * Temporarily block all signals while we modify the gl objects.
11691  */
11692   gl_list_trappable_signals(&all_signals);
11693   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11694 /*
11695  * Suspend or terminate the process?
11696  */
11697   if(attr & (GLSA_SUSP | GLSA_TERM)) {
11698     gl_suspend_process(signo, gl, ngl);
11699 /*
11700  * Resize the terminal? Note that ioctl() isn't defined as being
11701  * signal safe, so we can't call gl_update_size() here. However,
11702  * gl_get_line() checks for resizes on each call, so simply arrange
11703  * for the application's event loop to call gl_get_line() as soon as
11704  * it becomes possible to write to the terminal. Note that if the
11705  * caller is calling select() or poll when this happens, these functions
11706  * get interrupted, since a signal has been caught.
11707  */
11708   } else if(attr & GLSA_SIZE) {
11709     for(i=0; i<ngl; i++)
11710       gl[i].pending_io = GLP_WRITE;
11711   };
11712 /*
11713  * Restore the process signal mask that was superseded by the call
11714  * to gl_mask_signals().
11715  */
11716   sigprocmask(SIG_SETMASK, &oldset, NULL);
11717   return;
11718 }
11719 
11720 /*.......................................................................
11721  * Respond to an externally caught process suspension or
11722  * termination signal.
11723  *
11724  * After restoring the terminal to a usable state, suspend or
11725  * terminate the calling process, using the original signal with its
11726  * default disposition restored to do so. If the process subsequently
11727  * resumes, resume editing any input lines that were being entered.
11728  *
11729  * Input:
11730  *  signo    int    The signal number to suspend the process with. Note
11731  *                  that the default disposition of this signal will be
11732  *                  restored before the signal is sent, so provided
11733  *                  that the default disposition of this signal is to
11734  *                  either suspend or terminate the application,
11735  *                  that is what wil happen, regardless of what signal
11736  *                  handler is currently assigned to this signal.
11737  *  gl   GetLine *  The first element of an array of 'ngl' GetLine objects
11738  *                  whose terminals should be restored to a sane state
11739  *                  while the application is suspended.
11740  *  ngl      int    The number of elements in the gl[] array.
11741  */
11742 static void gl_suspend_process(int signo, GetLine *gl, int ngl)
11743 {
11744   sigset_t only_signo;          /* A signal set containing just signo */
11745   sigset_t oldset;              /* The signal mask on entry to this function */
11746   sigset_t all_signals;         /* A signal set containing all signals */
11747   struct sigaction old_action;  /* The current signal handler */
11748   struct sigaction def_action;  /* The default signal handler */
11749   int i;
11750 /*
11751  * Create a signal mask containing the signal that was trapped.
11752  */
11753   sigemptyset(&only_signo);
11754   sigaddset(&only_signo, signo);
11755 /*
11756  * Temporarily block all signals.
11757  */
11758   gl_list_trappable_signals(&all_signals);
11759   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11760 /*
11761  * Restore the terminal to a usable state.
11762  */
11763   for(i=0; i<ngl; i++) {
11764     GetLine *obj = gl + i;
11765     if(obj->raw_mode) {
11766       _gl_normal_io(obj);
11767       if(!obj->raw_mode)        /* Check that gl_normal_io() succeded */
11768 	obj->raw_mode = -1;     /* Flag raw mode as needing to be restored */
11769     };
11770   };
11771 /*
11772  * Restore the system default disposition of the signal that we
11773  * caught.  Note that this signal is currently blocked. Note that we
11774  * don't use memcpy() to copy signal sets here, because the signal safety
11775  * of memcpy() is undefined.
11776  */
11777   def_action.sa_handler = SIG_DFL;
11778   {
11779     char *orig = (char *) &all_signals;
11780     char *dest = (char *) &def_action.sa_mask;
11781     for(i=0; i<sizeof(sigset_t); i++)
11782       *dest++ = *orig++;
11783   };
11784   sigaction(signo, &def_action, &old_action);
11785 /*
11786  * Resend the signal, and unblock it so that it gets delivered to
11787  * the application. This will invoke the default action of this signal.
11788  */
11789   raise(signo);
11790   sigprocmask(SIG_UNBLOCK, &only_signo, NULL);
11791 /*
11792  * If the process resumes again, it will resume here.
11793  * Block the signal again, then restore our signal handler.
11794  */
11795   sigprocmask(SIG_BLOCK, &only_signo, NULL);
11796   sigaction(signo, &old_action, NULL);
11797 /*
11798  * Resume command-line editing.
11799  */
11800   for(i=0; i<ngl; i++) {
11801     GetLine *obj = gl + i;
11802     if(obj->raw_mode == -1) { /* Did we flag the need to restore raw mode? */
11803       obj->raw_mode = 0;      /* gl_raw_io() does nothing unless raw_mode==0 */
11804       _gl_raw_io(obj, 1);
11805     };
11806   };
11807 /*
11808  * Restore the process signal mask to the way it was when this function
11809  * was called.
11810  */
11811   sigprocmask(SIG_SETMASK, &oldset, NULL);
11812   return;
11813 }
11814 
11815 /*.......................................................................
11816  * Return the information about the default attributes of a given signal.
11817  * The attributes that are returned are as defined by the standards that
11818  * created them, including POSIX, SVR4 and 4.3+BSD, and are taken from a
11819  * table in Richard Steven's book, "Advanced programming in the UNIX
11820  * environment".
11821  *
11822  * Input:
11823  *  signo        int   The signal to be characterized.
11824  * Output:
11825  *  return       int   A bitwise union of GlSigAttr enumerators, or 0
11826  *                     if the signal isn't known.
11827  */
11828 static int gl_classify_signal(int signo)
11829 {
11830   int i;
11831 /*
11832  * Search for the specified signal in the gl_signal_list[] table.
11833  */
11834   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11835     const struct GlDefSignal *sig = gl_signal_list + i;
11836     if(sig->signo == signo)
11837       return sig->attr;
11838   };
11839 /*
11840  * Signal not known.
11841  */
11842   return 0;
11843 }
11844 
11845 /*.......................................................................
11846  * When in non-blocking server mode, this function can be used to abandon
11847  * the current incompletely entered input line, and prepare to start
11848  * editing a new line on the next call to gl_get_line().
11849  *
11850  * Input:
11851  *  gl      GetLine *  The line editor resource object.
11852  */
11853 void gl_abandon_line(GetLine *gl)
11854 {
11855   sigset_t oldset;    /* The process signal mask to restore */
11856 /*
11857  * Check the arguments.
11858  */
11859   if(!gl) {
11860     errno = EINVAL;
11861     return;
11862   };
11863 /*
11864  * Temporarily block all signals while we modify the contents of gl.
11865  */
11866   gl_mask_signals(gl, &oldset);
11867 /*
11868  * Mark the input line as discarded.
11869  */
11870   _gl_abandon_line(gl);
11871 /*
11872  * Restore the process signal mask that was superseded by the call
11873  * to gl_mask_signals().
11874  */
11875   gl_unmask_signals(gl, &oldset);
11876   return;
11877 }
11878 
11879 /*.......................................................................
11880  * This is the private body of the gl_abandon_line() function. It
11881  * assumes that the caller has checked its arguments and blocked the
11882  * delivery of signals.
11883  */
11884 void _gl_abandon_line(GetLine *gl)
11885 {
11886   gl->endline = 1;
11887   gl->pending_io = GLP_WRITE;
11888 }
11889 
11890 /*.......................................................................
11891  * How many characters are needed to write a number as an octal string?
11892  *
11893  * Input:
11894  *  num   unsigned   The to be measured.
11895  * Output:
11896  *  return     int   The number of characters needed.
11897  */
11898 static int gl_octal_width(unsigned num)
11899 {
11900   int n;    /* The number of characters needed to render the number */
11901   for(n=1; num /= 8; n++)
11902     ;
11903   return n;
11904 }
11905 
11906 /*.......................................................................
11907  * Tell gl_get_line() the current terminal size. Note that this is only
11908  * necessary on systems where changes in terminal size aren't reported
11909  * via SIGWINCH.
11910  *
11911  * Input:
11912  *  gl            GetLine *  The resource object of gl_get_line().
11913  *  ncolumn           int    The number of columns in the terminal.
11914  *  nline             int    The number of lines in the terminal.
11915  * Output:
11916  *  return            int    0 - OK.
11917  *                           1 - Error.
11918  */
11919 int gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11920 {
11921   sigset_t oldset;      /* The signals that were blocked on entry */
11922                         /*  to this function */
11923   int status;           /* The return status */
11924 /*
11925  * Block all signals while accessing gl.
11926  */
11927   gl_mask_signals(gl, &oldset);
11928 /*
11929  * Install the new terminal size.
11930  */
11931   status = _gl_set_term_size(gl, ncolumn, nline);
11932 /*
11933  * Restore the process signal mask before returning.
11934  */
11935   gl_unmask_signals(gl, &oldset);
11936   return status;
11937 }
11938 
11939 /*.......................................................................
11940  * This is the private body of the gl_set_term_size() function. It
11941  * assumes that the caller has checked its arguments and blocked the
11942  * delivery of signals.
11943  */
11944 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11945 {
11946 /*
11947  * Check the arguments.
11948  */
11949   if(!gl) {
11950     errno = EINVAL;
11951     return 1;
11952   };
11953 /*
11954  * Reject non-sensical dimensions.
11955  */
11956   if(ncolumn <= 0 || nline <= 0) {
11957     _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG);
11958     errno = EINVAL;
11959     return 1;
11960   };
11961 /*
11962  * Install the new dimensions in the terminal driver if possible, so
11963  * that future calls to gl_query_size() get the new value.
11964  */
11965 #ifdef TIOCSWINSZ
11966   if(gl->is_term) {
11967     struct winsize size;
11968     size.ws_row = nline;
11969     size.ws_col = ncolumn;
11970     size.ws_xpixel = 0;
11971     size.ws_ypixel = 0;
11972     if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) {
11973       _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG);
11974       return 1;
11975     };
11976   };
11977 #endif
11978 /*
11979  * If an input line is in the process of being edited, redisplay it to
11980  * accomodate the new dimensions, and record the new dimensions in
11981  * gl->nline and gl->ncolumn.
11982  */
11983   return gl_handle_tty_resize(gl, ncolumn, nline);
11984 }
11985 
11986 /*.......................................................................
11987  * Record a character in the input line buffer at a given position.
11988  *
11989  * Input:
11990  *  gl    GetLine *   The resource object of gl_get_line().
11991  *  c        char     The character to be recorded.
11992  *  bufpos    int     The index in the buffer at which to record the
11993  *                    character.
11994  * Output:
11995  *  return    int     0 - OK.
11996  *                    1 - Insufficient room.
11997  */
11998 static int gl_buffer_char(GetLine *gl, char c, int bufpos)
11999 {
12000 /*
12001  * Guard against buffer overruns.
12002  */
12003   if(bufpos >= gl->linelen)
12004     return 1;
12005 /*
12006  * Record the new character.
12007  */
12008   gl->line[bufpos] = c;
12009 /*
12010  * If the new character was placed beyond the end of the current input
12011  * line, update gl->ntotal to reflect the increased number of characters
12012  * that are in gl->line, and terminate the string.
12013  */
12014   if(bufpos >= gl->ntotal) {
12015     gl->ntotal = bufpos+1;
12016     gl->line[gl->ntotal] = '\0';
12017   };
12018   return 0;
12019 }
12020 
12021 /*.......................................................................
12022  * Copy a given string into the input buffer, overwriting the current
12023  * contents.
12024  *
12025  * Input:
12026  *  gl    GetLine *   The resource object of gl_get_line().
12027  *  s  const char *   The string to be recorded.
12028  *  n         int     The number of characters to be copied from the
12029  *                    string.
12030  *  bufpos    int     The index in the buffer at which to place the
12031  *                    the first character of the string.
12032  * Output:
12033  *  return    int     0 - OK.
12034  *                    1 - String truncated to fit.
12035  */
12036 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos)
12037 {
12038   int nnew;  /* The number of characters actually recorded */
12039   int i;
12040 /*
12041  * How many of the characters will fit within the buffer?
12042  */
12043   nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos);
12044 /*
12045  * Record the first nnew characters of s[] in the buffer.
12046  */
12047   for(i=0; i<nnew; i++)
12048     gl_buffer_char(gl, s[i], bufpos + i);
12049 /*
12050  * Was the string truncated?
12051  */
12052   return nnew < n;
12053 }
12054 
12055 /*.......................................................................
12056  * Make room in the input buffer for a string to be inserted. This
12057  * involves moving the characters that follow a specified point, towards
12058  * the end of the buffer.
12059  *
12060  * Input:
12061  *  gl    GetLine *   The resource object of gl_get_line().
12062  *  start     int     The index of the first character to be moved.
12063  *  n         int     The width of the gap.
12064  * Output:
12065  *  return    int     0 - OK.
12066  *                    1 - Insufficient room.
12067  */
12068 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n)
12069 {
12070 /*
12071  * Ensure that the buffer has sufficient space.
12072  */
12073   if(gl->ntotal + n > gl->linelen)
12074     return 1;
12075 /*
12076  * Move everything including and beyond the character at 'start'
12077  * towards the end of the string.
12078  */
12079   memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1);
12080 /*
12081  * Update the recorded size of the line.
12082  */
12083   gl->ntotal += n;
12084   return 1;
12085 }
12086 
12087 /*.......................................................................
12088  * Remove a given number of characters from the input buffer. This
12089  * involves moving the characters that follow the removed characters to
12090  * where the removed sub-string started in the input buffer.
12091  *
12092  * Input:
12093  *  gl    GetLine *   The resource object of gl_get_line().
12094  *  start     int     The first character to be removed.
12095  *  n         int     The number of characters to remove.
12096  */
12097 static void gl_remove_from_buffer(GetLine *gl, int start, int n)
12098 {
12099   memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1);
12100 /*
12101  * Update the recorded size of the line.
12102  */
12103   gl->ntotal -= n;
12104 }
12105 
12106 /*.......................................................................
12107  * Truncate the string in the input line buffer after a given number of
12108  * characters.
12109  *
12110  * Input:
12111  *  gl       GetLine *   The resource object of gl_get_line().
12112  *  n            int     The new length of the line.
12113  * Output:
12114  *  return       int     0 - OK.
12115  *                       1 - n > gl->linelen.
12116  */
12117 static int gl_truncate_buffer(GetLine *gl, int n)
12118 {
12119   if(n > gl->linelen)
12120     return 1;
12121   gl->line[n] = '\0';
12122   gl->ntotal = n;
12123   return 0;
12124 }
12125 
12126 /*.......................................................................
12127  * When the contents of gl->line[] are changed without calling any of the
12128  * gl_ buffer manipulation functions, this function must be called to
12129  * compute the length of this string, and ancillary information.
12130  *
12131  * Input:
12132  *  gl      GetLine *   The resource object of gl_get_line().
12133  */
12134 static void gl_update_buffer(GetLine *gl)
12135 {
12136   int len;  /* The length of the line */
12137 /*
12138  * Measure the length of the input line.
12139  */
12140   for(len=0; len <= gl->linelen && gl->line[len]; len++)
12141     ;
12142 /*
12143  * Just in case the string wasn't correctly terminated, do so here.
12144  */
12145   gl->line[len] = '\0';
12146 /*
12147  * Record the number of characters that are now in gl->line[].
12148  */
12149   gl->ntotal = len;
12150 /*
12151  * Ensure that the cursor stays within the bounds of the modified
12152  * input line.
12153  */
12154   if(gl->buff_curpos > gl->ntotal)
12155     gl->buff_curpos = gl->ntotal;
12156 /*
12157  * Arrange for the input line to be redrawn.
12158  */
12159   gl_queue_redisplay(gl);
12160   return;
12161 }
12162 
12163 /*.......................................................................
12164  * Erase the displayed input line, including its prompt, and leave the
12165  * cursor where the erased line started. Note that to allow this
12166  * function to be used when responding to a terminal resize, this
12167  * function is designed to work even if the horizontal cursor position
12168  * doesn't match the internally recorded position.
12169  *
12170  * Input:
12171  *  gl      GetLine *   The resource object of gl_get_line().
12172  * Output:
12173  *  return      int     0 - OK.
12174  *                      1 - Error.
12175  */
12176 static int gl_erase_line(GetLine *gl)
12177 {
12178 /*
12179  * Is a line currently displayed?
12180  */
12181   if(gl->displayed) {
12182 /*
12183  * Relative the the start of the input line, which terminal line of
12184  * the current input line is the cursor currently on?
12185  */
12186     int cursor_line = gl->term_curpos / gl->ncolumn;
12187 /*
12188  * Move the cursor to the start of the line.
12189  */
12190     for( ; cursor_line > 0; cursor_line--) {
12191       if(gl_print_control_sequence(gl, 1, gl->up))
12192 	return 1;
12193     };
12194     if(gl_print_control_sequence(gl, 1, gl->bol))
12195       return 1;
12196 /*
12197  * Clear from the start of the line to the end of the terminal.
12198  */
12199     if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12200       return 1;
12201 /*
12202  * Mark the line as no longer displayed.
12203  */
12204     gl_line_erased(gl);
12205   };
12206   return 0;
12207 }
12208 
12209 /*.......................................................................
12210  * Arrange for the input line to be redisplayed by gl_flush_output(),
12211  * as soon as the output queue becomes empty.
12212  *
12213  * Input:
12214  *  gl          GetLine *   The resource object of gl_get_line().
12215  */
12216 static void gl_queue_redisplay(GetLine *gl)
12217 {
12218   gl->redisplay = 1;
12219   gl->pending_io = GLP_WRITE;
12220 }
12221 
12222 /*.......................................................................
12223  * Truncate the displayed input line starting from the current
12224  * terminal cursor position, and leave the cursor at the end of the
12225  * truncated line. The input-line buffer is not affected.
12226  *
12227  * Input:
12228  *  gl     GetLine *   The resource object of gl_get_line().
12229  * Output:
12230  *  return     int     0 - OK.
12231  *                     1 - Error.
12232  */
12233 static int gl_truncate_display(GetLine *gl)
12234 {
12235 /*
12236  * Keep a record of the current terminal cursor position.
12237  */
12238   int term_curpos = gl->term_curpos;
12239 /*
12240  * First clear from the cursor to the end of the current input line.
12241  */
12242   if(gl_print_control_sequence(gl, 1, gl->clear_eol))
12243     return 1;
12244 /*
12245  * If there is more than one line displayed, go to the start of the
12246  * next line and clear from there to the end of the display. Note that
12247  * we can't use clear_eod to do the whole job of clearing from the
12248  * current cursor position to the end of the terminal because
12249  * clear_eod is only defined when used at the start of a terminal line
12250  * (eg. with gnome terminals, clear_eod clears from the start of the
12251  * current terminal line, rather than from the current cursor
12252  * position).
12253  */
12254   if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) {
12255     if(gl_print_control_sequence(gl, 1, gl->down) ||
12256        gl_print_control_sequence(gl, 1, gl->bol) ||
12257        gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12258       return 1;
12259 /*
12260  * Where is the cursor now?
12261  */
12262     gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1);
12263 /*
12264  * Restore the cursor position.
12265  */
12266     gl_set_term_curpos(gl, term_curpos);
12267   };
12268 /*
12269  * Update the recorded position of the final character.
12270  */
12271   gl->term_len = gl->term_curpos;
12272   return 0;
12273 }
12274 
12275 /*.......................................................................
12276  * Return the set of all trappable signals.
12277  *
12278  * Input:
12279  *  signals   sigset_t *  The set of signals will be recorded in
12280  *                        *signals.
12281  */
12282 static void gl_list_trappable_signals(sigset_t *signals)
12283 {
12284 /*
12285  * Start with the set of all signals.
12286  */
12287   sigfillset(signals);
12288 /*
12289  * Remove un-trappable signals from this set.
12290  */
12291 #ifdef SIGKILL
12292   sigdelset(signals, SIGKILL);
12293 #endif
12294 #ifdef SIGSTOP
12295   sigdelset(signals, SIGSTOP);
12296 #endif
12297 }
12298 
12299 /*.......................................................................
12300  * Read an input line from a non-interactive input stream.
12301  *
12302  * Input:
12303  *  gl     GetLine *   The resource object of gl_get_line().
12304  * Output:
12305  *  return     int     0 - OK
12306  *                     1 - Error.
12307  */
12308 static int gl_read_stream_line(GetLine *gl)
12309 {
12310   char c = '\0'; /* The latest character read from fp */
12311 /*
12312  * Record the fact that we are about to read input.
12313  */
12314   gl->pending_io = GLP_READ;
12315 /*
12316  * If we are starting a new line, reset the line-editing parameters,
12317  * and discard the previous input line.
12318  */
12319   if(gl->endline) {
12320     gl_reset_editor(gl);
12321     gl_truncate_buffer(gl, 0);
12322   };
12323 /*
12324  * Read one character at a time.
12325  */
12326   while(gl->ntotal < gl->linelen && c != '\n') {
12327 /*
12328  * Attempt to read one more character.
12329  */
12330     switch(gl_read_input(gl, &c)) {
12331     case GL_READ_OK:
12332       break;
12333     case GL_READ_EOF:        /* Reached end-of-file? */
12334 /*
12335  * If any characters were read before the end-of-file condition,
12336  * interpolate a newline character, so that the caller sees a
12337  * properly terminated line. Otherwise return an end-of-file
12338  * condition.
12339  */
12340       if(gl->ntotal > 0) {
12341 	c = '\n';
12342       } else {
12343 	gl_record_status(gl, GLR_EOF, 0);
12344 	return 1;
12345       };
12346       break;
12347     case GL_READ_BLOCKED:    /* Input blocked? */
12348       gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12349       return 1;
12350       break;
12351     case GL_READ_ERROR:     /* I/O error? */
12352       return 1;
12353       break;
12354     };
12355 /*
12356  * Append the character to the line buffer.
12357  */
12358     if(gl_buffer_char(gl, c, gl->ntotal))
12359       return 1;
12360   };
12361 /*
12362  * Was the end of the input line reached before running out of buffer space?
12363  */
12364   gl->endline = (c == '\n');
12365   return 0;
12366 }
12367 
12368 /*.......................................................................
12369  * Read a single character from a non-interactive input stream.
12370  *
12371  * Input:
12372  *  gl     GetLine *   The resource object of gl_get_line().
12373  * Output:
12374  *  return     int     The character, or EOF on error.
12375  */
12376 static int gl_read_stream_char(GetLine *gl)
12377 {
12378   char c = '\0';    /* The latest character read from fp */
12379   int retval = EOF; /* The return value of this function */
12380 /*
12381  * Arrange to discard any incomplete input line.
12382  */
12383   _gl_abandon_line(gl);
12384 /*
12385  * Record the fact that we are about to read input.
12386  */
12387   gl->pending_io = GLP_READ;
12388 /*
12389  * Attempt to read one more character.
12390  */
12391   switch(gl_read_input(gl, &c)) {
12392   case GL_READ_OK:      /* Success */
12393     retval = c;
12394     break;
12395   case GL_READ_BLOCKED: /* The read blocked */
12396     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12397     retval = EOF;  /* Failure */
12398     break;
12399   case GL_READ_EOF:     /* End of file reached */
12400     gl_record_status(gl, GLR_EOF, 0);
12401     retval = EOF;  /* Failure */
12402     break;
12403   case GL_READ_ERROR:
12404     retval = EOF;  /* Failure */
12405     break;
12406   };
12407   return retval;
12408 }
12409 
12410 /*.......................................................................
12411  * Bind a key sequence to a given action.
12412  *
12413  * Input:
12414  *  gl          GetLine *   The resource object of gl_get_line().
12415  *  origin  GlKeyOrigin     The originator of the key binding.
12416  *  key      const char *   The key-sequence to be bound (or unbound).
12417  *  action   const char *   The name of the action to bind the key to,
12418  *                          or either NULL or "" to unbind the
12419  *                          key-sequence.
12420  * Output:
12421  *  return          int     0 - OK
12422  *                          1 - Error.
12423  */
12424 int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq,
12425 		   const char *action)
12426 {
12427   KtBinder binder;  /* The private internal equivalent of 'origin' */
12428 /*
12429  * Check the arguments.
12430  */
12431   if(!gl || !keyseq) {
12432     errno = EINVAL;
12433     if(gl)
12434       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
12435     return 1;
12436   };
12437 /*
12438  * An empty action string requests that the key-sequence be unbound.
12439  * This is indicated to _kt_set_keybinding() by passing a NULL action
12440  * string, so convert an empty string to a NULL action pointer.
12441  */
12442   if(action && *action=='\0')
12443     action = NULL;
12444 /*
12445  * Translate the public originator enumeration to the private equivalent.
12446  */
12447   binder = origin==GL_USER_KEY ? KTB_USER : KTB_NORM;
12448 /*
12449  * Bind the action to a given key-sequence?
12450  */
12451   if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
12452     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
12453     return 1;
12454   };
12455   return 0;
12456 }
12457 
12458 /*.......................................................................
12459  * This is the public wrapper around the gl_clear_termina() function.
12460  * It clears the terminal and leaves the cursor at the home position.
12461  * In server I/O mode, the next call to gl_get_line() will also
12462  * redisplay the current input line.
12463  *
12464  * Input:
12465  *  gl          GetLine *   The resource object of gl_get_line().
12466  * Output:
12467  *  return          int     0 - OK.
12468  *                          1 - Error.
12469  */
12470 int gl_erase_terminal(GetLine *gl)
12471 {
12472   sigset_t oldset;      /* The signals that were blocked on entry */
12473                         /*  to this function */
12474   int status;           /* The return status */
12475 /*
12476  * Block all signals while accessing gl.
12477  */
12478   gl_mask_signals(gl, &oldset);
12479 /*
12480  * Clear the terminal.
12481  */
12482   status = gl_clear_screen(gl, 1, NULL);
12483 /*
12484  * Attempt to flush the clear-screen control codes to the terminal.
12485  * If this doesn't complete the job, the next call to gl_get_line()
12486  * will.
12487  */
12488   (void) gl_flush_output(gl);
12489 /*
12490  * Restore the process signal mask before returning.
12491  */
12492   gl_unmask_signals(gl, &oldset);
12493   return status;
12494 }
12495 
12496 /*.......................................................................
12497  * This function must be called by any function that erases the input
12498  * line.
12499  *
12500  * Input:
12501  *  gl          GetLine *   The resource object of gl_get_line().
12502  */
12503 static void gl_line_erased(GetLine *gl)
12504 {
12505   gl->displayed = 0;
12506   gl->term_curpos = 0;
12507   gl->term_len = 0;
12508 }
12509 
12510 /*.......................................................................
12511  * Append a specified line to the history list.
12512  *
12513  * Input:
12514  *  gl          GetLine *   The resource object of gl_get_line().
12515  *  line     const char *   The line to be added.
12516  * Output:
12517  *  return          int     0 - OK.
12518  *                          1 - Error.
12519  */
12520 int gl_append_history(GetLine *gl, const char *line)
12521 {
12522   sigset_t oldset;      /* The signals that were blocked on entry */
12523                         /*  to this function */
12524   int status;           /* The return status */
12525 /*
12526  * Check the arguments.
12527  */
12528   if(!gl || !line) {
12529     errno = EINVAL;
12530     return 1;
12531   };
12532 /*
12533  * Block all signals.
12534  */
12535   if(gl_mask_signals(gl, &oldset))
12536     return 1;
12537 /*
12538  * Execute the private body of the function while signals are blocked.
12539  */
12540   status = _gl_append_history(gl, line);
12541 /*
12542  * Restore the process signal mask.
12543  */
12544   gl_unmask_signals(gl, &oldset);
12545   return status;
12546 }
12547 
12548 /*.......................................................................
12549  * This is the private body of the public function, gl_append_history().
12550  * It assumes that the caller has checked its arguments and blocked the
12551  * delivery of signals.
12552  */
12553 static int _gl_append_history(GetLine *gl, const char *line)
12554 {
12555   int status =_glh_add_history(gl->glh, line, 0);
12556   if(status)
12557     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
12558   return status;
12559 }
12560 
12561 /*.......................................................................
12562  * Enable or disable the automatic addition of newly entered lines to the
12563  * history list.
12564  *
12565  * Input:
12566  *  gl          GetLine *   The resource object of gl_get_line().
12567  *  enable          int     If true, subsequently entered lines will
12568  *                          automatically be added to the history list
12569  *                          before they are returned to the caller of
12570  *                          gl_get_line(). If 0, the choice of how and
12571  *                          when to archive lines in the history list,
12572  *                          is left up to the calling application, which
12573  *                          can do so via calls to gl_append_history().
12574  * Output:
12575  *  return          int     0 - OK.
12576  *                          1 - Error.
12577  */
12578 int gl_automatic_history(GetLine *gl, int enable)
12579 {
12580   sigset_t oldset;      /* The signals that were blocked on entry */
12581                         /*  to this function */
12582 /*
12583  * Check the arguments.
12584  */
12585   if(!gl) {
12586     errno = EINVAL;
12587     return 1;
12588   };
12589 /*
12590  * Block all signals.
12591  */
12592   if(gl_mask_signals(gl, &oldset))
12593     return 1;
12594 /*
12595  * Execute the private body of the function while signals are blocked.
12596  */
12597   gl->automatic_history = enable;
12598 /*
12599  * Restore the process signal mask.
12600  */
12601   gl_unmask_signals(gl, &oldset);
12602   return 0;
12603 }
12604 
12605 /*.......................................................................
12606  * This is a public function that reads a single uninterpretted
12607  * character from the user, without displaying anything.
12608  *
12609  * Input:
12610  *  gl     GetLine *  A resource object previously returned by
12611  *                    new_GetLine().
12612  * Output:
12613  *  return     int    The character that was read, or EOF if the read
12614  *                    had to be aborted (in which case you can call
12615  *                    gl_return_status() to find out why).
12616  */
12617 int gl_read_char(GetLine *gl)
12618 {
12619   int retval;   /* The return value of _gl_read_char() */
12620 /*
12621  * This function can be called from application callback functions,
12622  * so check whether signals have already been masked, so that we don't
12623  * do it again, and overwrite gl->old_signal_set.
12624  */
12625   int was_masked = gl->signals_masked;
12626 /*
12627  * Check the arguments.
12628  */
12629   if(!gl) {
12630     errno = EINVAL;
12631     return EOF;
12632   };
12633 /*
12634  * Temporarily block all of the signals that we have been asked to trap.
12635  */
12636   if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set))
12637     return EOF;
12638 /*
12639  * Perform the character reading task.
12640  */
12641   retval = _gl_read_char(gl);
12642 /*
12643  * Restore the process signal mask to how it was when this function was
12644  * first called.
12645  */
12646   if(!was_masked)
12647     gl_unmask_signals(gl, &gl->old_signal_set);
12648   return retval;
12649 }
12650 
12651 /*.......................................................................
12652  * This is the main body of the public function gl_read_char().
12653  */
12654 static int _gl_read_char(GetLine *gl)
12655 {
12656   int retval = EOF;  /* The return value */
12657   int waserr = 0;    /* True if an error occurs */
12658   char c;            /* The character read */
12659 /*
12660  * This function can be called from application callback functions,
12661  * so check whether signals have already been overriden, so that we don't
12662  * overwrite the preserved signal handlers with gl_get_line()s. Also
12663  * record whether we are currently in raw I/O mode or not, so that this
12664  * can be left in the same state on leaving this function.
12665  */
12666   int was_overriden = gl->signals_overriden;
12667   int was_raw = gl->raw_mode;
12668 /*
12669  * Also keep a record of the direction of any I/O that gl_get_line()
12670  * is awaiting, so that we can restore this status on return.
12671  */
12672   GlPendingIO old_pending_io = gl->pending_io;
12673 /*
12674  * Assume that this call will successfully complete the input operation
12675  * until proven otherwise.
12676  */
12677   gl_clear_status(gl);
12678 /*
12679  * If this is the first call to this function or gl_get_line(),
12680  * since new_GetLine(), complete any postponed configuration.
12681  */
12682   if(!gl->configured) {
12683     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
12684     gl->configured = 1;
12685   };
12686 /*
12687  * Before installing our signal handler functions, record the fact
12688  * that there are no pending signals.
12689  */
12690   gl_pending_signal = -1;
12691 /*
12692  * Temporarily override the signal handlers of the calling program,
12693  * so that we can intercept signals that would leave the terminal
12694  * in a bad state.
12695  */
12696   if(!was_overriden)
12697     waserr = gl_override_signal_handlers(gl);
12698 /*
12699  * After recording the current terminal settings, switch the terminal
12700  * into raw input mode, without redisplaying any partially entered input
12701  * line.
12702  */
12703   if(!was_raw)
12704     waserr = waserr || _gl_raw_io(gl, 0);
12705 /*
12706  * Attempt to read the line. This will require more than one attempt if
12707  * either a current temporary input file is opened by gl_get_input_line()
12708  * or the end of a temporary input file is reached by gl_read_stream_line().
12709  */
12710   while(!waserr) {
12711 /*
12712  * Read a line from a non-interactive stream?
12713  */
12714     if(gl->file_fp || !gl->is_term) {
12715       retval = gl_read_stream_char(gl);
12716       if(retval != EOF) {            /* Success? */
12717 	break;
12718       } else if(gl->file_fp) {  /* End of temporary input file? */
12719 	gl_revert_input(gl);
12720 	gl_record_status(gl, GLR_NEWLINE, 0);
12721       } else {                  /* An error? */
12722 	waserr = 1;
12723 	break;
12724       };
12725     };
12726 /*
12727  * Read from the terminal? Note that the above if() block may have
12728  * changed gl->file_fp, so it is necessary to retest it here, rather
12729  * than using an else statement.
12730  */
12731     if(!gl->file_fp && gl->is_term) {
12732 /*
12733  * Flush any pending output to the terminal before waiting
12734  * for the user to type a character.
12735  */
12736       if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) {
12737 	retval = EOF;
12738 /*
12739  * Read one character. Don't append it to the key buffer, since
12740  * this would subseuqnely appear as bogus input to the line editor.
12741  */
12742       } else if(gl_read_terminal(gl, 0, &c) == 0) {
12743 /*
12744  * Record the character for return.
12745  */
12746 	retval = c;
12747 /*
12748  * In this mode, count each character as being a new key-sequence.
12749  */
12750 	gl->keyseq_count++;
12751 /*
12752  * Delete the character that was read, from the key-press buffer.
12753  */
12754 	gl_discard_chars(gl, 1);
12755       };
12756       if(retval==EOF)
12757 	waserr = 1;
12758       else
12759 	break;
12760     };
12761   };
12762 /*
12763  * If an error occurred, but gl->rtn_status is still set to
12764  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
12765  * leave it at whatever specific value was assigned by the function
12766  * that aborted input. This means that only functions that trap
12767  * non-generic errors have to remember to update gl->rtn_status
12768  * themselves.
12769  */
12770   if(waserr && gl->rtn_status == GLR_NEWLINE)
12771     gl_record_status(gl, GLR_ERROR, errno);
12772 /*
12773  * Restore terminal settings, if they were changed by this function.
12774  */
12775   if(!was_raw && gl->io_mode != GL_SERVER_MODE)
12776     _gl_normal_io(gl);
12777 /*
12778  * Restore the signal handlers, if they were overriden by this function.
12779  */
12780   if(!was_overriden)
12781     gl_restore_signal_handlers(gl);
12782 /*
12783  * If this function gets aborted early, the errno value associated
12784  * with the event that caused this to happen is recorded in
12785  * gl->rtn_errno. Since errno may have been overwritten by cleanup
12786  * functions after this, restore its value to the value that it had
12787  * when the error condition occured, so that the caller can examine it
12788  * to find out what happened.
12789  */
12790   errno = gl->rtn_errno;
12791 /*
12792  * Error conditions are signalled to the caller, by setting the returned
12793  * character to EOF.
12794  */
12795   if(gl->rtn_status != GLR_NEWLINE)
12796     retval = EOF;
12797 /*
12798  * Restore the indication of what direction of I/O gl_get_line()
12799  * was awaiting before this call.
12800  */
12801   gl->pending_io = old_pending_io;
12802 /*
12803  * Return the acquired character.
12804  */
12805   return retval;
12806 }
12807 
12808 /*.......................................................................
12809  * Reset the GetLine completion status. This function should be called
12810  * at the start of gl_get_line(), gl_read_char() and gl_query_char()
12811  * to discard the completion status and non-zero errno value of any
12812  * preceding calls to these functions.
12813  *
12814  * Input:
12815  *  gl       GetLine *  The resource object of this module.
12816  */
12817 static void gl_clear_status(GetLine *gl)
12818 {
12819   gl_record_status(gl, GLR_NEWLINE, 0);
12820 }
12821 
12822 /*.......................................................................
12823  * When an error or other event causes gl_get_line() to return, this
12824  * function should be called to record information about what
12825  * happened, including the value of errno and the value that
12826  * gl_return_status() should return.
12827  *
12828  * Input:
12829  *  gl                GetLine *  The resource object of this module.
12830  *  rtn_status GlReturnStatus    The completion status. To clear a
12831  *                               previous abnormal completion status,
12832  *                               specify GLR_NEWLINE (this is what
12833  *                               gl_clear_status() does).
12834  *  rtn_errno             int    The associated value of errno.
12835  */
12836 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
12837 			     int rtn_errno)
12838 {
12839 /*
12840  * If rtn_status==GLR_NEWLINE, then this resets the completion status, so we
12841  * should always heed this. Otherwise, only record the first abnormal
12842  * condition that occurs after such a reset.
12843  */
12844   if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) {
12845     gl->rtn_status = rtn_status;
12846     gl->rtn_errno = rtn_errno;
12847   };
12848 }
12849 
12850