xref: /titanic_41/usr/src/lib/libtecla/common/getline.c (revision fa03b00a436afdcf824024c08b7a443559cb6ebf)
1 /*
2  * Copyright (c) 2000, 2001, 2002, 2003, 2004 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  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
34  * Use is subject to license terms.
35  */
36 
37 #pragma ident	"%Z%%M%	%I%	%E% SMI"
38 
39 /*
40  * Standard headers.
41  */
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <signal.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <ctype.h>
48 #include <setjmp.h>
49 #include <stdarg.h>
50 
51 /*
52  * UNIX headers.
53  */
54 #include <sys/ioctl.h>
55 #ifdef HAVE_SELECT
56 #ifdef HAVE_SYS_SELECT_H
57 #include <sys/select.h>
58 #endif
59 #include <sys/time.h>
60 #include <sys/types.h>
61 #endif
62 
63 /*
64  * Handle the different sources of terminal control string and size
65  * information. Note that if no terminal information database is available,
66  * ANSI VT100 control sequences are used.
67  */
68 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
69 /*
70  * Include curses.h or ncurses/curses.h depending on which is available.
71  */
72 #ifdef HAVE_CURSES_H
73 #include <curses.h>
74 #elif defined(HAVE_NCURSES_CURSES_H)
75 #include <ncurses/curses.h>
76 #endif
77 /*
78  * Include term.h where available.
79  */
80 #if defined(HAVE_TERM_H)
81 #include <term.h>
82 #elif defined(HAVE_NCURSES_TERM_H)
83 #include <ncurses/term.h>
84 #endif
85 /*
86  * When using termcap, include termcap.h on systems that have it.
87  * Otherwise assume that all prototypes are provided by curses.h.
88  */
89 #if defined(USE_TERMCAP) && defined(HAVE_TERMCAP_H)
90 #include <termcap.h>
91 #endif
92 
93 /*
94  * Under Solaris default Curses the output function that tputs takes is
95  * declared to have a char argument. On all other systems and on Solaris
96  * X/Open Curses (Issue 4, Version 2) it expects an int argument (using
97  * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib
98  * selects XPG4v2 Curses on Solaris 2.6 and later).
99  *
100  * Similarly, under Mac OS X, the return value of the tputs output
101  * function is declared as void, whereas it is declared as int on
102  * other systems.
103  */
104 #if defined __sun && defined __SVR4 && !defined _XOPEN_CURSES
105 typedef int TputsRetType;
106 typedef char TputsArgType;              /* int tputs(char c, FILE *fp) */
107 #define TPUTS_RETURNS_VALUE 1
108 #elif defined(__APPLE__) && defined(__MACH__)
109 typedef void TputsRetType;
110 typedef int TputsArgType;               /* void tputs(int c, FILE *fp) */
111 #define TPUTS_RETURNS_VALUE 0
112 #else
113 typedef int TputsRetType;
114 typedef int TputsArgType;               /* int tputs(int c, FILE *fp) */
115 #define TPUTS_RETURNS_VALUE 1
116 #endif
117 
118 /*
119  * Use the above specifications to prototype our tputs callback function.
120  */
121 static TputsRetType gl_tputs_putchar(TputsArgType c);
122 
123 #endif  /* defined(USE_TERMINFO) || defined(USE_TERMCAP) */
124 
125 /*
126  * If the library is being compiled without filesystem access facilities,
127  * ensure that none of the action functions that normally do access the
128  * filesystem are bound by default, and that it they do get bound, that
129  * they don't do anything.
130  */
131 #if WITHOUT_FILE_SYSTEM
132 #define HIDE_FILE_SYSTEM
133 #endif
134 
135 /*
136  * POSIX headers.
137  */
138 #include <unistd.h>
139 #include <fcntl.h>
140 #include <termios.h>
141 
142 /*
143  * Provide typedefs for standard POSIX structures.
144  */
145 typedef struct sigaction SigAction;
146 typedef struct termios Termios;
147 
148 /*
149  * Which flag is used to select non-blocking I/O with fcntl()?
150  */
151 #undef NON_BLOCKING_FLAG
152 #if defined(O_NONBLOCK)
153 #define NON_BLOCKING_FLAG (O_NONBLOCK)
154 #elif defined(O_NDELAY)
155 #define NON_BLOCKING_FLAG (O_NDELAY)
156 #endif
157 
158 /*
159  * What value should we give errno if I/O blocks when it shouldn't.
160  */
161 #undef BLOCKED_ERRNO
162 #if defined(EAGAIN)
163 #define BLOCKED_ERRNO (EAGAIN)
164 #elif defined(EWOULDBLOCK)
165 #define BLOCKED_ERRNO (EWOULDBLOCK)
166 #elif defined(EIO)
167 #define BLOCKED_ERRNO (EIO)
168 #else
169 #define BLOCKED_ERRNO 0
170 #endif
171 
172 /*
173  * Local headers.
174  */
175 #ifndef WITHOUT_FILE_SYSTEM
176 #include "pathutil.h"
177 #endif
178 #include "libtecla.h"
179 #include "keytab.h"
180 #include "getline.h"
181 #include "ioutil.h"
182 #include "history.h"
183 #include "freelist.h"
184 #include "stringrp.h"
185 #include "chrqueue.h"
186 #include "cplmatch.h"
187 #ifndef WITHOUT_FILE_SYSTEM
188 #include "expand.h"
189 #endif
190 #include "errmsg.h"
191 
192 /*
193  * Enumerate the available editing styles.
194  */
195 typedef enum {
196   GL_EMACS_MODE,   /* Emacs style editing */
197   GL_VI_MODE,      /* Vi style editing */
198   GL_NO_EDITOR     /* Fall back to the basic OS-provided editing */
199 } GlEditor;
200 
201 /*
202  * Set the largest key-sequence that can be handled.
203  */
204 #define GL_KEY_MAX 64
205 
206 /*
207  * In vi mode, the following datatype is used to implement the
208  * undo command. It records a copy of the input line from before
209  * the command-mode action which edited the input line.
210  */
211 typedef struct {
212   char *line;        /* A historical copy of the input line */
213   int buff_curpos;   /* The historical location of the cursor in */
214                      /*  line[] when the line was modified. */
215   int ntotal;        /* The number of characters in line[] */
216   int saved;         /* True once a line has been saved after the */
217                      /*  last call to gl_interpret_char(). */
218 } ViUndo;
219 
220 /*
221  * In vi mode, the following datatype is used to record information
222  * needed by the vi-repeat-change command.
223  */
224 typedef struct {
225   KtAction action;           /* The last action function that made a */
226                              /*  change to the line. */
227   int count;                 /* The repeat count that was passed to the */
228                              /*  above command. */
229   int input_curpos;          /* Whenever vi command mode is entered, the */
230                              /*  the position at which it was first left */
231                              /*  is recorded here. */
232   int command_curpos;        /* Whenever vi command mode is entered, the */
233                              /*  the location of the cursor is recorded */
234                              /*  here. */
235   char input_char;           /* Commands that call gl_read_terminal() */
236                              /*  record the character here, so that it can */
237                              /*  used on repeating the function. */
238   int saved;                 /* True if a function has been saved since the */
239                              /*  last call to gl_interpret_char(). */
240   int active;                /* True while a function is being repeated. */
241 } ViRepeat;
242 
243 /*
244  * The following datatype is used to encapsulate information specific
245  * to vi mode.
246  */
247 typedef struct {
248   ViUndo undo;               /* Information needed to implement the vi */
249                              /*  undo command. */
250   ViRepeat repeat;           /* Information needed to implement the vi */
251                              /*  repeat command. */
252   int command;               /* True in vi command-mode */
253   int find_forward;          /* True if the last character search was in the */
254                              /*  forward direction. */
255   int find_onto;             /* True if the last character search left the */
256                              /*  on top of the located character, as opposed */
257                              /*  to just before or after it. */
258   char find_char;            /* The last character sought, or '\0' if no */
259                              /*  searches have been performed yet. */
260 } ViMode;
261 
262 #ifdef HAVE_SELECT
263 /*
264  * Define a type for recording a file-descriptor callback and its associated
265  * data.
266  */
267 typedef struct {
268   GlFdEventFn *fn;   /* The callback function */
269   void *data;        /* Anonymous data to pass to the callback function */
270 } GlFdHandler;
271 
272 /*
273  * A list of nodes of the following type is used to record file-activity
274  * event handlers, but only on systems that have the select() system call.
275  */
276 typedef struct GlFdNode GlFdNode;
277 struct GlFdNode {
278   GlFdNode *next;    /* The next in the list of nodes */
279   int fd;            /* The file descriptor being watched */
280   GlFdHandler rd;    /* The callback to call when fd is readable */
281   GlFdHandler wr;    /* The callback to call when fd is writable */
282   GlFdHandler ur;    /* The callback to call when fd has urgent data */
283 };
284 
285 /*
286  * Set the number of the above structures to allocate every time that
287  * the freelist of GlFdNode's becomes exhausted.
288  */
289 #define GLFD_FREELIST_BLOCKING 10
290 
291 
292 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
293 			      GlFdEvent event);
294 
295 static int gl_call_timeout_handler(GetLine *gl);
296 
297 #endif
298 
299 /*
300  * Each signal that gl_get_line() traps is described by a list node
301  * of the following type.
302  */
303 typedef struct GlSignalNode GlSignalNode;
304 struct GlSignalNode {
305   GlSignalNode *next;  /* The next signal in the list */
306   int signo;           /* The number of the signal */
307   sigset_t proc_mask;  /* A process mask which only includes signo */
308   SigAction original;  /* The signal disposition of the calling program */
309                        /*  for this signal. */
310   unsigned flags;      /* A bitwise union of GlSignalFlags enumerators */
311   GlAfterSignal after; /* What to do after the signal has been handled */
312   int errno_value;     /* What to set errno to */
313 };
314 
315 /*
316  * Set the number of the above structures to allocate every time that
317  * the freelist of GlSignalNode's becomes exhausted.
318  */
319 #define GLS_FREELIST_BLOCKING 30
320 
321 /*
322  * Completion handlers and their callback data are recorded in
323  * nodes of the following type.
324  */
325 typedef struct GlCplCallback GlCplCallback;
326 struct GlCplCallback {
327   CplMatchFn *fn;            /* The completion callback function */
328   void *data;                /* Arbitrary callback data */
329 };
330 
331 /*
332  * The following function is used as the default completion handler when
333  * the filesystem is to be hidden. It simply reports no completions.
334  */
335 #ifdef HIDE_FILE_SYSTEM
336 static CPL_MATCH_FN(gl_no_completions);
337 #endif
338 
339 /*
340  * Specify how many GlCplCallback nodes are added to the GlCplCallback freelist
341  * whenever it becomes exhausted.
342  */
343 #define GL_CPL_FREELIST_BLOCKING 10
344 
345 /*
346  * External action functions and their callback data are recorded in
347  * nodes of the following type.
348  */
349 typedef struct GlExternalAction GlExternalAction;
350 struct GlExternalAction {
351   GlActionFn *fn;          /* The function which implements the action */
352   void *data;              /* Arbitrary callback data */
353 };
354 
355 /*
356  * Specify how many GlExternalAction nodes are added to the
357  * GlExternalAction freelist whenever it becomes exhausted.
358  */
359 #define GL_EXT_ACT_FREELIST_BLOCKING 10
360 
361 /*
362  * Define the contents of the GetLine object.
363  * Note that the typedef for this object can be found in libtecla.h.
364  */
365 struct GetLine {
366   ErrMsg *err;               /* The error-reporting buffer */
367   GlHistory *glh;            /* The line-history buffer */
368   WordCompletion *cpl;       /* String completion resource object */
369   GlCplCallback cplfn;       /* The completion callback */
370 #ifndef WITHOUT_FILE_SYSTEM
371   ExpandFile *ef;            /* ~user/, $envvar and wildcard expansion */
372                              /*  resource object. */
373 #endif
374   StringGroup *capmem;       /* Memory for recording terminal capability */
375                              /*  strings. */
376   GlCharQueue *cq;           /* The terminal output character queue */
377   int input_fd;              /* The file descriptor to read on */
378   int output_fd;             /* The file descriptor to write to */
379   FILE *input_fp;            /* A stream wrapper around input_fd */
380   FILE *output_fp;           /* A stream wrapper around output_fd */
381   FILE *file_fp;             /* When input is being temporarily taken from */
382                              /*  a file, this is its file-pointer. Otherwise */
383                              /*  it is NULL. */
384   char *term;                /* The terminal type specified on the last call */
385                              /*  to gl_change_terminal(). */
386   int is_term;               /* True if stdin is a terminal */
387   GlWriteFn *flush_fn;       /* The function to call to write to the terminal */
388   GlIOMode io_mode;          /* The I/O mode established by gl_io_mode() */
389   int raw_mode;              /* True while the terminal is in raw mode */
390   GlPendingIO pending_io;    /* The type of I/O that is currently pending */
391   GlReturnStatus rtn_status; /* The reason why gl_get_line() returned */
392   int rtn_errno;             /* THe value of errno associated with rtn_status */
393   size_t linelen;            /* The max number of characters per line */
394   char *line;                /* A line-input buffer of allocated size */
395                              /*  linelen+2. The extra 2 characters are */
396                              /*  reserved for "\n\0". */
397   char *cutbuf;              /* A cut-buffer of the same size as line[] */
398   char *prompt;              /* The current prompt string */
399   int prompt_len;            /* The length of the prompt string */
400   int prompt_changed;        /* True after a callback changes the prompt */
401   int prompt_style;          /* How the prompt string is displayed */
402   FreeList *cpl_mem;         /* Memory for GlCplCallback objects */
403   FreeList *ext_act_mem;     /* Memory for GlExternalAction objects */
404   FreeList *sig_mem;         /* Memory for nodes of the signal list */
405   GlSignalNode *sigs;        /* The head of the list of signals */
406   int signals_masked;        /* True between calls to gl_mask_signals() and */
407                              /*  gl_unmask_signals() */
408   int signals_overriden;     /* True between calls to gl_override_signals() */
409                              /*  and gl_restore_signals() */
410   sigset_t all_signal_set;   /* The set of all signals that we are trapping */
411   sigset_t old_signal_set;   /* The set of blocked signals on entry to */
412                              /*  gl_get_line(). */
413   sigset_t use_signal_set;   /* The subset of all_signal_set to unblock */
414                              /*  while waiting for key-strokes */
415   Termios oldattr;           /* Saved terminal attributes. */
416   KeyTab *bindings;          /* A table of key-bindings */
417   int ntotal;                /* The number of characters in gl->line[] */
418   int buff_curpos;           /* The cursor position within gl->line[] */
419   int term_curpos;           /* The cursor position on the terminal */
420   int term_len;              /* The number of terminal characters used to */
421                              /*  display the current input line. */
422   int buff_mark;             /* A marker location in the buffer */
423   int insert_curpos;         /* The cursor position at start of insert */
424   int insert;                /* True in insert mode */
425   int number;                /* If >= 0, a numeric argument is being read */
426   int endline;               /* True to tell gl_get_input_line() to return */
427                              /*  the current contents of gl->line[] */
428   int displayed;             /* True if an input line is currently displayed */
429   int redisplay;             /* If true, the input line will be redrawn */
430                              /*  either after the current action function */
431                              /*  returns, or when gl_get_input_line() */
432                              /*  is next called. */
433   int postpone;              /* _gl_normal_io() sets this flag, to */
434                              /*  postpone any redisplays until */
435                              /*  is next called, to resume line editing. */
436   char keybuf[GL_KEY_MAX+1]; /* A buffer of currently unprocessed key presses */
437   int nbuf;                  /* The number of characters in keybuf[] */
438   int nread;                 /* The number of characters read from keybuf[] */
439   KtAction current_action;   /* The action function that is being invoked */
440   int current_count;         /* The repeat count passed to */
441                              /*  current_acction.fn() */
442   GlhLineID preload_id;      /* When not zero, this should be the ID of a */
443                              /*  line in the history buffer for potential */
444                              /*  recall. */
445   int preload_history;       /* If true, preload the above history line when */
446                              /*  gl_get_input_line() is next called. */
447   long keyseq_count;         /* The number of key sequences entered by the */
448                              /*  the user since new_GetLine() was called. */
449   long last_search;          /* The value of keyseq_count during the last */
450                              /*  history search operation. */
451   GlEditor editor;           /* The style of editing, (eg. vi or emacs) */
452   int silence_bell;          /* True if gl_ring_bell() should do nothing. */
453   int automatic_history;     /* True to automatically archive entered lines */
454                              /*  in the history list. */
455   ViMode vi;                 /* Parameters used when editing in vi mode */
456   const char *left;          /* The string that moves the cursor 1 character */
457                              /*  left. */
458   const char *right;         /* The string that moves the cursor 1 character */
459                              /*  right. */
460   const char *up;            /* The string that moves the cursor 1 character */
461                              /*  up. */
462   const char *down;          /* The string that moves the cursor 1 character */
463                              /*  down. */
464   const char *home;          /* The string that moves the cursor home */
465   const char *bol;           /* Move cursor to beginning of line */
466   const char *clear_eol;     /* The string that clears from the cursor to */
467                              /*  the end of the line. */
468   const char *clear_eod;     /* The string that clears from the cursor to */
469                              /*  the end of the display. */
470   const char *u_arrow;       /* The string returned by the up-arrow key */
471   const char *d_arrow;       /* The string returned by the down-arrow key */
472   const char *l_arrow;       /* The string returned by the left-arrow key */
473   const char *r_arrow;       /* The string returned by the right-arrow key */
474   const char *sound_bell;    /* The string needed to ring the terminal bell */
475   const char *bold;          /* Switch to the bold font */
476   const char *underline;     /* Underline subsequent characters */
477   const char *standout;      /* Turn on standout mode */
478   const char *dim;           /* Switch to a dim font */
479   const char *reverse;       /* Turn on reverse video */
480   const char *blink;         /* Switch to a blinking font */
481   const char *text_attr_off; /* Turn off all text attributes */
482   int nline;                 /* The height of the terminal in lines */
483   int ncolumn;               /* The width of the terminal in columns */
484 #ifdef USE_TERMCAP
485   char *tgetent_buf;         /* The buffer that is used by tgetent() to */
486                              /*  store a terminal description. */
487   char *tgetstr_buf;         /* The buffer that is used by tgetstr() to */
488                              /*  store terminal capabilities. */
489 #endif
490 #ifdef USE_TERMINFO
491   const char *left_n;        /* The parameter string that moves the cursor */
492                              /*  n characters left. */
493   const char *right_n;       /* The parameter string that moves the cursor */
494                              /*  n characters right. */
495 #endif
496   char *app_file;            /* The pathname of the application-specific */
497                              /*  .teclarc configuration file, or NULL. */
498   char *user_file;           /* The pathname of the user-specific */
499                              /*  .teclarc configuration file, or NULL. */
500   int configured;            /* True as soon as any teclarc configuration */
501                              /*  file has been read. */
502   int echo;                  /* True to display the line as it is being */
503                              /*  entered. If 0, only the prompt will be */
504                              /*  displayed, and the line will not be */
505                              /*  archived in the history list. */
506   int last_signal;           /* The last signal that was caught by */
507                              /*  the last call to gl_get_line(), or -1 */
508                              /*  if no signal has been caught yet. */
509 #ifdef HAVE_SELECT
510   FreeList *fd_node_mem;     /* A freelist of GlFdNode structures */
511   GlFdNode *fd_nodes;        /* The list of fd event descriptions */
512   fd_set rfds;               /* The set of fds to watch for readability */
513   fd_set wfds;               /* The set of fds to watch for writability */
514   fd_set ufds;               /* The set of fds to watch for urgent data */
515   int max_fd;                /* The maximum file-descriptor being watched */
516   struct {                   /* Inactivity timeout related data */
517     struct timeval dt;       /* The inactivity timeout when timer.fn() */
518                              /*  isn't 0 */
519     GlTimeoutFn *fn;         /* The application callback to call when */
520                              /*  the inactivity timer expires, or 0 if */
521                              /*  timeouts are not required. */
522     void *data;              /* Application provided data to be passed to */
523                              /*  timer.fn(). */
524   } timer;
525 #endif
526 };
527 
528 /*
529  * Define the max amount of space needed to store a termcap terminal
530  * description. Unfortunately this has to be done by guesswork, so
531  * there is the potential for buffer overflows if we guess too small.
532  * Fortunately termcap has been replaced by terminfo on most
533  * platforms, and with terminfo this isn't an issue. The value that I
534  * am using here is the conventional value, as recommended by certain
535  * web references.
536  */
537 #ifdef USE_TERMCAP
538 #define TERMCAP_BUF_SIZE 2048
539 #endif
540 
541 /*
542  * Set the size of the string segments used to store terminal capability
543  * strings.
544  */
545 #define CAPMEM_SEGMENT_SIZE 512
546 
547 /*
548  * If no terminal size information is available, substitute the
549  * following vt100 default sizes.
550  */
551 #define GL_DEF_NLINE 24
552 #define GL_DEF_NCOLUMN 80
553 
554 /*
555  * Enumerate the attributes needed to classify different types of
556  * signals. These attributes reflect the standard default
557  * characteristics of these signals (according to Richard Steven's
558  * Advanced Programming in the UNIX Environment). Note that these values
559  * are all powers of 2, so that they can be combined in a bitwise union.
560  */
561 typedef enum {
562   GLSA_TERM=1,   /* A signal that terminates processes */
563   GLSA_SUSP=2,   /* A signal that suspends processes */
564   GLSA_CONT=4,   /* A signal that is sent when suspended processes resume */
565   GLSA_IGN=8,    /* A signal that is ignored */
566   GLSA_CORE=16,  /* A signal that generates a core dump */
567   GLSA_HARD=32,  /* A signal generated by a hardware exception */
568   GLSA_SIZE=64   /* A signal indicating terminal size changes */
569 } GlSigAttr;
570 
571 /*
572  * List the signals that we need to catch. In general these are
573  * those that by default terminate or suspend the process, since
574  * in such cases we need to restore terminal settings.
575  */
576 static const struct GlDefSignal {
577   int signo;            /* The number of the signal */
578   unsigned flags;       /* A bitwise union of GlSignalFlags enumerators */
579   GlAfterSignal after;  /* What to do after the signal has been delivered */
580   int attr;             /* The default attributes of this signal, expressed */
581                         /* as a bitwise union of GlSigAttr enumerators */
582   int errno_value;      /* What to set errno to */
583 } gl_signal_list[] = {
584   {SIGABRT,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR},
585   {SIGALRM,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
586   {SIGCONT,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_CONT|GLSA_IGN,  0},
587 #if defined(SIGHUP)
588 #ifdef ENOTTY
589   {SIGHUP,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           ENOTTY},
590 #else
591   {SIGHUP,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
592 #endif
593 #endif
594   {SIGINT,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
595 #if defined(SIGPIPE)
596 #ifdef EPIPE
597   {SIGPIPE,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EPIPE},
598 #else
599   {SIGPIPE,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
600 #endif
601 #endif
602 #ifdef SIGPOLL
603   {SIGPOLL,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
604 #endif
605 #ifdef SIGPWR
606   {SIGPWR,    GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_IGN,            0},
607 #endif
608 #ifdef SIGQUIT
609   {SIGQUIT,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR},
610 #endif
611   {SIGTERM,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
612 #ifdef SIGTSTP
613   {SIGTSTP,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
614 #endif
615 #ifdef SIGTTIN
616   {SIGTTIN,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
617 #endif
618 #ifdef SIGTTOU
619   {SIGTTOU,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
620 #endif
621 #ifdef SIGUSR1
622   {SIGUSR1,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
623 #endif
624 #ifdef SIGUSR2
625   {SIGUSR2,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
626 #endif
627 #ifdef SIGVTALRM
628   {SIGVTALRM, GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
629 #endif
630 #ifdef SIGWINCH
631   {SIGWINCH,  GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_SIZE|GLSA_IGN,  0},
632 #endif
633 #ifdef SIGXCPU
634   {SIGXCPU,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0},
635 #endif
636 #ifdef SIGXFSZ
637   {SIGXFSZ,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0},
638 #endif
639 };
640 
641 /*
642  * Define file-scope variables for use in signal handlers.
643  */
644 static volatile sig_atomic_t gl_pending_signal = -1;
645 static sigjmp_buf gl_setjmp_buffer;
646 
647 static void gl_signal_handler(int signo);
648 
649 static int gl_check_caught_signal(GetLine *gl);
650 
651 /*
652  * Respond to an externally caught process suspension or
653  * termination signal.
654  */
655 static void gl_suspend_process(int signo, GetLine *gl, int ngl);
656 
657 /* Return the default attributes of a given signal */
658 
659 static int gl_classify_signal(int signo);
660 
661 /*
662  * Unfortunately both terminfo and termcap require one to use the tputs()
663  * function to output terminal control characters, and this function
664  * doesn't allow one to specify a file stream. As a result, the following
665  * file-scope variable is used to pass the current output file stream.
666  * This is bad, but there doesn't seem to be any alternative.
667  */
668 static GetLine *tputs_gl = NULL;
669 
670 /*
671  * Define a tab to be a string of 8 spaces.
672  */
673 #define TAB_WIDTH 8
674 
675 /*
676  * Lookup the current size of the terminal.
677  */
678 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline);
679 
680 /*
681  * Getline calls this to temporarily override certain signal handlers
682  * of the calling program.
683  */
684 static int gl_override_signal_handlers(GetLine *gl);
685 
686 /*
687  * Getline calls this to restore the signal handlers of the calling
688  * program.
689  */
690 static int gl_restore_signal_handlers(GetLine *gl);
691 
692 /*
693  * Temporarily block the delivery of all signals that gl_get_line()
694  * is currently configured to trap.
695  */
696 static int gl_mask_signals(GetLine *gl, sigset_t *oldset);
697 
698 /*
699  * Restore the process signal mask that was overriden by a previous
700  * call to gl_mask_signals().
701  */
702 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset);
703 
704 /*
705  * Unblock the signals that gl_get_line() has been configured to catch.
706  */
707 static int gl_catch_signals(GetLine *gl);
708 
709 /*
710  * Return the set of all trappable signals.
711  */
712 static void gl_list_trappable_signals(sigset_t *signals);
713 
714 /*
715  * Put the terminal into raw input mode, after saving the original
716  * terminal attributes in gl->oldattr.
717  */
718 static int gl_raw_terminal_mode(GetLine *gl);
719 
720 /*
721  * Restore the terminal attributes from gl->oldattr.
722  */
723 static int gl_restore_terminal_attributes(GetLine *gl);
724 
725 /*
726  * Switch to non-blocking I/O if possible.
727  */
728 static int gl_nonblocking_io(GetLine *gl, int fd);
729 
730 /*
731  * Switch to blocking I/O if possible.
732  */
733 static int gl_blocking_io(GetLine *gl, int fd);
734 
735 /*
736  * Read a line from the user in raw mode.
737  */
738 static int gl_get_input_line(GetLine *gl, const char *prompt,
739 			     const char *start_line, int start_pos);
740 
741 /*
742  * Query the user for a single character.
743  */
744 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar);
745 
746 /*
747  * Read input from a non-interactive input stream.
748  */
749 static int gl_read_stream_line(GetLine *gl);
750 
751 /*
752  * Read a single character from a non-interactive input stream.
753  */
754 static int gl_read_stream_char(GetLine *gl);
755 
756 /*
757  * Prepare to edit a new line.
758  */
759 static int gl_present_line(GetLine *gl, const char *prompt,
760 			   const char *start_line, int start_pos);
761 
762 /*
763  * Reset all line input parameters for a new input line.
764  */
765 static void gl_reset_input_line(GetLine *gl);
766 
767 /*
768  * Handle the receipt of the potential start of a new key-sequence from
769  * the user.
770  */
771 static int gl_interpret_char(GetLine *gl, char c);
772 
773 /*
774  * Bind a single control or meta character to an action.
775  */
776 static int gl_bind_control_char(GetLine *gl, KtBinder binder,
777 				char c, const char *action);
778 
779 /*
780  * Set up terminal-specific key bindings.
781  */
782 static int gl_bind_terminal_keys(GetLine *gl);
783 
784 /*
785  * Lookup terminal control string and size information.
786  */
787 static int gl_control_strings(GetLine *gl, const char *term);
788 
789 /*
790  * Wrappers around the terminfo and termcap functions that lookup
791  * strings in the terminal information databases.
792  */
793 #ifdef USE_TERMINFO
794 static const char *gl_tigetstr(GetLine *gl, const char *name);
795 #elif defined(USE_TERMCAP)
796 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr);
797 #endif
798 
799 /*
800  * Output a binary string directly to the terminal.
801  */
802 static int gl_print_raw_string(GetLine *gl, int buffered,
803 			       const char *string, int n);
804 
805 /*
806  * Print an informational message, starting and finishing on new lines.
807  * After the list of strings to be printed, the last argument MUST be
808  * GL_END_INFO.
809  */
810 static int gl_print_info(GetLine *gl, ...);
811 #define GL_END_INFO ((const char *)0)
812 
813 /*
814  * Start a newline and place the cursor at its start.
815  */
816 static int gl_start_newline(GetLine *gl, int buffered);
817 
818 /*
819  * Output a terminal control sequence.
820  */
821 static int gl_print_control_sequence(GetLine *gl, int nline,
822 				     const char *string);
823 
824 /*
825  * Output a character or string to the terminal after converting tabs
826  * to spaces and control characters to a caret followed by the modified
827  * character.
828  */
829 static int gl_print_char(GetLine *gl, char c, char pad);
830 static int gl_print_string(GetLine *gl, const char *string, char pad);
831 
832 /*
833  * Delete nc characters starting from the one under the cursor.
834  * Optionally copy the deleted characters to the cut buffer.
835  */
836 static int gl_delete_chars(GetLine *gl, int nc, int cut);
837 
838 /*
839  * Add a character to the line buffer at the current cursor position,
840  * inserting or overwriting according the current mode.
841  */
842 static int gl_add_char_to_line(GetLine *gl, char c);
843 
844 /*
845  * Insert/append a string to the line buffer and terminal at the current
846  * cursor position.
847  */
848 static int gl_add_string_to_line(GetLine *gl, const char *s);
849 
850 /*
851  * Record a new character in the input-line buffer.
852  */
853 static int gl_buffer_char(GetLine *gl, char c, int bufpos);
854 
855 /*
856  * Record a string in the input-line buffer.
857  */
858 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos);
859 
860 /*
861  * Make way to insert a string in the input-line buffer.
862  */
863 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n);
864 
865 /*
866  * Remove characters from the input-line buffer, and move any characters
867  * that followed them to the start of the vacated space.
868  */
869 static void gl_remove_from_buffer(GetLine *gl, int start, int n);
870 
871 /*
872  * Terminate the input-line buffer after a specified number of characters.
873  */
874 static int gl_truncate_buffer(GetLine *gl, int n);
875 
876 /*
877  * Delete the displayed part of the input line that follows the current
878  * terminal cursor position.
879  */
880 static int gl_truncate_display(GetLine *gl);
881 
882 /*
883  * Accomodate changes to the contents of the input line buffer
884  * that weren't made by the above gl_*buffer functions.
885  */
886 static void gl_update_buffer(GetLine *gl);
887 
888 /*
889  * Read a single character from the terminal.
890  */
891 static int gl_read_terminal(GetLine *gl, int keep, char *c);
892 
893 /*
894  * Discard processed characters from the key-press lookahead buffer.
895  */
896 static void gl_discard_chars(GetLine *gl, int nused);
897 
898 /*
899  * Move the terminal cursor n positions to the left or right.
900  */
901 static int gl_terminal_move_cursor(GetLine *gl, int n);
902 
903 /*
904  * Move the terminal cursor to a given position.
905  */
906 static int gl_set_term_curpos(GetLine *gl, int term_curpos);
907 
908 /*
909  * Set the position of the cursor both in the line input buffer and on the
910  * terminal.
911  */
912 static int gl_place_cursor(GetLine *gl, int buff_curpos);
913 
914 /*
915  * How many characters are needed to write a number as an octal string?
916  */
917 static int gl_octal_width(unsigned num);
918 
919 /*
920  * Return the number of spaces needed to display a tab character at
921  * a given location of the terminal.
922  */
923 static int gl_displayed_tab_width(GetLine *gl, int term_curpos);
924 
925 /*
926  * Return the number of terminal characters needed to display a
927  * given raw character.
928  */
929 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos);
930 
931 /*
932  * Return the number of terminal characters needed to display a
933  * given substring.
934  */
935 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
936 				     int term_curpos);
937 
938 /*
939  * Return non-zero if 'c' is to be considered part of a word.
940  */
941 static int gl_is_word_char(int c);
942 
943 /*
944  * Read a tecla configuration file.
945  */
946 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who);
947 
948 /*
949  * Read a tecla configuration string.
950  */
951 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who);
952 
953 /*
954  * Define the callback function used by _gl_parse_config_line() to
955  * read the next character of a configuration stream.
956  */
957 #define GLC_GETC_FN(fn) int (fn)(void *stream)
958 typedef GLC_GETC_FN(GlcGetcFn);
959 
960 static GLC_GETC_FN(glc_file_getc);  /* Read from a file */
961 static GLC_GETC_FN(glc_buff_getc);  /* Read from a string */
962 
963 /*
964  * Parse a single configuration command line.
965  */
966 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
967 				 const char *origin, KtBinder who, int *lineno);
968 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
969 				  const char *errmsg);
970 
971 /*
972  * Bind the actual arrow key bindings to match those of the symbolic
973  * arrow-key bindings.
974  */
975 static int _gl_bind_arrow_keys(GetLine *gl);
976 
977 /*
978  * Copy the binding of the specified symbolic arrow-key binding to
979  * the terminal specific, and default arrow-key key-sequences.
980  */
981 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
982 				const char *term_seq,
983 				const char *def_seq1,
984 				const char *def_seq2);
985 
986 /*
987  * After the gl_read_from_file() action has been used to tell gl_get_line()
988  * to temporarily read input from a file, gl_revert_input() arranges
989  * for input to be reverted to the input stream last registered with
990  * gl_change_terminal().
991  */
992 static void gl_revert_input(GetLine *gl);
993 
994 /*
995  * Flush unwritten characters to the terminal.
996  */
997 static int gl_flush_output(GetLine *gl);
998 
999 /*
1000  * The callback through which all terminal output is routed.
1001  * This simply appends characters to a queue buffer, which is
1002  * subsequently flushed to the output channel by gl_flush_output().
1003  */
1004 static GL_WRITE_FN(gl_write_fn);
1005 
1006 /*
1007  * The callback function which the output character queue object
1008  * calls to transfer characters to the output channel.
1009  */
1010 static GL_WRITE_FN(gl_flush_terminal);
1011 
1012 /*
1013  * Enumerate the possible return statuses of gl_read_input().
1014  */
1015 typedef enum {
1016   GL_READ_OK,      /* A character was read successfully */
1017   GL_READ_ERROR,   /* A read-error occurred */
1018   GL_READ_BLOCKED, /* The read would have blocked the caller */
1019   GL_READ_EOF      /* The end of the current input file was reached */
1020 } GlReadStatus;
1021 
1022 static GlReadStatus gl_read_input(GetLine *gl, char *c);
1023 /*
1024  * Private functions of gl_read_input().
1025  */
1026 static int gl_event_handler(GetLine *gl, int fd);
1027 static int gl_read_unmasked(GetLine *gl, int fd, char *c);
1028 
1029 
1030 /*
1031  * A private function of gl_tty_signals().
1032  */
1033 static int gl_set_tty_signal(int signo, void (*handler)(int));
1034 
1035 /*
1036  * Change the editor style being emulated.
1037  */
1038 static int gl_change_editor(GetLine *gl, GlEditor editor);
1039 
1040 /*
1041  * Searching in a given direction, return the index of a given (or
1042  * read) character in the input line, or the character that precedes
1043  * it in the specified search direction. Return -1 if not found.
1044  */
1045 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c);
1046 
1047 /*
1048  * Return the buffer index of the nth word ending after the cursor.
1049  */
1050 static int gl_nth_word_end_forward(GetLine *gl, int n);
1051 
1052 /*
1053  * Return the buffer index of the nth word start after the cursor.
1054  */
1055 static int gl_nth_word_start_forward(GetLine *gl, int n);
1056 
1057 /*
1058  * Return the buffer index of the nth word start before the cursor.
1059  */
1060 static int gl_nth_word_start_backward(GetLine *gl, int n);
1061 
1062 /*
1063  * When called when vi command mode is enabled, this function saves the
1064  * current line and cursor position for potential restoration later
1065  * by the vi undo command.
1066  */
1067 static void gl_save_for_undo(GetLine *gl);
1068 
1069 /*
1070  * If in vi mode, switch to vi command mode.
1071  */
1072 static void gl_vi_command_mode(GetLine *gl);
1073 
1074 /*
1075  * In vi mode this is used to delete up to or onto a given or read
1076  * character in the input line. Also switch to insert mode if requested
1077  * after the deletion.
1078  */
1079 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
1080 			  int onto, int change);
1081 
1082 /*
1083  * Copy the characters between the cursor and the count'th instance of
1084  * a specified (or read) character in the input line, into the cut buffer.
1085  */
1086 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto);
1087 
1088 /*
1089  * Return the line index of the parenthesis that either matches the one under
1090  * the cursor, or not over a parenthesis character, the index of the next
1091  * close parenthesis. Return -1 if not found.
1092  */
1093 static int gl_index_of_matching_paren(GetLine *gl);
1094 
1095 /*
1096  * Replace a malloc'd string (or NULL), with another malloc'd copy of
1097  * a string (or NULL).
1098  */
1099 static int gl_record_string(char **sptr, const char *string);
1100 
1101 /*
1102  * Enumerate text display attributes as powers of two, suitable for
1103  * use in a bit-mask.
1104  */
1105 typedef enum {
1106   GL_TXT_STANDOUT=1,   /* Display text highlighted */
1107   GL_TXT_UNDERLINE=2,  /* Display text underlined */
1108   GL_TXT_REVERSE=4,    /* Display text with reverse video */
1109   GL_TXT_BLINK=8,      /* Display blinking text */
1110   GL_TXT_DIM=16,       /* Display text in a dim font */
1111   GL_TXT_BOLD=32       /* Display text using a bold font */
1112 } GlTextAttr;
1113 
1114 /*
1115  * Display the prompt regardless of the current visibility mode.
1116  */
1117 static int gl_display_prompt(GetLine *gl);
1118 
1119 /*
1120  * Return the number of characters used by the prompt on the terminal.
1121  */
1122 static int gl_displayed_prompt_width(GetLine *gl);
1123 
1124 /*
1125  * Prepare to return the current input line to the caller of gl_get_line().
1126  */
1127 static int gl_line_ended(GetLine *gl, int newline_char);
1128 
1129 /*
1130  * Arrange for the input line to be redisplayed when the current contents
1131  * of the output queue have been flushed.
1132  */
1133 static void gl_queue_redisplay(GetLine *gl);
1134 
1135 /*
1136  * Erase the displayed representation of the input line, without
1137  * touching the buffered copy.
1138  */
1139 static int gl_erase_line(GetLine *gl);
1140 
1141 /*
1142  * This function is called whenever the input line has been erased.
1143  */
1144 static void gl_line_erased(GetLine *gl);
1145 
1146 /*
1147  * Arrange for the current input line to be discarded.
1148  */
1149 void _gl_abandon_line(GetLine *gl);
1150 
1151 /*
1152  * The following are private internally callable versions of pertinent
1153  * public functions. Unlike their public wrapper functions, they don't
1154  * block signals while running, and assume that their arguments are valid.
1155  * They are designed to be called from places where signals are already
1156  * blocked, and where simple sanity checks have already been applied to
1157  * their arguments.
1158  */
1159 static char *_gl_get_line(GetLine *gl, const char *prompt,
1160 			  const char *start_line, int start_pos);
1161 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar);
1162 static int _gl_read_char(GetLine *gl);
1163 static int _gl_update_size(GetLine *gl);
1164 /*
1165  * Redraw the current input line to account for a change in the terminal
1166  * size. Also install the new size in gl.
1167  */
1168 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline);
1169 
1170 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
1171 			       const char *term);
1172 static int _gl_configure_getline(GetLine *gl, const char *app_string,
1173 				 const char *app_file, const char *user_file);
1174 static int _gl_save_history(GetLine *gl, const char *filename,
1175 			    const char *comment, int max_lines);
1176 static int _gl_load_history(GetLine *gl, const char *filename,
1177 			    const char *comment);
1178 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
1179 			GlFdEventFn *callback, void *data);
1180 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
1181 			      GlTerminalSize *size);
1182 static void _gl_replace_prompt(GetLine *gl, const char *prompt);
1183 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
1184 			   GlAfterSignal after, int errno_value);
1185 static int _gl_raw_io(GetLine *gl, int redisplay);
1186 static int _gl_normal_io(GetLine *gl);
1187 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
1188 				 int list_only, const char *name,
1189 				 const char *keyseq);
1190 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
1191 			       const char *name, const char *keyseq);
1192 static int _gl_io_mode(GetLine *gl, GlIOMode mode);
1193 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline);
1194 static int _gl_append_history(GetLine *gl, const char *line);
1195 
1196 /*
1197  * Reset the completion status and associated errno value in
1198  * gl->rtn_status and gl->rtn_errno.
1199  */
1200 static void gl_clear_status(GetLine *gl);
1201 
1202 /*
1203  * Record a completion status, unless a previous abnormal completion
1204  * status has already been recorded for the current call.
1205  */
1206 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
1207 			     int rtn_errno);
1208 
1209 /*
1210  * Set the maximum length of a line in a user's tecla configuration
1211  * file (not counting comments).
1212  */
1213 #define GL_CONF_BUFLEN 100
1214 
1215 /*
1216  * Set the maximum number of arguments supported by individual commands
1217  * in tecla configuration files.
1218  */
1219 #define GL_CONF_MAXARG 10
1220 
1221 /*
1222  * Prototype the available action functions.
1223  */
1224 static KT_KEY_FN(gl_user_interrupt);
1225 static KT_KEY_FN(gl_abort);
1226 static KT_KEY_FN(gl_suspend);
1227 static KT_KEY_FN(gl_stop_output);
1228 static KT_KEY_FN(gl_start_output);
1229 static KT_KEY_FN(gl_literal_next);
1230 static KT_KEY_FN(gl_cursor_left);
1231 static KT_KEY_FN(gl_cursor_right);
1232 static KT_KEY_FN(gl_insert_mode);
1233 static KT_KEY_FN(gl_beginning_of_line);
1234 static KT_KEY_FN(gl_end_of_line);
1235 static KT_KEY_FN(gl_delete_line);
1236 static KT_KEY_FN(gl_kill_line);
1237 static KT_KEY_FN(gl_forward_word);
1238 static KT_KEY_FN(gl_backward_word);
1239 static KT_KEY_FN(gl_forward_delete_char);
1240 static KT_KEY_FN(gl_backward_delete_char);
1241 static KT_KEY_FN(gl_forward_delete_word);
1242 static KT_KEY_FN(gl_backward_delete_word);
1243 static KT_KEY_FN(gl_delete_refind);
1244 static KT_KEY_FN(gl_delete_invert_refind);
1245 static KT_KEY_FN(gl_delete_to_column);
1246 static KT_KEY_FN(gl_delete_to_parenthesis);
1247 static KT_KEY_FN(gl_forward_delete_find);
1248 static KT_KEY_FN(gl_backward_delete_find);
1249 static KT_KEY_FN(gl_forward_delete_to);
1250 static KT_KEY_FN(gl_backward_delete_to);
1251 static KT_KEY_FN(gl_upcase_word);
1252 static KT_KEY_FN(gl_downcase_word);
1253 static KT_KEY_FN(gl_capitalize_word);
1254 static KT_KEY_FN(gl_redisplay);
1255 static KT_KEY_FN(gl_clear_screen);
1256 static KT_KEY_FN(gl_transpose_chars);
1257 static KT_KEY_FN(gl_set_mark);
1258 static KT_KEY_FN(gl_exchange_point_and_mark);
1259 static KT_KEY_FN(gl_kill_region);
1260 static KT_KEY_FN(gl_copy_region_as_kill);
1261 static KT_KEY_FN(gl_yank);
1262 static KT_KEY_FN(gl_up_history);
1263 static KT_KEY_FN(gl_down_history);
1264 static KT_KEY_FN(gl_history_search_backward);
1265 static KT_KEY_FN(gl_history_re_search_backward);
1266 static KT_KEY_FN(gl_history_search_forward);
1267 static KT_KEY_FN(gl_history_re_search_forward);
1268 static KT_KEY_FN(gl_complete_word);
1269 #ifndef HIDE_FILE_SYSTEM
1270 static KT_KEY_FN(gl_expand_filename);
1271 static KT_KEY_FN(gl_read_from_file);
1272 static KT_KEY_FN(gl_read_init_files);
1273 static KT_KEY_FN(gl_list_glob);
1274 #endif
1275 static KT_KEY_FN(gl_del_char_or_list_or_eof);
1276 static KT_KEY_FN(gl_list_or_eof);
1277 static KT_KEY_FN(gl_beginning_of_history);
1278 static KT_KEY_FN(gl_end_of_history);
1279 static KT_KEY_FN(gl_digit_argument);
1280 static KT_KEY_FN(gl_newline);
1281 static KT_KEY_FN(gl_repeat_history);
1282 static KT_KEY_FN(gl_vi_insert);
1283 static KT_KEY_FN(gl_vi_overwrite);
1284 static KT_KEY_FN(gl_change_case);
1285 static KT_KEY_FN(gl_vi_insert_at_bol);
1286 static KT_KEY_FN(gl_vi_append_at_eol);
1287 static KT_KEY_FN(gl_vi_append);
1288 static KT_KEY_FN(gl_backward_kill_line);
1289 static KT_KEY_FN(gl_goto_column);
1290 static KT_KEY_FN(gl_forward_to_word);
1291 static KT_KEY_FN(gl_vi_replace_char);
1292 static KT_KEY_FN(gl_vi_change_rest_of_line);
1293 static KT_KEY_FN(gl_vi_change_line);
1294 static KT_KEY_FN(gl_vi_change_to_bol);
1295 static KT_KEY_FN(gl_vi_change_refind);
1296 static KT_KEY_FN(gl_vi_change_invert_refind);
1297 static KT_KEY_FN(gl_vi_change_to_column);
1298 static KT_KEY_FN(gl_vi_change_to_parenthesis);
1299 static KT_KEY_FN(gl_vi_forward_change_word);
1300 static KT_KEY_FN(gl_vi_backward_change_word);
1301 static KT_KEY_FN(gl_vi_forward_change_find);
1302 static KT_KEY_FN(gl_vi_backward_change_find);
1303 static KT_KEY_FN(gl_vi_forward_change_to);
1304 static KT_KEY_FN(gl_vi_backward_change_to);
1305 static KT_KEY_FN(gl_vi_forward_change_char);
1306 static KT_KEY_FN(gl_vi_backward_change_char);
1307 static KT_KEY_FN(gl_forward_copy_char);
1308 static KT_KEY_FN(gl_backward_copy_char);
1309 static KT_KEY_FN(gl_forward_find_char);
1310 static KT_KEY_FN(gl_backward_find_char);
1311 static KT_KEY_FN(gl_forward_to_char);
1312 static KT_KEY_FN(gl_backward_to_char);
1313 static KT_KEY_FN(gl_repeat_find_char);
1314 static KT_KEY_FN(gl_invert_refind_char);
1315 static KT_KEY_FN(gl_append_yank);
1316 static KT_KEY_FN(gl_backward_copy_word);
1317 static KT_KEY_FN(gl_forward_copy_word);
1318 static KT_KEY_FN(gl_copy_to_bol);
1319 static KT_KEY_FN(gl_copy_refind);
1320 static KT_KEY_FN(gl_copy_invert_refind);
1321 static KT_KEY_FN(gl_copy_to_column);
1322 static KT_KEY_FN(gl_copy_to_parenthesis);
1323 static KT_KEY_FN(gl_copy_rest_of_line);
1324 static KT_KEY_FN(gl_copy_line);
1325 static KT_KEY_FN(gl_backward_copy_find);
1326 static KT_KEY_FN(gl_forward_copy_find);
1327 static KT_KEY_FN(gl_backward_copy_to);
1328 static KT_KEY_FN(gl_forward_copy_to);
1329 static KT_KEY_FN(gl_vi_undo);
1330 static KT_KEY_FN(gl_emacs_editing_mode);
1331 static KT_KEY_FN(gl_vi_editing_mode);
1332 static KT_KEY_FN(gl_ring_bell);
1333 static KT_KEY_FN(gl_vi_repeat_change);
1334 static KT_KEY_FN(gl_find_parenthesis);
1335 static KT_KEY_FN(gl_list_history);
1336 static KT_KEY_FN(gl_list_completions);
1337 static KT_KEY_FN(gl_run_external_action);
1338 
1339 /*
1340  * Name the available action functions.
1341  */
1342 static const struct {const char *name; KT_KEY_FN(*fn);} gl_actions[] = {
1343   {"user-interrupt",             gl_user_interrupt},
1344   {"abort",                      gl_abort},
1345   {"suspend",                    gl_suspend},
1346   {"stop-output",                gl_stop_output},
1347   {"start-output",               gl_start_output},
1348   {"literal-next",               gl_literal_next},
1349   {"cursor-right",               gl_cursor_right},
1350   {"cursor-left",                gl_cursor_left},
1351   {"insert-mode",                gl_insert_mode},
1352   {"beginning-of-line",          gl_beginning_of_line},
1353   {"end-of-line",                gl_end_of_line},
1354   {"delete-line",                gl_delete_line},
1355   {"kill-line",                  gl_kill_line},
1356   {"forward-word",               gl_forward_word},
1357   {"backward-word",              gl_backward_word},
1358   {"forward-delete-char",        gl_forward_delete_char},
1359   {"backward-delete-char",       gl_backward_delete_char},
1360   {"forward-delete-word",        gl_forward_delete_word},
1361   {"backward-delete-word",       gl_backward_delete_word},
1362   {"delete-refind",              gl_delete_refind},
1363   {"delete-invert-refind",       gl_delete_invert_refind},
1364   {"delete-to-column",           gl_delete_to_column},
1365   {"delete-to-parenthesis",      gl_delete_to_parenthesis},
1366   {"forward-delete-find",        gl_forward_delete_find},
1367   {"backward-delete-find",       gl_backward_delete_find},
1368   {"forward-delete-to",          gl_forward_delete_to},
1369   {"backward-delete-to",         gl_backward_delete_to},
1370   {"upcase-word",                gl_upcase_word},
1371   {"downcase-word",              gl_downcase_word},
1372   {"capitalize-word",            gl_capitalize_word},
1373   {"redisplay",                  gl_redisplay},
1374   {"clear-screen",               gl_clear_screen},
1375   {"transpose-chars",            gl_transpose_chars},
1376   {"set-mark",                   gl_set_mark},
1377   {"exchange-point-and-mark",    gl_exchange_point_and_mark},
1378   {"kill-region",                gl_kill_region},
1379   {"copy-region-as-kill",        gl_copy_region_as_kill},
1380   {"yank",                       gl_yank},
1381   {"up-history",                 gl_up_history},
1382   {"down-history",               gl_down_history},
1383   {"history-search-backward",    gl_history_search_backward},
1384   {"history-re-search-backward", gl_history_re_search_backward},
1385   {"history-search-forward",     gl_history_search_forward},
1386   {"history-re-search-forward",  gl_history_re_search_forward},
1387   {"complete-word",              gl_complete_word},
1388 #ifndef HIDE_FILE_SYSTEM
1389   {"expand-filename",            gl_expand_filename},
1390   {"read-from-file",             gl_read_from_file},
1391   {"read-init-files",            gl_read_init_files},
1392   {"list-glob",                  gl_list_glob},
1393 #endif
1394   {"del-char-or-list-or-eof",    gl_del_char_or_list_or_eof},
1395   {"beginning-of-history",       gl_beginning_of_history},
1396   {"end-of-history",             gl_end_of_history},
1397   {"digit-argument",             gl_digit_argument},
1398   {"newline",                    gl_newline},
1399   {"repeat-history",             gl_repeat_history},
1400   {"vi-insert",                  gl_vi_insert},
1401   {"vi-overwrite",               gl_vi_overwrite},
1402   {"vi-insert-at-bol",           gl_vi_insert_at_bol},
1403   {"vi-append-at-eol",           gl_vi_append_at_eol},
1404   {"vi-append",                  gl_vi_append},
1405   {"change-case",                gl_change_case},
1406   {"backward-kill-line",         gl_backward_kill_line},
1407   {"goto-column",                gl_goto_column},
1408   {"forward-to-word",            gl_forward_to_word},
1409   {"vi-replace-char",            gl_vi_replace_char},
1410   {"vi-change-rest-of-line",     gl_vi_change_rest_of_line},
1411   {"vi-change-line",             gl_vi_change_line},
1412   {"vi-change-to-bol",           gl_vi_change_to_bol},
1413   {"vi-change-refind",           gl_vi_change_refind},
1414   {"vi-change-invert-refind",    gl_vi_change_invert_refind},
1415   {"vi-change-to-column",        gl_vi_change_to_column},
1416   {"vi-change-to-parenthesis",   gl_vi_change_to_parenthesis},
1417   {"forward-copy-char",          gl_forward_copy_char},
1418   {"backward-copy-char",         gl_backward_copy_char},
1419   {"forward-find-char",          gl_forward_find_char},
1420   {"backward-find-char",         gl_backward_find_char},
1421   {"forward-to-char",            gl_forward_to_char},
1422   {"backward-to-char",           gl_backward_to_char},
1423   {"repeat-find-char",           gl_repeat_find_char},
1424   {"invert-refind-char",         gl_invert_refind_char},
1425   {"append-yank",                gl_append_yank},
1426   {"backward-copy-word",         gl_backward_copy_word},
1427   {"forward-copy-word",          gl_forward_copy_word},
1428   {"copy-to-bol",                gl_copy_to_bol},
1429   {"copy-refind",                gl_copy_refind},
1430   {"copy-invert-refind",         gl_copy_invert_refind},
1431   {"copy-to-column",             gl_copy_to_column},
1432   {"copy-to-parenthesis",        gl_copy_to_parenthesis},
1433   {"copy-rest-of-line",          gl_copy_rest_of_line},
1434   {"copy-line",                  gl_copy_line},
1435   {"backward-copy-find",         gl_backward_copy_find},
1436   {"forward-copy-find",          gl_forward_copy_find},
1437   {"backward-copy-to",           gl_backward_copy_to},
1438   {"forward-copy-to",            gl_forward_copy_to},
1439   {"list-or-eof",                gl_list_or_eof},
1440   {"vi-undo",                    gl_vi_undo},
1441   {"vi-backward-change-word",    gl_vi_backward_change_word},
1442   {"vi-forward-change-word",     gl_vi_forward_change_word},
1443   {"vi-backward-change-find",    gl_vi_backward_change_find},
1444   {"vi-forward-change-find",     gl_vi_forward_change_find},
1445   {"vi-backward-change-to",      gl_vi_backward_change_to},
1446   {"vi-forward-change-to",       gl_vi_forward_change_to},
1447   {"vi-backward-change-char",    gl_vi_backward_change_char},
1448   {"vi-forward-change-char",     gl_vi_forward_change_char},
1449   {"emacs-mode",                 gl_emacs_editing_mode},
1450   {"vi-mode",                    gl_vi_editing_mode},
1451   {"ring-bell",                  gl_ring_bell},
1452   {"vi-repeat-change",           gl_vi_repeat_change},
1453   {"find-parenthesis",           gl_find_parenthesis},
1454   {"list-history",               gl_list_history},
1455 };
1456 
1457 /*
1458  * Define the default key-bindings in emacs mode.
1459  */
1460 static const KtKeyBinding gl_emacs_bindings[] = {
1461   {"right",        "cursor-right"},
1462   {"^F",           "cursor-right"},
1463   {"left",         "cursor-left"},
1464   {"^B",           "cursor-left"},
1465   {"M-i",          "insert-mode"},
1466   {"M-I",          "insert-mode"},
1467   {"^A",           "beginning-of-line"},
1468   {"^E",           "end-of-line"},
1469   {"^U",           "delete-line"},
1470   {"^K",           "kill-line"},
1471   {"M-f",          "forward-word"},
1472   {"M-F",          "forward-word"},
1473   {"M-b",          "backward-word"},
1474   {"M-B",          "backward-word"},
1475   {"^D",           "del-char-or-list-or-eof"},
1476   {"^H",           "backward-delete-char"},
1477   {"^?",           "backward-delete-char"},
1478   {"M-d",          "forward-delete-word"},
1479   {"M-D",          "forward-delete-word"},
1480   {"M-^H",         "backward-delete-word"},
1481   {"M-^?",         "backward-delete-word"},
1482   {"M-u",          "upcase-word"},
1483   {"M-U",          "upcase-word"},
1484   {"M-l",          "downcase-word"},
1485   {"M-L",          "downcase-word"},
1486   {"M-c",          "capitalize-word"},
1487   {"M-C",          "capitalize-word"},
1488   {"^R",           "redisplay"},
1489   {"^L",           "clear-screen"},
1490   {"^T",           "transpose-chars"},
1491   {"^@",           "set-mark"},
1492   {"^X^X",         "exchange-point-and-mark"},
1493   {"^W",           "kill-region"},
1494   {"M-w",          "copy-region-as-kill"},
1495   {"M-W",          "copy-region-as-kill"},
1496   {"^Y",           "yank"},
1497   {"^P",           "up-history"},
1498   {"up",           "up-history"},
1499   {"^N",           "down-history"},
1500   {"down",         "down-history"},
1501   {"M-p",          "history-search-backward"},
1502   {"M-P",          "history-search-backward"},
1503   {"M-n",          "history-search-forward"},
1504   {"M-N",          "history-search-forward"},
1505   {"\t",           "complete-word"},
1506 #ifndef HIDE_FILE_SYSTEM
1507   {"^X*",          "expand-filename"},
1508   {"^X^F",         "read-from-file"},
1509   {"^X^R",         "read-init-files"},
1510   {"^Xg",          "list-glob"},
1511   {"^XG",          "list-glob"},
1512 #endif
1513   {"^Xh",          "list-history"},
1514   {"^XH",          "list-history"},
1515   {"M-<",          "beginning-of-history"},
1516   {"M->",          "end-of-history"},
1517   {"M-0",          "digit-argument"},
1518   {"M-1",          "digit-argument"},
1519   {"M-2",          "digit-argument"},
1520   {"M-3",          "digit-argument"},
1521   {"M-4",          "digit-argument"},
1522   {"M-5",          "digit-argument"},
1523   {"M-6",          "digit-argument"},
1524   {"M-7",          "digit-argument"},
1525   {"M-8",          "digit-argument"},
1526   {"M-9",          "digit-argument"},
1527   {"\r",           "newline"},
1528   {"\n",           "newline"},
1529   {"M-o",          "repeat-history"},
1530   {"M-C-v",        "vi-mode"},
1531 };
1532 
1533 /*
1534  * Define the default key-bindings in vi mode. Note that in vi-mode
1535  * meta-key bindings are command-mode bindings. For example M-i first
1536  * switches to command mode if not already in that mode, then moves
1537  * the cursor one position right, as in vi.
1538  */
1539 static const KtKeyBinding gl_vi_bindings[] = {
1540   {"^D",           "list-or-eof"},
1541 #ifndef HIDE_FILE_SYSTEM
1542   {"^G",           "list-glob"},
1543 #endif
1544   {"^H",           "backward-delete-char"},
1545   {"\t",           "complete-word"},
1546   {"\r",           "newline"},
1547   {"\n",           "newline"},
1548   {"^L",           "clear-screen"},
1549   {"^N",           "down-history"},
1550   {"^P",           "up-history"},
1551   {"^R",           "redisplay"},
1552   {"^U",           "backward-kill-line"},
1553   {"^W",           "backward-delete-word"},
1554 #ifndef HIDE_FILE_SYSTEM
1555   {"^X^F",         "read-from-file"},
1556   {"^X^R",         "read-init-files"},
1557   {"^X*",          "expand-filename"},
1558 #endif
1559   {"^?",           "backward-delete-char"},
1560   {"M- ",          "cursor-right"},
1561   {"M-$",          "end-of-line"},
1562 #ifndef HIDE_FILE_SYSTEM
1563   {"M-*",          "expand-filename"},
1564 #endif
1565   {"M-+",          "down-history"},
1566   {"M--",          "up-history"},
1567   {"M-<",          "beginning-of-history"},
1568   {"M->",          "end-of-history"},
1569   {"M-^",          "beginning-of-line"},
1570   {"M-;",          "repeat-find-char"},
1571   {"M-,",          "invert-refind-char"},
1572   {"M-|",          "goto-column"},
1573   {"M-~",          "change-case"},
1574   {"M-.",          "vi-repeat-change"},
1575   {"M-%",          "find-parenthesis"},
1576   {"M-0",          "digit-argument"},
1577   {"M-1",          "digit-argument"},
1578   {"M-2",          "digit-argument"},
1579   {"M-3",          "digit-argument"},
1580   {"M-4",          "digit-argument"},
1581   {"M-5",          "digit-argument"},
1582   {"M-6",          "digit-argument"},
1583   {"M-7",          "digit-argument"},
1584   {"M-8",          "digit-argument"},
1585   {"M-9",          "digit-argument"},
1586   {"M-a",          "vi-append"},
1587   {"M-A",          "vi-append-at-eol"},
1588   {"M-b",          "backward-word"},
1589   {"M-B",          "backward-word"},
1590   {"M-C",          "vi-change-rest-of-line"},
1591   {"M-cb",         "vi-backward-change-word"},
1592   {"M-cB",         "vi-backward-change-word"},
1593   {"M-cc",         "vi-change-line"},
1594   {"M-ce",         "vi-forward-change-word"},
1595   {"M-cE",         "vi-forward-change-word"},
1596   {"M-cw",         "vi-forward-change-word"},
1597   {"M-cW",         "vi-forward-change-word"},
1598   {"M-cF",         "vi-backward-change-find"},
1599   {"M-cf",         "vi-forward-change-find"},
1600   {"M-cT",         "vi-backward-change-to"},
1601   {"M-ct",         "vi-forward-change-to"},
1602   {"M-c;",         "vi-change-refind"},
1603   {"M-c,",         "vi-change-invert-refind"},
1604   {"M-ch",         "vi-backward-change-char"},
1605   {"M-c^H",        "vi-backward-change-char"},
1606   {"M-c^?",        "vi-backward-change-char"},
1607   {"M-cl",         "vi-forward-change-char"},
1608   {"M-c ",         "vi-forward-change-char"},
1609   {"M-c^",         "vi-change-to-bol"},
1610   {"M-c0",         "vi-change-to-bol"},
1611   {"M-c$",         "vi-change-rest-of-line"},
1612   {"M-c|",         "vi-change-to-column"},
1613   {"M-c%",         "vi-change-to-parenthesis"},
1614   {"M-dh",         "backward-delete-char"},
1615   {"M-d^H",        "backward-delete-char"},
1616   {"M-d^?",        "backward-delete-char"},
1617   {"M-dl",         "forward-delete-char"},
1618   {"M-d ",         "forward-delete-char"},
1619   {"M-dd",         "delete-line"},
1620   {"M-db",         "backward-delete-word"},
1621   {"M-dB",         "backward-delete-word"},
1622   {"M-de",         "forward-delete-word"},
1623   {"M-dE",         "forward-delete-word"},
1624   {"M-dw",         "forward-delete-word"},
1625   {"M-dW",         "forward-delete-word"},
1626   {"M-dF",         "backward-delete-find"},
1627   {"M-df",         "forward-delete-find"},
1628   {"M-dT",         "backward-delete-to"},
1629   {"M-dt",         "forward-delete-to"},
1630   {"M-d;",         "delete-refind"},
1631   {"M-d,",         "delete-invert-refind"},
1632   {"M-d^",         "backward-kill-line"},
1633   {"M-d0",         "backward-kill-line"},
1634   {"M-d$",         "kill-line"},
1635   {"M-D",          "kill-line"},
1636   {"M-d|",         "delete-to-column"},
1637   {"M-d%",         "delete-to-parenthesis"},
1638   {"M-e",          "forward-word"},
1639   {"M-E",          "forward-word"},
1640   {"M-f",          "forward-find-char"},
1641   {"M-F",          "backward-find-char"},
1642   {"M--",          "up-history"},
1643   {"M-h",          "cursor-left"},
1644   {"M-H",          "beginning-of-history"},
1645   {"M-i",          "vi-insert"},
1646   {"M-I",          "vi-insert-at-bol"},
1647   {"M-j",          "down-history"},
1648   {"M-J",          "history-search-forward"},
1649   {"M-k",          "up-history"},
1650   {"M-K",          "history-search-backward"},
1651   {"M-l",          "cursor-right"},
1652   {"M-L",          "end-of-history"},
1653   {"M-n",          "history-re-search-forward"},
1654   {"M-N",          "history-re-search-backward"},
1655   {"M-p",          "append-yank"},
1656   {"M-P",          "yank"},
1657   {"M-r",          "vi-replace-char"},
1658   {"M-R",          "vi-overwrite"},
1659   {"M-s",          "vi-forward-change-char"},
1660   {"M-S",          "vi-change-line"},
1661   {"M-t",          "forward-to-char"},
1662   {"M-T",          "backward-to-char"},
1663   {"M-u",          "vi-undo"},
1664   {"M-w",          "forward-to-word"},
1665   {"M-W",          "forward-to-word"},
1666   {"M-x",          "forward-delete-char"},
1667   {"M-X",          "backward-delete-char"},
1668   {"M-yh",         "backward-copy-char"},
1669   {"M-y^H",        "backward-copy-char"},
1670   {"M-y^?",        "backward-copy-char"},
1671   {"M-yl",         "forward-copy-char"},
1672   {"M-y ",         "forward-copy-char"},
1673   {"M-ye",         "forward-copy-word"},
1674   {"M-yE",         "forward-copy-word"},
1675   {"M-yw",         "forward-copy-word"},
1676   {"M-yW",         "forward-copy-word"},
1677   {"M-yb",         "backward-copy-word"},
1678   {"M-yB",         "backward-copy-word"},
1679   {"M-yf",         "forward-copy-find"},
1680   {"M-yF",         "backward-copy-find"},
1681   {"M-yt",         "forward-copy-to"},
1682   {"M-yT",         "backward-copy-to"},
1683   {"M-y;",         "copy-refind"},
1684   {"M-y,",         "copy-invert-refind"},
1685   {"M-y^",         "copy-to-bol"},
1686   {"M-y0",         "copy-to-bol"},
1687   {"M-y$",         "copy-rest-of-line"},
1688   {"M-yy",         "copy-line"},
1689   {"M-Y",          "copy-line"},
1690   {"M-y|",         "copy-to-column"},
1691   {"M-y%",         "copy-to-parenthesis"},
1692   {"M-^E",         "emacs-mode"},
1693   {"M-^H",         "cursor-left"},
1694   {"M-^?",         "cursor-left"},
1695   {"M-^L",         "clear-screen"},
1696   {"M-^N",         "down-history"},
1697   {"M-^P",         "up-history"},
1698   {"M-^R",         "redisplay"},
1699   {"M-^D",         "list-or-eof"},
1700   {"M-\r",         "newline"},
1701   {"M-\t",         "complete-word"},
1702   {"M-\n",         "newline"},
1703 #ifndef HIDE_FILE_SYSTEM
1704   {"M-^X^R",       "read-init-files"},
1705 #endif
1706   {"M-^Xh",        "list-history"},
1707   {"M-^XH",        "list-history"},
1708   {"down",         "down-history"},
1709   {"up",           "up-history"},
1710   {"left",         "cursor-left"},
1711   {"right",        "cursor-right"},
1712 };
1713 
1714 /*.......................................................................
1715  * Create a new GetLine object.
1716  *
1717  * Input:
1718  *  linelen  size_t    The maximum line length to allow for.
1719  *  histlen  size_t    The number of bytes to allocate for recording
1720  *                     a circular buffer of history lines.
1721  * Output:
1722  *  return  GetLine *  The new object, or NULL on error.
1723  */
new_GetLine(size_t linelen,size_t histlen)1724 GetLine *new_GetLine(size_t linelen, size_t histlen)
1725 {
1726   GetLine *gl;  /* The object to be returned */
1727   int i;
1728 /*
1729  * Check the arguments.
1730  */
1731   if(linelen < 10) {
1732     errno = ENOMEM;
1733     return NULL;
1734   };
1735 /*
1736  * Allocate the container.
1737  */
1738   gl = (GetLine *) malloc(sizeof(GetLine));
1739   if(!gl) {
1740     errno = ENOMEM;
1741     return NULL;
1742   };
1743 /*
1744  * Before attempting any operation that might fail, initialize the
1745  * container at least up to the point at which it can safely be passed
1746  * to del_GetLine().
1747  */
1748   gl->err = NULL;
1749   gl->glh = NULL;
1750   gl->cpl = NULL;
1751 #ifndef HIDE_FILE_SYSTEM
1752   gl->cplfn.fn = cpl_file_completions;
1753 #else
1754   gl->cplfn.fn = gl_no_completions;
1755 #endif
1756   gl->cplfn.data = NULL;
1757 #ifndef WITHOUT_FILE_SYSTEM
1758   gl->ef = NULL;
1759 #endif
1760   gl->capmem = NULL;
1761   gl->cq = NULL;
1762   gl->input_fd = -1;
1763   gl->output_fd = -1;
1764   gl->input_fp = NULL;
1765   gl->output_fp = NULL;
1766   gl->file_fp = NULL;
1767   gl->term = NULL;
1768   gl->is_term = 0;
1769   gl->flush_fn = gl_flush_terminal;
1770   gl->io_mode = GL_NORMAL_MODE;
1771   gl->raw_mode = 0;
1772   gl->pending_io = GLP_WRITE;  /* We will start by writing the prompt */
1773   gl_clear_status(gl);
1774   gl->linelen = linelen;
1775   gl->line = NULL;
1776   gl->cutbuf = NULL;
1777   gl->prompt = NULL;
1778   gl->prompt_len = 0;
1779   gl->prompt_changed = 0;
1780   gl->prompt_style = GL_LITERAL_PROMPT;
1781   gl->cpl_mem = NULL;
1782   gl->ext_act_mem = NULL;
1783   gl->sig_mem = NULL;
1784   gl->sigs = NULL;
1785   gl->signals_masked = 0;
1786   gl->signals_overriden = 0;
1787   sigemptyset(&gl->all_signal_set);
1788   sigemptyset(&gl->old_signal_set);
1789   sigemptyset(&gl->use_signal_set);
1790   gl->bindings = NULL;
1791   gl->ntotal = 0;
1792   gl->buff_curpos = 0;
1793   gl->term_curpos = 0;
1794   gl->term_len = 0;
1795   gl->buff_mark = 0;
1796   gl->insert_curpos = 0;
1797   gl->insert = 1;
1798   gl->number = -1;
1799   gl->endline = 1;
1800   gl->displayed = 0;
1801   gl->redisplay = 0;
1802   gl->postpone = 0;
1803   gl->keybuf[0]='\0';
1804   gl->nbuf = 0;
1805   gl->nread = 0;
1806   gl->current_action.fn = 0;
1807   gl->current_action.data = NULL;
1808   gl->current_count = 0;
1809   gl->preload_id = 0;
1810   gl->preload_history = 0;
1811   gl->keyseq_count = 0;
1812   gl->last_search = -1;
1813   gl->editor = GL_EMACS_MODE;
1814   gl->silence_bell = 0;
1815   gl->automatic_history = 1;
1816   gl->vi.undo.line = NULL;
1817   gl->vi.undo.buff_curpos = 0;
1818   gl->vi.undo.ntotal = 0;
1819   gl->vi.undo.saved = 0;
1820   gl->vi.repeat.action.fn = 0;
1821   gl->vi.repeat.action.data = 0;
1822   gl->vi.repeat.count = 0;
1823   gl->vi.repeat.input_curpos = 0;
1824   gl->vi.repeat.command_curpos = 0;
1825   gl->vi.repeat.input_char = '\0';
1826   gl->vi.repeat.saved = 0;
1827   gl->vi.repeat.active = 0;
1828   gl->vi.command = 0;
1829   gl->vi.find_forward = 0;
1830   gl->vi.find_onto = 0;
1831   gl->vi.find_char = '\0';
1832   gl->left = NULL;
1833   gl->right = NULL;
1834   gl->up = NULL;
1835   gl->down = NULL;
1836   gl->home = NULL;
1837   gl->bol = 0;
1838   gl->clear_eol = NULL;
1839   gl->clear_eod = NULL;
1840   gl->u_arrow = NULL;
1841   gl->d_arrow = NULL;
1842   gl->l_arrow = NULL;
1843   gl->r_arrow = NULL;
1844   gl->sound_bell = NULL;
1845   gl->bold = NULL;
1846   gl->underline = NULL;
1847   gl->standout = NULL;
1848   gl->dim = NULL;
1849   gl->reverse = NULL;
1850   gl->blink = NULL;
1851   gl->text_attr_off = NULL;
1852   gl->nline = 0;
1853   gl->ncolumn = 0;
1854 #ifdef USE_TERMINFO
1855   gl->left_n = NULL;
1856   gl->right_n = NULL;
1857 #elif defined(USE_TERMCAP)
1858   gl->tgetent_buf = NULL;
1859   gl->tgetstr_buf = NULL;
1860 #endif
1861   gl->app_file = NULL;
1862   gl->user_file = NULL;
1863   gl->configured = 0;
1864   gl->echo = 1;
1865   gl->last_signal = -1;
1866 #ifdef HAVE_SELECT
1867   gl->fd_node_mem = NULL;
1868   gl->fd_nodes = NULL;
1869   FD_ZERO(&gl->rfds);
1870   FD_ZERO(&gl->wfds);
1871   FD_ZERO(&gl->ufds);
1872   gl->max_fd = 0;
1873   gl->timer.dt.tv_sec = 0;
1874   gl->timer.dt.tv_usec = 0;
1875   gl->timer.fn = 0;
1876   gl->timer.data = NULL;
1877 #endif
1878 /*
1879  * Allocate an error reporting buffer.
1880  */
1881   gl->err = _new_ErrMsg();
1882   if(!gl->err)
1883     return del_GetLine(gl);
1884 /*
1885  * Allocate the history buffer.
1886  */
1887   gl->glh = _new_GlHistory(histlen);
1888   if(!gl->glh)
1889     return del_GetLine(gl);
1890 /*
1891  * Allocate the resource object for file-completion.
1892  */
1893   gl->cpl = new_WordCompletion();
1894   if(!gl->cpl)
1895     return del_GetLine(gl);
1896 /*
1897  * Allocate the resource object for file-completion.
1898  */
1899 #ifndef WITHOUT_FILE_SYSTEM
1900   gl->ef = new_ExpandFile();
1901   if(!gl->ef)
1902     return del_GetLine(gl);
1903 #endif
1904 /*
1905  * Allocate a string-segment memory allocator for use in storing terminal
1906  * capablity strings.
1907  */
1908   gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE);
1909   if(!gl->capmem)
1910     return del_GetLine(gl);
1911 /*
1912  * Allocate the character queue that is used to buffer terminal output.
1913  */
1914   gl->cq = _new_GlCharQueue();
1915   if(!gl->cq)
1916     return del_GetLine(gl);
1917 /*
1918  * Allocate a line buffer, leaving 2 extra characters for the terminating
1919  * '\n' and '\0' characters
1920  */
1921   gl->line = (char *) malloc(linelen + 2);
1922   if(!gl->line) {
1923     errno = ENOMEM;
1924     return del_GetLine(gl);
1925   };
1926 /*
1927  * Start with an empty input line.
1928  */
1929   gl_truncate_buffer(gl, 0);
1930 /*
1931  * Allocate a cut buffer.
1932  */
1933   gl->cutbuf = (char *) malloc(linelen + 2);
1934   if(!gl->cutbuf) {
1935     errno = ENOMEM;
1936     return del_GetLine(gl);
1937   };
1938   gl->cutbuf[0] = '\0';
1939 /*
1940  * Allocate an initial empty prompt.
1941  */
1942   _gl_replace_prompt(gl, NULL);
1943   if(!gl->prompt) {
1944     errno = ENOMEM;
1945     return del_GetLine(gl);
1946   };
1947 /*
1948  * Allocate a vi undo buffer.
1949  */
1950   gl->vi.undo.line = (char *) malloc(linelen + 2);
1951   if(!gl->vi.undo.line) {
1952     errno = ENOMEM;
1953     return del_GetLine(gl);
1954   };
1955   gl->vi.undo.line[0] = '\0';
1956 /*
1957  * Allocate a freelist from which to allocate nodes for the list
1958  * of completion functions.
1959  */
1960   gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING);
1961   if(!gl->cpl_mem)
1962     return del_GetLine(gl);
1963 /*
1964  * Allocate a freelist from which to allocate nodes for the list
1965  * of external action functions.
1966  */
1967   gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction),
1968 				  GL_EXT_ACT_FREELIST_BLOCKING);
1969   if(!gl->ext_act_mem)
1970     return del_GetLine(gl);
1971 /*
1972  * Allocate a freelist from which to allocate nodes for the list
1973  * of signals.
1974  */
1975   gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING);
1976   if(!gl->sig_mem)
1977     return del_GetLine(gl);
1978 /*
1979  * Install initial dispositions for the default list of signals that
1980  * gl_get_line() traps.
1981  */
1982   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
1983     const struct GlDefSignal *sig = gl_signal_list + i;
1984     if(_gl_trap_signal(gl, sig->signo, sig->flags, sig->after,
1985 		       sig->errno_value))
1986       return del_GetLine(gl);
1987   };
1988 /*
1989  * Allocate an empty table of key bindings.
1990  */
1991   gl->bindings = _new_KeyTab();
1992   if(!gl->bindings)
1993     return del_GetLine(gl);
1994 /*
1995  * Define the available actions that can be bound to key sequences.
1996  */
1997   for(i=0; i<sizeof(gl_actions)/sizeof(gl_actions[0]); i++) {
1998     if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn, NULL))
1999       return del_GetLine(gl);
2000   };
2001 /*
2002  * Set up the default bindings.
2003  */
2004   if(gl_change_editor(gl, gl->editor))
2005     return del_GetLine(gl);
2006 /*
2007  * Allocate termcap buffers.
2008  */
2009 #ifdef USE_TERMCAP
2010   gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2011   gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2012   if(!gl->tgetent_buf || !gl->tgetstr_buf) {
2013     errno = ENOMEM;
2014     return del_GetLine(gl);
2015   };
2016 #endif
2017 /*
2018  * Set up for I/O assuming stdin and stdout.
2019  */
2020   if(_gl_change_terminal(gl, stdin, stdout, getenv("TERM")))
2021     return del_GetLine(gl);
2022 /*
2023  * Create a freelist for use in allocating GlFdNode list nodes.
2024  */
2025 #ifdef HAVE_SELECT
2026   gl->fd_node_mem = _new_FreeList(sizeof(GlFdNode), GLFD_FREELIST_BLOCKING);
2027   if(!gl->fd_node_mem)
2028     return del_GetLine(gl);
2029 #endif
2030 /*
2031  * We are done for now.
2032  */
2033   return gl;
2034 }
2035 
2036 /*.......................................................................
2037  * Delete a GetLine object.
2038  *
2039  * Input:
2040  *  gl     GetLine *  The object to be deleted.
2041  * Output:
2042  *  return GetLine *  The deleted object (always NULL).
2043  */
del_GetLine(GetLine * gl)2044 GetLine *del_GetLine(GetLine *gl)
2045 {
2046   if(gl) {
2047 /*
2048  * If the terminal is in raw server mode, reset it.
2049  */
2050     _gl_normal_io(gl);
2051 /*
2052  * Deallocate all objects contained by gl.
2053  */
2054     gl->err = _del_ErrMsg(gl->err);
2055     gl->glh = _del_GlHistory(gl->glh);
2056     gl->cpl = del_WordCompletion(gl->cpl);
2057 #ifndef WITHOUT_FILE_SYSTEM
2058     gl->ef = del_ExpandFile(gl->ef);
2059 #endif
2060     gl->capmem = _del_StringGroup(gl->capmem);
2061     gl->cq = _del_GlCharQueue(gl->cq);
2062     if(gl->file_fp)
2063       fclose(gl->file_fp);
2064     if(gl->term)
2065       free(gl->term);
2066     if(gl->line)
2067       free(gl->line);
2068     if(gl->cutbuf)
2069       free(gl->cutbuf);
2070     if(gl->prompt)
2071       free(gl->prompt);
2072     gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1);
2073     gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1);
2074     gl->sig_mem = _del_FreeList(gl->sig_mem, 1);
2075     gl->sigs = NULL;       /* Already freed by freeing sig_mem */
2076     gl->bindings = _del_KeyTab(gl->bindings);
2077     if(gl->vi.undo.line)
2078       free(gl->vi.undo.line);
2079 #ifdef USE_TERMCAP
2080     if(gl->tgetent_buf)
2081       free(gl->tgetent_buf);
2082     if(gl->tgetstr_buf)
2083       free(gl->tgetstr_buf);
2084 #endif
2085     if(gl->app_file)
2086       free(gl->app_file);
2087     if(gl->user_file)
2088       free(gl->user_file);
2089 #ifdef HAVE_SELECT
2090     gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1);
2091     gl->fd_nodes = NULL;  /* Already freed by freeing gl->fd_node_mem */
2092 #endif
2093 /*
2094  * Delete the now empty container.
2095  */
2096     free(gl);
2097   };
2098   return NULL;
2099 }
2100 
2101 /*.......................................................................
2102  * Bind a control or meta character to an action.
2103  *
2104  * Input:
2105  *  gl         GetLine *  The resource object of this program.
2106  *  binder    KtBinder    The source of the binding.
2107  *  c             char    The control or meta character.
2108  *                        If this is '\0', the call is ignored.
2109  *  action  const char *  The action name to bind the key to.
2110  * Output:
2111  *  return         int    0 - OK.
2112  *                        1 - Error.
2113  */
gl_bind_control_char(GetLine * gl,KtBinder binder,char c,const char * action)2114 static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c,
2115 				const char *action)
2116 {
2117   char keyseq[2];
2118 /*
2119  * Quietly reject binding to the NUL control character, since this
2120  * is an ambiguous prefix of all bindings.
2121  */
2122   if(c == '\0')
2123     return 0;
2124 /*
2125  * Making sure not to bind characters which aren't either control or
2126  * meta characters.
2127  */
2128   if(IS_CTRL_CHAR(c) || IS_META_CHAR(c)) {
2129     keyseq[0] = c;
2130     keyseq[1] = '\0';
2131   } else {
2132     return 0;
2133   };
2134 /*
2135  * Install the binding.
2136  */
2137   if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
2138     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
2139     return 1;
2140   };
2141   return 0;
2142 }
2143 
2144 /*.......................................................................
2145  * Read a line from the user.
2146  *
2147  * Input:
2148  *  gl       GetLine *  A resource object returned by new_GetLine().
2149  *  prompt      char *  The prompt to prefix the line with.
2150  *  start_line  char *  The initial contents of the input line, or NULL
2151  *                      if it should start out empty.
2152  *  start_pos    int    If start_line isn't NULL, this specifies the
2153  *                      index of the character over which the cursor
2154  *                      should initially be positioned within the line.
2155  *                      If you just want it to follow the last character
2156  *                      of the line, send -1.
2157  * Output:
2158  *  return      char *  An internal buffer containing the input line, or
2159  *                      NULL at the end of input. If the line fitted in
2160  *                      the buffer there will be a '\n' newline character
2161  *                      before the terminating '\0'. If it was truncated
2162  *                      there will be no newline character, and the remains
2163  *                      of the line should be retrieved via further calls
2164  *                      to this function.
2165  */
gl_get_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2166 char *gl_get_line(GetLine *gl, const char *prompt,
2167 		  const char *start_line, int start_pos)
2168 {
2169   char *retval;   /* The return value of _gl_get_line() */
2170 /*
2171  * Check the arguments.
2172  */
2173   if(!gl) {
2174     errno = EINVAL;
2175     return NULL;
2176   };
2177 /*
2178  * Temporarily block all of the signals that we have been asked to trap.
2179  */
2180   if(gl_mask_signals(gl, &gl->old_signal_set))
2181     return NULL;
2182 /*
2183  * Perform the command-line editing task.
2184  */
2185   retval = _gl_get_line(gl, prompt, start_line, start_pos);
2186 /*
2187  * Restore the process signal mask to how it was when this function was
2188  * first called.
2189  */
2190   gl_unmask_signals(gl, &gl->old_signal_set);
2191   return retval;
2192 }
2193 
2194 
2195 /*.......................................................................
2196  * This is the main body of the public function gl_get_line().
2197  */
_gl_get_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2198 static char *_gl_get_line(GetLine *gl, const char *prompt,
2199 			  const char *start_line, int start_pos)
2200 {
2201   int waserr = 0;    /* True if an error occurs */
2202 /*
2203  * Assume that this call will successfully complete the input
2204  * line until proven otherwise.
2205  */
2206   gl_clear_status(gl);
2207 /*
2208  * If this is the first call to this function since new_GetLine(),
2209  * complete any postponed configuration.
2210  */
2211   if(!gl->configured) {
2212     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2213     gl->configured = 1;
2214   };
2215 /*
2216  * Before installing our signal handler functions, record the fact
2217  * that there are no pending signals.
2218  */
2219   gl_pending_signal = -1;
2220 /*
2221  * Temporarily override the signal handlers of the calling program,
2222  * so that we can intercept signals that would leave the terminal
2223  * in a bad state.
2224  */
2225   waserr = gl_override_signal_handlers(gl);
2226 /*
2227  * After recording the current terminal settings, switch the terminal
2228  * into raw input mode.
2229  */
2230   waserr = waserr || _gl_raw_io(gl, 1);
2231 /*
2232  * Attempt to read the line. This will require more than one attempt if
2233  * either a current temporary input file is opened by gl_get_input_line()
2234  * or the end of a temporary input file is reached by gl_read_stream_line().
2235  */
2236   while(!waserr) {
2237 /*
2238  * Read a line from a non-interactive stream?
2239  */
2240     if(gl->file_fp || !gl->is_term) {
2241       if(gl_read_stream_line(gl)==0) {
2242 	break;
2243       } else if(gl->file_fp) {
2244 	gl_revert_input(gl);
2245 	gl_record_status(gl, GLR_NEWLINE, 0);
2246       } else {
2247 	waserr = 1;
2248 	break;
2249       };
2250     };
2251 /*
2252  * Read from the terminal? Note that the above if() block may have
2253  * changed gl->file_fp, so it is necessary to retest it here, rather
2254  * than using an else statement.
2255  */
2256     if(!gl->file_fp && gl->is_term) {
2257       if(gl_get_input_line(gl, prompt, start_line, start_pos))
2258 	waserr = 1;
2259       else
2260 	break;
2261     };
2262   };
2263 /*
2264  * If an error occurred, but gl->rtn_status is still set to
2265  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
2266  * leave it at whatever specific value was assigned by the function
2267  * that aborted input. This means that only functions that trap
2268  * non-generic errors have to remember to update gl->rtn_status
2269  * themselves.
2270  */
2271   if(waserr && gl->rtn_status == GLR_NEWLINE)
2272     gl_record_status(gl, GLR_ERROR, errno);
2273 /*
2274  * Restore terminal settings.
2275  */
2276   if(gl->io_mode != GL_SERVER_MODE)
2277     _gl_normal_io(gl);
2278 /*
2279  * Restore the signal handlers.
2280  */
2281   gl_restore_signal_handlers(gl);
2282 /*
2283  * If gl_get_line() gets aborted early, the errno value associated
2284  * with the event that caused this to happen is recorded in
2285  * gl->rtn_errno. Since errno may have been overwritten by cleanup
2286  * functions after this, restore its value to the value that it had
2287  * when the error condition occured, so that the caller can examine it
2288  * to find out what happened.
2289  */
2290   errno = gl->rtn_errno;
2291 /*
2292  * Check the completion status to see how to return.
2293  */
2294   switch(gl->rtn_status) {
2295   case GLR_NEWLINE:    /* Success */
2296     return gl->line;
2297   case GLR_BLOCKED:    /* These events abort the current input line, */
2298   case GLR_SIGNAL:     /*  when in normal blocking I/O mode, but only */
2299   case GLR_TIMEOUT:    /*  temporarily pause line editing when in */
2300   case GLR_FDABORT:    /*  non-blocking server I/O mode. */
2301     if(gl->io_mode != GL_SERVER_MODE)
2302       _gl_abandon_line(gl);
2303     return NULL;
2304   case GLR_ERROR:      /* Unrecoverable errors abort the input line, */
2305   case GLR_EOF:        /*  regardless of the I/O mode. */
2306   default:
2307     _gl_abandon_line(gl);
2308     return NULL;
2309   };
2310 }
2311 
2312 /*.......................................................................
2313  * Read a single character from the user.
2314  *
2315  * Input:
2316  *  gl       GetLine *  A resource object returned by new_GetLine().
2317  *  prompt      char *  The prompt to prefix the line with, or NULL if
2318  *                      no prompt is required.
2319  *  defchar     char    The character to substitute if the
2320  *                      user simply hits return, or '\n' if you don't
2321  *                      need to substitute anything.
2322  * Output:
2323  *  return       int    The character that was read, or EOF if the read
2324  *                      had to be aborted (in which case you can call
2325  *                      gl_return_status() to find out why).
2326  */
gl_query_char(GetLine * gl,const char * prompt,char defchar)2327 int gl_query_char(GetLine *gl, const char *prompt, char defchar)
2328 {
2329   int retval;   /* The return value of _gl_query_char() */
2330 /*
2331  * Check the arguments.
2332  */
2333   if(!gl) {
2334     errno = EINVAL;
2335     return EOF;
2336   };
2337 /*
2338  * Temporarily block all of the signals that we have been asked to trap.
2339  */
2340   if(gl_mask_signals(gl, &gl->old_signal_set))
2341     return EOF;
2342 /*
2343  * Perform the character reading task.
2344  */
2345   retval = _gl_query_char(gl, prompt, defchar);
2346 /*
2347  * Restore the process signal mask to how it was when this function was
2348  * first called.
2349  */
2350   gl_unmask_signals(gl, &gl->old_signal_set);
2351   return retval;
2352 }
2353 
2354 /*.......................................................................
2355  * This is the main body of the public function gl_query_char().
2356  */
_gl_query_char(GetLine * gl,const char * prompt,char defchar)2357 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar)
2358 {
2359   int c = EOF;       /* The character to be returned */
2360   int waserr = 0;    /* True if an error occurs */
2361 /*
2362  * Assume that this call will successfully complete the input operation
2363  * until proven otherwise.
2364  */
2365   gl_clear_status(gl);
2366 /*
2367  * If this is the first call to this function or gl_get_line(),
2368  * since new_GetLine(), complete any postponed configuration.
2369  */
2370   if(!gl->configured) {
2371     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2372     gl->configured = 1;
2373   };
2374 /*
2375  * Before installing our signal handler functions, record the fact
2376  * that there are no pending signals.
2377  */
2378   gl_pending_signal = -1;
2379 /*
2380  * Temporarily override the signal handlers of the calling program,
2381  * so that we can intercept signals that would leave the terminal
2382  * in a bad state.
2383  */
2384   waserr = gl_override_signal_handlers(gl);
2385 /*
2386  * After recording the current terminal settings, switch the terminal
2387  * into raw input mode without redisplaying any partially entered
2388  * input line.
2389  */
2390   waserr = waserr || _gl_raw_io(gl, 0);
2391 /*
2392  * Attempt to read the line. This will require more than one attempt if
2393  * either a current temporary input file is opened by gl_get_input_line()
2394  * or the end of a temporary input file is reached by gl_read_stream_line().
2395  */
2396   while(!waserr) {
2397 /*
2398  * Read a line from a non-interactive stream?
2399  */
2400     if(gl->file_fp || !gl->is_term) {
2401       c = gl_read_stream_char(gl);
2402       if(c != EOF) {            /* Success? */
2403 	if(c=='\n') c = defchar;
2404 	break;
2405       } else if(gl->file_fp) {  /* End of temporary input file? */
2406 	gl_revert_input(gl);
2407 	gl_record_status(gl, GLR_NEWLINE, 0);
2408       } else {                  /* An error? */
2409 	waserr = 1;
2410 	break;
2411       };
2412     };
2413 /*
2414  * Read from the terminal? Note that the above if() block may have
2415  * changed gl->file_fp, so it is necessary to retest it here, rather
2416  * than using an else statement.
2417  */
2418     if(!gl->file_fp && gl->is_term) {
2419       c = gl_get_query_char(gl, prompt, defchar);
2420       if(c==EOF)
2421 	waserr = 1;
2422       else
2423 	break;
2424     };
2425   };
2426 /*
2427  * If an error occurred, but gl->rtn_status is still set to
2428  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
2429  * leave it at whatever specific value was assigned by the function
2430  * that aborted input. This means that only functions that trap
2431  * non-generic errors have to remember to update gl->rtn_status
2432  * themselves.
2433  */
2434   if(waserr && gl->rtn_status == GLR_NEWLINE)
2435     gl_record_status(gl, GLR_ERROR, errno);
2436 /*
2437  * Restore terminal settings.
2438  */
2439   if(gl->io_mode != GL_SERVER_MODE)
2440     _gl_normal_io(gl);
2441 /*
2442  * Restore the signal handlers.
2443  */
2444   gl_restore_signal_handlers(gl);
2445 /*
2446  * If this function gets aborted early, the errno value associated
2447  * with the event that caused this to happen is recorded in
2448  * gl->rtn_errno. Since errno may have been overwritten by cleanup
2449  * functions after this, restore its value to the value that it had
2450  * when the error condition occured, so that the caller can examine it
2451  * to find out what happened.
2452  */
2453   errno = gl->rtn_errno;
2454 /*
2455  * Error conditions are signalled to the caller, by setting the returned
2456  * character to EOF.
2457  */
2458   if(gl->rtn_status != GLR_NEWLINE)
2459     c = EOF;
2460 /*
2461  * In this mode, every character that is read is a completed
2462  * transaction, just like reading a completed input line, so prepare
2463  * for the next input line or character.
2464  */
2465   _gl_abandon_line(gl);
2466 /*
2467  * Return the acquired character.
2468  */
2469   return c;
2470 }
2471 
2472 /*.......................................................................
2473  * Record of the signal handlers of the calling program, so that they
2474  * can be restored later.
2475  *
2476  * Input:
2477  *  gl    GetLine *   The resource object of this library.
2478  * Output:
2479  *  return    int     0 - OK.
2480  *                    1 - Error.
2481  */
gl_override_signal_handlers(GetLine * gl)2482 static int gl_override_signal_handlers(GetLine *gl)
2483 {
2484   GlSignalNode *sig;   /* A node in the list of signals to be caught */
2485 /*
2486  * Set up our signal handler.
2487  */
2488   SigAction act;
2489   act.sa_handler = gl_signal_handler;
2490   memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t));
2491   act.sa_flags = 0;
2492 /*
2493  * Get the subset of the signals that we are supposed to trap that
2494  * should actually be trapped.
2495  */
2496   sigemptyset(&gl->use_signal_set);
2497   for(sig=gl->sigs; sig; sig=sig->next) {
2498 /*
2499  * Trap this signal? If it is blocked by the calling program and we
2500  * haven't been told to unblock it, don't arrange to trap this signal.
2501  */
2502     if(sig->flags & GLS_UNBLOCK_SIG ||
2503        !sigismember(&gl->old_signal_set, sig->signo)) {
2504       if(sigaddset(&gl->use_signal_set, sig->signo) == -1) {
2505 	_err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
2506 	return 1;
2507       };
2508     };
2509   };
2510 /*
2511  * Override the actions of the signals that we are trapping.
2512  */
2513   for(sig=gl->sigs; sig; sig=sig->next) {
2514     if(sigismember(&gl->use_signal_set, sig->signo)) {
2515       sigdelset(&act.sa_mask, sig->signo);
2516       if(sigaction(sig->signo, &act, &sig->original)) {
2517 	_err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2518 	return 1;
2519       };
2520       sigaddset(&act.sa_mask, sig->signo);
2521     };
2522   };
2523 /*
2524  * Record the fact that the application's signal handlers have now
2525  * been overriden.
2526  */
2527   gl->signals_overriden = 1;
2528 /*
2529  * Just in case a SIGWINCH signal was sent to the process while our
2530  * SIGWINCH signal handler wasn't in place, check to see if the terminal
2531  * size needs updating.
2532  */
2533   if(_gl_update_size(gl))
2534     return 1;
2535   return 0;
2536 }
2537 
2538 /*.......................................................................
2539  * Restore the signal handlers of the calling program.
2540  *
2541  * Input:
2542  *  gl     GetLine *  The resource object of this library.
2543  * Output:
2544  *  return     int    0 - OK.
2545  *                    1 - Error.
2546  */
gl_restore_signal_handlers(GetLine * gl)2547 static int gl_restore_signal_handlers(GetLine *gl)
2548 {
2549   GlSignalNode *sig;   /* A node in the list of signals to be caught */
2550 /*
2551  * Restore application signal handlers that were overriden
2552  * by gl_override_signal_handlers().
2553  */
2554   for(sig=gl->sigs; sig; sig=sig->next) {
2555     if(sigismember(&gl->use_signal_set, sig->signo) &&
2556        sigaction(sig->signo, &sig->original, NULL)) {
2557       _err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2558       return 1;
2559     };
2560   };
2561 /*
2562  * Record the fact that the application's signal handlers have now
2563  * been restored.
2564  */
2565   gl->signals_overriden = 0;
2566   return 0;
2567 }
2568 
2569 /*.......................................................................
2570  * This signal handler simply records the fact that a given signal was
2571  * caught in the file-scope gl_pending_signal variable.
2572  */
gl_signal_handler(int signo)2573 static void gl_signal_handler(int signo)
2574 {
2575   gl_pending_signal = signo;
2576   siglongjmp(gl_setjmp_buffer, 1);
2577 }
2578 
2579 /*.......................................................................
2580  * Switch the terminal into raw mode after storing the previous terminal
2581  * settings in gl->attributes.
2582  *
2583  * Input:
2584  *  gl     GetLine *   The resource object of this program.
2585  * Output:
2586  *  return     int     0 - OK.
2587  *                     1 - Error.
2588  */
gl_raw_terminal_mode(GetLine * gl)2589 static int gl_raw_terminal_mode(GetLine *gl)
2590 {
2591   Termios newattr;   /* The new terminal attributes */
2592 /*
2593  * If the terminal is already in raw mode, do nothing.
2594  */
2595   if(gl->raw_mode)
2596     return 0;
2597 /*
2598  * Record the current terminal attributes.
2599  */
2600   if(tcgetattr(gl->input_fd, &gl->oldattr)) {
2601     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
2602     return 1;
2603   };
2604 /*
2605  * This function shouldn't do anything but record the current terminal
2606  * attritubes if editing has been disabled.
2607  */
2608   if(gl->editor == GL_NO_EDITOR)
2609     return 0;
2610 /*
2611  * Modify the existing attributes.
2612  */
2613   newattr = gl->oldattr;
2614 /*
2615  * Turn off local echo, canonical input mode and extended input processing.
2616  */
2617   newattr.c_lflag &= ~(ECHO | ICANON | IEXTEN);
2618 /*
2619  * Don't translate carriage return to newline, turn off input parity
2620  * checking, don't strip off 8th bit, turn off output flow control.
2621  */
2622   newattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP);
2623 /*
2624  * Clear size bits, turn off parity checking, and allow 8-bit characters.
2625  */
2626   newattr.c_cflag &= ~(CSIZE | PARENB);
2627   newattr.c_cflag |= CS8;
2628 /*
2629  * Turn off output processing.
2630  */
2631   newattr.c_oflag &= ~(OPOST);
2632 /*
2633  * Request one byte at a time, without waiting.
2634  */
2635   newattr.c_cc[VMIN] = gl->io_mode==GL_SERVER_MODE ? 0:1;
2636   newattr.c_cc[VTIME] = 0;
2637 /*
2638  * Install the new terminal modes.
2639  */
2640   while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) {
2641     if(errno != EINTR) {
2642       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2643       return 1;
2644     };
2645   };
2646 /*
2647  * Record the new terminal mode.
2648  */
2649   gl->raw_mode = 1;
2650   return 0;
2651 }
2652 
2653 /*.......................................................................
2654  * Restore the terminal attributes recorded in gl->oldattr.
2655  *
2656  * Input:
2657  *  gl     GetLine *   The resource object of this library.
2658  * Output:
2659  *  return     int     0 - OK.
2660  *                     1 - Error.
2661  */
gl_restore_terminal_attributes(GetLine * gl)2662 static int gl_restore_terminal_attributes(GetLine *gl)
2663 {
2664   int waserr = 0;
2665 /*
2666  * If not in raw mode, do nothing.
2667  */
2668   if(!gl->raw_mode)
2669     return 0;
2670 /*
2671  * Before changing the terminal attributes, make sure that all output
2672  * has been passed to the terminal.
2673  */
2674   if(gl_flush_output(gl))
2675     waserr = 1;
2676 /*
2677  * Reset the terminal attributes to the values that they had on
2678  * entry to gl_get_line().
2679  */
2680   while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) {
2681     if(errno != EINTR) {
2682       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2683       waserr = 1;
2684       break;
2685     };
2686   };
2687 /*
2688  * Record the new terminal mode.
2689  */
2690   gl->raw_mode = 0;
2691   return waserr;
2692 }
2693 
2694 /*.......................................................................
2695  * Switch the terminal file descriptor to use non-blocking I/O.
2696  *
2697  * Input:
2698  *  gl         GetLine *  The resource object of gl_get_line().
2699  *  fd             int    The file descriptor to make non-blocking.
2700  */
gl_nonblocking_io(GetLine * gl,int fd)2701 static int gl_nonblocking_io(GetLine *gl, int fd)
2702 {
2703   int fcntl_flags;   /* The new file-descriptor control flags */
2704 /*
2705  * Is non-blocking I/O supported on this system?  Note that even
2706  * without non-blocking I/O, the terminal will probably still act as
2707  * though it was non-blocking, because we also set the terminal
2708  * attributes to return immediately if no input is available and we
2709  * use select() to wait to be able to write. If select() also isn't
2710  * available, then input will probably remain fine, but output could
2711  * block, depending on the behaviour of the terminal driver.
2712  */
2713 #if defined(NON_BLOCKING_FLAG)
2714 /*
2715  * Query the current file-control flags, and add the
2716  * non-blocking I/O flag.
2717  */
2718   fcntl_flags = fcntl(fd, F_GETFL) | NON_BLOCKING_FLAG;
2719 /*
2720  * Install the new control flags.
2721  */
2722   if(fcntl(fd, F_SETFL, fcntl_flags) == -1) {
2723     _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2724     return 1;
2725   };
2726 #endif
2727   return 0;
2728 }
2729 
2730 /*.......................................................................
2731  * Switch to blocking terminal I/O.
2732  *
2733  * Input:
2734  *  gl         GetLine *  The resource object of gl_get_line().
2735  *  fd             int    The file descriptor to make blocking.
2736  */
gl_blocking_io(GetLine * gl,int fd)2737 static int gl_blocking_io(GetLine *gl, int fd)
2738 {
2739   int fcntl_flags;   /* The new file-descriptor control flags */
2740 /*
2741  * Is non-blocking I/O implemented on this system?
2742  */
2743 #if defined(NON_BLOCKING_FLAG)
2744 /*
2745  * Query the current file control flags and remove the non-blocking
2746  * I/O flag.
2747  */
2748   fcntl_flags = fcntl(fd, F_GETFL) & ~NON_BLOCKING_FLAG;
2749 /*
2750  * Install the modified control flags.
2751  */
2752   if(fcntl(fd, F_SETFL, fcntl_flags) == -1) {
2753     _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2754     return 1;
2755   };
2756 #endif
2757   return 0;
2758 }
2759 
2760 /*.......................................................................
2761  * Read a new input line from the user.
2762  *
2763  * Input:
2764  *  gl         GetLine *  The resource object of this library.
2765  *  prompt        char *  The prompt to prefix the line with, or NULL to
2766  *                        use the same prompt that was used by the previous
2767  *                        line.
2768  *  start_line    char *  The initial contents of the input line, or NULL
2769  *                        if it should start out empty.
2770  *  start_pos      int    If start_line isn't NULL, this specifies the
2771  *                        index of the character over which the cursor
2772  *                        should initially be positioned within the line.
2773  *                        If you just want it to follow the last character
2774  *                        of the line, send -1.
2775  * Output:
2776  *  return    int    0 - OK.
2777  *                   1 - Error.
2778  */
gl_get_input_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2779 static int gl_get_input_line(GetLine *gl, const char *prompt,
2780 			     const char *start_line, int start_pos)
2781 {
2782   char c;               /* The character being read */
2783 /*
2784  * Flush any pending output to the terminal.
2785  */
2786   if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2787     return 1;
2788 /*
2789  * Are we starting a new line?
2790  */
2791   if(gl->endline) {
2792 /*
2793  * Delete any incompletely enterred line.
2794  */
2795     if(gl_erase_line(gl))
2796       return 1;
2797 /*
2798  * Display the new line to be edited.
2799  */
2800     if(gl_present_line(gl, prompt, start_line, start_pos))
2801       return 1;
2802   };
2803 /*
2804  * Read one character at a time.
2805  */
2806   while(gl_read_terminal(gl, 1, &c) == 0) {
2807 /*
2808  * Increment the count of the number of key sequences entered.
2809  */
2810     gl->keyseq_count++;
2811 /*
2812  * Interpret the character either as the start of a new key-sequence,
2813  * as a continuation of a repeat count, or as a printable character
2814  * to be added to the line.
2815  */
2816     if(gl_interpret_char(gl, c))
2817       break;
2818 /*
2819  * If we just ran an action function which temporarily asked for
2820  * input to be taken from a file, abort this call.
2821  */
2822     if(gl->file_fp)
2823       return 0;
2824 /*
2825  * Has the line been completed?
2826  */
2827     if(gl->endline)
2828       return gl_line_ended(gl, c);
2829   };
2830 /*
2831  * To get here, gl_read_terminal() must have returned non-zero. See
2832  * whether a signal was caught that requested that the current line
2833  * be returned.
2834  */
2835   if(gl->endline)
2836     return gl_line_ended(gl, '\n');
2837 /*
2838  * If I/O blocked while attempting to get the latest character
2839  * of the key sequence, rewind the key buffer to allow interpretation of
2840  * the current key sequence to be restarted on the next call to this
2841  * function.
2842  */
2843   if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ)
2844     gl->nread = 0;
2845   return 1;
2846 }
2847 
2848 /*.......................................................................
2849  * This is the private function of gl_query_char() that handles
2850  * prompting the user, reading a character from the terminal, and
2851  * displaying what the user entered.
2852  *
2853  * Input:
2854  *  gl         GetLine *  The resource object of this library.
2855  *  prompt        char *  The prompt to prefix the line with.
2856  *  defchar       char    The character to substitute if the
2857  *                        user simply hits return, or '\n' if you don't
2858  *                        need to substitute anything.
2859  * Output:
2860  *  return         int    The character that was read, or EOF if something
2861  *                        prevented a character from being read.
2862  */
gl_get_query_char(GetLine * gl,const char * prompt,int defchar)2863 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar)
2864 {
2865   char c;               /* The character being read */
2866   int retval;           /* The return value of this function */
2867 /*
2868  * Flush any pending output to the terminal.
2869  */
2870   if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2871     return EOF;
2872 /*
2873  * Delete any incompletely entered line.
2874  */
2875   if(gl_erase_line(gl))
2876     return EOF;
2877 /*
2878  * Reset the line input parameters and display the prompt, if any.
2879  */
2880   if(gl_present_line(gl, prompt, NULL, 0))
2881     return EOF;
2882 /*
2883  * Read one character.
2884  */
2885   if(gl_read_terminal(gl, 1, &c) == 0) {
2886 /*
2887  * In this mode, count each character as being a new key-sequence.
2888  */
2889     gl->keyseq_count++;
2890 /*
2891  * Delete the character that was read, from the key-press buffer.
2892  */
2893     gl_discard_chars(gl, gl->nread);
2894 /*
2895  * Convert carriage returns to newlines.
2896  */
2897     if(c == '\r')
2898       c = '\n';
2899 /*
2900  * If the user just hit return, subsitute the default character.
2901  */
2902     if(c == '\n')
2903       c = defchar;
2904 /*
2905  * Display the entered character to the right of the prompt.
2906  */
2907     if(c!='\n') {
2908       if(gl_end_of_line(gl, 1, NULL)==0)
2909 	gl_print_char(gl, c, ' ');
2910     };
2911 /*
2912  * Record the return character, and mark the call as successful.
2913  */
2914     retval = c;
2915     gl_record_status(gl, GLR_NEWLINE, 0);
2916 /*
2917  * Was a signal caught whose disposition is to cause the current input
2918  * line to be returned? If so return a newline character.
2919  */
2920   } else if(gl->endline) {
2921     retval = '\n';
2922     gl_record_status(gl, GLR_NEWLINE, 0);
2923   } else {
2924     retval = EOF;
2925   };
2926 /*
2927  * Start a new line.
2928  */
2929   if(gl_start_newline(gl, 1))
2930     return EOF;
2931 /*
2932  * Attempt to flush any pending output.
2933  */
2934   (void) gl_flush_output(gl);
2935 /*
2936  * Return either the character that was read, or EOF if an error occurred.
2937  */
2938   return retval;
2939 }
2940 
2941 /*.......................................................................
2942  * Add a character to the line buffer at the current cursor position,
2943  * inserting or overwriting according the current mode.
2944  *
2945  * Input:
2946  *  gl   GetLine *   The resource object of this library.
2947  *  c       char     The character to be added.
2948  * Output:
2949  *  return   int     0 - OK.
2950  *                   1 - Insufficient room.
2951  */
gl_add_char_to_line(GetLine * gl,char c)2952 static int gl_add_char_to_line(GetLine *gl, char c)
2953 {
2954 /*
2955  * Keep a record of the current cursor position.
2956  */
2957   int buff_curpos = gl->buff_curpos;
2958   int term_curpos = gl->term_curpos;
2959 /*
2960  * Work out the displayed width of the new character.
2961  */
2962   int width = gl_displayed_char_width(gl, c, term_curpos);
2963 /*
2964  * If we are in insert mode, or at the end of the line,
2965  * check that we can accomodate a new character in the buffer.
2966  * If not, simply return, leaving it up to the calling program
2967  * to check for the absence of a newline character.
2968  */
2969   if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen)
2970     return 0;
2971 /*
2972  * Are we adding characters to the line (ie. inserting or appending)?
2973  */
2974   if(gl->insert || buff_curpos >= gl->ntotal) {
2975 /*
2976  * If inserting, make room for the new character.
2977  */
2978     if(buff_curpos < gl->ntotal)
2979       gl_make_gap_in_buffer(gl, buff_curpos, 1);
2980 /*
2981  * Copy the character into the buffer.
2982  */
2983     gl_buffer_char(gl, c, buff_curpos);
2984     gl->buff_curpos++;
2985 /*
2986  * Redraw the line from the cursor position to the end of the line,
2987  * and move the cursor to just after the added character.
2988  */
2989     if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
2990        gl_set_term_curpos(gl, term_curpos + width))
2991       return 1;
2992 /*
2993  * Are we overwriting an existing character?
2994  */
2995   } else {
2996 /*
2997  * Get the width of the character being overwritten.
2998  */
2999     int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos],
3000 					    term_curpos);
3001 /*
3002  * Overwrite the character in the buffer.
3003  */
3004     gl_buffer_char(gl, c, buff_curpos);
3005 /*
3006  * If we are replacing with a narrower character, we need to
3007  * redraw the terminal string to the end of the line, then
3008  * overwrite the trailing old_width - width characters
3009  * with spaces.
3010  */
3011     if(old_width > width) {
3012       if(gl_print_string(gl, gl->line + buff_curpos, '\0'))
3013 	return 1;
3014 /*
3015  * Clear to the end of the terminal.
3016  */
3017       if(gl_truncate_display(gl))
3018 	return 1;
3019 /*
3020  * Move the cursor to the end of the new character.
3021  */
3022       if(gl_set_term_curpos(gl, term_curpos + width))
3023 	return 1;
3024       gl->buff_curpos++;
3025 /*
3026  * If we are replacing with a wider character, then we will be
3027  * inserting new characters, and thus extending the line.
3028  */
3029     } else if(width > old_width) {
3030 /*
3031  * Redraw the line from the cursor position to the end of the line,
3032  * and move the cursor to just after the added character.
3033  */
3034       if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3035 	 gl_set_term_curpos(gl, term_curpos + width))
3036 	return 1;
3037       gl->buff_curpos++;
3038 /*
3039  * The original and replacement characters have the same width,
3040  * so simply overwrite.
3041  */
3042     } else {
3043 /*
3044  * Copy the character into the buffer.
3045  */
3046       gl_buffer_char(gl, c, buff_curpos);
3047       gl->buff_curpos++;
3048 /*
3049  * Overwrite the original character.
3050  */
3051       if(gl_print_char(gl, c, gl->line[gl->buff_curpos]))
3052 	return 1;
3053     };
3054   };
3055   return 0;
3056 }
3057 
3058 /*.......................................................................
3059  * Insert/append a string to the line buffer and terminal at the current
3060  * cursor position.
3061  *
3062  * Input:
3063  *  gl   GetLine *   The resource object of this library.
3064  *  s       char *   The string to be added.
3065  * Output:
3066  *  return   int     0 - OK.
3067  *                   1 - Insufficient room.
3068  */
gl_add_string_to_line(GetLine * gl,const char * s)3069 static int gl_add_string_to_line(GetLine *gl, const char *s)
3070 {
3071   int buff_slen;   /* The length of the string being added to line[] */
3072   int term_slen;   /* The length of the string being written to the terminal */
3073   int buff_curpos; /* The original value of gl->buff_curpos */
3074   int term_curpos; /* The original value of gl->term_curpos */
3075 /*
3076  * Keep a record of the current cursor position.
3077  */
3078   buff_curpos = gl->buff_curpos;
3079   term_curpos = gl->term_curpos;
3080 /*
3081  * How long is the string to be added?
3082  */
3083   buff_slen = strlen(s);
3084   term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos);
3085 /*
3086  * Check that we can accomodate the string in the buffer.
3087  * If not, simply return, leaving it up to the calling program
3088  * to check for the absence of a newline character.
3089  */
3090   if(gl->ntotal + buff_slen > gl->linelen)
3091     return 0;
3092 /*
3093  * Move the characters that follow the cursor in the buffer by
3094  * buff_slen characters to the right.
3095  */
3096   if(gl->ntotal > gl->buff_curpos)
3097     gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen);
3098 /*
3099  * Copy the string into the buffer.
3100  */
3101   gl_buffer_string(gl, s, buff_slen, gl->buff_curpos);
3102   gl->buff_curpos += buff_slen;
3103 /*
3104  * Write the modified part of the line to the terminal, then move
3105  * the terminal cursor to the end of the displayed input string.
3106  */
3107   if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3108      gl_set_term_curpos(gl, term_curpos + term_slen))
3109     return 1;
3110   return 0;
3111 }
3112 
3113 /*.......................................................................
3114  * Read a single character from the terminal.
3115  *
3116  * Input:
3117  *  gl    GetLine *   The resource object of this library.
3118  *  keep      int     If true, the returned character will be kept in
3119  *                    the input buffer, for potential replays. It should
3120  *                    subsequently be removed from the buffer when the
3121  *                    key sequence that it belongs to has been fully
3122  *                    processed, by calling gl_discard_chars().
3123  * Input/Output:
3124  *  c        char *   The character that is read, is assigned to *c.
3125  * Output:
3126  *  return    int     0 - OK.
3127  *                    1 - Either an I/O error occurred, or a signal was
3128  *                        caught who's disposition is to abort gl_get_line()
3129  *                        or to have gl_get_line() return the current line
3130  *                        as though the user had pressed return. In the
3131  *                        latter case gl->endline will be non-zero.
3132  */
gl_read_terminal(GetLine * gl,int keep,char * c)3133 static int gl_read_terminal(GetLine *gl, int keep, char *c)
3134 {
3135 /*
3136  * Before waiting for a new character to be input, flush unwritten
3137  * characters to the terminal.
3138  */
3139   if(gl_flush_output(gl))
3140     return 1;
3141 /*
3142  * Record the fact that we are about to read from the terminal.
3143  */
3144   gl->pending_io = GLP_READ;
3145 /*
3146  * If there is already an unread character in the buffer,
3147  * return it.
3148  */
3149   if(gl->nread < gl->nbuf) {
3150     *c = gl->keybuf[gl->nread];
3151 /*
3152  * Retain the character in the key buffer, but mark it as having been read?
3153  */
3154     if(keep) {
3155       gl->nread++;
3156 /*
3157  * Completely remove the character from the key buffer?
3158  */
3159     } else {
3160       memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1,
3161 	      gl->nbuf - gl->nread - 1);
3162     };
3163     return 0;
3164   };
3165 /*
3166  * Make sure that there is space in the key buffer for one more character.
3167  * This should always be true if gl_interpret_char() is called for each
3168  * new character added, since it will clear the buffer once it has recognized
3169  * or rejected a key sequence.
3170  */
3171   if(gl->nbuf + 1 > GL_KEY_MAX) {
3172     gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.",
3173 		  GL_END_INFO);
3174     errno = EIO;
3175     return 1;
3176   };
3177 /*
3178  * Read one character from the terminal.
3179  */
3180   switch(gl_read_input(gl, c)) {
3181   case GL_READ_OK:
3182     break;
3183   case GL_READ_BLOCKED:
3184     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
3185     return 1;
3186     break;
3187   default:
3188     return 1;
3189     break;
3190   };
3191 /*
3192  * Append the character to the key buffer?
3193  */
3194   if(keep) {
3195     gl->keybuf[gl->nbuf] = *c;
3196     gl->nread = ++gl->nbuf;
3197   };
3198   return 0;
3199 }
3200 
3201 /*.......................................................................
3202  * Read one or more keypresses from the terminal of an input stream.
3203  *
3204  * Input:
3205  *  gl           GetLine *  The resource object of this module.
3206  *  c               char *  The character that was read is assigned to *c.
3207  * Output:
3208  *  return  GlReadStatus    The completion status of the read operation.
3209  */
gl_read_input(GetLine * gl,char * c)3210 static GlReadStatus gl_read_input(GetLine *gl, char *c)
3211 {
3212 /*
3213  * We may have to repeat the read if window change signals are received.
3214  */
3215   for(;;) {
3216 /*
3217  * Which file descriptor should we read from? Mark this volatile, so
3218  * that siglongjmp() can't clobber it.
3219  */
3220     volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd;
3221 /*
3222  * If the endline flag becomes set, don't wait for another character.
3223  */
3224     if(gl->endline)
3225       return GL_READ_ERROR;
3226 /*
3227  * Since the code in this function can block, trap signals.
3228  */
3229     if(sigsetjmp(gl_setjmp_buffer, 1)==0) {
3230 /*
3231  * Handle the different I/O modes.
3232  */
3233       switch(gl->io_mode) {
3234 /*
3235  * In normal I/O mode, we call the event handler before attempting
3236  * to read, since read() blocks.
3237  */
3238       case GL_NORMAL_MODE:
3239 	if(gl_event_handler(gl, fd))
3240 	  return GL_READ_ERROR;
3241 	return gl_read_unmasked(gl, fd, c);  /* Read one character */
3242 	break;
3243 /*
3244  * In non-blocking server I/O mode, we attempt to read a character,
3245  * and only if this fails, call the event handler to wait for a any
3246  * user-configured timeout and any other user-configured events.  In
3247  * addition, we turn off the fcntl() non-blocking flag when reading
3248  * from the terminal, to work around a bug in Solaris. We can do this
3249  * without causing the read() to block, because when in non-blocking
3250  * server-I/O mode, gl_raw_io() sets the VMIN terminal attribute to 0,
3251  * which tells the terminal driver to return immediately if no
3252  * characters are available to be read.
3253  */
3254       case GL_SERVER_MODE:
3255 	{
3256 	  GlReadStatus status;        /* The return status */
3257 	  if(isatty(fd))              /* If we reading from a terminal, */
3258 	     gl_blocking_io(gl, fd);  /* switch to blocking I/O */
3259 	  status = gl_read_unmasked(gl, fd, c); /* Try reading */
3260 	  if(status == GL_READ_BLOCKED) {       /* Nothing readable yet */
3261 	    if(gl_event_handler(gl, fd))        /* Wait for input */
3262 	      status = GL_READ_ERROR;
3263 	    else
3264 	      status = gl_read_unmasked(gl, fd, c); /* Try reading again */
3265 	  };
3266 	  gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */
3267 	  return status;
3268 	};
3269 	break;
3270       };
3271     };
3272 /*
3273  * To get here, one of the signals that we are trapping must have
3274  * been received. Note that by using sigsetjmp() instead of setjmp()
3275  * the signal mask that was blocking these signals will have been
3276  * reinstated, so we can be sure that no more of these signals will
3277  * be received until we explicitly unblock them again.
3278  *
3279  * First, if non-blocking I/O was temporarily disabled, reinstate it.
3280  */
3281     if(gl->io_mode == GL_SERVER_MODE)
3282       gl_nonblocking_io(gl, fd);
3283 /*
3284  * Now respond to the signal that was caught.
3285  */
3286     if(gl_check_caught_signal(gl))
3287       return GL_READ_ERROR;
3288   };
3289 }
3290 
3291 /*.......................................................................
3292  * This is a private function of gl_read_input(), which unblocks signals
3293  * temporarily while it reads a single character from the specified file
3294  * descriptor.
3295  *
3296  * Input:
3297  *  gl          GetLine *  The resource object of this module.
3298  *  fd              int    The file descriptor to read from.
3299  *  c              char *  The character that was read is assigned to *c.
3300  * Output:
3301  *  return GlReadStatus    The completion status of the read.
3302  */
gl_read_unmasked(GetLine * gl,int fd,char * c)3303 static int gl_read_unmasked(GetLine *gl, int fd, char *c)
3304 {
3305   int nread;  /* The return value of read() */
3306 /*
3307  * Unblock the signals that we are trapping, while waiting for I/O.
3308  */
3309   gl_catch_signals(gl);
3310 /*
3311  * Attempt to read one character from the terminal, restarting the read
3312  * if any signals that we aren't trapping, are received.
3313  */
3314   do {
3315     errno = 0;
3316     nread = read(fd, c, 1);
3317   } while(nread < 0 && errno==EINTR);
3318 /*
3319  * Block all of the signals that we are trapping.
3320  */
3321   gl_mask_signals(gl, NULL);
3322 /*
3323  * Check the completion status of the read.
3324  */
3325   switch(nread) {
3326   case 1:
3327     return GL_READ_OK;
3328   case 0:
3329     return (isatty(fd) || errno != 0) ? GL_READ_BLOCKED : GL_READ_EOF;
3330   default:
3331     return GL_READ_ERROR;
3332   };
3333 }
3334 
3335 /*.......................................................................
3336  * Remove a specified number of characters from the start of the
3337  * key-press lookahead buffer, gl->keybuf[], and arrange for the next
3338  * read to start from the character at the start of the shifted buffer.
3339  *
3340  * Input:
3341  *  gl      GetLine *  The resource object of this module.
3342  *  nused       int    The number of characters to discard from the start
3343  *                     of the buffer.
3344  */
gl_discard_chars(GetLine * gl,int nused)3345 static void gl_discard_chars(GetLine *gl, int nused)
3346 {
3347   int nkeep = gl->nbuf - nused;
3348   if(nkeep > 0) {
3349     memmove(gl->keybuf, gl->keybuf + nused, nkeep);
3350     gl->nbuf = nkeep;
3351     gl->nread = 0;
3352   } else {
3353     gl->nbuf = gl->nread = 0;
3354   };
3355 }
3356 
3357 /*.......................................................................
3358  * This function is called to handle signals caught between calls to
3359  * sigsetjmp() and siglongjmp().
3360  *
3361  * Input:
3362  *  gl      GetLine *   The resource object of this library.
3363  * Output:
3364  *  return      int     0 - Signal handled internally.
3365  *                      1 - Signal requires gl_get_line() to abort.
3366  */
gl_check_caught_signal(GetLine * gl)3367 static int gl_check_caught_signal(GetLine *gl)
3368 {
3369   GlSignalNode *sig;      /* The signal disposition */
3370   SigAction keep_action;  /* The signal disposition of tecla signal handlers */
3371   unsigned flags;         /* The signal processing flags to use */
3372   int signo;              /* The signal to be handled */
3373 /*
3374  * Was no signal caught?
3375  */
3376   if(gl_pending_signal == -1)
3377     return 0;
3378 /*
3379  * Get the signal to be handled.
3380  */
3381   signo = gl_pending_signal;
3382 /*
3383  * Mark the signal as handled. Note that at this point, all of
3384  * the signals that we are trapping are blocked from delivery.
3385  */
3386   gl_pending_signal = -1;
3387 /*
3388  * Record the signal that was caught, so that the user can query it later.
3389  */
3390   gl->last_signal = signo;
3391 /*
3392  * In non-blocking server mode, the application is responsible for
3393  * responding to terminal signals, and we don't want gl_get_line()s
3394  * normal signal handling to clash with this, so whenever a signal
3395  * is caught, we arrange for gl_get_line() to abort and requeue the
3396  * signal while signals are still blocked. If the application
3397  * had the signal unblocked when gl_get_line() was called, the signal
3398  * will be delivered again as soon as gl_get_line() restores the
3399  * process signal mask, just before returning to the application.
3400  * Note that the caller of this function should set gl->pending_io
3401  * to the appropriate choice of GLP_READ and GLP_WRITE, before returning.
3402  */
3403   if(gl->io_mode==GL_SERVER_MODE) {
3404     gl_record_status(gl, GLR_SIGNAL, EINTR);
3405     raise(signo);
3406     return 1;
3407   };
3408 /*
3409  * Lookup the requested disposition of this signal.
3410  */
3411   for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next)
3412     ;
3413   if(!sig)
3414     return 0;
3415 /*
3416  * Get the signal response flags for this signal.
3417  */
3418   flags = sig->flags;
3419 /*
3420  * Did we receive a terminal size signal?
3421  */
3422 #ifdef SIGWINCH
3423   if(signo == SIGWINCH && _gl_update_size(gl))
3424     return 1;
3425 #endif
3426 /*
3427  * Start a fresh line?
3428  */
3429   if(flags & GLS_RESTORE_LINE) {
3430     if(gl_start_newline(gl, 0))
3431       return 1;
3432   };
3433 /*
3434  * Restore terminal settings to how they were before gl_get_line() was
3435  * called?
3436  */
3437   if(flags & GLS_RESTORE_TTY)
3438     gl_restore_terminal_attributes(gl);
3439 /*
3440  * Restore signal handlers to how they were before gl_get_line() was
3441  * called? If this hasn't been requested, only reinstate the signal
3442  * handler of the signal that we are handling.
3443  */
3444   if(flags & GLS_RESTORE_SIG) {
3445     gl_restore_signal_handlers(gl);
3446     gl_unmask_signals(gl, &gl->old_signal_set);
3447   } else {
3448     (void) sigaction(sig->signo, &sig->original, &keep_action);
3449     (void) sigprocmask(SIG_UNBLOCK, &sig->proc_mask, NULL);
3450   };
3451 /*
3452  * Forward the signal to the application's signal handler.
3453  */
3454   if(!(flags & GLS_DONT_FORWARD))
3455     raise(signo);
3456 /*
3457  * Reinstate our signal handlers.
3458  */
3459   if(flags & GLS_RESTORE_SIG) {
3460     gl_mask_signals(gl, NULL);
3461     gl_override_signal_handlers(gl);
3462   } else {
3463     (void) sigaction(sig->signo, &keep_action, NULL);
3464     (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL);
3465   };
3466 /*
3467  * Do we need to reinstate our terminal settings?
3468  */
3469   if(flags & GLS_RESTORE_TTY)
3470     gl_raw_terminal_mode(gl);
3471 /*
3472  * Redraw the line?
3473  */
3474   if(flags & GLS_REDRAW_LINE)
3475     gl_queue_redisplay(gl);
3476 /*
3477  * What next?
3478  */
3479   switch(sig->after) {
3480   case GLS_RETURN:
3481     gl_newline(gl, 1, NULL);
3482     return gl_flush_output(gl);
3483     break;
3484   case GLS_ABORT:
3485     gl_record_status(gl, GLR_SIGNAL, sig->errno_value);
3486     return 1;
3487     break;
3488   case GLS_CONTINUE:
3489     return gl_flush_output(gl);
3490     break;
3491   };
3492   return 0;
3493 }
3494 
3495 /*.......................................................................
3496  * Get pertinent terminal control strings and the initial terminal size.
3497  *
3498  * Input:
3499  *  gl     GetLine *  The resource object of this library.
3500  *  term      char *  The type of the terminal.
3501  * Output:
3502  *  return     int    0 - OK.
3503  *                    1 - Error.
3504  */
gl_control_strings(GetLine * gl,const char * term)3505 static int gl_control_strings(GetLine *gl, const char *term)
3506 {
3507   int bad_term = 0;   /* True if term is unusable */
3508 /*
3509  * Discard any existing control strings from a previous terminal.
3510  */
3511   gl->left = NULL;
3512   gl->right = NULL;
3513   gl->up = NULL;
3514   gl->down = NULL;
3515   gl->home = NULL;
3516   gl->bol = 0;
3517   gl->clear_eol = NULL;
3518   gl->clear_eod = NULL;
3519   gl->u_arrow = NULL;
3520   gl->d_arrow = NULL;
3521   gl->l_arrow = NULL;
3522   gl->r_arrow = NULL;
3523   gl->sound_bell = NULL;
3524   gl->bold = NULL;
3525   gl->underline = NULL;
3526   gl->standout = NULL;
3527   gl->dim = NULL;
3528   gl->reverse = NULL;
3529   gl->blink = NULL;
3530   gl->text_attr_off = NULL;
3531   gl->nline = 0;
3532   gl->ncolumn = 0;
3533 #ifdef USE_TERMINFO
3534   gl->left_n = NULL;
3535   gl->right_n = NULL;
3536 #endif
3537 /*
3538  * If possible lookup the information in a terminal information
3539  * database.
3540  */
3541 #ifdef USE_TERMINFO
3542   {
3543     int errret;
3544     if(!term || setupterm((char *)term, gl->input_fd, &errret) == ERR) {
3545       bad_term = 1;
3546     } else {
3547       _clr_StringGroup(gl->capmem);
3548       gl->left = gl_tigetstr(gl, "cub1");
3549       gl->right = gl_tigetstr(gl, "cuf1");
3550       gl->up = gl_tigetstr(gl, "cuu1");
3551       gl->down = gl_tigetstr(gl, "cud1");
3552       gl->home = gl_tigetstr(gl, "home");
3553       gl->clear_eol = gl_tigetstr(gl, "el");
3554       gl->clear_eod = gl_tigetstr(gl, "ed");
3555       gl->u_arrow = gl_tigetstr(gl, "kcuu1");
3556       gl->d_arrow = gl_tigetstr(gl, "kcud1");
3557       gl->l_arrow = gl_tigetstr(gl, "kcub1");
3558       gl->r_arrow = gl_tigetstr(gl, "kcuf1");
3559       gl->left_n = gl_tigetstr(gl, "cub");
3560       gl->right_n = gl_tigetstr(gl, "cuf");
3561       gl->sound_bell = gl_tigetstr(gl, "bel");
3562       gl->bold = gl_tigetstr(gl, "bold");
3563       gl->underline = gl_tigetstr(gl, "smul");
3564       gl->standout = gl_tigetstr(gl, "smso");
3565       gl->dim = gl_tigetstr(gl, "dim");
3566       gl->reverse = gl_tigetstr(gl, "rev");
3567       gl->blink = gl_tigetstr(gl, "blink");
3568       gl->text_attr_off = gl_tigetstr(gl, "sgr0");
3569     };
3570   };
3571 #elif defined(USE_TERMCAP)
3572   if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) {
3573     bad_term = 1;
3574   } else {
3575     char *tgetstr_buf_ptr = gl->tgetstr_buf;
3576     _clr_StringGroup(gl->capmem);
3577     gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr);
3578     gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr);
3579     gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr);
3580     gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr);
3581     gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr);
3582     gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr);
3583     gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr);
3584     gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr);
3585     gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr);
3586     gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr);
3587     gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr);
3588     gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr);
3589     gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr);
3590     gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr);
3591     gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr);
3592     gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr);
3593     gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr);
3594     gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr);
3595     gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr);
3596   };
3597 #endif
3598 /*
3599  * Report term being unusable.
3600  */
3601   if(bad_term) {
3602     gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)",
3603 		  "\". Will assume vt100.", GL_END_INFO);
3604   };
3605 /*
3606  * Fill in missing information with ANSI VT100 strings.
3607  */
3608   if(!gl->left)
3609     gl->left = "\b";    /* ^H */
3610   if(!gl->right)
3611     gl->right = GL_ESC_STR "[C";
3612   if(!gl->up)
3613     gl->up = GL_ESC_STR "[A";
3614   if(!gl->down)
3615     gl->down = "\n";
3616   if(!gl->home)
3617     gl->home = GL_ESC_STR "[H";
3618   if(!gl->bol)
3619     gl->bol = "\r";
3620   if(!gl->clear_eol)
3621     gl->clear_eol = GL_ESC_STR "[K";
3622   if(!gl->clear_eod)
3623     gl->clear_eod = GL_ESC_STR "[J";
3624   if(!gl->u_arrow)
3625     gl->u_arrow = GL_ESC_STR "[A";
3626   if(!gl->d_arrow)
3627     gl->d_arrow = GL_ESC_STR "[B";
3628   if(!gl->l_arrow)
3629     gl->l_arrow = GL_ESC_STR "[D";
3630   if(!gl->r_arrow)
3631     gl->r_arrow = GL_ESC_STR "[C";
3632   if(!gl->sound_bell)
3633     gl->sound_bell = "\a";
3634   if(!gl->bold)
3635     gl->bold = GL_ESC_STR "[1m";
3636   if(!gl->underline)
3637     gl->underline = GL_ESC_STR "[4m";
3638   if(!gl->standout)
3639     gl->standout = GL_ESC_STR "[1;7m";
3640   if(!gl->dim)
3641     gl->dim = "";  /* Not available */
3642   if(!gl->reverse)
3643     gl->reverse = GL_ESC_STR "[7m";
3644   if(!gl->blink)
3645     gl->blink = GL_ESC_STR "[5m";
3646   if(!gl->text_attr_off)
3647     gl->text_attr_off = GL_ESC_STR "[m";
3648 /*
3649  * Find out the current terminal size.
3650  */
3651   (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL);
3652   return 0;
3653 }
3654 
3655 #ifdef USE_TERMINFO
3656 /*.......................................................................
3657  * This is a private function of gl_control_strings() used to look up
3658  * a termninal capability string from the terminfo database and make
3659  * a private copy of it.
3660  *
3661  * Input:
3662  *  gl         GetLine *  The resource object of gl_get_line().
3663  *  name    const char *  The name of the terminfo string to look up.
3664  * Output:
3665  *  return  const char *  The local copy of the capability, or NULL
3666  *                        if not available.
3667  */
gl_tigetstr(GetLine * gl,const char * name)3668 static const char *gl_tigetstr(GetLine *gl, const char *name)
3669 {
3670   const char *value = tigetstr((char *)name);
3671   if(!value || value == (char *) -1)
3672     return NULL;
3673   return _sg_store_string(gl->capmem, value, 0);
3674 }
3675 #elif defined(USE_TERMCAP)
3676 /*.......................................................................
3677  * This is a private function of gl_control_strings() used to look up
3678  * a termninal capability string from the termcap database and make
3679  * a private copy of it. Note that some emulations of tgetstr(), such
3680  * as that used by Solaris, ignores the buffer pointer that is past to
3681  * it, so we can't assume that a private copy has been made that won't
3682  * be trashed by another call to gl_control_strings() by another
3683  * GetLine object. So we make what may be a redundant private copy
3684  * of the string in gl->capmem.
3685  *
3686  * Input:
3687  *  gl         GetLine *  The resource object of gl_get_line().
3688  *  name    const char *  The name of the terminfo string to look up.
3689  * Input/Output:
3690  *  bufptr        char ** On input *bufptr points to the location in
3691  *                        gl->tgetstr_buf at which to record the
3692  *                        capability string. On output *bufptr is
3693  *                        incremented over the stored string.
3694  * Output:
3695  *  return  const char *  The local copy of the capability, or NULL
3696  *                        on error.
3697  */
gl_tgetstr(GetLine * gl,const char * name,char ** bufptr)3698 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr)
3699 {
3700   const char *value = tgetstr((char *)name, bufptr);
3701   if(!value || value == (char *) -1)
3702     return NULL;
3703   return _sg_store_string(gl->capmem, value, 0);
3704 }
3705 #endif
3706 
3707 /*.......................................................................
3708  * This is an action function that implements a user interrupt (eg. ^C).
3709  */
KT_KEY_FN(gl_user_interrupt)3710 static KT_KEY_FN(gl_user_interrupt)
3711 {
3712   raise(SIGINT);
3713   return 1;
3714 }
3715 
3716 /*.......................................................................
3717  * This is an action function that implements the abort signal.
3718  */
KT_KEY_FN(gl_abort)3719 static KT_KEY_FN(gl_abort)
3720 {
3721   raise(SIGABRT);
3722   return 1;
3723 }
3724 
3725 /*.......................................................................
3726  * This is an action function that sends a suspend signal (eg. ^Z) to the
3727  * the parent process.
3728  */
KT_KEY_FN(gl_suspend)3729 static KT_KEY_FN(gl_suspend)
3730 {
3731   raise(SIGTSTP);
3732   return 0;
3733 }
3734 
3735 /*.......................................................................
3736  * This is an action function that halts output to the terminal.
3737  */
KT_KEY_FN(gl_stop_output)3738 static KT_KEY_FN(gl_stop_output)
3739 {
3740   tcflow(gl->output_fd, TCOOFF);
3741   return 0;
3742 }
3743 
3744 /*.......................................................................
3745  * This is an action function that resumes halted terminal output.
3746  */
KT_KEY_FN(gl_start_output)3747 static KT_KEY_FN(gl_start_output)
3748 {
3749   tcflow(gl->output_fd, TCOON);
3750   return 0;
3751 }
3752 
3753 /*.......................................................................
3754  * This is an action function that allows the next character to be accepted
3755  * without any interpretation as a special character.
3756  */
KT_KEY_FN(gl_literal_next)3757 static KT_KEY_FN(gl_literal_next)
3758 {
3759   char c;   /* The character to be added to the line */
3760   int i;
3761 /*
3762  * Get the character to be inserted literally.
3763  */
3764   if(gl_read_terminal(gl, 1, &c))
3765     return 1;
3766 /*
3767  * Add the character to the line 'count' times.
3768  */
3769   for(i=0; i<count; i++)
3770     gl_add_char_to_line(gl, c);
3771   return 0;
3772 }
3773 
3774 /*.......................................................................
3775  * Return the width of a tab character at a given position when
3776  * displayed at a given position on the terminal. This is needed
3777  * because the width of tab characters depends on where they are,
3778  * relative to the preceding tab stops.
3779  *
3780  * Input:
3781  *  gl       GetLine *  The resource object of this library.
3782  *  term_curpos  int    The destination terminal location of the character.
3783  * Output:
3784  *  return       int    The number of terminal charaters needed.
3785  */
gl_displayed_tab_width(GetLine * gl,int term_curpos)3786 static int gl_displayed_tab_width(GetLine *gl, int term_curpos)
3787 {
3788   return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH);
3789 }
3790 
3791 /*.......................................................................
3792  * Return the number of characters needed to display a given character
3793  * on the screen. Tab characters require eight spaces, and control
3794  * characters are represented by a caret followed by the modified
3795  * character.
3796  *
3797  * Input:
3798  *  gl       GetLine *  The resource object of this library.
3799  *  c           char    The character to be displayed.
3800  *  term_curpos  int    The destination terminal location of the character.
3801  *                      This is needed because the width of tab characters
3802  *                      depends on where they are, relative to the
3803  *                      preceding tab stops.
3804  * Output:
3805  *  return       int    The number of terminal charaters needed.
3806  */
gl_displayed_char_width(GetLine * gl,char c,int term_curpos)3807 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos)
3808 {
3809   if(c=='\t')
3810     return gl_displayed_tab_width(gl, term_curpos);
3811   if(IS_CTRL_CHAR(c))
3812     return 2;
3813   if(!isprint((int)(unsigned char) c))
3814     return gl_octal_width((int)(unsigned char)c) + 1;
3815   return 1;
3816 }
3817 
3818 
3819 /*.......................................................................
3820  * Work out the length of given string of characters on the terminal.
3821  *
3822  * Input:
3823  *  gl       GetLine *  The resource object of this library.
3824  *  string      char *  The string to be measured.
3825  *  nc           int    The number of characters to be measured, or -1
3826  *                      to measure the whole string.
3827  *  term_curpos  int    The destination terminal location of the character.
3828  *                      This is needed because the width of tab characters
3829  *                      depends on where they are, relative to the
3830  *                      preceding tab stops.
3831  * Output:
3832  *  return       int    The number of displayed characters.
3833  */
gl_displayed_string_width(GetLine * gl,const char * string,int nc,int term_curpos)3834 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
3835 				     int term_curpos)
3836 {
3837   int slen = 0;   /* The displayed number of characters */
3838   int i;
3839 /*
3840  * How many characters are to be measured?
3841  */
3842   if(nc < 0)
3843     nc = strlen(string);
3844 /*
3845  * Add up the length of the displayed string.
3846  */
3847   for(i=0; i<nc; i++)
3848     slen += gl_displayed_char_width(gl, string[i], term_curpos + slen);
3849   return slen;
3850 }
3851 
3852 /*.......................................................................
3853  * Write a string verbatim to the current terminal or output stream.
3854  *
3855  * Note that when async-signal safety is required, the 'buffered'
3856  * argument must be 0, and n must not be -1.
3857  *
3858  * Input:
3859  *  gl         GetLine *  The resource object of the gl_get_line().
3860  *  buffered       int    If true, used buffered I/O when writing to
3861  *                        the terminal. Otherwise use async-signal-safe
3862  *                        unbuffered I/O.
3863  *  string  const char *  The string to be written (this need not be
3864  *                        '\0' terminated unless n<0).
3865  *  n              int    The number of characters to write from the
3866  *                        prefix of string[], or -1 to request that
3867  *                        gl_print_raw_string() use strlen() to figure
3868  *                        out the length.
3869  * Output:
3870  *  return         int    0 - OK.
3871  *                        1 - Error.
3872  */
gl_print_raw_string(GetLine * gl,int buffered,const char * string,int n)3873 static int gl_print_raw_string(GetLine *gl, int buffered,
3874 			       const char *string, int n)
3875 {
3876   GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn;
3877 /*
3878  * Only display output when echoing is turned on.
3879  */
3880   if(gl->echo) {
3881     int ndone = 0;   /* The number of characters written so far */
3882 /*
3883  * When using un-buffered I/O, flush pending output first.
3884  */
3885     if(!buffered) {
3886       if(gl_flush_output(gl))
3887 	return 1;
3888     };
3889 /*
3890  * If no length has been provided, measure the length of the string.
3891  */
3892     if(n < 0)
3893       n = strlen(string);
3894 /*
3895  * Write the string.
3896  */
3897     if(write_fn(gl, string + ndone, n-ndone) != n)
3898       return 1;
3899   };
3900   return 0;
3901 }
3902 
3903 /*.......................................................................
3904  * Output a terminal control sequence. When using terminfo,
3905  * this must be a sequence returned by tgetstr() or tigetstr()
3906  * respectively.
3907  *
3908  * Input:
3909  *  gl     GetLine *   The resource object of this library.
3910  *  nline      int     The number of lines affected by the operation,
3911  *                     or 1 if not relevant.
3912  *  string    char *   The control sequence to be sent.
3913  * Output:
3914  *  return     int     0 - OK.
3915  *                     1 - Error.
3916  */
gl_print_control_sequence(GetLine * gl,int nline,const char * string)3917 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string)
3918 {
3919   int waserr = 0;   /* True if an error occurs */
3920 /*
3921  * Only write characters to the terminal when echoing is enabled.
3922  */
3923   if(gl->echo) {
3924 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3925     tputs_gl = gl;
3926     errno = 0;
3927     tputs((char *)string, nline, gl_tputs_putchar);
3928     waserr = errno != 0;
3929 #else
3930     waserr = gl_print_raw_string(gl, 1, string, -1);
3931 #endif
3932   };
3933   return waserr;
3934 }
3935 
3936 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3937 /*.......................................................................
3938  * The following callback function is called by tputs() to output a raw
3939  * control character to the terminal.
3940  */
gl_tputs_putchar(TputsArgType c)3941 static TputsRetType gl_tputs_putchar(TputsArgType c)
3942 {
3943   char ch = c;
3944 #if TPUTS_RETURNS_VALUE
3945   return gl_print_raw_string(tputs_gl, 1, &ch, 1);
3946 #else
3947   (void) gl_print_raw_string(tputs_gl, 1, &ch, 1);
3948 #endif
3949 }
3950 #endif
3951 
3952 /*.......................................................................
3953  * Move the terminal cursor n characters to the left or right.
3954  *
3955  * Input:
3956  *  gl     GetLine *   The resource object of this program.
3957  *  n          int     number of positions to the right (> 0) or left (< 0).
3958  * Output:
3959  *  return     int     0 - OK.
3960  *                     1 - Error.
3961  */
gl_terminal_move_cursor(GetLine * gl,int n)3962 static int gl_terminal_move_cursor(GetLine *gl, int n)
3963 {
3964   int cur_row, cur_col; /* The current terminal row and column index of */
3965                         /*  the cursor wrt the start of the input line. */
3966   int new_row, new_col; /* The target terminal row and column index of */
3967                         /*  the cursor wrt the start of the input line. */
3968 /*
3969  * Do nothing if the input line isn't currently displayed. In this
3970  * case, the cursor will be moved to the right place when the line
3971  * is next redisplayed.
3972  */
3973   if(!gl->displayed)
3974     return 0;
3975 /*
3976  * How far can we move left?
3977  */
3978   if(gl->term_curpos + n < 0)
3979     n = gl->term_curpos;
3980 /*
3981  * Break down the current and target cursor locations into rows and columns.
3982  */
3983   cur_row = gl->term_curpos / gl->ncolumn;
3984   cur_col = gl->term_curpos % gl->ncolumn;
3985   new_row = (gl->term_curpos + n) / gl->ncolumn;
3986   new_col = (gl->term_curpos + n) % gl->ncolumn;
3987 /*
3988  * Move down to the next line.
3989  */
3990   for(; cur_row < new_row; cur_row++) {
3991     if(gl_print_control_sequence(gl, 1, gl->down))
3992       return 1;
3993   };
3994 /*
3995  * Move up to the previous line.
3996  */
3997   for(; cur_row > new_row; cur_row--) {
3998     if(gl_print_control_sequence(gl, 1, gl->up))
3999       return 1;
4000   };
4001 /*
4002  * Move to the right within the target line?
4003  */
4004   if(cur_col < new_col) {
4005 #ifdef USE_TERMINFO
4006 /*
4007  * Use a parameterized control sequence if it generates less control
4008  * characters (guess based on ANSI terminal termcap entry).
4009  */
4010     if(gl->right_n != NULL && new_col - cur_col > 1) {
4011       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n,
4012            (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4013 	return 1;
4014     } else
4015 #endif
4016     {
4017       for(; cur_col < new_col; cur_col++) {
4018         if(gl_print_control_sequence(gl, 1, gl->right))
4019           return 1;
4020       };
4021     };
4022 /*
4023  * Move to the left within the target line?
4024  */
4025   } else if(cur_col > new_col) {
4026 #ifdef USE_TERMINFO
4027 /*
4028  * Use a parameterized control sequence if it generates less control
4029  * characters (guess based on ANSI terminal termcap entry).
4030  */
4031     if(gl->left_n != NULL && cur_col - new_col > 3) {
4032       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n,
4033            (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4034 	return 1;
4035     } else
4036 #endif
4037     {
4038       for(; cur_col > new_col; cur_col--) {
4039         if(gl_print_control_sequence(gl, 1, gl->left))
4040           return 1;
4041       };
4042     };
4043   }
4044 /*
4045  * Update the recorded position of the terminal cursor.
4046  */
4047   gl->term_curpos += n;
4048   return 0;
4049 }
4050 
4051 /*.......................................................................
4052  * Write a character to the terminal after expanding tabs and control
4053  * characters to their multi-character representations.
4054  *
4055  * Input:
4056  *  gl    GetLine *   The resource object of this program.
4057  *  c        char     The character to be output.
4058  *  pad      char     Many terminals have the irritating feature that
4059  *                    when one writes a character in the last column of
4060  *                    of the terminal, the cursor isn't wrapped to the
4061  *                    start of the next line until one more character
4062  *                    is written. Some terminals don't do this, so
4063  *                    after such a write, we don't know where the
4064  *                    terminal is unless we output an extra character.
4065  *                    This argument specifies the character to write.
4066  *                    If at the end of the input line send '\0' or a
4067  *                    space, and a space will be written. Otherwise,
4068  *                    pass the next character in the input line
4069  *                    following the one being written.
4070  * Output:
4071  *  return    int     0 - OK.
4072  */
gl_print_char(GetLine * gl,char c,char pad)4073 static int gl_print_char(GetLine *gl, char c, char pad)
4074 {
4075   char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */
4076   int nchar;                  /* The number of terminal characters */
4077   int i;
4078 /*
4079  * Check for special characters.
4080  */
4081   if(c == '\t') {
4082 /*
4083  * How many spaces do we need to represent a tab at the current terminal
4084  * column?
4085  */
4086     nchar = gl_displayed_tab_width(gl, gl->term_curpos);
4087 /*
4088  * Compose the tab string.
4089  */
4090     for(i=0; i<nchar; i++)
4091       string[i] = ' ';
4092   } else if(IS_CTRL_CHAR(c)) {
4093     string[0] = '^';
4094     string[1] = CTRL_TO_CHAR(c);
4095     nchar = 2;
4096   } else if(!isprint((int)(unsigned char) c)) {
4097     snprintf(string, sizeof(string), "\\%o", (int)(unsigned char)c);
4098     nchar = strlen(string);
4099   } else {
4100     string[0] = c;
4101     nchar = 1;
4102   };
4103 /*
4104  * Terminate the string.
4105  */
4106   string[nchar] = '\0';
4107 /*
4108  * Write the string to the terminal.
4109  */
4110   if(gl_print_raw_string(gl, 1, string, -1))
4111     return 1;
4112 /*
4113  * Except for one exception to be described in a moment, the cursor should
4114  * now have been positioned after the character that was just output.
4115  */
4116   gl->term_curpos += nchar;
4117 /*
4118  * Keep a record of the number of characters in the terminal version
4119  * of the input line.
4120  */
4121   if(gl->term_curpos > gl->term_len)
4122     gl->term_len = gl->term_curpos;
4123 /*
4124  * If the new character ended exactly at the end of a line,
4125  * most terminals won't move the cursor onto the next line until we
4126  * have written a character on the next line, so append an extra
4127  * space then move the cursor back.
4128  */
4129   if(gl->term_curpos % gl->ncolumn == 0) {
4130     int term_curpos = gl->term_curpos;
4131     if(gl_print_char(gl, pad ? pad : ' ', ' ') ||
4132        gl_set_term_curpos(gl, term_curpos))
4133       return 1;
4134   };
4135   return 0;
4136 }
4137 
4138 /*.......................................................................
4139  * Write a string to the terminal after expanding tabs and control
4140  * characters to their multi-character representations.
4141  *
4142  * Input:
4143  *  gl    GetLine *   The resource object of this program.
4144  *  string   char *   The string to be output.
4145  *  pad      char     Many terminals have the irritating feature that
4146  *                    when one writes a character in the last column of
4147  *                    of the terminal, the cursor isn't wrapped to the
4148  *                    start of the next line until one more character
4149  *                    is written. Some terminals don't do this, so
4150  *                    after such a write, we don't know where the
4151  *                    terminal is unless we output an extra character.
4152  *                    This argument specifies the character to write.
4153  *                    If at the end of the input line send '\0' or a
4154  *                    space, and a space will be written. Otherwise,
4155  *                    pass the next character in the input line
4156  *                    following the one being written.
4157  * Output:
4158  *  return    int     0 - OK.
4159  */
gl_print_string(GetLine * gl,const char * string,char pad)4160 static int gl_print_string(GetLine *gl, const char *string, char pad)
4161 {
4162   const char *cptr;   /* A pointer into string[] */
4163   for(cptr=string; *cptr; cptr++) {
4164     char nextc = cptr[1];
4165     if(gl_print_char(gl, *cptr, nextc ? nextc : pad))
4166       return 1;
4167   };
4168   return 0;
4169 }
4170 
4171 /*.......................................................................
4172  * Move the terminal cursor position.
4173  *
4174  * Input:
4175  *  gl      GetLine *  The resource object of this library.
4176  *  term_curpos int    The destination terminal cursor position.
4177  * Output:
4178  *  return      int    0 - OK.
4179  *                     1 - Error.
4180  */
gl_set_term_curpos(GetLine * gl,int term_curpos)4181 static int gl_set_term_curpos(GetLine *gl, int term_curpos)
4182 {
4183   return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos);
4184 }
4185 
4186 /*.......................................................................
4187  * This is an action function that moves the buffer cursor one character
4188  * left, and updates the terminal cursor to match.
4189  */
KT_KEY_FN(gl_cursor_left)4190 static KT_KEY_FN(gl_cursor_left)
4191 {
4192   return gl_place_cursor(gl, gl->buff_curpos - count);
4193 }
4194 
4195 /*.......................................................................
4196  * This is an action function that moves the buffer cursor one character
4197  * right, and updates the terminal cursor to match.
4198  */
KT_KEY_FN(gl_cursor_right)4199 static KT_KEY_FN(gl_cursor_right)
4200 {
4201   return gl_place_cursor(gl, gl->buff_curpos + count);
4202 }
4203 
4204 /*.......................................................................
4205  * This is an action function that toggles between overwrite and insert
4206  * mode.
4207  */
KT_KEY_FN(gl_insert_mode)4208 static KT_KEY_FN(gl_insert_mode)
4209 {
4210   gl->insert = !gl->insert;
4211   return 0;
4212 }
4213 
4214 /*.......................................................................
4215  * This is an action function which moves the cursor to the beginning of
4216  * the line.
4217  */
KT_KEY_FN(gl_beginning_of_line)4218 static KT_KEY_FN(gl_beginning_of_line)
4219 {
4220   return gl_place_cursor(gl, 0);
4221 }
4222 
4223 /*.......................................................................
4224  * This is an action function which moves the cursor to the end of
4225  * the line.
4226  */
KT_KEY_FN(gl_end_of_line)4227 static KT_KEY_FN(gl_end_of_line)
4228 {
4229   return gl_place_cursor(gl, gl->ntotal);
4230 }
4231 
4232 /*.......................................................................
4233  * This is an action function which deletes the entire contents of the
4234  * current line.
4235  */
KT_KEY_FN(gl_delete_line)4236 static KT_KEY_FN(gl_delete_line)
4237 {
4238 /*
4239  * If in vi command mode, preserve the current line for potential
4240  * use by vi-undo.
4241  */
4242   gl_save_for_undo(gl);
4243 /*
4244  * Copy the contents of the line to the cut buffer.
4245  */
4246   strlcpy(gl->cutbuf, gl->line, gl->linelen);
4247 /*
4248  * Clear the buffer.
4249  */
4250   gl_truncate_buffer(gl, 0);
4251 /*
4252  * Move the terminal cursor to just after the prompt.
4253  */
4254   if(gl_place_cursor(gl, 0))
4255     return 1;
4256 /*
4257  * Clear from the end of the prompt to the end of the terminal.
4258  */
4259   if(gl_truncate_display(gl))
4260     return 1;
4261   return 0;
4262 }
4263 
4264 /*.......................................................................
4265  * This is an action function which deletes all characters between the
4266  * current cursor position and the end of the line.
4267  */
KT_KEY_FN(gl_kill_line)4268 static KT_KEY_FN(gl_kill_line)
4269 {
4270 /*
4271  * If in vi command mode, preserve the current line for potential
4272  * use by vi-undo.
4273  */
4274   gl_save_for_undo(gl);
4275 /*
4276  * Copy the part of the line that is about to be deleted to the cut buffer.
4277  */
4278   strlcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->linelen);
4279 /*
4280  * Terminate the buffered line at the current cursor position.
4281  */
4282   gl_truncate_buffer(gl, gl->buff_curpos);
4283 /*
4284  * Clear the part of the line that follows the cursor.
4285  */
4286   if(gl_truncate_display(gl))
4287     return 1;
4288 /*
4289  * Explicitly reset the cursor position to allow vi command mode
4290  * constraints on its position to be set.
4291  */
4292   return gl_place_cursor(gl, gl->buff_curpos);
4293 }
4294 
4295 /*.......................................................................
4296  * This is an action function which deletes all characters between the
4297  * start of the line and the current cursor position.
4298  */
KT_KEY_FN(gl_backward_kill_line)4299 static KT_KEY_FN(gl_backward_kill_line)
4300 {
4301 /*
4302  * How many characters are to be deleted from before the cursor?
4303  */
4304   int nc = gl->buff_curpos - gl->insert_curpos;
4305   if (!nc)
4306     return 0;
4307 /*
4308  * Move the cursor to the start of the line, or in vi input mode,
4309  * the start of the sub-line at which insertion started, and delete
4310  * up to the old cursor position.
4311  */
4312   return gl_place_cursor(gl, gl->insert_curpos) ||
4313          gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command);
4314 }
4315 
4316 /*.......................................................................
4317  * This is an action function which moves the cursor forward by a word.
4318  */
KT_KEY_FN(gl_forward_word)4319 static KT_KEY_FN(gl_forward_word)
4320 {
4321   return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) +
4322 			 (gl->editor==GL_EMACS_MODE));
4323 }
4324 
4325 /*.......................................................................
4326  * This is an action function which moves the cursor forward to the start
4327  * of the next word.
4328  */
KT_KEY_FN(gl_forward_to_word)4329 static KT_KEY_FN(gl_forward_to_word)
4330 {
4331   return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count));
4332 }
4333 
4334 /*.......................................................................
4335  * This is an action function which moves the cursor backward by a word.
4336  */
KT_KEY_FN(gl_backward_word)4337 static KT_KEY_FN(gl_backward_word)
4338 {
4339   return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count));
4340 }
4341 
4342 /*.......................................................................
4343  * Delete one or more characters, starting with the one under the cursor.
4344  *
4345  * Input:
4346  *  gl     GetLine *  The resource object of this library.
4347  *  nc         int    The number of characters to delete.
4348  *  cut        int    If true, copy the characters to the cut buffer.
4349  * Output:
4350  *  return     int    0 - OK.
4351  *                    1 - Error.
4352  */
gl_delete_chars(GetLine * gl,int nc,int cut)4353 static int gl_delete_chars(GetLine *gl, int nc, int cut)
4354 {
4355 /*
4356  * If in vi command mode, preserve the current line for potential
4357  * use by vi-undo.
4358  */
4359   gl_save_for_undo(gl);
4360 /*
4361  * If there are fewer than nc characters following the cursor, limit
4362  * nc to the number available.
4363  */
4364   if(gl->buff_curpos + nc > gl->ntotal)
4365     nc = gl->ntotal - gl->buff_curpos;
4366 /*
4367  * Copy the about to be deleted region to the cut buffer.
4368  */
4369   if(cut) {
4370     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc);
4371     gl->cutbuf[nc] = '\0';
4372   }
4373 /*
4374  * Nothing to delete?
4375  */
4376   if(nc <= 0)
4377     return 0;
4378 /*
4379  * In vi overwrite mode, restore any previously overwritten characters
4380  * from the undo buffer.
4381  */
4382   if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) {
4383 /*
4384  * How many of the characters being deleted can be restored from the
4385  * undo buffer?
4386  */
4387     int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ?
4388       nc : gl->vi.undo.ntotal - gl->buff_curpos;
4389 /*
4390  * Restore any available characters.
4391  */
4392     if(nrestore > 0) {
4393       gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore,
4394 		       gl->buff_curpos);
4395     };
4396 /*
4397  * If their were insufficient characters in the undo buffer, then this
4398  * implies that we are deleting from the end of the line, so we need
4399  * to terminate the line either where the undo buffer ran out, or if
4400  * we are deleting from beyond the end of the undo buffer, at the current
4401  * cursor position.
4402  */
4403     if(nc != nrestore) {
4404       gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ?
4405 			 gl->vi.undo.ntotal : gl->buff_curpos);
4406     };
4407   } else {
4408 /*
4409  * Copy the remaining part of the line back over the deleted characters.
4410  */
4411     gl_remove_from_buffer(gl, gl->buff_curpos, nc);
4412   };
4413 /*
4414  * Redraw the remaining characters following the cursor.
4415  */
4416   if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0'))
4417     return 1;
4418 /*
4419  * Clear to the end of the terminal.
4420  */
4421   if(gl_truncate_display(gl))
4422     return 1;
4423 /*
4424  * Place the cursor at the start of where the deletion was performed.
4425  */
4426   return gl_place_cursor(gl, gl->buff_curpos);
4427 }
4428 
4429 /*.......................................................................
4430  * This is an action function which deletes character(s) under the
4431  * cursor without moving the cursor.
4432  */
KT_KEY_FN(gl_forward_delete_char)4433 static KT_KEY_FN(gl_forward_delete_char)
4434 {
4435 /*
4436  * Delete 'count' characters.
4437  */
4438   return gl_delete_chars(gl, count, gl->vi.command);
4439 }
4440 
4441 /*.......................................................................
4442  * This is an action function which deletes character(s) under the
4443  * cursor and moves the cursor back one character.
4444  */
KT_KEY_FN(gl_backward_delete_char)4445 static KT_KEY_FN(gl_backward_delete_char)
4446 {
4447 /*
4448  * Restrict the deletion count to the number of characters that
4449  * precede the insertion point.
4450  */
4451   if(count > gl->buff_curpos - gl->insert_curpos)
4452     count = gl->buff_curpos - gl->insert_curpos;
4453 /*
4454  * If in vi command mode, preserve the current line for potential
4455  * use by vi-undo.
4456  */
4457   gl_save_for_undo(gl);
4458   return gl_cursor_left(gl, count, NULL) ||
4459     gl_delete_chars(gl, count, gl->vi.command);
4460 }
4461 
4462 /*.......................................................................
4463  * Starting from the cursor position delete to the specified column.
4464  */
KT_KEY_FN(gl_delete_to_column)4465 static KT_KEY_FN(gl_delete_to_column)
4466 {
4467   if (--count >= gl->buff_curpos)
4468     return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL);
4469   else
4470     return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL);
4471 }
4472 
4473 /*.......................................................................
4474  * Starting from the cursor position delete characters to a matching
4475  * parenthesis.
4476  */
KT_KEY_FN(gl_delete_to_parenthesis)4477 static KT_KEY_FN(gl_delete_to_parenthesis)
4478 {
4479   int curpos = gl_index_of_matching_paren(gl);
4480   if(curpos >= 0) {
4481     gl_save_for_undo(gl);
4482     if(curpos >= gl->buff_curpos)
4483       return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL);
4484     else
4485       return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
4486   };
4487   return 0;
4488 }
4489 
4490 /*.......................................................................
4491  * This is an action function which deletes from the cursor to the end
4492  * of the word that the cursor is either in or precedes.
4493  */
KT_KEY_FN(gl_forward_delete_word)4494 static KT_KEY_FN(gl_forward_delete_word)
4495 {
4496 /*
4497  * If in vi command mode, preserve the current line for potential
4498  * use by vi-undo.
4499  */
4500   gl_save_for_undo(gl);
4501 /*
4502  * In emacs mode delete to the end of the word. In vi mode delete to the
4503  * start of the net word.
4504  */
4505   if(gl->editor == GL_EMACS_MODE) {
4506     return gl_delete_chars(gl,
4507 		gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1);
4508   } else {
4509     return gl_delete_chars(gl,
4510 		gl_nth_word_start_forward(gl,count) - gl->buff_curpos,
4511 		gl->vi.command);
4512   };
4513 }
4514 
4515 /*.......................................................................
4516  * This is an action function which deletes the word that precedes the
4517  * cursor.
4518  */
KT_KEY_FN(gl_backward_delete_word)4519 static KT_KEY_FN(gl_backward_delete_word)
4520 {
4521 /*
4522  * Keep a record of the current cursor position.
4523  */
4524   int buff_curpos = gl->buff_curpos;
4525 /*
4526  * If in vi command mode, preserve the current line for potential
4527  * use by vi-undo.
4528  */
4529   gl_save_for_undo(gl);
4530 /*
4531  * Move back 'count' words.
4532  */
4533   if(gl_backward_word(gl, count, NULL))
4534     return 1;
4535 /*
4536  * Delete from the new cursor position to the original one.
4537  */
4538   return gl_delete_chars(gl, buff_curpos - gl->buff_curpos,
4539   			 gl->editor == GL_EMACS_MODE || gl->vi.command);
4540 }
4541 
4542 /*.......................................................................
4543  * Searching in a given direction, delete to the count'th
4544  * instance of a specified or queried character, in the input line.
4545  *
4546  * Input:
4547  *  gl       GetLine *  The getline resource object.
4548  *  count        int    The number of times to search.
4549  *  c           char    The character to be searched for, or '\0' if
4550  *                      the character should be read from the user.
4551  *  forward      int    True if searching forward.
4552  *  onto         int    True if the search should end on top of the
4553  *                      character, false if the search should stop
4554  *                      one character before the character in the
4555  *                      specified search direction.
4556  *  change       int    If true, this function is being called upon
4557  *                      to do a vi change command, in which case the
4558  *                      user will be left in insert mode after the
4559  *                      deletion.
4560  * Output:
4561  *  return       int    0 - OK.
4562  *                      1 - Error.
4563  */
gl_delete_find(GetLine * gl,int count,char c,int forward,int onto,int change)4564 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
4565 			  int onto, int change)
4566 {
4567 /*
4568  * Search for the character, and abort the deletion if not found.
4569  */
4570   int pos = gl_find_char(gl, count, forward, onto, c);
4571   if(pos < 0)
4572     return 0;
4573 /*
4574  * If in vi command mode, preserve the current line for potential
4575  * use by vi-undo.
4576  */
4577   gl_save_for_undo(gl);
4578 /*
4579  * Allow the cursor to be at the end of the line if this is a change
4580  * command.
4581  */
4582   if(change)
4583     gl->vi.command = 0;
4584 /*
4585  * Delete the appropriate span of characters.
4586  */
4587   if(forward) {
4588     if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1))
4589       return 1;
4590   } else {
4591     int buff_curpos = gl->buff_curpos;
4592     if(gl_place_cursor(gl, pos) ||
4593        gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1))
4594       return 1;
4595   };
4596 /*
4597  * If this is a change operation, switch the insert mode.
4598  */
4599   if(change && gl_vi_insert(gl, 0, NULL))
4600     return 1;
4601   return 0;
4602 }
4603 
4604 /*.......................................................................
4605  * This is an action function which deletes forward from the cursor up to and
4606  * including a specified character.
4607  */
KT_KEY_FN(gl_forward_delete_find)4608 static KT_KEY_FN(gl_forward_delete_find)
4609 {
4610   return gl_delete_find(gl, count, '\0', 1, 1, 0);
4611 }
4612 
4613 /*.......................................................................
4614  * This is an action function which deletes backward from the cursor back to
4615  * and including a specified character.
4616  */
KT_KEY_FN(gl_backward_delete_find)4617 static KT_KEY_FN(gl_backward_delete_find)
4618 {
4619   return gl_delete_find(gl, count, '\0', 0, 1, 0);
4620 }
4621 
4622 /*.......................................................................
4623  * This is an action function which deletes forward from the cursor up to but
4624  * not including a specified character.
4625  */
KT_KEY_FN(gl_forward_delete_to)4626 static KT_KEY_FN(gl_forward_delete_to)
4627 {
4628   return gl_delete_find(gl, count, '\0', 1, 0, 0);
4629 }
4630 
4631 /*.......................................................................
4632  * This is an action function which deletes backward from the cursor back to
4633  * but not including a specified character.
4634  */
KT_KEY_FN(gl_backward_delete_to)4635 static KT_KEY_FN(gl_backward_delete_to)
4636 {
4637   return gl_delete_find(gl, count, '\0', 0, 0, 0);
4638 }
4639 
4640 /*.......................................................................
4641  * This is an action function which deletes to a character specified by a
4642  * previous search.
4643  */
KT_KEY_FN(gl_delete_refind)4644 static KT_KEY_FN(gl_delete_refind)
4645 {
4646   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
4647 			gl->vi.find_onto, 0);
4648 }
4649 
4650 /*.......................................................................
4651  * This is an action function which deletes to a character specified by a
4652  * previous search, but in the opposite direction.
4653  */
KT_KEY_FN(gl_delete_invert_refind)4654 static KT_KEY_FN(gl_delete_invert_refind)
4655 {
4656   return gl_delete_find(gl, count, gl->vi.find_char,
4657 			!gl->vi.find_forward, gl->vi.find_onto, 0);
4658 }
4659 
4660 /*.......................................................................
4661  * This is an action function which converts the characters in the word
4662  * following the cursor to upper case.
4663  */
KT_KEY_FN(gl_upcase_word)4664 static KT_KEY_FN(gl_upcase_word)
4665 {
4666 /*
4667  * Locate the count'th word ending after the cursor.
4668  */
4669   int last = gl_nth_word_end_forward(gl, count);
4670 /*
4671  * If in vi command mode, preserve the current line for potential
4672  * use by vi-undo.
4673  */
4674   gl_save_for_undo(gl);
4675 /*
4676  * Upcase characters from the current cursor position to 'last'.
4677  */
4678   while(gl->buff_curpos <= last) {
4679     char *cptr = gl->line + gl->buff_curpos;
4680 /*
4681  * Convert the character to upper case?
4682  */
4683     if(islower((int)(unsigned char) *cptr))
4684       gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos);
4685     gl->buff_curpos++;
4686 /*
4687  * Write the possibly modified character back. Note that for non-modified
4688  * characters we want to do this as well, so as to advance the cursor.
4689  */
4690     if(gl_print_char(gl, *cptr, cptr[1]))
4691       return 1;
4692   };
4693   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4694 }
4695 
4696 /*.......................................................................
4697  * This is an action function which converts the characters in the word
4698  * following the cursor to lower case.
4699  */
KT_KEY_FN(gl_downcase_word)4700 static KT_KEY_FN(gl_downcase_word)
4701 {
4702 /*
4703  * Locate the count'th word ending after the cursor.
4704  */
4705   int last = gl_nth_word_end_forward(gl, count);
4706 /*
4707  * If in vi command mode, preserve the current line for potential
4708  * use by vi-undo.
4709  */
4710   gl_save_for_undo(gl);
4711 /*
4712  * Upcase characters from the current cursor position to 'last'.
4713  */
4714   while(gl->buff_curpos <= last) {
4715     char *cptr = gl->line + gl->buff_curpos;
4716 /*
4717  * Convert the character to upper case?
4718  */
4719     if(isupper((int)(unsigned char) *cptr))
4720       gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos);
4721     gl->buff_curpos++;
4722 /*
4723  * Write the possibly modified character back. Note that for non-modified
4724  * characters we want to do this as well, so as to advance the cursor.
4725  */
4726     if(gl_print_char(gl, *cptr, cptr[1]))
4727       return 1;
4728   };
4729   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4730 }
4731 
4732 /*.......................................................................
4733  * This is an action function which converts the first character of the
4734  * following word to upper case, in order to capitalize the word, and
4735  * leaves the cursor at the end of the word.
4736  */
KT_KEY_FN(gl_capitalize_word)4737 static KT_KEY_FN(gl_capitalize_word)
4738 {
4739   char *cptr;   /* &gl->line[gl->buff_curpos] */
4740   int first;    /* True for the first letter of the word */
4741   int i;
4742 /*
4743  * Keep a record of the current insert mode and the cursor position.
4744  */
4745   int insert = gl->insert;
4746 /*
4747  * If in vi command mode, preserve the current line for potential
4748  * use by vi-undo.
4749  */
4750   gl_save_for_undo(gl);
4751 /*
4752  * We want to overwrite the modified word.
4753  */
4754   gl->insert = 0;
4755 /*
4756  * Capitalize 'count' words.
4757  */
4758   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
4759     int pos = gl->buff_curpos;
4760 /*
4761  * If we are not already within a word, skip to the start of the word.
4762  */
4763     for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr);
4764 	pos++, cptr++)
4765       ;
4766 /*
4767  * Move the cursor to the new position.
4768  */
4769     if(gl_place_cursor(gl, pos))
4770       return 1;
4771 /*
4772  * While searching for the end of the word, change lower case letters
4773  * to upper case.
4774  */
4775     for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr);
4776 	gl->buff_curpos++, cptr++) {
4777 /*
4778  * Convert the character to upper case?
4779  */
4780       if(first) {
4781 	if(islower((int)(unsigned char) *cptr))
4782 	  gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
4783       } else {
4784 	if(isupper((int)(unsigned char) *cptr))
4785 	  gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
4786       };
4787       first = 0;
4788 /*
4789  * Write the possibly modified character back. Note that for non-modified
4790  * characters we want to do this as well, so as to advance the cursor.
4791  */
4792       if(gl_print_char(gl, *cptr, cptr[1]))
4793 	return 1;
4794     };
4795   };
4796 /*
4797  * Restore the insertion mode.
4798  */
4799   gl->insert = insert;
4800   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4801 }
4802 
4803 /*.......................................................................
4804  * This is an action function which redraws the current line.
4805  */
KT_KEY_FN(gl_redisplay)4806 static KT_KEY_FN(gl_redisplay)
4807 {
4808 /*
4809  * Keep a record of the current cursor position.
4810  */
4811   int buff_curpos = gl->buff_curpos;
4812 /*
4813  * Do nothing if there is no line to be redisplayed.
4814  */
4815   if(gl->endline)
4816     return 0;
4817 /*
4818  * Erase the current input line.
4819  */
4820   if(gl_erase_line(gl))
4821     return 1;
4822 /*
4823  * Display the current prompt.
4824  */
4825   if(gl_display_prompt(gl))
4826     return 1;
4827 /*
4828  * Render the part of the line that the user has typed in so far.
4829  */
4830   if(gl_print_string(gl, gl->line, '\0'))
4831     return 1;
4832 /*
4833  * Restore the cursor position.
4834  */
4835   if(gl_place_cursor(gl, buff_curpos))
4836     return 1;
4837 /*
4838  * Mark the redisplay operation as having been completed.
4839  */
4840   gl->redisplay = 0;
4841 /*
4842  * Flush the redisplayed line to the terminal.
4843  */
4844   return gl_flush_output(gl);
4845 }
4846 
4847 /*.......................................................................
4848  * This is an action function which clears the display and redraws the
4849  * input line from the home position.
4850  */
KT_KEY_FN(gl_clear_screen)4851 static KT_KEY_FN(gl_clear_screen)
4852 {
4853 /*
4854  * Home the cursor and clear from there to the end of the display.
4855  */
4856   if(gl_print_control_sequence(gl, gl->nline, gl->home) ||
4857      gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
4858     return 1;
4859 /*
4860  * The input line is no longer displayed.
4861  */
4862   gl_line_erased(gl);
4863 /*
4864  * Arrange for the input line to be redisplayed.
4865  */
4866   gl_queue_redisplay(gl);
4867   return 0;
4868 }
4869 
4870 /*.......................................................................
4871  * This is an action function which swaps the character under the cursor
4872  * with the character to the left of the cursor.
4873  */
KT_KEY_FN(gl_transpose_chars)4874 static KT_KEY_FN(gl_transpose_chars)
4875 {
4876   char from[3];     /* The original string of 2 characters */
4877   char swap[3];     /* The swapped string of two characters */
4878 /*
4879  * If we are at the beginning or end of the line, there aren't two
4880  * characters to swap.
4881  */
4882   if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal)
4883     return 0;
4884 /*
4885  * If in vi command mode, preserve the current line for potential
4886  * use by vi-undo.
4887  */
4888   gl_save_for_undo(gl);
4889 /*
4890  * Get the original and swapped strings of the two characters.
4891  */
4892   from[0] = gl->line[gl->buff_curpos - 1];
4893   from[1] = gl->line[gl->buff_curpos];
4894   from[2] = '\0';
4895   swap[0] = gl->line[gl->buff_curpos];
4896   swap[1] = gl->line[gl->buff_curpos - 1];
4897   swap[2] = '\0';
4898 /*
4899  * Move the cursor to the start of the two characters.
4900  */
4901   if(gl_place_cursor(gl, gl->buff_curpos-1))
4902     return 1;
4903 /*
4904  * Swap the two characters in the buffer.
4905  */
4906   gl_buffer_char(gl, swap[0], gl->buff_curpos);
4907   gl_buffer_char(gl, swap[1], gl->buff_curpos+1);
4908 /*
4909  * If the sum of the displayed width of the two characters
4910  * in their current and final positions is the same, swapping can
4911  * be done by just overwriting with the two swapped characters.
4912  */
4913   if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) ==
4914      gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) {
4915     int insert = gl->insert;
4916     gl->insert = 0;
4917     if(gl_print_char(gl, swap[0], swap[1]) ||
4918        gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2]))
4919       return 1;
4920     gl->insert = insert;
4921 /*
4922  * If the swapped substring has a different displayed size, we need to
4923  * redraw everything after the first of the characters.
4924  */
4925   } else {
4926     if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') ||
4927        gl_truncate_display(gl))
4928       return 1;
4929   };
4930 /*
4931  * Advance the cursor to the character after the swapped pair.
4932  */
4933   return gl_place_cursor(gl, gl->buff_curpos + 2);
4934 }
4935 
4936 /*.......................................................................
4937  * This is an action function which sets a mark at the current cursor
4938  * location.
4939  */
KT_KEY_FN(gl_set_mark)4940 static KT_KEY_FN(gl_set_mark)
4941 {
4942   gl->buff_mark = gl->buff_curpos;
4943   return 0;
4944 }
4945 
4946 /*.......................................................................
4947  * This is an action function which swaps the mark location for the
4948  * cursor location.
4949  */
KT_KEY_FN(gl_exchange_point_and_mark)4950 static KT_KEY_FN(gl_exchange_point_and_mark)
4951 {
4952 /*
4953  * Get the old mark position, and limit to the extent of the input
4954  * line.
4955  */
4956   int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal;
4957 /*
4958  * Make the current cursor position the new mark.
4959  */
4960   gl->buff_mark = gl->buff_curpos;
4961 /*
4962  * Move the cursor to the old mark position.
4963  */
4964   return gl_place_cursor(gl, old_mark);
4965 }
4966 
4967 /*.......................................................................
4968  * This is an action function which deletes the characters between the
4969  * mark and the cursor, recording them in gl->cutbuf for later pasting.
4970  */
KT_KEY_FN(gl_kill_region)4971 static KT_KEY_FN(gl_kill_region)
4972 {
4973 /*
4974  * If in vi command mode, preserve the current line for potential
4975  * use by vi-undo.
4976  */
4977   gl_save_for_undo(gl);
4978 /*
4979  * Limit the mark to be within the line.
4980  */
4981   if(gl->buff_mark > gl->ntotal)
4982     gl->buff_mark = gl->ntotal;
4983 /*
4984  * If there are no characters between the cursor and the mark, simply clear
4985  * the cut buffer.
4986  */
4987   if(gl->buff_mark == gl->buff_curpos) {
4988     gl->cutbuf[0] = '\0';
4989     return 0;
4990   };
4991 /*
4992  * If the mark is before the cursor, swap the cursor and the mark.
4993  */
4994   if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL))
4995     return 1;
4996 /*
4997  * Delete the characters.
4998  */
4999   if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1))
5000     return 1;
5001 /*
5002  * Make the mark the same as the cursor position.
5003  */
5004   gl->buff_mark = gl->buff_curpos;
5005   return 0;
5006 }
5007 
5008 /*.......................................................................
5009  * This is an action function which records the characters between the
5010  * mark and the cursor, in gl->cutbuf for later pasting.
5011  */
KT_KEY_FN(gl_copy_region_as_kill)5012 static KT_KEY_FN(gl_copy_region_as_kill)
5013 {
5014   int ca, cb;  /* The indexes of the first and last characters in the region */
5015   int mark;    /* The position of the mark */
5016 /*
5017  * Get the position of the mark, limiting it to lie within the line.
5018  */
5019   mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark;
5020 /*
5021  * If there are no characters between the cursor and the mark, clear
5022  * the cut buffer.
5023  */
5024   if(mark == gl->buff_curpos) {
5025     gl->cutbuf[0] = '\0';
5026     return 0;
5027   };
5028 /*
5029  * Get the line indexes of the first and last characters in the region.
5030  */
5031   if(mark < gl->buff_curpos) {
5032     ca = mark;
5033     cb = gl->buff_curpos - 1;
5034   } else {
5035     ca = gl->buff_curpos;
5036     cb = mark - 1;
5037   };
5038 /*
5039  * Copy the region to the cut buffer.
5040  */
5041   memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca);
5042   gl->cutbuf[cb + 1 - ca] = '\0';
5043   return 0;
5044 }
5045 
5046 /*.......................................................................
5047  * This is an action function which inserts the contents of the cut
5048  * buffer at the current cursor location.
5049  */
KT_KEY_FN(gl_yank)5050 static KT_KEY_FN(gl_yank)
5051 {
5052   int i;
5053 /*
5054  * Set the mark at the current location.
5055  */
5056   gl->buff_mark = gl->buff_curpos;
5057 /*
5058  * Do nothing else if the cut buffer is empty.
5059  */
5060   if(gl->cutbuf[0] == '\0')
5061     return gl_ring_bell(gl, 1, NULL);
5062 /*
5063  * If in vi command mode, preserve the current line for potential
5064  * use by vi-undo.
5065  */
5066   gl_save_for_undo(gl);
5067 /*
5068  * Insert the string count times.
5069  */
5070   for(i=0; i<count; i++) {
5071     if(gl_add_string_to_line(gl, gl->cutbuf))
5072       return 1;
5073   };
5074 /*
5075  * gl_add_string_to_line() leaves the cursor after the last character that
5076  * was pasted, whereas vi leaves the cursor over the last character pasted.
5077  */
5078   if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL))
5079     return 1;
5080   return 0;
5081 }
5082 
5083 /*.......................................................................
5084  * This is an action function which inserts the contents of the cut
5085  * buffer one character beyond the current cursor location.
5086  */
KT_KEY_FN(gl_append_yank)5087 static KT_KEY_FN(gl_append_yank)
5088 {
5089   int was_command = gl->vi.command;
5090   int i;
5091 /*
5092  * If the cut buffer is empty, ring the terminal bell.
5093  */
5094   if(gl->cutbuf[0] == '\0')
5095     return gl_ring_bell(gl, 1, NULL);
5096 /*
5097  * Set the mark at the current location + 1.
5098  */
5099   gl->buff_mark = gl->buff_curpos + 1;
5100 /*
5101  * If in vi command mode, preserve the current line for potential
5102  * use by vi-undo.
5103  */
5104   gl_save_for_undo(gl);
5105 /*
5106  * Arrange to paste the text in insert mode after the current character.
5107  */
5108   if(gl_vi_append(gl, 0, NULL))
5109     return 1;
5110 /*
5111  * Insert the string count times.
5112  */
5113   for(i=0; i<count; i++) {
5114     if(gl_add_string_to_line(gl, gl->cutbuf))
5115       return 1;
5116   };
5117 /*
5118  * Switch back to command mode if necessary.
5119  */
5120   if(was_command)
5121     gl_vi_command_mode(gl);
5122   return 0;
5123 }
5124 
5125 /*.......................................................................
5126  * Attempt to ask the terminal for its current size. On systems that
5127  * don't support the TIOCWINSZ ioctl() for querying the terminal size,
5128  * the current values of gl->ncolumn and gl->nrow are returned.
5129  *
5130  * Input:
5131  *  gl     GetLine *  The resource object of gl_get_line().
5132  * Input/Output:
5133  *  ncolumn    int *  The number of columns will be assigned to *ncolumn.
5134  *  nline      int *  The number of lines will be assigned to *nline.
5135  */
gl_query_size(GetLine * gl,int * ncolumn,int * nline)5136 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline)
5137 {
5138 #ifdef TIOCGWINSZ
5139 /*
5140  * Query the new terminal window size. Ignore invalid responses.
5141  */
5142   struct winsize size;
5143   if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 &&
5144      size.ws_row > 0 && size.ws_col > 0) {
5145     *ncolumn = size.ws_col;
5146     *nline = size.ws_row;
5147     return;
5148   };
5149 #endif
5150 /*
5151  * Return the existing values.
5152  */
5153   *ncolumn = gl->ncolumn;
5154   *nline = gl->nline;
5155   return;
5156 }
5157 
5158 /*.......................................................................
5159  * Query the size of the terminal, and if it has changed, redraw the
5160  * current input line accordingly.
5161  *
5162  * Input:
5163  *  gl     GetLine *  The resource object of gl_get_line().
5164  * Output:
5165  *  return     int    0 - OK.
5166  *                    1 - Error.
5167  */
_gl_update_size(GetLine * gl)5168 static int _gl_update_size(GetLine *gl)
5169 {
5170   int ncolumn, nline;    /* The new size of the terminal */
5171 /*
5172  * Query the new terminal window size.
5173  */
5174   gl_query_size(gl, &ncolumn, &nline);
5175 /*
5176  * Update gl and the displayed line to fit the new dimensions.
5177  */
5178   return gl_handle_tty_resize(gl, ncolumn, nline);
5179 }
5180 
5181 /*.......................................................................
5182  * Redraw the current input line to account for a change in the terminal
5183  * size. Also install the new size in gl.
5184  *
5185  * Input:
5186  *  gl     GetLine *  The resource object of gl_get_line().
5187  *  ncolumn    int    The new number of columns.
5188  *  nline      int    The new number of lines.
5189  * Output:
5190  *  return     int    0 - OK.
5191  *                    1 - Error.
5192  */
gl_handle_tty_resize(GetLine * gl,int ncolumn,int nline)5193 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline)
5194 {
5195 /*
5196  * If the input device isn't a terminal, just record the new size.
5197  */
5198   if(!gl->is_term) {
5199     gl->nline = nline;
5200     gl->ncolumn = ncolumn;
5201 /*
5202  * Has the size actually changed?
5203  */
5204   } else if(ncolumn != gl->ncolumn || nline != gl->nline) {
5205 /*
5206  * If we are currently editing a line, erase it.
5207  */
5208     if(gl_erase_line(gl))
5209       return 1;
5210 /*
5211  * Update the recorded window size.
5212  */
5213     gl->nline = nline;
5214     gl->ncolumn = ncolumn;
5215 /*
5216  * Arrange for the input line to be redrawn before the next character
5217  * is read from the terminal.
5218  */
5219     gl_queue_redisplay(gl);
5220   };
5221   return 0;
5222 }
5223 
5224 /*.......................................................................
5225  * This is the action function that recalls the previous line in the
5226  * history buffer.
5227  */
KT_KEY_FN(gl_up_history)5228 static KT_KEY_FN(gl_up_history)
5229 {
5230 /*
5231  * In vi mode, switch to command mode, since the user is very
5232  * likely to want to move around newly recalled lines.
5233  */
5234   gl_vi_command_mode(gl);
5235 /*
5236  * Forget any previous recall session.
5237  */
5238   gl->preload_id = 0;
5239 /*
5240  * Record the key sequence number of this search action.
5241  */
5242   gl->last_search = gl->keyseq_count;
5243 /*
5244  * We don't want a search prefix for this function.
5245  */
5246   if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5247     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5248     return 1;
5249   };
5250 /*
5251  * Recall the count'th next older line in the history list. If the first one
5252  * fails we can return since nothing has changed, otherwise we must continue
5253  * and update the line state.
5254  */
5255   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5256     return 0;
5257   while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1))
5258     ;
5259 /*
5260  * Accomodate the new contents of gl->line[].
5261  */
5262   gl_update_buffer(gl);
5263 /*
5264  * Arrange to have the cursor placed at the end of the new line.
5265  */
5266   gl->buff_curpos = gl->ntotal;
5267 /*
5268  * Erase and display the new line.
5269  */
5270   gl_queue_redisplay(gl);
5271   return 0;
5272 }
5273 
5274 /*.......................................................................
5275  * This is the action function that recalls the next line in the
5276  * history buffer.
5277  */
KT_KEY_FN(gl_down_history)5278 static KT_KEY_FN(gl_down_history)
5279 {
5280 /*
5281  * In vi mode, switch to command mode, since the user is very
5282  * likely to want to move around newly recalled lines.
5283  */
5284   gl_vi_command_mode(gl);
5285 /*
5286  * Record the key sequence number of this search action.
5287  */
5288   gl->last_search = gl->keyseq_count;
5289 /*
5290  * If no search is currently in progress continue a previous recall
5291  * session from a previous entered line if possible.
5292  */
5293   if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) {
5294     _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1);
5295     gl->preload_id = 0;
5296   } else {
5297 /*
5298  * We don't want a search prefix for this function.
5299  */
5300     if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5301       _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5302       return 1;
5303     };
5304 /*
5305  * Recall the count'th next newer line in the history list. If the first one
5306  * fails we can return since nothing has changed otherwise we must continue
5307  * and update the line state.
5308  */
5309     if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5310       return 0;
5311     while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1))
5312       ;
5313   };
5314 /*
5315  * Accomodate the new contents of gl->line[].
5316  */
5317   gl_update_buffer(gl);
5318 /*
5319  * Arrange to have the cursor placed at the end of the new line.
5320  */
5321   gl->buff_curpos = gl->ntotal;
5322 /*
5323  * Erase and display the new line.
5324  */
5325   gl_queue_redisplay(gl);
5326   return 0;
5327 }
5328 
5329 /*.......................................................................
5330  * This is the action function that recalls the previous line in the
5331  * history buffer whos prefix matches the characters that currently
5332  * precede the cursor. By setting count=-1, this can be used internally
5333  * to force searching for the prefix used in the last search.
5334  */
KT_KEY_FN(gl_history_search_backward)5335 static KT_KEY_FN(gl_history_search_backward)
5336 {
5337 /*
5338  * In vi mode, switch to command mode, since the user is very
5339  * likely to want to move around newly recalled lines.
5340  */
5341   gl_vi_command_mode(gl);
5342 /*
5343  * Forget any previous recall session.
5344  */
5345   gl->preload_id = 0;
5346 /*
5347  * Record the key sequence number of this search action.
5348  */
5349   gl->last_search = gl->keyseq_count;
5350 /*
5351  * If a prefix search isn't already in progress, replace the search
5352  * prefix to the string that precedes the cursor. In vi command mode
5353  * include the character that is under the cursor in the string.  If
5354  * count<0 keep the previous search prefix regardless, so as to force
5355  * a repeat search even if the last command wasn't a history command.
5356  */
5357   if(count >= 0 && !_glh_search_active(gl->glh) &&
5358      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5359 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5360     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5361     return 1;
5362   };
5363 /*
5364  * Search backwards for a match to the part of the line which precedes the
5365  * cursor.
5366  */
5367   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5368     return 0;
5369 /*
5370  * Accomodate the new contents of gl->line[].
5371  */
5372   gl_update_buffer(gl);
5373 /*
5374  * Arrange to have the cursor placed at the end of the new line.
5375  */
5376   gl->buff_curpos = gl->ntotal;
5377 /*
5378  * Erase and display the new line.
5379  */
5380   gl_queue_redisplay(gl);
5381   return 0;
5382 }
5383 
5384 /*.......................................................................
5385  * This is the action function that recalls the previous line in the
5386  * history buffer who's prefix matches that specified in an earlier call
5387  * to gl_history_search_backward() or gl_history_search_forward().
5388  */
KT_KEY_FN(gl_history_re_search_backward)5389 static KT_KEY_FN(gl_history_re_search_backward)
5390 {
5391   return gl_history_search_backward(gl, -1, NULL);
5392 }
5393 
5394 /*.......................................................................
5395  * This is the action function that recalls the next line in the
5396  * history buffer who's prefix matches that specified in the earlier call
5397  * to gl_history_search_backward) which started the history search.
5398  * By setting count=-1, this can be used internally to force searching
5399  * for the prefix used in the last search.
5400  */
KT_KEY_FN(gl_history_search_forward)5401 static KT_KEY_FN(gl_history_search_forward)
5402 {
5403 /*
5404  * In vi mode, switch to command mode, since the user is very
5405  * likely to want to move around newly recalled lines.
5406  */
5407   gl_vi_command_mode(gl);
5408 /*
5409  * Record the key sequence number of this search action.
5410  */
5411   gl->last_search = gl->keyseq_count;
5412 /*
5413  * If a prefix search isn't already in progress, replace the search
5414  * prefix to the string that precedes the cursor. In vi command mode
5415  * include the character that is under the cursor in the string.  If
5416  * count<0 keep the previous search prefix regardless, so as to force
5417  * a repeat search even if the last command wasn't a history command.
5418  */
5419   if(count >= 0 && !_glh_search_active(gl->glh) &&
5420      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5421 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5422     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5423     return 1;
5424   };
5425 /*
5426  * Search forwards for the next matching line.
5427  */
5428   if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5429     return 0;
5430 /*
5431  * Accomodate the new contents of gl->line[].
5432  */
5433   gl_update_buffer(gl);
5434 /*
5435  * Arrange for the cursor to be placed at the end of the new line.
5436  */
5437   gl->buff_curpos = gl->ntotal;
5438 /*
5439  * Erase and display the new line.
5440  */
5441   gl_queue_redisplay(gl);
5442   return 0;
5443 }
5444 
5445 /*.......................................................................
5446  * This is the action function that recalls the next line in the
5447  * history buffer who's prefix matches that specified in an earlier call
5448  * to gl_history_search_backward() or gl_history_search_forward().
5449  */
KT_KEY_FN(gl_history_re_search_forward)5450 static KT_KEY_FN(gl_history_re_search_forward)
5451 {
5452   return gl_history_search_forward(gl, -1, NULL);
5453 }
5454 
5455 #ifdef HIDE_FILE_SYSTEM
5456 /*.......................................................................
5457  * The following function is used as the default completion handler when
5458  * the filesystem is to be hidden. It simply reports no completions.
5459  */
CPL_MATCH_FN(gl_no_completions)5460 static CPL_MATCH_FN(gl_no_completions)
5461 {
5462   return 0;
5463 }
5464 #endif
5465 
5466 /*.......................................................................
5467  * This is the tab completion function that completes the filename that
5468  * precedes the cursor position. Its callback data argument must be a
5469  * pointer to a GlCplCallback containing the completion callback function
5470  * and its callback data, or NULL to use the builtin filename completer.
5471  */
KT_KEY_FN(gl_complete_word)5472 static KT_KEY_FN(gl_complete_word)
5473 {
5474   CplMatches *matches;    /* The possible completions */
5475   int suffix_len;         /* The length of the completion extension */
5476   int cont_len;           /* The length of any continuation suffix */
5477   int nextra;             /* The number of characters being added to the */
5478                           /*  total length of the line. */
5479   int buff_pos;           /* The buffer index at which the completion is */
5480                           /*  to be inserted. */
5481   int waserr = 0;         /* True after errors */
5482 /*
5483  * Get the container of the completion callback and its callback data.
5484  */
5485   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
5486 /*
5487  * In vi command mode, switch to append mode so that the character under
5488  * the cursor is included in the completion (otherwise people can't
5489  * complete at the end of the line).
5490  */
5491   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5492     return 1;
5493 /*
5494  * Get the cursor position at which the completion is to be inserted.
5495  */
5496   buff_pos = gl->buff_curpos;
5497 /*
5498  * Perform the completion.
5499  */
5500   matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data,
5501 			      cb->fn);
5502 /*
5503  * No matching completions?
5504  */
5505   if(!matches) {
5506     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
5507 /*
5508  * Are there any completions?
5509  */
5510   } else if(matches->nmatch >= 1) {
5511 /*
5512  * If there any ambiguous matches, report them, starting on a new line.
5513  */
5514     if(matches->nmatch > 1 && gl->echo) {
5515       if(_gl_normal_io(gl) ||
5516 	 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
5517 	waserr = 1;
5518     };
5519 /*
5520  * Get the length of the suffix and any continuation suffix to add to it.
5521  */
5522     suffix_len = strlen(matches->suffix);
5523     cont_len = strlen(matches->cont_suffix);
5524 /*
5525  * If there is an unambiguous match, and the continuation suffix ends in
5526  * a newline, strip that newline and arrange to have getline return
5527  * after this action function returns.
5528  */
5529     if(matches->nmatch==1 && cont_len > 0 &&
5530        matches->cont_suffix[cont_len - 1] == '\n') {
5531       cont_len--;
5532       if(gl_newline(gl, 1, NULL))
5533 	waserr = 1;
5534     };
5535 /*
5536  * Work out the number of characters that are to be added.
5537  */
5538     nextra = suffix_len + cont_len;
5539 /*
5540  * Is there anything to be added?
5541  */
5542     if(!waserr && nextra) {
5543 /*
5544  * Will there be space for the expansion in the line buffer?
5545  */
5546       if(gl->ntotal + nextra < gl->linelen) {
5547 /*
5548  * Make room to insert the filename extension.
5549  */
5550 	gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5551 /*
5552  * Insert the filename extension.
5553  */
5554 	gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos);
5555 /*
5556  * Add the terminating characters.
5557  */
5558 	gl_buffer_string(gl, matches->cont_suffix, cont_len,
5559 			 gl->buff_curpos + suffix_len);
5560 /*
5561  * Place the cursor position at the end of the completion.
5562  */
5563 	gl->buff_curpos += nextra;
5564 /*
5565  * If we don't have to redisplay the whole line, redisplay the part
5566  * of the line which follows the original cursor position, and place
5567  * the cursor at the end of the completion.
5568  */
5569 	if(gl->displayed) {
5570 	  if(gl_truncate_display(gl) ||
5571 	     gl_print_string(gl, gl->line + buff_pos, '\0') ||
5572 	     gl_place_cursor(gl, gl->buff_curpos))
5573 	    waserr = 1;
5574 	};
5575       } else {
5576 	(void) gl_print_info(gl,
5577 			     "Insufficient room in line for file completion.",
5578 			     GL_END_INFO);
5579 	waserr = 1;
5580       };
5581     };
5582   };
5583 /*
5584  * If any output had to be written to the terminal, then editing will
5585  * have been suspended, make sure that we are back in raw line editing
5586  * mode before returning.
5587  */
5588   if(_gl_raw_io(gl, 1))
5589     waserr = 1;
5590   return 0;
5591 }
5592 
5593 #ifndef HIDE_FILE_SYSTEM
5594 /*.......................................................................
5595  * This is the function that expands the filename that precedes the
5596  * cursor position. It expands ~user/ expressions, $envvar expressions,
5597  * and wildcards.
5598  */
KT_KEY_FN(gl_expand_filename)5599 static KT_KEY_FN(gl_expand_filename)
5600 {
5601   char *start_path;      /* The pointer to the start of the pathname in */
5602                          /*  gl->line[]. */
5603   FileExpansion *result; /* The results of the filename expansion */
5604   int pathlen;           /* The length of the pathname being expanded */
5605   int length;            /* The number of characters needed to display the */
5606                          /*  expanded files. */
5607   int nextra;            /* The number of characters to be added */
5608   int i,j;
5609 /*
5610  * In vi command mode, switch to append mode so that the character under
5611  * the cursor is included in the completion (otherwise people can't
5612  * complete at the end of the line).
5613  */
5614   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5615     return 1;
5616 /*
5617  * Locate the start of the filename that precedes the cursor position.
5618  */
5619   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5620   if(!start_path)
5621     return 1;
5622 /*
5623  * Get the length of the string that is to be expanded.
5624  */
5625   pathlen = gl->buff_curpos - (start_path - gl->line);
5626 /*
5627  * Attempt to expand it.
5628  */
5629   result = ef_expand_file(gl->ef, start_path, pathlen);
5630 /*
5631  * If there was an error, report the error on a new line.
5632  */
5633   if(!result)
5634     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
5635 /*
5636  * If no files matched, report this as well.
5637  */
5638   if(result->nfile == 0 || !result->exists)
5639     return gl_print_info(gl, "No files match.", GL_END_INFO);
5640 /*
5641  * If in vi command mode, preserve the current line for potential use by
5642  * vi-undo.
5643  */
5644   gl_save_for_undo(gl);
5645 /*
5646  * Work out how much space we will need to display all of the matching
5647  * filenames, taking account of the space that we need to place between
5648  * them, and the number of additional '\' characters needed to escape
5649  * spaces, tabs and backslash characters in the individual filenames.
5650  */
5651   length = 0;
5652   for(i=0; i<result->nfile; i++) {
5653     char *file = result->files[i];
5654     while(*file) {
5655       int c = *file++;
5656       switch(c) {
5657       case ' ': case '\t': case '\\': case '*': case '?': case '[':
5658 	length++;  /* Count extra backslash characters */
5659       };
5660       length++;    /* Count the character itself */
5661     };
5662     length++;      /* Count the space that follows each filename */
5663   };
5664 /*
5665  * Work out the number of characters that are to be added.
5666  */
5667   nextra = length - pathlen;
5668 /*
5669  * Will there be space for the expansion in the line buffer?
5670  */
5671   if(gl->ntotal + nextra >= gl->linelen) {
5672     return gl_print_info(gl, "Insufficient room in line for file expansion.",
5673 			 GL_END_INFO);
5674   } else {
5675 /*
5676  * Do we need to move the part of the line that followed the unexpanded
5677  * filename?
5678  */
5679     if(nextra > 0) {
5680       gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5681     } else if(nextra < 0) {
5682       gl->buff_curpos += nextra;
5683       gl_remove_from_buffer(gl, gl->buff_curpos, -nextra);
5684     };
5685 /*
5686  * Insert the filenames, separated by spaces, and with internal spaces,
5687  * tabs and backslashes escaped with backslashes.
5688  */
5689     for(i=0,j=start_path - gl->line; i<result->nfile; i++) {
5690       char *file = result->files[i];
5691       while(*file) {
5692 	int c = *file++;
5693 	switch(c) {
5694 	case ' ': case '\t': case '\\': case '*': case '?': case '[':
5695 	  gl_buffer_char(gl, '\\', j++);
5696 	};
5697 	gl_buffer_char(gl, c, j++);
5698       };
5699       gl_buffer_char(gl, ' ', j++);
5700     };
5701   };
5702 /*
5703  * Redisplay the part of the line which follows the start of
5704  * the original filename.
5705  */
5706   if(gl_place_cursor(gl, start_path - gl->line) ||
5707      gl_truncate_display(gl) ||
5708      gl_print_string(gl, start_path, start_path[length]))
5709     return 1;
5710 /*
5711  * Move the cursor to the end of the expansion.
5712  */
5713   return gl_place_cursor(gl, (start_path - gl->line) + length);
5714 }
5715 #endif
5716 
5717 #ifndef HIDE_FILE_SYSTEM
5718 /*.......................................................................
5719  * This is the action function that lists glob expansions of the
5720  * filename that precedes the cursor position. It expands ~user/
5721  * expressions, $envvar expressions, and wildcards.
5722  */
KT_KEY_FN(gl_list_glob)5723 static KT_KEY_FN(gl_list_glob)
5724 {
5725   char *start_path;      /* The pointer to the start of the pathname in */
5726                          /*  gl->line[]. */
5727   FileExpansion *result; /* The results of the filename expansion */
5728   int pathlen;           /* The length of the pathname being expanded */
5729 /*
5730  * Locate the start of the filename that precedes the cursor position.
5731  */
5732   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5733   if(!start_path)
5734     return 1;
5735 /*
5736  * Get the length of the string that is to be expanded.
5737  */
5738   pathlen = gl->buff_curpos - (start_path - gl->line);
5739 /*
5740  * Attempt to expand it.
5741  */
5742   result = ef_expand_file(gl->ef, start_path, pathlen);
5743 /*
5744  * If there was an error, report it.
5745  */
5746   if(!result) {
5747     return gl_print_info(gl,  ef_last_error(gl->ef), GL_END_INFO);
5748 /*
5749  * If no files matched, report this as well.
5750  */
5751   } else if(result->nfile == 0 || !result->exists) {
5752     return gl_print_info(gl, "No files match.", GL_END_INFO);
5753 /*
5754  * List the matching expansions.
5755  */
5756   } else if(gl->echo) {
5757     if(gl_start_newline(gl, 1) ||
5758        _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn))
5759       return 1;
5760     gl_queue_redisplay(gl);
5761   };
5762   return 0;
5763 }
5764 #endif
5765 
5766 /*.......................................................................
5767  * Return non-zero if a character should be considered a part of a word.
5768  *
5769  * Input:
5770  *  c       int  The character to be tested.
5771  * Output:
5772  *  return  int  True if the character should be considered part of a word.
5773  */
gl_is_word_char(int c)5774 static int gl_is_word_char(int c)
5775 {
5776   return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL;
5777 }
5778 
5779 /*.......................................................................
5780  * Override the builtin file-completion callback that is bound to the
5781  * "complete_word" action function.
5782  *
5783  * Input:
5784  *  gl            GetLine *  The resource object of the command-line input
5785  *                           module.
5786  *  data             void *  This is passed to match_fn() whenever it is
5787  *                           called. It could, for example, point to a
5788  *                           symbol table where match_fn() could look
5789  *                           for possible completions.
5790  *  match_fn   CplMatchFn *  The function that will identify the prefix
5791  *                           to be completed from the input line, and
5792  *                           report matching symbols.
5793  * Output:
5794  *  return            int    0 - OK.
5795  *                           1 - Error.
5796  */
gl_customize_completion(GetLine * gl,void * data,CplMatchFn * match_fn)5797 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn)
5798 {
5799   sigset_t oldset; /* The signals that were blocked on entry to this function */
5800 /*
5801  * Check the arguments.
5802  */
5803   if(!gl || !match_fn) {
5804     if(gl)
5805       _err_record_msg(gl->err, "NULL argument", END_ERR_MSG);
5806     errno = EINVAL;
5807     return 1;
5808   };
5809 /*
5810  * Temporarily block all signals.
5811  */
5812   gl_mask_signals(gl, &oldset);
5813 /*
5814  * Record the new completion function and its callback data.
5815  */
5816   gl->cplfn.fn = match_fn;
5817   gl->cplfn.data = data;
5818 /*
5819  * Restore the process signal mask before returning.
5820  */
5821   gl_unmask_signals(gl, &oldset);
5822   return 0;
5823 }
5824 
5825 /*.......................................................................
5826  * Change the terminal (or stream) that getline interacts with.
5827  *
5828  * Input:
5829  *  gl            GetLine *  The resource object of the command-line input
5830  *                           module.
5831  *  input_fp         FILE *  The stdio stream to read from.
5832  *  output_fp        FILE *  The stdio stream to write to.
5833  *  term             char *  The terminal type. This can be NULL if
5834  *                           either or both of input_fp and output_fp don't
5835  *                           refer to a terminal. Otherwise it should refer
5836  *                           to an entry in the terminal information database.
5837  * Output:
5838  *  return            int    0 - OK.
5839  *                           1 - Error.
5840  */
gl_change_terminal(GetLine * gl,FILE * input_fp,FILE * output_fp,const char * term)5841 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5842 		       const char *term)
5843 {
5844   sigset_t oldset; /* The signals that were blocked on entry to this function */
5845   int status;      /* The return status of _gl_change_terminal() */
5846 /*
5847  * Check the arguments.
5848  */
5849   if(!gl) {
5850     errno = EINVAL;
5851     return 1;
5852   };
5853 /*
5854  * Block all signals.
5855  */
5856   if(gl_mask_signals(gl, &oldset))
5857     return 1;
5858 /*
5859  * Execute the private body of the function while signals are blocked.
5860  */
5861   status = _gl_change_terminal(gl, input_fp, output_fp, term);
5862 /*
5863  * Restore the process signal mask.
5864  */
5865   gl_unmask_signals(gl, &oldset);
5866   return status;
5867 }
5868 
5869 /*.......................................................................
5870  * This is the private body of the gl_change_terminal() function. It
5871  * assumes that the caller has checked its arguments and blocked the
5872  * delivery of signals.
5873  */
_gl_change_terminal(GetLine * gl,FILE * input_fp,FILE * output_fp,const char * term)5874 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5875 			       const char *term)
5876 {
5877   int is_term = 0;   /* True if both input_fd and output_fd are associated */
5878                      /*  with a terminal. */
5879 /*
5880  * Require that input_fp and output_fp both be valid.
5881  */
5882   if(!input_fp || !output_fp) {
5883     gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).",
5884 		  GL_END_INFO);
5885     return 1;
5886   };
5887 /*
5888  * Are we displacing an existing terminal (as opposed to setting the
5889  * initial terminal)?
5890  */
5891   if(gl->input_fd >= 0) {
5892 /*
5893  * Make sure to leave the previous terminal in a usable state.
5894  */
5895     if(_gl_normal_io(gl))
5896       return 1;
5897 /*
5898  * Remove the displaced terminal from the list of fds to watch.
5899  */
5900 #ifdef HAVE_SELECT
5901     FD_CLR(gl->input_fd, &gl->rfds);
5902 #endif
5903   };
5904 /*
5905  * Record the file descriptors and streams.
5906  */
5907   gl->input_fp = input_fp;
5908   gl->input_fd = fileno(input_fp);
5909   gl->output_fp = output_fp;
5910   gl->output_fd = fileno(output_fp);
5911 /*
5912  * If needed, expand the record of the maximum file-descriptor that might
5913  * need to be monitored with select().
5914  */
5915 #ifdef HAVE_SELECT
5916   if(gl->input_fd > gl->max_fd)
5917     gl->max_fd = gl->input_fd;
5918 #endif
5919 /*
5920  * Disable terminal interaction until we have enough info to interact
5921  * with the terminal.
5922  */
5923   gl->is_term = 0;
5924 /*
5925  * For terminal editing, we need both output_fd and input_fd to refer to
5926  * a terminal. While we can't verify that they both point to the same
5927  * terminal, we can verify that they point to terminals.
5928  */
5929   is_term = isatty(gl->input_fd) && isatty(gl->output_fd);
5930 /*
5931  * If we are interacting with a terminal and no terminal type has been
5932  * specified, treat it as a generic ANSI terminal.
5933  */
5934   if(is_term && !term)
5935     term = "ansi";
5936 /*
5937  * Make a copy of the terminal type string.
5938  */
5939   if(term != gl->term) {
5940 /*
5941  * Delete any old terminal type string.
5942  */
5943     if(gl->term) {
5944       free(gl->term);
5945       gl->term = NULL;
5946     };
5947 /*
5948  * Make a copy of the new terminal-type string, if any.
5949  */
5950     if(term) {
5951       size_t termsz = strlen(term)+1;
5952 
5953       gl->term = (char *) malloc(termsz);
5954       if(gl->term)
5955 	strlcpy(gl->term, term, termsz);
5956     };
5957   };
5958 /*
5959  * Clear any terminal-specific key bindings that were taken from the
5960  * settings of the last terminal.
5961  */
5962   _kt_clear_bindings(gl->bindings, KTB_TERM);
5963 /*
5964  * If we have a terminal install new bindings for it.
5965  */
5966   if(is_term) {
5967 /*
5968  * Get the current settings of the terminal.
5969  */
5970     if(tcgetattr(gl->input_fd, &gl->oldattr)) {
5971       _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
5972       return 1;
5973     };
5974 /*
5975  * If we don't set this now, gl_control_strings() won't know
5976  * that it is talking to a terminal.
5977  */
5978     gl->is_term = 1;
5979 /*
5980  * Lookup the terminal control string and size information.
5981  */
5982     if(gl_control_strings(gl, term)) {
5983       gl->is_term = 0;
5984       return 1;
5985     };
5986 /*
5987  * Bind terminal-specific keys.
5988  */
5989     if(gl_bind_terminal_keys(gl))
5990       return 1;
5991   };
5992 /*
5993  * Assume that the caller has given us a terminal in a sane state.
5994  */
5995   gl->io_mode = GL_NORMAL_MODE;
5996 /*
5997  * Switch into the currently configured I/O mode.
5998  */
5999   if(_gl_io_mode(gl, gl->io_mode))
6000     return 1;
6001   return 0;
6002 }
6003 
6004 /*.......................................................................
6005  * Set up terminal-specific key bindings.
6006  *
6007  * Input:
6008  *  gl            GetLine *  The resource object of the command-line input
6009  *                           module.
6010  * Output:
6011  *  return            int    0 - OK.
6012  *                           1 - Error.
6013  */
gl_bind_terminal_keys(GetLine * gl)6014 static int gl_bind_terminal_keys(GetLine *gl)
6015 {
6016 /*
6017  * Install key-bindings for the special terminal characters.
6018  */
6019   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR],
6020 			  "user-interrupt") ||
6021      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") ||
6022      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend"))
6023     return 1;
6024 /*
6025  * In vi-mode, arrange for the above characters to be seen in command
6026  * mode.
6027  */
6028   if(gl->editor == GL_VI_MODE) {
6029     if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]),
6030 			    "user-interrupt") ||
6031        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]),
6032 			    "abort") ||
6033        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]),
6034 			    "suspend"))
6035       return 1;
6036   };
6037 /*
6038  * Non-universal special keys.
6039  */
6040 #ifdef VLNEXT
6041   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT],
6042 			  "literal-next"))
6043     return 1;
6044 #else
6045   if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) {
6046     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6047     return 1;
6048   };
6049 #endif
6050 /*
6051  * Bind action functions to the terminal-specific arrow keys
6052  * looked up by gl_control_strings().
6053  */
6054   if(_gl_bind_arrow_keys(gl))
6055     return 1;
6056   return 0;
6057 }
6058 
6059 /*.......................................................................
6060  * This function is normally bound to control-D. When it is invoked within
6061  * a line it deletes the character which follows the cursor. When invoked
6062  * at the end of the line it lists possible file completions, and when
6063  * invoked on an empty line it causes gl_get_line() to return EOF. This
6064  * function emulates the one that is normally bound to control-D by tcsh.
6065  */
KT_KEY_FN(gl_del_char_or_list_or_eof)6066 static KT_KEY_FN(gl_del_char_or_list_or_eof)
6067 {
6068 /*
6069  * If we have an empty line arrange to return EOF.
6070  */
6071   if(gl->ntotal < 1) {
6072     gl_record_status(gl, GLR_EOF, 0);
6073     return 1;
6074 /*
6075  * If we are at the end of the line list possible completions.
6076  */
6077   } else if(gl->buff_curpos >= gl->ntotal) {
6078     return gl_list_completions(gl, 1, NULL);
6079 /*
6080  * Within the line delete the character that follows the cursor.
6081  */
6082   } else {
6083 /*
6084  * If in vi command mode, first preserve the current line for potential use
6085  * by vi-undo.
6086  */
6087     gl_save_for_undo(gl);
6088 /*
6089  * Delete 'count' characters.
6090  */
6091     return gl_forward_delete_char(gl, count, NULL);
6092   };
6093 }
6094 
6095 /*.......................................................................
6096  * This function is normally bound to control-D in vi mode. When it is
6097  * invoked within a line it lists possible file completions, and when
6098  * invoked on an empty line it causes gl_get_line() to return EOF. This
6099  * function emulates the one that is normally bound to control-D by tcsh.
6100  */
KT_KEY_FN(gl_list_or_eof)6101 static KT_KEY_FN(gl_list_or_eof)
6102 {
6103 /*
6104  * If we have an empty line arrange to return EOF.
6105  */
6106   if(gl->ntotal < 1) {
6107     gl_record_status(gl, GLR_EOF, 0);
6108     return 1;
6109 /*
6110  * Otherwise list possible completions.
6111  */
6112   } else {
6113     return gl_list_completions(gl, 1, NULL);
6114   };
6115 }
6116 
6117 /*.......................................................................
6118  * List possible completions of the word that precedes the cursor. The
6119  * callback data argument must either be NULL to select the default
6120  * file completion callback, or be a GlCplCallback object containing the
6121  * completion callback function to call.
6122  */
KT_KEY_FN(gl_list_completions)6123 static KT_KEY_FN(gl_list_completions)
6124 {
6125   int waserr = 0;   /* True after errors */
6126 /*
6127  * Get the container of the completion callback and its callback data.
6128  */
6129   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
6130 /*
6131  * Get the list of possible completions.
6132  */
6133   CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos,
6134 					  cb->data, cb->fn);
6135 /*
6136  * No matching completions?
6137  */
6138   if(!matches) {
6139     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
6140 /*
6141  * List the matches.
6142  */
6143   } else if(matches->nmatch > 0 && gl->echo) {
6144     if(_gl_normal_io(gl) ||
6145        _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
6146       waserr = 1;
6147   };
6148 /*
6149  * If any output had to be written to the terminal, then editing will
6150  * have been suspended, make sure that we are back in raw line editing
6151  * mode before returning.
6152  */
6153   if(_gl_raw_io(gl, 1))
6154     waserr = 1;
6155   return waserr;
6156 }
6157 
6158 /*.......................................................................
6159  * Where the user has used the symbolic arrow-key names to specify
6160  * arrow key bindings, bind the specified action functions to the default
6161  * and terminal specific arrow key sequences.
6162  *
6163  * Input:
6164  *  gl     GetLine *   The getline resource object.
6165  * Output:
6166  *  return     int     0 - OK.
6167  *                     1 - Error.
6168  */
_gl_bind_arrow_keys(GetLine * gl)6169 static int _gl_bind_arrow_keys(GetLine *gl)
6170 {
6171 /*
6172  * Process each of the arrow keys.
6173  */
6174   if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") ||
6175      _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") ||
6176      _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") ||
6177      _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC"))
6178     return 1;
6179   return 0;
6180 }
6181 
6182 /*.......................................................................
6183  * Lookup the action function of a symbolic arrow-key binding, and bind
6184  * it to the terminal-specific and default arrow-key sequences. Note that
6185  * we don't trust the terminal-specified key sequences to be correct.
6186  * The main reason for this is that on some machines the xterm terminfo
6187  * entry is for hardware X-terminals, rather than xterm terminal emulators
6188  * and the two terminal types emit different character sequences when the
6189  * their cursor keys are pressed. As a result we also supply a couple
6190  * of default key sequences.
6191  *
6192  * Input:
6193  *  gl          GetLine *   The resource object of gl_get_line().
6194  *  name           char *   The symbolic name of the arrow key.
6195  *  term_seq       char *   The terminal-specific arrow-key sequence.
6196  *  def_seq1       char *   The first default arrow-key sequence.
6197  *  def_seq2       char *   The second arrow-key sequence.
6198  * Output:
6199  *  return          int     0 - OK.
6200  *                          1 - Error.
6201  */
_gl_rebind_arrow_key(GetLine * gl,const char * name,const char * term_seq,const char * def_seq1,const char * def_seq2)6202 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
6203 				const char *term_seq, const char *def_seq1,
6204 				const char *def_seq2)
6205 {
6206   KeySym *keysym;  /* The binding-table entry matching the arrow-key name */
6207   int nsym;        /* The number of ambiguous matches */
6208 /*
6209  * Lookup the key binding for the symbolic name of the arrow key. This
6210  * will either be the default action, or a user provided one.
6211  */
6212   if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym)
6213      == KT_EXACT_MATCH) {
6214 /*
6215  * Get the action function.
6216  */
6217     KtAction *action = keysym->actions + keysym->binder;
6218     KtKeyFn *fn = action->fn;
6219     void *data = action->data;
6220 /*
6221  * Bind this to each of the specified key sequences.
6222  */
6223     if((term_seq &&
6224 	_kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) ||
6225        (def_seq1 &&
6226 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) ||
6227        (def_seq2 &&
6228 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) {
6229       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6230       return 1;
6231     };
6232   };
6233   return 0;
6234 }
6235 
6236 /*.......................................................................
6237  * Read getline configuration information from a given file.
6238  *
6239  * Input:
6240  *  gl           GetLine *  The getline resource object.
6241  *  filename  const char *  The name of the file to read configuration
6242  *                          information from. The contents of this file
6243  *                          are as described in the gl_get_line(3) man
6244  *                          page for the default ~/.teclarc configuration
6245  *                          file.
6246  *  who         KtBinder    Who bindings are to be installed for.
6247  * Output:
6248  *  return           int    0 - OK.
6249  *                          1 - Irrecoverable error.
6250  */
_gl_read_config_file(GetLine * gl,const char * filename,KtBinder who)6251 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who)
6252 {
6253 /*
6254  * If filesystem access is to be excluded, configuration files can't
6255  * be read.
6256  */
6257 #ifdef WITHOUT_FILE_SYSTEM
6258   _err_record_msg(gl->err,
6259 		  "Can't read configuration files without filesystem access",
6260 		  END_ERR_MSG);
6261   errno = EINVAL;
6262   return 1;
6263 #else
6264   FileExpansion *expansion; /* The expansion of the filename */
6265   FILE *fp;                 /* The opened file */
6266   int waserr = 0;           /* True if an error occurred while reading */
6267   int lineno = 1;           /* The line number being processed */
6268 /*
6269  * Check the arguments.
6270  */
6271   if(!gl || !filename) {
6272     if(gl)
6273       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6274     errno = EINVAL;
6275     return 1;
6276   };
6277 /*
6278  * Expand the filename.
6279  */
6280   expansion = ef_expand_file(gl->ef, filename, -1);
6281   if(!expansion) {
6282     gl_print_info(gl, "Unable to expand ", filename, " (",
6283 		  ef_last_error(gl->ef), ").", GL_END_INFO);
6284     return 1;
6285   };
6286 /*
6287  * Attempt to open the file.
6288  */
6289   fp = fopen(expansion->files[0], "r");
6290 /*
6291  * It isn't an error for there to be no configuration file.
6292  */
6293   if(!fp)
6294     return 0;
6295 /*
6296  * Parse the contents of the file.
6297  */
6298   while(!waserr && !feof(fp))
6299     waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who,
6300 				   &lineno);
6301 /*
6302  * Bind action functions to the terminal-specific arrow keys.
6303  */
6304   if(_gl_bind_arrow_keys(gl))
6305     return 1;
6306 /*
6307  * Clean up.
6308  */
6309   (void) fclose(fp);
6310   return waserr;
6311 #endif
6312 }
6313 
6314 /*.......................................................................
6315  * Read GetLine configuration information from a string. The contents of
6316  * the string are the same as those described in the gl_get_line(3)
6317  * man page for the contents of the ~/.teclarc configuration file.
6318  */
_gl_read_config_string(GetLine * gl,const char * buffer,KtBinder who)6319 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who)
6320 {
6321   const char *bptr;         /* A pointer into buffer[] */
6322   int waserr = 0;           /* True if an error occurred while reading */
6323   int lineno = 1;           /* The line number being processed */
6324 /*
6325  * Check the arguments.
6326  */
6327   if(!gl || !buffer) {
6328     if(gl)
6329       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6330     errno = EINVAL;
6331     return 1;
6332   };
6333 /*
6334  * Get a pointer to the start of the buffer.
6335  */
6336   bptr = buffer;
6337 /*
6338  * Parse the contents of the buffer.
6339  */
6340   while(!waserr && *bptr)
6341     waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno);
6342 /*
6343  * Bind action functions to the terminal-specific arrow keys.
6344  */
6345   if(_gl_bind_arrow_keys(gl))
6346     return 1;
6347   return waserr;
6348 }
6349 
6350 /*.......................................................................
6351  * Parse the next line of a getline configuration file.
6352  *
6353  * Input:
6354  *  gl         GetLine *  The getline resource object.
6355  *  stream        void *  The pointer representing the stream to be read
6356  *                        by getc_fn().
6357  *  getc_fn  GlcGetcFn *  A callback function which when called with
6358  *                       'stream' as its argument, returns the next
6359  *                        unread character from the stream.
6360  *  origin  const char *  The name of the entity being read (eg. a
6361  *                        file name).
6362  *  who       KtBinder    Who bindings are to be installed for.
6363  * Input/Output:
6364  *  lineno         int *  The line number being processed is to be
6365  *                        maintained in *lineno.
6366  * Output:
6367  *  return         int    0 - OK.
6368  *                        1 - Irrecoverable error.
6369  */
_gl_parse_config_line(GetLine * gl,void * stream,GlcGetcFn * getc_fn,const char * origin,KtBinder who,int * lineno)6370 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
6371 				 const char *origin, KtBinder who, int *lineno)
6372 {
6373   char buffer[GL_CONF_BUFLEN+1];  /* The input line buffer */
6374   char *argv[GL_CONF_MAXARG];     /* The argument list */
6375   int argc = 0;                   /* The number of arguments in argv[] */
6376   int c;                          /* A character from the file */
6377   int escaped = 0;                /* True if the next character is escaped */
6378   int i;
6379 /*
6380  * Skip spaces and tabs.
6381  */
6382   do c = getc_fn(stream); while(c==' ' || c=='\t');
6383 /*
6384  * Comments extend to the end of the line.
6385  */
6386   if(c=='#')
6387     do c = getc_fn(stream); while(c != '\n' && c != EOF);
6388 /*
6389  * Ignore empty lines.
6390  */
6391   if(c=='\n' || c==EOF) {
6392     (*lineno)++;
6393     return 0;
6394   };
6395 /*
6396  * Record the buffer location of the start of the first argument.
6397  */
6398   argv[argc] = buffer;
6399 /*
6400  * Read the rest of the line, stopping early if a comment is seen, or
6401  * the buffer overflows, and replacing sequences of spaces with a
6402  * '\0', and recording the thus terminated string as an argument.
6403  */
6404   i = 0;
6405   while(i<GL_CONF_BUFLEN) {
6406 /*
6407  * Did we hit the end of the latest argument?
6408  */
6409     if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) {
6410 /*
6411  * Terminate the argument.
6412  */
6413       buffer[i++] = '\0';
6414       argc++;
6415 /*
6416  * Skip spaces and tabs.
6417  */
6418       while(c==' ' || c=='\t')
6419 	c = getc_fn(stream);
6420 /*
6421  * If we hit the end of the line, or the start of a comment, exit the loop.
6422  */
6423       if(c==EOF || c=='\n' || c=='#')
6424 	break;
6425 /*
6426  * Start recording the next argument.
6427  */
6428       if(argc >= GL_CONF_MAXARG) {
6429 	gl_report_config_error(gl, origin, *lineno, "Too many arguments.");
6430 	do c = getc_fn(stream); while(c!='\n' && c!=EOF);  /* Skip past eol */
6431 	return 0;
6432       };
6433       argv[argc] = buffer + i;
6434 /*
6435  * The next character was preceded by spaces, so it isn't escaped.
6436  */
6437       escaped = 0;
6438     } else {
6439 /*
6440  * If we hit an unescaped backslash, this means that we should arrange
6441  * to treat the next character like a simple alphabetical character.
6442  */
6443       if(c=='\\' && !escaped) {
6444 	escaped = 1;
6445 /*
6446  * Splice lines where the newline is escaped.
6447  */
6448       } else if(c=='\n' && escaped) {
6449 	(*lineno)++;
6450 /*
6451  * Record a normal character, preserving any preceding backslash.
6452  */
6453       } else {
6454 	if(escaped)
6455 	  buffer[i++] = '\\';
6456 	if(i>=GL_CONF_BUFLEN)
6457 	  break;
6458 	escaped = 0;
6459 	buffer[i++] = c;
6460       };
6461 /*
6462  * Get the next character.
6463  */
6464       c = getc_fn(stream);
6465     };
6466   };
6467 /*
6468  * Did the buffer overflow?
6469  */
6470   if(i>=GL_CONF_BUFLEN) {
6471     gl_report_config_error(gl, origin, *lineno, "Line too long.");
6472     return 0;
6473   };
6474 /*
6475  * The first argument should be a command name.
6476  */
6477   if(strcmp(argv[0], "bind") == 0) {
6478     const char *action = NULL; /* A NULL action removes a keybinding */
6479     const char *keyseq = NULL;
6480     switch(argc) {
6481     case 3:
6482       action = argv[2];
6483     case 2:              /* Note the intentional fallthrough */
6484       keyseq = argv[1];
6485 /*
6486  * Attempt to record the new keybinding.
6487  */
6488       if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) {
6489 	gl_report_config_error(gl, origin, *lineno,
6490 			       _kt_last_error(gl->bindings));
6491       };
6492       break;
6493     default:
6494       gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments.");
6495     };
6496   } else if(strcmp(argv[0], "edit-mode") == 0) {
6497     if(argc == 2 && strcmp(argv[1], "emacs") == 0) {
6498       gl_change_editor(gl, GL_EMACS_MODE);
6499     } else if(argc == 2 && strcmp(argv[1], "vi") == 0) {
6500       gl_change_editor(gl, GL_VI_MODE);
6501     } else if(argc == 2 && strcmp(argv[1], "none") == 0) {
6502       gl_change_editor(gl, GL_NO_EDITOR);
6503     } else {
6504       gl_report_config_error(gl, origin, *lineno,
6505 			     "The argument of editor should be vi or emacs.");
6506     };
6507   } else if(strcmp(argv[0], "nobeep") == 0) {
6508     gl->silence_bell = 1;
6509   } else {
6510     gl_report_config_error(gl, origin, *lineno, "Unknown command name.");
6511   };
6512 /*
6513  * Skip any trailing comment.
6514  */
6515   while(c != '\n' && c != EOF)
6516     c = getc_fn(stream);
6517   (*lineno)++;
6518   return 0;
6519 }
6520 
6521 /*.......................................................................
6522  * This is a private function of _gl_parse_config_line() which prints
6523  * out an error message about the contents of the line, prefixed by the
6524  * name of the origin of the line and its line number.
6525  *
6526  * Input:
6527  *  gl         GetLine *  The resource object of gl_get_line().
6528  *  origin  const char *  The name of the entity being read (eg. a
6529  *                        file name).
6530  *  lineno         int    The line number at which the error occurred.
6531  *  errmsg  const char *  The error message.
6532  * Output:
6533  *  return         int    0 - OK.
6534  *                        1 - Error.
6535  */
gl_report_config_error(GetLine * gl,const char * origin,int lineno,const char * errmsg)6536 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
6537 				  const char *errmsg)
6538 {
6539   char lnum[20];   /* A buffer in which to render a single integer */
6540 /*
6541  * Convert the line number into a string.
6542  */
6543   snprintf(lnum, sizeof(lnum), "%d", lineno);
6544 /*
6545  * Have the string printed on the terminal.
6546  */
6547   return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO);
6548 }
6549 
6550 /*.......................................................................
6551  * This is the _gl_parse_config_line() callback function which reads the
6552  * next character from a configuration file.
6553  */
GLC_GETC_FN(glc_file_getc)6554 static GLC_GETC_FN(glc_file_getc)
6555 {
6556   return fgetc((FILE *) stream);
6557 }
6558 
6559 /*.......................................................................
6560  * This is the _gl_parse_config_line() callback function which reads the
6561  * next character from a buffer. Its stream argument is a pointer to a
6562  * variable which is, in turn, a pointer into the buffer being read from.
6563  */
GLC_GETC_FN(glc_buff_getc)6564 static GLC_GETC_FN(glc_buff_getc)
6565 {
6566   const char **lptr = (char const **) stream;
6567   return **lptr ? *(*lptr)++ : EOF;
6568 }
6569 
6570 #ifndef HIDE_FILE_SYSTEM
6571 /*.......................................................................
6572  * When this action is triggered, it arranges to temporarily read command
6573  * lines from the regular file whos name precedes the cursor.
6574  * The current line is first discarded.
6575  */
KT_KEY_FN(gl_read_from_file)6576 static KT_KEY_FN(gl_read_from_file)
6577 {
6578   char *start_path;       /* The pointer to the start of the pathname in */
6579                           /*  gl->line[]. */
6580   FileExpansion *result;  /* The results of the filename expansion */
6581   int pathlen;            /* The length of the pathname being expanded */
6582 /*
6583  * Locate the start of the filename that precedes the cursor position.
6584  */
6585   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
6586   if(!start_path)
6587     return 1;
6588 /*
6589  * Get the length of the pathname string.
6590  */
6591   pathlen = gl->buff_curpos - (start_path - gl->line);
6592 /*
6593  * Attempt to expand the pathname.
6594  */
6595   result = ef_expand_file(gl->ef, start_path, pathlen);
6596 /*
6597  * If there was an error, report the error on a new line.
6598  */
6599   if(!result) {
6600     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
6601 /*
6602  * If no files matched, report this as well.
6603  */
6604   } else if(result->nfile == 0 || !result->exists) {
6605     return gl_print_info(gl, "No files match.", GL_END_INFO);
6606 /*
6607  * Complain if more than one file matches.
6608  */
6609   } else if(result->nfile > 1) {
6610     return gl_print_info(gl, "More than one file matches.", GL_END_INFO);
6611 /*
6612  * Disallow input from anything but normal files. In principle we could
6613  * also support input from named pipes. Terminal files would be a problem
6614  * since we wouldn't know the terminal type, and other types of files
6615  * might cause the library to lock up.
6616  */
6617   } else if(!_pu_path_is_file(result->files[0])) {
6618     return gl_print_info(gl, "Not a normal file.", GL_END_INFO);
6619   } else {
6620 /*
6621  * Attempt to open and install the specified file for reading.
6622  */
6623     gl->file_fp = fopen(result->files[0], "r");
6624     if(!gl->file_fp) {
6625       return gl_print_info(gl, "Unable to open: ", result->files[0],
6626 			   GL_END_INFO);
6627     };
6628 /*
6629  * If needed, expand the record of the maximum file-descriptor that might
6630  * need to be monitored with select().
6631  */
6632 #ifdef HAVE_SELECT
6633     if(fileno(gl->file_fp) > gl->max_fd)
6634       gl->max_fd = fileno(gl->file_fp);
6635 #endif
6636 /*
6637  * Is non-blocking I/O needed?
6638  */
6639     if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE &&
6640        gl_nonblocking_io(gl, fileno(gl->file_fp))) {
6641       gl_revert_input(gl);
6642       return gl_print_info(gl, "Can't read file %s with non-blocking I/O",
6643 			   result->files[0]);
6644     };
6645 /*
6646  * Inform the user what is happening.
6647  */
6648     if(gl_print_info(gl, "<Taking input from ", result->files[0], ">",
6649 		     GL_END_INFO))
6650       return 1;
6651   };
6652   return 0;
6653 }
6654 #endif
6655 
6656 /*.......................................................................
6657  * Close any temporary file that is being used for input.
6658  *
6659  * Input:
6660  *  gl     GetLine *  The getline resource object.
6661  */
gl_revert_input(GetLine * gl)6662 static void gl_revert_input(GetLine *gl)
6663 {
6664   if(gl->file_fp)
6665     fclose(gl->file_fp);
6666   gl->file_fp = NULL;
6667   gl->endline = 1;
6668 }
6669 
6670 /*.......................................................................
6671  * This is the action function that recalls the oldest line in the
6672  * history buffer.
6673  */
KT_KEY_FN(gl_beginning_of_history)6674 static KT_KEY_FN(gl_beginning_of_history)
6675 {
6676 /*
6677  * In vi mode, switch to command mode, since the user is very
6678  * likely to want to move around newly recalled lines.
6679  */
6680   gl_vi_command_mode(gl);
6681 /*
6682  * Forget any previous recall session.
6683  */
6684   gl->preload_id = 0;
6685 /*
6686  * Record the key sequence number of this search action.
6687  */
6688   gl->last_search = gl->keyseq_count;
6689 /*
6690  * Recall the next oldest line in the history list.
6691  */
6692   if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6693     return 0;
6694 /*
6695  * Accomodate the new contents of gl->line[].
6696  */
6697   gl_update_buffer(gl);
6698 /*
6699  * Arrange to have the cursor placed at the end of the new line.
6700  */
6701   gl->buff_curpos = gl->ntotal;
6702 /*
6703  * Erase and display the new line.
6704  */
6705   gl_queue_redisplay(gl);
6706   return 0;
6707 }
6708 
6709 /*.......................................................................
6710  * If a history session is currently in progress, this action function
6711  * recalls the line that was being edited when the session started. If
6712  * no history session is in progress, it does nothing.
6713  */
KT_KEY_FN(gl_end_of_history)6714 static KT_KEY_FN(gl_end_of_history)
6715 {
6716 /*
6717  * In vi mode, switch to command mode, since the user is very
6718  * likely to want to move around newly recalled lines.
6719  */
6720   gl_vi_command_mode(gl);
6721 /*
6722  * Forget any previous recall session.
6723  */
6724   gl->preload_id = 0;
6725 /*
6726  * Record the key sequence number of this search action.
6727  */
6728   gl->last_search = gl->keyseq_count;
6729 /*
6730  * Recall the next oldest line in the history list.
6731  */
6732   if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6733     return 0;
6734 /*
6735  * Accomodate the new contents of gl->line[].
6736  */
6737   gl_update_buffer(gl);
6738 /*
6739  * Arrange to have the cursor placed at the end of the new line.
6740  */
6741   gl->buff_curpos = gl->ntotal;
6742 /*
6743  * Erase and display the new line.
6744  */
6745   gl_queue_redisplay(gl);
6746   return 0;
6747 }
6748 
6749 /*.......................................................................
6750  * This action function is treated specially, in that its count argument
6751  * is set to the end keystroke of the keysequence that activated it.
6752  * It accumulates a numeric argument, adding one digit on each call in
6753  * which the last keystroke was a numeric digit.
6754  */
KT_KEY_FN(gl_digit_argument)6755 static KT_KEY_FN(gl_digit_argument)
6756 {
6757 /*
6758  * Was the last keystroke a digit?
6759  */
6760   int is_digit = isdigit((int)(unsigned char) count);
6761 /*
6762  * In vi command mode, a lone '0' means goto-start-of-line.
6763  */
6764   if(gl->vi.command && gl->number < 0 && count == '0')
6765     return gl_beginning_of_line(gl, count, NULL);
6766 /*
6767  * Are we starting to accumulate a new number?
6768  */
6769   if(gl->number < 0 || !is_digit)
6770     gl->number = 0;
6771 /*
6772  * Was the last keystroke a digit?
6773  */
6774   if(is_digit) {
6775 /*
6776  * Read the numeric value of the digit, without assuming ASCII.
6777  */
6778     int n;
6779     char s[2]; s[0] = count; s[1] = '\0';
6780     n = atoi(s);
6781 /*
6782  * Append the new digit.
6783  */
6784     gl->number = gl->number * 10 + n;
6785   };
6786   return 0;
6787 }
6788 
6789 /*.......................................................................
6790  * The newline action function sets gl->endline to tell
6791  * gl_get_input_line() that the line is now complete.
6792  */
KT_KEY_FN(gl_newline)6793 static KT_KEY_FN(gl_newline)
6794 {
6795   GlhLineID id;    /* The last history line recalled while entering this line */
6796 /*
6797  * Flag the line as ended.
6798  */
6799   gl->endline = 1;
6800 /*
6801  * Record the next position in the history buffer, for potential
6802  * recall by an action function on the next call to gl_get_line().
6803  */
6804   id = _glh_line_id(gl->glh, 1);
6805   if(id)
6806     gl->preload_id = id;
6807   return 0;
6808 }
6809 
6810 /*.......................................................................
6811  * The 'repeat' action function sets gl->endline to tell
6812  * gl_get_input_line() that the line is now complete, and records the
6813  * ID of the next history line in gl->preload_id so that the next call
6814  * to gl_get_input_line() will preload the line with that history line.
6815  */
KT_KEY_FN(gl_repeat_history)6816 static KT_KEY_FN(gl_repeat_history)
6817 {
6818   gl->endline = 1;
6819   gl->preload_id = _glh_line_id(gl->glh, 1);
6820   gl->preload_history = 1;
6821   return 0;
6822 }
6823 
6824 /*.......................................................................
6825  * Flush unwritten characters to the terminal.
6826  *
6827  * Input:
6828  *  gl     GetLine *  The getline resource object.
6829  * Output:
6830  *  return     int    0 - OK.
6831  *                    1 - Either an error occured, or the output
6832  *                        blocked and non-blocking I/O is being used.
6833  *                        See gl->rtn_status for details.
6834  */
gl_flush_output(GetLine * gl)6835 static int gl_flush_output(GetLine *gl)
6836 {
6837 /*
6838  * Record the fact that we are about to write to the terminal.
6839  */
6840   gl->pending_io = GLP_WRITE;
6841 /*
6842  * Attempt to flush the output to the terminal.
6843  */
6844   errno = 0;
6845   switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) {
6846   case GLQ_FLUSH_DONE:
6847     return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL);
6848     break;
6849   case GLQ_FLUSH_AGAIN:      /* Output blocked */
6850     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
6851     return 1;
6852     break;
6853   default:                   /* Abort the line if an error occurs */
6854     gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno);
6855     return 1;
6856     break;
6857   };
6858 }
6859 
6860 /*.......................................................................
6861  * This is the callback which _glq_flush_queue() uses to write buffered
6862  * characters to the terminal.
6863  */
GL_WRITE_FN(gl_flush_terminal)6864 static GL_WRITE_FN(gl_flush_terminal)
6865 {
6866   int ndone = 0;    /* The number of characters written so far */
6867 /*
6868  * Get the line-editor resource object.
6869  */
6870   GetLine *gl = (GetLine *) data;
6871 /*
6872  * Transfer the latest array of characters to stdio.
6873  */
6874   while(ndone < n) {
6875     int nnew = write(gl->output_fd, s, n-ndone);
6876 /*
6877  * If the write was successful, add to the recorded number of bytes
6878  * that have now been written.
6879  */
6880     if(nnew > 0) {
6881       ndone += nnew;
6882 /*
6883  * If a signal interrupted the call, restart the write(), since all of
6884  * the signals that gl_get_line() has been told to watch for are
6885  * currently blocked.
6886  */
6887     } else if(errno == EINTR) {
6888       continue;
6889 /*
6890  * If we managed to write something before an I/O error occurred, or
6891  * output blocked before anything was written, report the number of
6892  * bytes that were successfully written before this happened.
6893  */
6894     } else if(ndone > 0
6895 #if defined(EAGAIN)
6896 	      || errno==EAGAIN
6897 #endif
6898 #if defined(EWOULDBLOCK)
6899 	      || errno==EWOULDBLOCK
6900 #endif
6901 	      ) {
6902       return ndone;
6903 
6904 /*
6905  * To get here, an error must have occurred before anything new could
6906  * be written.
6907  */
6908     } else {
6909       return -1;
6910     };
6911   };
6912 /*
6913  * To get here, we must have successfully written the number of
6914  * bytes that was specified.
6915  */
6916   return n;
6917 }
6918 
6919 /*.......................................................................
6920  * Change the style of editing to emulate a given editor.
6921  *
6922  * Input:
6923  *  gl       GetLine *  The getline resource object.
6924  *  editor  GlEditor    The type of editor to emulate.
6925  * Output:
6926  *  return       int    0 - OK.
6927  *                      1 - Error.
6928  */
gl_change_editor(GetLine * gl,GlEditor editor)6929 static int gl_change_editor(GetLine *gl, GlEditor editor)
6930 {
6931 /*
6932  * Install the default key-bindings of the requested editor.
6933  */
6934   switch(editor) {
6935   case GL_EMACS_MODE:
6936     _kt_clear_bindings(gl->bindings, KTB_NORM);
6937     _kt_clear_bindings(gl->bindings, KTB_TERM);
6938     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings,
6939 		   sizeof(gl_emacs_bindings)/sizeof(gl_emacs_bindings[0]));
6940     break;
6941   case GL_VI_MODE:
6942     _kt_clear_bindings(gl->bindings, KTB_NORM);
6943     _kt_clear_bindings(gl->bindings, KTB_TERM);
6944     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings,
6945 			    sizeof(gl_vi_bindings)/sizeof(gl_vi_bindings[0]));
6946     break;
6947   case GL_NO_EDITOR:
6948     break;
6949   default:
6950     _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG);
6951     errno = EINVAL;
6952     return 1;
6953   };
6954 /*
6955  * Record the new editing mode.
6956  */
6957   gl->editor = editor;
6958   gl->vi.command = 0;     /* Start in input mode */
6959   gl->insert_curpos = 0;
6960 /*
6961  * Reinstate terminal-specific bindings.
6962  */
6963   if(gl->editor != GL_NO_EDITOR && gl->input_fp)
6964     (void) gl_bind_terminal_keys(gl);
6965   return 0;
6966 }
6967 
6968 /*.......................................................................
6969  * This is an action function that switches to editing using emacs bindings
6970  */
KT_KEY_FN(gl_emacs_editing_mode)6971 static KT_KEY_FN(gl_emacs_editing_mode)
6972 {
6973   return gl_change_editor(gl, GL_EMACS_MODE);
6974 }
6975 
6976 /*.......................................................................
6977  * This is an action function that switches to editing using vi bindings
6978  */
KT_KEY_FN(gl_vi_editing_mode)6979 static KT_KEY_FN(gl_vi_editing_mode)
6980 {
6981   return gl_change_editor(gl, GL_VI_MODE);
6982 }
6983 
6984 /*.......................................................................
6985  * This is the action function that switches to insert mode.
6986  */
KT_KEY_FN(gl_vi_insert)6987 static KT_KEY_FN(gl_vi_insert)
6988 {
6989 /*
6990  * If in vi command mode, preserve the current line for potential
6991  * use by vi-undo.
6992  */
6993   gl_save_for_undo(gl);
6994 /*
6995  * Switch to vi insert mode.
6996  */
6997   gl->insert = 1;
6998   gl->vi.command = 0;
6999   gl->insert_curpos = gl->buff_curpos;
7000   return 0;
7001 }
7002 
7003 /*.......................................................................
7004  * This is an action function that switches to overwrite mode.
7005  */
KT_KEY_FN(gl_vi_overwrite)7006 static KT_KEY_FN(gl_vi_overwrite)
7007 {
7008 /*
7009  * If in vi command mode, preserve the current line for potential
7010  * use by vi-undo.
7011  */
7012   gl_save_for_undo(gl);
7013 /*
7014  * Switch to vi overwrite mode.
7015  */
7016   gl->insert = 0;
7017   gl->vi.command = 0;
7018   gl->insert_curpos = gl->buff_curpos;
7019   return 0;
7020 }
7021 
7022 /*.......................................................................
7023  * This action function toggles the case of the character under the
7024  * cursor.
7025  */
KT_KEY_FN(gl_change_case)7026 static KT_KEY_FN(gl_change_case)
7027 {
7028   int i;
7029 /*
7030  * Keep a record of the current insert mode and the cursor position.
7031  */
7032   int insert = gl->insert;
7033 /*
7034  * If in vi command mode, preserve the current line for potential
7035  * use by vi-undo.
7036  */
7037   gl_save_for_undo(gl);
7038 /*
7039  * We want to overwrite the modified word.
7040  */
7041   gl->insert = 0;
7042 /*
7043  * Toggle the case of 'count' characters.
7044  */
7045   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
7046     char *cptr = gl->line + gl->buff_curpos++;
7047 /*
7048  * Convert the character to upper case?
7049  */
7050     if(islower((int)(unsigned char) *cptr))
7051       gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
7052     else if(isupper((int)(unsigned char) *cptr))
7053       gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
7054 /*
7055  * Write the possibly modified character back. Note that for non-modified
7056  * characters we want to do this as well, so as to advance the cursor.
7057  */
7058       if(gl_print_char(gl, *cptr, cptr[1]))
7059 	return 1;
7060   };
7061 /*
7062  * Restore the insertion mode.
7063  */
7064   gl->insert = insert;
7065   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7066 }
7067 
7068 /*.......................................................................
7069  * This is the action function which implements the vi-style action which
7070  * moves the cursor to the start of the line, then switches to insert mode.
7071  */
KT_KEY_FN(gl_vi_insert_at_bol)7072 static KT_KEY_FN(gl_vi_insert_at_bol)
7073 {
7074   gl_save_for_undo(gl);
7075   return gl_beginning_of_line(gl, 0, NULL) ||
7076          gl_vi_insert(gl, 0, NULL);
7077 
7078 }
7079 
7080 /*.......................................................................
7081  * This is the action function which implements the vi-style action which
7082  * moves the cursor to the end of the line, then switches to insert mode
7083  * to allow text to be appended to the line.
7084  */
KT_KEY_FN(gl_vi_append_at_eol)7085 static KT_KEY_FN(gl_vi_append_at_eol)
7086 {
7087   gl_save_for_undo(gl);
7088   gl->vi.command = 0;	/* Allow cursor at EOL */
7089   return gl_end_of_line(gl, 0, NULL) ||
7090          gl_vi_insert(gl, 0, NULL);
7091 }
7092 
7093 /*.......................................................................
7094  * This is the action function which implements the vi-style action which
7095  * moves the cursor to right one then switches to insert mode, thus
7096  * allowing text to be appended after the next character.
7097  */
KT_KEY_FN(gl_vi_append)7098 static KT_KEY_FN(gl_vi_append)
7099 {
7100   gl_save_for_undo(gl);
7101   gl->vi.command = 0;	/* Allow cursor at EOL */
7102   return gl_cursor_right(gl, 1, NULL) ||
7103          gl_vi_insert(gl, 0, NULL);
7104 }
7105 
7106 /*.......................................................................
7107  * This action function moves the cursor to the column specified by the
7108  * numeric argument. Column indexes start at 1.
7109  */
KT_KEY_FN(gl_goto_column)7110 static KT_KEY_FN(gl_goto_column)
7111 {
7112   return gl_place_cursor(gl, count - 1);
7113 }
7114 
7115 /*.......................................................................
7116  * Starting with the character under the cursor, replace 'count'
7117  * characters with the next character that the user types.
7118  */
KT_KEY_FN(gl_vi_replace_char)7119 static KT_KEY_FN(gl_vi_replace_char)
7120 {
7121   char c;  /* The replacement character */
7122   int i;
7123 /*
7124  * Keep a record of the current insert mode.
7125  */
7126   int insert = gl->insert;
7127 /*
7128  * Get the replacement character.
7129  */
7130   if(gl->vi.repeat.active) {
7131     c = gl->vi.repeat.input_char;
7132   } else {
7133     if(gl_read_terminal(gl, 1, &c))
7134       return 1;
7135     gl->vi.repeat.input_char = c;
7136   };
7137 /*
7138  * Are there 'count' characters to be replaced?
7139  */
7140   if(gl->ntotal - gl->buff_curpos >= count) {
7141 /*
7142  * If in vi command mode, preserve the current line for potential
7143  * use by vi-undo.
7144  */
7145     gl_save_for_undo(gl);
7146 /*
7147  * Temporarily switch to overwrite mode.
7148  */
7149     gl->insert = 0;
7150 /*
7151  * Overwrite the current character plus count-1 subsequent characters
7152  * with the replacement character.
7153  */
7154     for(i=0; i<count; i++)
7155       gl_add_char_to_line(gl, c);
7156 /*
7157  * Restore the original insert/overwrite mode.
7158  */
7159     gl->insert = insert;
7160   };
7161   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7162 }
7163 
7164 /*.......................................................................
7165  * This is an action function which changes all characters between the
7166  * current cursor position and the end of the line.
7167  */
KT_KEY_FN(gl_vi_change_rest_of_line)7168 static KT_KEY_FN(gl_vi_change_rest_of_line)
7169 {
7170   gl_save_for_undo(gl);
7171   gl->vi.command = 0;	/* Allow cursor at EOL */
7172   return gl_kill_line(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7173 }
7174 
7175 /*.......................................................................
7176  * This is an action function which changes all characters between the
7177  * start of the line and the current cursor position.
7178  */
KT_KEY_FN(gl_vi_change_to_bol)7179 static KT_KEY_FN(gl_vi_change_to_bol)
7180 {
7181   return gl_backward_kill_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7182 }
7183 
7184 /*.......................................................................
7185  * This is an action function which deletes the entire contents of the
7186  * current line and switches to insert mode.
7187  */
KT_KEY_FN(gl_vi_change_line)7188 static KT_KEY_FN(gl_vi_change_line)
7189 {
7190   return gl_delete_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7191 }
7192 
7193 /*.......................................................................
7194  * Starting from the cursor position and looking towards the end of the
7195  * line, copy 'count' characters to the cut buffer.
7196  */
KT_KEY_FN(gl_forward_copy_char)7197 static KT_KEY_FN(gl_forward_copy_char)
7198 {
7199 /*
7200  * Limit the count to the number of characters available.
7201  */
7202   if(gl->buff_curpos + count >= gl->ntotal)
7203     count = gl->ntotal - gl->buff_curpos;
7204   if(count < 0)
7205     count = 0;
7206 /*
7207  * Copy the characters to the cut buffer.
7208  */
7209   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7210   gl->cutbuf[count] = '\0';
7211   return 0;
7212 }
7213 
7214 /*.......................................................................
7215  * Starting from the character before the cursor position and looking
7216  * backwards towards the start of the line, copy 'count' characters to
7217  * the cut buffer.
7218  */
KT_KEY_FN(gl_backward_copy_char)7219 static KT_KEY_FN(gl_backward_copy_char)
7220 {
7221 /*
7222  * Limit the count to the number of characters available.
7223  */
7224   if(count > gl->buff_curpos)
7225     count = gl->buff_curpos;
7226   if(count < 0)
7227     count = 0;
7228   gl_place_cursor(gl, gl->buff_curpos - count);
7229 /*
7230  * Copy the characters to the cut buffer.
7231  */
7232   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7233   gl->cutbuf[count] = '\0';
7234   return 0;
7235 }
7236 
7237 /*.......................................................................
7238  * Starting from the cursor position copy to the specified column into the
7239  * cut buffer.
7240  */
KT_KEY_FN(gl_copy_to_column)7241 static KT_KEY_FN(gl_copy_to_column)
7242 {
7243   if (--count >= gl->buff_curpos)
7244     return gl_forward_copy_char(gl, count - gl->buff_curpos, NULL);
7245   else
7246     return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL);
7247 }
7248 
7249 /*.......................................................................
7250  * Starting from the cursor position copy characters up to a matching
7251  * parenthesis into the cut buffer.
7252  */
KT_KEY_FN(gl_copy_to_parenthesis)7253 static KT_KEY_FN(gl_copy_to_parenthesis)
7254 {
7255   int curpos = gl_index_of_matching_paren(gl);
7256   if(curpos >= 0) {
7257     gl_save_for_undo(gl);
7258     if(curpos >= gl->buff_curpos)
7259       return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1, NULL);
7260     else
7261       return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
7262   };
7263   return 0;
7264 }
7265 
7266 /*.......................................................................
7267  * Starting from the cursor position copy the rest of the line into the
7268  * cut buffer.
7269  */
KT_KEY_FN(gl_copy_rest_of_line)7270 static KT_KEY_FN(gl_copy_rest_of_line)
7271 {
7272 /*
7273  * Copy the characters to the cut buffer.
7274  */
7275   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos);
7276   gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0';
7277   return 0;
7278 }
7279 
7280 /*.......................................................................
7281  * Copy from the beginning of the line to the cursor position into the
7282  * cut buffer.
7283  */
KT_KEY_FN(gl_copy_to_bol)7284 static KT_KEY_FN(gl_copy_to_bol)
7285 {
7286 /*
7287  * Copy the characters to the cut buffer.
7288  */
7289   memcpy(gl->cutbuf, gl->line, gl->buff_curpos);
7290   gl->cutbuf[gl->buff_curpos] = '\0';
7291   gl_place_cursor(gl, 0);
7292   return 0;
7293 }
7294 
7295 /*.......................................................................
7296  * Copy the entire line into the cut buffer.
7297  */
KT_KEY_FN(gl_copy_line)7298 static KT_KEY_FN(gl_copy_line)
7299 {
7300 /*
7301  * Copy the characters to the cut buffer.
7302  */
7303   memcpy(gl->cutbuf, gl->line, gl->ntotal);
7304   gl->cutbuf[gl->ntotal] = '\0';
7305   return 0;
7306 }
7307 
7308 /*.......................................................................
7309  * Search forwards for the next character that the user enters.
7310  */
KT_KEY_FN(gl_forward_find_char)7311 static KT_KEY_FN(gl_forward_find_char)
7312 {
7313   int pos = gl_find_char(gl, count, 1, 1, '\0');
7314   return pos >= 0 && gl_place_cursor(gl, pos);
7315 }
7316 
7317 /*.......................................................................
7318  * Search backwards for the next character that the user enters.
7319  */
KT_KEY_FN(gl_backward_find_char)7320 static KT_KEY_FN(gl_backward_find_char)
7321 {
7322   int pos = gl_find_char(gl, count, 0, 1, '\0');
7323   return pos >= 0 && gl_place_cursor(gl, pos);
7324 }
7325 
7326 /*.......................................................................
7327  * Search forwards for the next character that the user enters. Move up to,
7328  * but not onto, the found character.
7329  */
KT_KEY_FN(gl_forward_to_char)7330 static KT_KEY_FN(gl_forward_to_char)
7331 {
7332   int pos = gl_find_char(gl, count, 1, 0, '\0');
7333   return pos >= 0 && gl_place_cursor(gl, pos);
7334 }
7335 
7336 /*.......................................................................
7337  * Search backwards for the next character that the user enters. Move back to,
7338  * but not onto, the found character.
7339  */
KT_KEY_FN(gl_backward_to_char)7340 static KT_KEY_FN(gl_backward_to_char)
7341 {
7342   int pos = gl_find_char(gl, count, 0, 0, '\0');
7343   return pos >= 0 && gl_place_cursor(gl, pos);
7344 }
7345 
7346 /*.......................................................................
7347  * Searching in a given direction, return the index of a given (or
7348  * read) character in the input line, or the character that precedes
7349  * it in the specified search direction. Return -1 if not found.
7350  *
7351  * Input:
7352  *  gl       GetLine *  The getline resource object.
7353  *  count        int    The number of times to search.
7354  *  forward      int    True if searching forward.
7355  *  onto         int    True if the search should end on top of the
7356  *                      character, false if the search should stop
7357  *                      one character before the character in the
7358  *                      specified search direction.
7359  *  c           char    The character to be sought, or '\0' if the
7360  *                      character should be read from the user.
7361  * Output:
7362  *  return       int    The index of the character in gl->line[], or
7363  *                      -1 if not found.
7364  */
gl_find_char(GetLine * gl,int count,int forward,int onto,char c)7365 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c)
7366 {
7367   int pos;     /* The index reached in searching the input line */
7368   int i;
7369 /*
7370  * Get a character from the user?
7371  */
7372   if(!c) {
7373 /*
7374  * If we are in the process of repeating a previous change command, substitute
7375  * the last find character.
7376  */
7377     if(gl->vi.repeat.active) {
7378       c = gl->vi.find_char;
7379     } else {
7380       if(gl_read_terminal(gl, 1, &c))
7381 	return -1;
7382 /*
7383  * Record the details of the new search, for use by repeat finds.
7384  */
7385       gl->vi.find_forward = forward;
7386       gl->vi.find_onto = onto;
7387       gl->vi.find_char = c;
7388     };
7389   };
7390 /*
7391  * Which direction should we search?
7392  */
7393   if(forward) {
7394 /*
7395  * Search forwards 'count' times for the character, starting with the
7396  * character that follows the cursor.
7397  */
7398     for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) {
7399 /*
7400  * Advance past the last match (or past the current cursor position
7401  * on the first search).
7402  */
7403       pos++;
7404 /*
7405  * Search for the next instance of c.
7406  */
7407       for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++)
7408 	;
7409     };
7410 /*
7411  * If the character was found and we have been requested to return the
7412  * position of the character that precedes the desired character, then
7413  * we have gone one character too far.
7414  */
7415     if(!onto && pos<gl->ntotal)
7416       pos--;
7417   } else {
7418 /*
7419  * Search backwards 'count' times for the character, starting with the
7420  * character that precedes the cursor.
7421  */
7422     for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) {
7423 /*
7424  * Step back one from the last match (or from the current cursor
7425  * position on the first search).
7426  */
7427       pos--;
7428 /*
7429  * Search for the next instance of c.
7430  */
7431       for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--)
7432 	;
7433     };
7434 /*
7435  * If the character was found and we have been requested to return the
7436  * position of the character that precedes the desired character, then
7437  * we have gone one character too far.
7438  */
7439     if(!onto && pos>=gl->insert_curpos)
7440       pos++;
7441   };
7442 /*
7443  * If found, return the cursor position of the count'th match.
7444  * Otherwise ring the terminal bell.
7445  */
7446   if(pos >= gl->insert_curpos && pos < gl->ntotal) {
7447     return pos;
7448   } else {
7449     (void) gl_ring_bell(gl, 1, NULL);
7450     return -1;
7451   }
7452 }
7453 
7454 /*.......................................................................
7455  * Repeat the last character search in the same direction as the last
7456  * search.
7457  */
KT_KEY_FN(gl_repeat_find_char)7458 static KT_KEY_FN(gl_repeat_find_char)
7459 {
7460   int pos = gl->vi.find_char ?
7461     gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto,
7462 		 gl->vi.find_char) : -1;
7463   return pos >= 0 && gl_place_cursor(gl, pos);
7464 }
7465 
7466 /*.......................................................................
7467  * Repeat the last character search in the opposite direction as the last
7468  * search.
7469  */
KT_KEY_FN(gl_invert_refind_char)7470 static KT_KEY_FN(gl_invert_refind_char)
7471 {
7472   int pos = gl->vi.find_char ?
7473     gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto,
7474 		 gl->vi.find_char) : -1;
7475   return pos >= 0 && gl_place_cursor(gl, pos);
7476 }
7477 
7478 /*.......................................................................
7479  * Search forward from the current position of the cursor for 'count'
7480  * word endings, returning the index of the last one found, or the end of
7481  * the line if there were less than 'count' words.
7482  *
7483  * Input:
7484  *  gl       GetLine *  The getline resource object.
7485  *  n            int    The number of word boundaries to search for.
7486  * Output:
7487  *  return       int    The buffer index of the located position.
7488  */
gl_nth_word_end_forward(GetLine * gl,int n)7489 static int gl_nth_word_end_forward(GetLine *gl, int n)
7490 {
7491   int bufpos;   /* The buffer index being checked. */
7492   int i;
7493 /*
7494  * In order to guarantee forward motion to the next word ending,
7495  * we need to start from one position to the right of the cursor
7496  * position, since this may already be at the end of a word.
7497  */
7498   bufpos = gl->buff_curpos + 1;
7499 /*
7500  * If we are at the end of the line, return the index of the last
7501  * real character on the line. Note that this will be -1 if the line
7502  * is empty.
7503  */
7504   if(bufpos >= gl->ntotal)
7505     return gl->ntotal - 1;
7506 /*
7507  * Search 'n' times, unless the end of the input line is reached first.
7508  */
7509   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7510 /*
7511  * If we are not already within a word, skip to the start of the next word.
7512  */
7513     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7514 	bufpos++)
7515       ;
7516 /*
7517  * Find the end of the next word.
7518  */
7519     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7520 	bufpos++)
7521       ;
7522   };
7523 /*
7524  * We will have overshot.
7525  */
7526   return bufpos > 0 ? bufpos-1 : bufpos;
7527 }
7528 
7529 /*.......................................................................
7530  * Search forward from the current position of the cursor for 'count'
7531  * word starts, returning the index of the last one found, or the end of
7532  * the line if there were less than 'count' words.
7533  *
7534  * Input:
7535  *  gl       GetLine *  The getline resource object.
7536  *  n            int    The number of word boundaries to search for.
7537  * Output:
7538  *  return       int    The buffer index of the located position.
7539  */
gl_nth_word_start_forward(GetLine * gl,int n)7540 static int gl_nth_word_start_forward(GetLine *gl, int n)
7541 {
7542   int bufpos;   /* The buffer index being checked. */
7543   int i;
7544 /*
7545  * Get the current cursor position.
7546  */
7547   bufpos = gl->buff_curpos;
7548 /*
7549  * Search 'n' times, unless the end of the input line is reached first.
7550  */
7551   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7552 /*
7553  * Find the end of the current word.
7554  */
7555     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7556 	bufpos++)
7557       ;
7558 /*
7559  * Skip to the start of the next word.
7560  */
7561     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7562 	bufpos++)
7563       ;
7564   };
7565   return bufpos;
7566 }
7567 
7568 /*.......................................................................
7569  * Search backward from the current position of the cursor for 'count'
7570  * word starts, returning the index of the last one found, or the start
7571  * of the line if there were less than 'count' words.
7572  *
7573  * Input:
7574  *  gl       GetLine *  The getline resource object.
7575  *  n            int    The number of word boundaries to search for.
7576  * Output:
7577  *  return       int    The buffer index of the located position.
7578  */
gl_nth_word_start_backward(GetLine * gl,int n)7579 static int gl_nth_word_start_backward(GetLine *gl, int n)
7580 {
7581   int bufpos;   /* The buffer index being checked. */
7582   int i;
7583 /*
7584  * Get the current cursor position.
7585  */
7586   bufpos = gl->buff_curpos;
7587 /*
7588  * Search 'n' times, unless the beginning of the input line (or vi insertion
7589  * point) is reached first.
7590  */
7591   for(i=0; i<n && bufpos > gl->insert_curpos; i++) {
7592 /*
7593  * Starting one character back from the last search, so as not to keep
7594  * settling on the same word-start, search backwards until finding a
7595  * word character.
7596  */
7597     while(--bufpos >= gl->insert_curpos &&
7598           !gl_is_word_char((int)gl->line[bufpos]))
7599       ;
7600 /*
7601  * Find the start of the word.
7602  */
7603     while(--bufpos >= gl->insert_curpos &&
7604           gl_is_word_char((int)gl->line[bufpos]))
7605       ;
7606 /*
7607  * We will have gone one character too far.
7608  */
7609     bufpos++;
7610   };
7611   return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos;
7612 }
7613 
7614 /*.......................................................................
7615  * Copy one or more words into the cut buffer without moving the cursor
7616  * or deleting text.
7617  */
KT_KEY_FN(gl_forward_copy_word)7618 static KT_KEY_FN(gl_forward_copy_word)
7619 {
7620 /*
7621  * Find the location of the count'th start or end of a word
7622  * after the cursor, depending on whether in emacs or vi mode.
7623  */
7624   int next = gl->editor == GL_EMACS_MODE ?
7625     gl_nth_word_end_forward(gl, count) :
7626     gl_nth_word_start_forward(gl, count);
7627 /*
7628  * How many characters are to be copied into the cut buffer?
7629  */
7630   int n = next - gl->buff_curpos;
7631 /*
7632  * Copy the specified segment and terminate the string.
7633  */
7634   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7635   gl->cutbuf[n] = '\0';
7636   return 0;
7637 }
7638 
7639 /*.......................................................................
7640  * Copy one or more words preceding the cursor into the cut buffer,
7641  * without moving the cursor or deleting text.
7642  */
KT_KEY_FN(gl_backward_copy_word)7643 static KT_KEY_FN(gl_backward_copy_word)
7644 {
7645 /*
7646  * Find the location of the count'th start of word before the cursor.
7647  */
7648   int next = gl_nth_word_start_backward(gl, count);
7649 /*
7650  * How many characters are to be copied into the cut buffer?
7651  */
7652   int n = gl->buff_curpos - next;
7653   gl_place_cursor(gl, next);
7654 /*
7655  * Copy the specified segment and terminate the string.
7656  */
7657   memcpy(gl->cutbuf, gl->line + next, n);
7658   gl->cutbuf[n] = '\0';
7659   return 0;
7660 }
7661 
7662 /*.......................................................................
7663  * Copy the characters between the cursor and the count'th instance of
7664  * a specified character in the input line, into the cut buffer.
7665  *
7666  * Input:
7667  *  gl       GetLine *  The getline resource object.
7668  *  count        int    The number of times to search.
7669  *  c           char    The character to be searched for, or '\0' if
7670  *                      the character should be read from the user.
7671  *  forward      int    True if searching forward.
7672  *  onto         int    True if the search should end on top of the
7673  *                      character, false if the search should stop
7674  *                      one character before the character in the
7675  *                      specified search direction.
7676  * Output:
7677  *  return       int    0 - OK.
7678  *                      1 - Error.
7679  *
7680  */
gl_copy_find(GetLine * gl,int count,char c,int forward,int onto)7681 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto)
7682 {
7683   int n;  /* The number of characters in the cut buffer */
7684 /*
7685  * Search for the character, and abort the operation if not found.
7686  */
7687   int pos = gl_find_char(gl, count, forward, onto, c);
7688   if(pos < 0)
7689     return 0;
7690 /*
7691  * Copy the specified segment.
7692  */
7693   if(forward) {
7694     n = pos + 1 - gl->buff_curpos;
7695     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7696   } else {
7697     n = gl->buff_curpos - pos;
7698     memcpy(gl->cutbuf, gl->line + pos, n);
7699     if(gl->editor == GL_VI_MODE)
7700       gl_place_cursor(gl, pos);
7701   }
7702 /*
7703  * Terminate the copy.
7704  */
7705   gl->cutbuf[n] = '\0';
7706   return 0;
7707 }
7708 
7709 /*.......................................................................
7710  * Copy a section up to and including a specified character into the cut
7711  * buffer without moving the cursor or deleting text.
7712  */
KT_KEY_FN(gl_forward_copy_find)7713 static KT_KEY_FN(gl_forward_copy_find)
7714 {
7715   return gl_copy_find(gl, count, '\0', 1, 1);
7716 }
7717 
7718 /*.......................................................................
7719  * Copy a section back to and including a specified character into the cut
7720  * buffer without moving the cursor or deleting text.
7721  */
KT_KEY_FN(gl_backward_copy_find)7722 static KT_KEY_FN(gl_backward_copy_find)
7723 {
7724   return gl_copy_find(gl, count, '\0', 0, 1);
7725 }
7726 
7727 /*.......................................................................
7728  * Copy a section up to and not including a specified character into the cut
7729  * buffer without moving the cursor or deleting text.
7730  */
KT_KEY_FN(gl_forward_copy_to)7731 static KT_KEY_FN(gl_forward_copy_to)
7732 {
7733   return gl_copy_find(gl, count, '\0', 1, 0);
7734 }
7735 
7736 /*.......................................................................
7737  * Copy a section back to and not including a specified character into the cut
7738  * buffer without moving the cursor or deleting text.
7739  */
KT_KEY_FN(gl_backward_copy_to)7740 static KT_KEY_FN(gl_backward_copy_to)
7741 {
7742   return gl_copy_find(gl, count, '\0', 0, 0);
7743 }
7744 
7745 /*.......................................................................
7746  * Copy to a character specified in a previous search into the cut
7747  * buffer without moving the cursor or deleting text.
7748  */
KT_KEY_FN(gl_copy_refind)7749 static KT_KEY_FN(gl_copy_refind)
7750 {
7751   return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7752 		      gl->vi.find_onto);
7753 }
7754 
7755 /*.......................................................................
7756  * Copy to a character specified in a previous search, but in the opposite
7757  * direction, into the cut buffer without moving the cursor or deleting text.
7758  */
KT_KEY_FN(gl_copy_invert_refind)7759 static KT_KEY_FN(gl_copy_invert_refind)
7760 {
7761   return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7762 		      gl->vi.find_onto);
7763 }
7764 
7765 /*.......................................................................
7766  * Set the position of the cursor in the line input buffer and the
7767  * terminal.
7768  *
7769  * Input:
7770  *  gl       GetLine *  The getline resource object.
7771  *  buff_curpos  int    The new buffer cursor position.
7772  * Output:
7773  *  return       int    0 - OK.
7774  *                      1 - Error.
7775  */
gl_place_cursor(GetLine * gl,int buff_curpos)7776 static int gl_place_cursor(GetLine *gl, int buff_curpos)
7777 {
7778 /*
7779  * Don't allow the cursor position to go out of the bounds of the input
7780  * line.
7781  */
7782   if(buff_curpos >= gl->ntotal)
7783     buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal;
7784   if(buff_curpos < 0)
7785     buff_curpos = 0;
7786 /*
7787  * Record the new buffer position.
7788  */
7789   gl->buff_curpos = buff_curpos;
7790 /*
7791  * Move the terminal cursor to the corresponding character.
7792  */
7793   return gl_set_term_curpos(gl, gl->prompt_len +
7794     gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len));
7795 }
7796 
7797 /*.......................................................................
7798  * In vi command mode, this function saves the current line to the
7799  * historical buffer needed by the undo command. In emacs mode it does
7800  * nothing. In order to allow action functions to call other action
7801  * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before
7802  * invoking an action, and thereafter once any call to this function
7803  * has set it to 1, further calls are ignored.
7804  *
7805  * Input:
7806  *  gl       GetLine *  The getline resource object.
7807  */
gl_save_for_undo(GetLine * gl)7808 static void gl_save_for_undo(GetLine *gl)
7809 {
7810   if(gl->vi.command && !gl->vi.undo.saved) {
7811     strlcpy(gl->vi.undo.line, gl->line, gl->linelen);
7812     gl->vi.undo.buff_curpos = gl->buff_curpos;
7813     gl->vi.undo.ntotal = gl->ntotal;
7814     gl->vi.undo.saved = 1;
7815   };
7816   if(gl->vi.command && !gl->vi.repeat.saved &&
7817      gl->current_action.fn != gl_vi_repeat_change) {
7818     gl->vi.repeat.action = gl->current_action;
7819     gl->vi.repeat.count = gl->current_count;
7820     gl->vi.repeat.saved = 1;
7821   };
7822   return;
7823 }
7824 
7825 /*.......................................................................
7826  * In vi mode, restore the line to the way it was before the last command
7827  * mode operation, storing the current line in the buffer so that the
7828  * undo operation itself can subsequently be undone.
7829  */
KT_KEY_FN(gl_vi_undo)7830 static KT_KEY_FN(gl_vi_undo)
7831 {
7832 /*
7833  * Get pointers into the two lines.
7834  */
7835   char *undo_ptr = gl->vi.undo.line;
7836   char *line_ptr = gl->line;
7837 /*
7838  * Swap the characters of the two buffers up to the length of the shortest
7839  * line.
7840  */
7841   while(*undo_ptr && *line_ptr) {
7842     char c = *undo_ptr;
7843     *undo_ptr++ = *line_ptr;
7844     *line_ptr++ = c;
7845   };
7846 /*
7847  * Copy the rest directly.
7848  */
7849   if(gl->ntotal > gl->vi.undo.ntotal) {
7850     strlcpy(undo_ptr, line_ptr, gl->linelen);
7851     *line_ptr = '\0';
7852   } else {
7853     strlcpy(line_ptr, undo_ptr, gl->linelen);
7854     *undo_ptr = '\0';
7855   };
7856 /*
7857  * Record the length of the stored string.
7858  */
7859   gl->vi.undo.ntotal = gl->ntotal;
7860 /*
7861  * Accomodate the new contents of gl->line[].
7862  */
7863   gl_update_buffer(gl);
7864 /*
7865  * Set both cursor positions to the leftmost of the saved and current
7866  * cursor positions to emulate what vi does.
7867  */
7868   if(gl->buff_curpos < gl->vi.undo.buff_curpos)
7869     gl->vi.undo.buff_curpos = gl->buff_curpos;
7870   else
7871     gl->buff_curpos = gl->vi.undo.buff_curpos;
7872 /*
7873  * Since we have bipassed calling gl_save_for_undo(), record repeat
7874  * information inline.
7875  */
7876   gl->vi.repeat.action.fn = gl_vi_undo;
7877   gl->vi.repeat.action.data = NULL;
7878   gl->vi.repeat.count = 1;
7879 /*
7880  * Display the restored line.
7881  */
7882   gl_queue_redisplay(gl);
7883   return 0;
7884 }
7885 
7886 /*.......................................................................
7887  * Delete the following word and leave the user in vi insert mode.
7888  */
KT_KEY_FN(gl_vi_forward_change_word)7889 static KT_KEY_FN(gl_vi_forward_change_word)
7890 {
7891   gl_save_for_undo(gl);
7892   gl->vi.command = 0;	/* Allow cursor at EOL */
7893   return gl_forward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7894 }
7895 
7896 /*.......................................................................
7897  * Delete the preceding word and leave the user in vi insert mode.
7898  */
KT_KEY_FN(gl_vi_backward_change_word)7899 static KT_KEY_FN(gl_vi_backward_change_word)
7900 {
7901   return gl_backward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7902 }
7903 
7904 /*.......................................................................
7905  * Delete the following section and leave the user in vi insert mode.
7906  */
KT_KEY_FN(gl_vi_forward_change_find)7907 static KT_KEY_FN(gl_vi_forward_change_find)
7908 {
7909   return gl_delete_find(gl, count, '\0', 1, 1, 1);
7910 }
7911 
7912 /*.......................................................................
7913  * Delete the preceding section and leave the user in vi insert mode.
7914  */
KT_KEY_FN(gl_vi_backward_change_find)7915 static KT_KEY_FN(gl_vi_backward_change_find)
7916 {
7917   return gl_delete_find(gl, count, '\0', 0, 1, 1);
7918 }
7919 
7920 /*.......................................................................
7921  * Delete the following section and leave the user in vi insert mode.
7922  */
KT_KEY_FN(gl_vi_forward_change_to)7923 static KT_KEY_FN(gl_vi_forward_change_to)
7924 {
7925   return gl_delete_find(gl, count, '\0', 1, 0, 1);
7926 }
7927 
7928 /*.......................................................................
7929  * Delete the preceding section and leave the user in vi insert mode.
7930  */
KT_KEY_FN(gl_vi_backward_change_to)7931 static KT_KEY_FN(gl_vi_backward_change_to)
7932 {
7933   return gl_delete_find(gl, count, '\0', 0, 0, 1);
7934 }
7935 
7936 /*.......................................................................
7937  * Delete to a character specified by a previous search and leave the user
7938  * in vi insert mode.
7939  */
KT_KEY_FN(gl_vi_change_refind)7940 static KT_KEY_FN(gl_vi_change_refind)
7941 {
7942   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7943 			gl->vi.find_onto, 1);
7944 }
7945 
7946 /*.......................................................................
7947  * Delete to a character specified by a previous search, but in the opposite
7948  * direction, and leave the user in vi insert mode.
7949  */
KT_KEY_FN(gl_vi_change_invert_refind)7950 static KT_KEY_FN(gl_vi_change_invert_refind)
7951 {
7952   return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7953 			gl->vi.find_onto, 1);
7954 }
7955 
7956 /*.......................................................................
7957  * Delete the following character and leave the user in vi insert mode.
7958  */
KT_KEY_FN(gl_vi_forward_change_char)7959 static KT_KEY_FN(gl_vi_forward_change_char)
7960 {
7961   gl_save_for_undo(gl);
7962   gl->vi.command = 0;	/* Allow cursor at EOL */
7963   return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0, NULL);
7964 }
7965 
7966 /*.......................................................................
7967  * Delete the preceding character and leave the user in vi insert mode.
7968  */
KT_KEY_FN(gl_vi_backward_change_char)7969 static KT_KEY_FN(gl_vi_backward_change_char)
7970 {
7971   return gl_backward_delete_char(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7972 }
7973 
7974 /*.......................................................................
7975  * Starting from the cursor position change characters to the specified column.
7976  */
KT_KEY_FN(gl_vi_change_to_column)7977 static KT_KEY_FN(gl_vi_change_to_column)
7978 {
7979   if (--count >= gl->buff_curpos)
7980     return gl_vi_forward_change_char(gl, count - gl->buff_curpos, NULL);
7981   else
7982     return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL);
7983 }
7984 
7985 /*.......................................................................
7986  * Starting from the cursor position change characters to a matching
7987  * parenthesis.
7988  */
KT_KEY_FN(gl_vi_change_to_parenthesis)7989 static KT_KEY_FN(gl_vi_change_to_parenthesis)
7990 {
7991   int curpos = gl_index_of_matching_paren(gl);
7992   if(curpos >= 0) {
7993     gl_save_for_undo(gl);
7994     if(curpos >= gl->buff_curpos)
7995       return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1, NULL);
7996     else
7997       return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1,
7998 					NULL);
7999   };
8000   return 0;
8001 }
8002 
8003 /*.......................................................................
8004  * If in vi mode, switch to vi command mode.
8005  *
8006  * Input:
8007  *  gl       GetLine *  The getline resource object.
8008  */
gl_vi_command_mode(GetLine * gl)8009 static void gl_vi_command_mode(GetLine *gl)
8010 {
8011   if(gl->editor == GL_VI_MODE && !gl->vi.command) {
8012     gl->insert = 1;
8013     gl->vi.command = 1;
8014     gl->vi.repeat.input_curpos = gl->insert_curpos;
8015     gl->vi.repeat.command_curpos = gl->buff_curpos;
8016     gl->insert_curpos = 0;	 /* unrestrict left motion boundary */
8017     gl_cursor_left(gl, 1, NULL); /* Vi moves 1 left on entering command mode */
8018   };
8019 }
8020 
8021 /*.......................................................................
8022  * This is an action function which rings the terminal bell.
8023  */
KT_KEY_FN(gl_ring_bell)8024 static KT_KEY_FN(gl_ring_bell)
8025 {
8026   return gl->silence_bell ? 0 :
8027     gl_print_control_sequence(gl, 1, gl->sound_bell);
8028 }
8029 
8030 /*.......................................................................
8031  * This is the action function which implements the vi-repeat-change
8032  * action.
8033  */
KT_KEY_FN(gl_vi_repeat_change)8034 static KT_KEY_FN(gl_vi_repeat_change)
8035 {
8036   int status;   /* The return status of the repeated action function */
8037   int i;
8038 /*
8039  * Nothing to repeat?
8040  */
8041   if(!gl->vi.repeat.action.fn)
8042     return gl_ring_bell(gl, 1, NULL);
8043 /*
8044  * Provide a way for action functions to know whether they are being
8045  * called by us.
8046  */
8047   gl->vi.repeat.active = 1;
8048 /*
8049  * Re-run the recorded function.
8050  */
8051   status = gl->vi.repeat.action.fn(gl, gl->vi.repeat.count,
8052 				   gl->vi.repeat.action.data);
8053 /*
8054  * Mark the repeat as completed.
8055  */
8056   gl->vi.repeat.active = 0;
8057 /*
8058  * Is we are repeating a function that has just switched to input
8059  * mode to allow the user to type, re-enter the text that the user
8060  * previously entered.
8061  */
8062   if(status==0 && !gl->vi.command) {
8063 /*
8064  * Make sure that the current line has been saved.
8065  */
8066     gl_save_for_undo(gl);
8067 /*
8068  * Repeat a previous insertion or overwrite?
8069  */
8070     if(gl->vi.repeat.input_curpos >= 0 &&
8071        gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos &&
8072        gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) {
8073 /*
8074  * Using the current line which is saved in the undo buffer, plus
8075  * the range of characters therein, as recorded by gl_vi_command_mode(),
8076  * add the characters that the user previously entered, to the input
8077  * line.
8078  */
8079       for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) {
8080 	if(gl_add_char_to_line(gl, gl->vi.undo.line[i]))
8081 	  return 1;
8082       };
8083     };
8084 /*
8085  * Switch back to command mode, now that the insertion has been repeated.
8086  */
8087     gl_vi_command_mode(gl);
8088   };
8089   return status;
8090 }
8091 
8092 /*.......................................................................
8093  * If the cursor is currently over a parenthesis character, return the
8094  * index of its matching parenthesis. If not currently over a parenthesis
8095  * character, return the next close parenthesis character to the right of
8096  * the cursor. If the respective parenthesis character isn't found,
8097  * ring the terminal bell and return -1.
8098  *
8099  * Input:
8100  *  gl       GetLine *  The getline resource object.
8101  * Output:
8102  *  return       int    Either the index of the matching parenthesis,
8103  *                      or -1 if not found.
8104  */
gl_index_of_matching_paren(GetLine * gl)8105 static int gl_index_of_matching_paren(GetLine *gl)
8106 {
8107   int i;
8108 /*
8109  * List the recognized parentheses, and their matches.
8110  */
8111   const char *o_paren = "([{";
8112   const char *c_paren = ")]}";
8113   const char *cptr;
8114 /*
8115  * Get the character that is currently under the cursor.
8116  */
8117   char c = gl->line[gl->buff_curpos];
8118 /*
8119  * If the character under the cursor is an open parenthesis, look forward
8120  * for the matching close parenthesis.
8121  */
8122   if((cptr=strchr(o_paren, c))) {
8123     char match = c_paren[cptr - o_paren];
8124     int matches_needed = 1;
8125     for(i=gl->buff_curpos+1; i<gl->ntotal; i++) {
8126       if(gl->line[i] == c)
8127 	matches_needed++;
8128       else if(gl->line[i] == match && --matches_needed==0)
8129 	return i;
8130     };
8131 /*
8132  * If the character under the cursor is an close parenthesis, look forward
8133  * for the matching open parenthesis.
8134  */
8135   } else if((cptr=strchr(c_paren, c))) {
8136     char match = o_paren[cptr - c_paren];
8137     int matches_needed = 1;
8138     for(i=gl->buff_curpos-1; i>=0; i--) {
8139       if(gl->line[i] == c)
8140 	matches_needed++;
8141       else if(gl->line[i] == match && --matches_needed==0)
8142 	return i;
8143     };
8144 /*
8145  * If not currently over a parenthesis character, search forwards for
8146  * the first close parenthesis (this is what the vi % binding does).
8147  */
8148   } else {
8149     for(i=gl->buff_curpos+1; i<gl->ntotal; i++)
8150       if(strchr(c_paren, gl->line[i]) != NULL)
8151 	return i;
8152   };
8153 /*
8154  * Not found.
8155  */
8156   (void) gl_ring_bell(gl, 1, NULL);
8157   return -1;
8158 }
8159 
8160 /*.......................................................................
8161  * If the cursor is currently over a parenthesis character, this action
8162  * function moves the cursor to its matching parenthesis.
8163  */
KT_KEY_FN(gl_find_parenthesis)8164 static KT_KEY_FN(gl_find_parenthesis)
8165 {
8166   int curpos = gl_index_of_matching_paren(gl);
8167   if(curpos >= 0)
8168     return gl_place_cursor(gl, curpos);
8169   return 0;
8170 }
8171 
8172 /*.......................................................................
8173  * Handle the receipt of the potential start of a new key-sequence from
8174  * the user.
8175  *
8176  * Input:
8177  *  gl      GetLine *   The resource object of this library.
8178  *  first_char char     The first character of the sequence.
8179  * Output:
8180  *  return      int     0 - OK.
8181  *                      1 - Error.
8182  */
gl_interpret_char(GetLine * gl,char first_char)8183 static int gl_interpret_char(GetLine *gl, char first_char)
8184 {
8185   char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */
8186   int nkey=0;                /* The number of characters in the key sequence */
8187   int count;                 /* The repeat count of an action function */
8188   int ret;                   /* The return value of an action function */
8189   int i;
8190 /*
8191  * Get the first character.
8192  */
8193   char c = first_char;
8194 /*
8195  * If editing is disabled, just add newly entered characters to the
8196  * input line buffer, and watch for the end of the line.
8197  */
8198   if(gl->editor == GL_NO_EDITOR) {
8199     gl_discard_chars(gl, 1);
8200     if(gl->ntotal >= gl->linelen)
8201       return 0;
8202     if(c == '\n' || c == '\r')
8203       return gl_newline(gl, 1, NULL);
8204     gl_buffer_char(gl, c, gl->ntotal);
8205     return 0;
8206   };
8207 /*
8208  * If the user is in the process of specifying a repeat count and the
8209  * new character is a digit, increment the repeat count accordingly.
8210  */
8211   if(gl->number >= 0 && isdigit((int)(unsigned char) c)) {
8212     gl_discard_chars(gl, 1);
8213     return gl_digit_argument(gl, c, NULL);
8214 /*
8215  * In vi command mode, all key-sequences entered need to be
8216  * either implicitly or explicitly prefixed with an escape character.
8217  */
8218   } else if(gl->vi.command && c != GL_ESC_CHAR) {
8219     keyseq[nkey++] = GL_ESC_CHAR;
8220 /*
8221  * If the first character of the sequence is a printable character,
8222  * then to avoid confusion with the special "up", "down", "left"
8223  * or "right" cursor key bindings, we need to prefix the
8224  * printable character with a backslash escape before looking it up.
8225  */
8226   } else if(!IS_META_CHAR(c) && !IS_CTRL_CHAR(c)) {
8227     keyseq[nkey++] = '\\';
8228   };
8229 /*
8230  * Compose a potentially multiple key-sequence in gl->keyseq.
8231  */
8232   while(nkey < GL_KEY_MAX) {
8233     KtAction *action; /* An action function */
8234     KeySym *keysym;   /* The symbol-table entry of a key-sequence */
8235     int nsym;         /* The number of ambiguously matching key-sequences */
8236 /*
8237  * If the character is an unprintable meta character, split it
8238  * into two characters, an escape character and the character
8239  * that was modified by the meta key.
8240  */
8241     if(IS_META_CHAR(c)) {
8242       keyseq[nkey++] = GL_ESC_CHAR;
8243       c = META_TO_CHAR(c);
8244       continue;
8245     };
8246 /*
8247  * Append the latest character to the key sequence.
8248  */
8249     keyseq[nkey++] = c;
8250 /*
8251  * When doing vi-style editing, an escape at the beginning of any binding
8252  * switches to command mode.
8253  */
8254     if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command)
8255       gl_vi_command_mode(gl);
8256 /*
8257  * Lookup the key sequence.
8258  */
8259     switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &keysym, &nsym)) {
8260     case KT_EXACT_MATCH:
8261 /*
8262  * Get the matching action function.
8263  */
8264       action = keysym->actions + keysym->binder;
8265 /*
8266  * Get the repeat count, passing the last keystroke if executing the
8267  * digit-argument action.
8268  */
8269       if(action->fn == gl_digit_argument) {
8270 	count = c;
8271       } else {
8272 	count = gl->number >= 0 ? gl->number : 1;
8273       };
8274 /*
8275  * Record the function that is being invoked.
8276  */
8277       gl->current_action = *action;
8278       gl->current_count = count;
8279 /*
8280  * Mark the current line as not yet preserved for use by the vi undo command.
8281  */
8282       gl->vi.undo.saved = 0;
8283       gl->vi.repeat.saved = 0;
8284 /*
8285  * Execute the action function. Note the action function can tell
8286  * whether the provided repeat count was defaulted or specified
8287  * explicitly by looking at whether gl->number is -1 or not. If
8288  * it is negative, then no repeat count was specified by the user.
8289  */
8290       ret = action->fn(gl, count, action->data);
8291 /*
8292  * In server mode, the action will return immediately if it tries to
8293  * read input from the terminal, and no input is currently available.
8294  * If this happens, abort. Note that gl_get_input_line() will rewind
8295  * the read-ahead buffer to allow the next call to redo the function
8296  * from scratch.
8297  */
8298       if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ)
8299 	return 1;
8300 /*
8301  * Discard the now processed characters from the key sequence buffer.
8302  */
8303       gl_discard_chars(gl, gl->nread);
8304 /*
8305  * If the latest action function wasn't a history action, cancel any
8306  * current history search.
8307  */
8308       if(gl->last_search != gl->keyseq_count)
8309 	_glh_cancel_search(gl->glh);
8310 /*
8311  * Reset the repeat count after running action functions.
8312  */
8313       if(action->fn != gl_digit_argument)
8314 	gl->number = -1;
8315       return ret ? 1 : 0;
8316       break;
8317     case KT_AMBIG_MATCH:    /* Ambiguous match - so read the next character */
8318       if(gl_read_terminal(gl, 1, &c))
8319 	return 1;
8320       break;
8321     case KT_NO_MATCH:
8322 /*
8323  * If the first character looked like it might be a prefix of a key-sequence
8324  * but it turned out not to be, ring the bell to tell the user that it
8325  * wasn't recognised.
8326  */
8327       if(keyseq[0] != '\\' && keyseq[0] != '\t') {
8328 	gl_ring_bell(gl, 1, NULL);
8329       } else {
8330 /*
8331  * The user typed a single printable character that doesn't match
8332  * the start of any keysequence, so add it to the line in accordance
8333  * with the current repeat count.
8334  */
8335 	count = gl->number >= 0 ? gl->number : 1;
8336 	for(i=0; i<count; i++)
8337 	  gl_add_char_to_line(gl, first_char);
8338 	gl->number = -1;
8339       };
8340       gl_discard_chars(gl, 1);
8341       _glh_cancel_search(gl->glh);
8342       return 0;
8343       break;
8344     case KT_BAD_MATCH:
8345       gl_ring_bell(gl, 1, NULL);
8346       gl_discard_chars(gl, gl->nread);
8347       _glh_cancel_search(gl->glh);
8348       return 1;
8349       break;
8350     };
8351   };
8352 /*
8353  * If the key sequence was too long to match, ring the bell, then
8354  * discard the first character, so that the next attempt to match a
8355  * key-sequence continues with the next key press. In practice this
8356  * shouldn't happen, since one isn't allowed to bind action functions
8357  * to keysequences that are longer than GL_KEY_MAX.
8358  */
8359   gl_ring_bell(gl, 1, NULL);
8360   gl_discard_chars(gl, 1);
8361   return 0;
8362 }
8363 
8364 /*.......................................................................
8365  * Configure the application and/or user-specific behavior of
8366  * gl_get_line().
8367  *
8368  * Note that calling this function between calling new_GetLine() and
8369  * the first call to gl_get_line(), disables the otherwise automatic
8370  * reading of ~/.teclarc on the first call to gl_get_line().
8371  *
8372  * Input:
8373  *  gl             GetLine *  The resource object of this library.
8374  *  app_string  const char *  Either NULL, or a string containing one
8375  *                            or more .teclarc command lines, separated
8376  *                            by newline characters. This can be used to
8377  *                            establish an application-specific
8378  *                            configuration, without the need for an external
8379  *                            file. This is particularly useful in embedded
8380  *                            environments where there is no filesystem.
8381  *  app_file    const char *  Either NULL, or the pathname of an
8382  *                            application-specific .teclarc file. The
8383  *                            contents of this file, if provided, are
8384  *                            read after the contents of app_string[].
8385  *  user_file   const char *  Either NULL, or the pathname of a
8386  *                            user-specific .teclarc file. Except in
8387  *                            embedded applications, this should
8388  *                            usually be "~/.teclarc".
8389  * Output:
8390  *  return             int    0 - OK.
8391  *                            1 - Bad argument(s).
8392  */
gl_configure_getline(GetLine * gl,const char * app_string,const char * app_file,const char * user_file)8393 int gl_configure_getline(GetLine *gl, const char *app_string,
8394 			 const char *app_file, const char *user_file)
8395 {
8396   sigset_t oldset; /* The signals that were blocked on entry to this function */
8397   int status;      /* The return status of _gl_configure_getline() */
8398 /*
8399  * Check the arguments.
8400  */
8401   if(!gl) {
8402     errno = EINVAL;
8403     return 1;
8404   };
8405 /*
8406  * Block all signals.
8407  */
8408   if(gl_mask_signals(gl, &oldset))
8409     return 1;
8410 /*
8411  * Execute the private body of the function while signals are blocked.
8412  */
8413   status = _gl_configure_getline(gl, app_string, app_file, user_file);
8414 /*
8415  * Restore the process signal mask.
8416  */
8417   gl_unmask_signals(gl, &oldset);
8418   return status;
8419 }
8420 
8421 /*.......................................................................
8422  * This is the private body of the gl_configure_getline() function. It
8423  * assumes that the caller has checked its arguments and blocked the
8424  * delivery of signals.
8425  */
_gl_configure_getline(GetLine * gl,const char * app_string,const char * app_file,const char * user_file)8426 static int _gl_configure_getline(GetLine *gl, const char *app_string,
8427 				 const char *app_file, const char *user_file)
8428 {
8429 /*
8430  * Mark getline as having been explicitly configured.
8431  */
8432   gl->configured = 1;
8433 /*
8434  * Start by parsing the configuration string, if provided.
8435  */
8436   if(app_string)
8437     (void) _gl_read_config_string(gl, app_string, KTB_NORM);
8438 /*
8439  * Now parse the application-specific configuration file, if provided.
8440  */
8441   if(app_file)
8442     (void) _gl_read_config_file(gl, app_file, KTB_NORM);
8443 /*
8444  * Finally, parse the user-specific configuration file, if provided.
8445  */
8446   if(user_file)
8447     (void) _gl_read_config_file(gl, user_file, KTB_USER);
8448 /*
8449  * Record the names of the configuration files to allow them to
8450  * be re-read if requested at a later time.
8451  */
8452   if(gl_record_string(&gl->app_file, app_file) ||
8453      gl_record_string(&gl->user_file, user_file)) {
8454     errno = ENOMEM;
8455     _err_record_msg(gl->err,
8456 	   "Insufficient memory to record tecla configuration file names",
8457 	   END_ERR_MSG);
8458     return 1;
8459   };
8460   return 0;
8461 }
8462 
8463 /*.......................................................................
8464  * Replace a malloc'd string (or NULL), with another malloc'd copy of
8465  * a string (or NULL).
8466  *
8467  * Input:
8468  *  sptr          char **  On input if *sptr!=NULL, *sptr will be
8469  *                         free'd and *sptr will be set to NULL. Then,
8470  *                         on output, if string!=NULL a malloc'd copy
8471  *                         of this string will be assigned to *sptr.
8472  *  string  const char *   The string to be copied, or NULL to simply
8473  *                         discard any existing string.
8474  * Output:
8475  *  return         int     0 - OK.
8476  *                         1 - Malloc failure (no error message is generated).
8477  */
gl_record_string(char ** sptr,const char * string)8478 static int gl_record_string(char **sptr, const char *string)
8479 {
8480 /*
8481  * If the original string is the same string, don't do anything.
8482  */
8483   if(*sptr == string || (*sptr && string && strcmp(*sptr, string)==0))
8484     return 0;
8485 /*
8486  * Discard any existing cached string.
8487  */
8488   if(*sptr) {
8489     free(*sptr);
8490     *sptr = NULL;
8491   };
8492 /*
8493  * Allocate memory for a copy of the specified string.
8494  */
8495   if(string) {
8496     size_t ssz = strlen(string) + 1;
8497     *sptr = (char *) malloc(ssz);
8498     if(!*sptr)
8499       return 1;
8500 /*
8501  * Copy the string.
8502  */
8503     strlcpy(*sptr, string, ssz);
8504   };
8505   return 0;
8506 }
8507 
8508 #ifndef HIDE_FILE_SYSTEM
8509 /*.......................................................................
8510  * Re-read any application-specific and user-specific files previously
8511  * specified via the gl_configure_getline() function.
8512  */
KT_KEY_FN(gl_read_init_files)8513 static KT_KEY_FN(gl_read_init_files)
8514 {
8515   return _gl_configure_getline(gl, NULL, gl->app_file, gl->user_file);
8516 }
8517 #endif
8518 
8519 /*.......................................................................
8520  * Save the contents of the history buffer to a given new file.
8521  *
8522  * Input:
8523  *  gl             GetLine *  The resource object of this library.
8524  *  filename    const char *  The name of the new file to write to.
8525  *  comment     const char *  Extra information such as timestamps will
8526  *                            be recorded on a line started with this
8527  *                            string, the idea being that the file can
8528  *                            double as a command file. Specify "" if
8529  *                            you don't care.
8530  *  max_lines          int    The maximum number of lines to save, or -1
8531  *                            to save all of the lines in the history
8532  *                            list.
8533  * Output:
8534  *  return             int     0 - OK.
8535  *                             1 - Error.
8536  */
gl_save_history(GetLine * gl,const char * filename,const char * comment,int max_lines)8537 int gl_save_history(GetLine *gl, const char *filename, const char *comment,
8538 		    int max_lines)
8539 {
8540   sigset_t oldset; /* The signals that were blocked on entry to this function */
8541   int status;      /* The return status of _gl_save_history() */
8542 /*
8543  * Check the arguments.
8544  */
8545   if(!gl || !filename || !comment) {
8546     if(gl)
8547       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8548     errno = EINVAL;
8549     return 1;
8550   };
8551 /*
8552  * Block all signals.
8553  */
8554   if(gl_mask_signals(gl, &oldset))
8555     return 1;
8556 /*
8557  * Execute the private body of the function while signals are blocked.
8558  */
8559   status = _gl_save_history(gl, filename, comment, max_lines);
8560 /*
8561  * Restore the process signal mask.
8562  */
8563   gl_unmask_signals(gl, &oldset);
8564   return status;
8565 }
8566 
8567 /*.......................................................................
8568  * This is the private body of the gl_save_history() function. It
8569  * assumes that the caller has checked its arguments and blocked the
8570  * delivery of signals.
8571  */
_gl_save_history(GetLine * gl,const char * filename,const char * comment,int max_lines)8572 static int _gl_save_history(GetLine *gl, const char *filename,
8573 			    const char *comment, int max_lines)
8574 {
8575 /*
8576  * If filesystem access is to be excluded, then history files can't
8577  * be written.
8578  */
8579 #ifdef WITHOUT_FILE_SYSTEM
8580   _err_record_msg(gl->err, "Can't save history without filesystem access",
8581 		  END_ERR_MSG);
8582   errno = EINVAL;
8583   return 1;
8584 #else
8585   FileExpansion *expansion; /* The expansion of the filename */
8586 /*
8587  * Expand the filename.
8588  */
8589   expansion = ef_expand_file(gl->ef, filename, -1);
8590   if(!expansion) {
8591     gl_print_info(gl, "Unable to expand ", filename, " (",
8592 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8593     return 1;
8594   };
8595 /*
8596  * Attempt to save to the specified file.
8597  */
8598   if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) {
8599     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8600     return 1;
8601   };
8602   return 0;
8603 #endif
8604 }
8605 
8606 /*.......................................................................
8607  * Restore the contents of the history buffer from a given new file.
8608  *
8609  * Input:
8610  *  gl             GetLine *  The resource object of this library.
8611  *  filename    const char *  The name of the new file to write to.
8612  *  comment     const char *  This must be the same string that was
8613  *                            passed to gl_save_history() when the file
8614  *                            was written.
8615  * Output:
8616  *  return             int     0 - OK.
8617  *                             1 - Error.
8618  */
gl_load_history(GetLine * gl,const char * filename,const char * comment)8619 int gl_load_history(GetLine *gl, const char *filename, const char *comment)
8620 {
8621   sigset_t oldset; /* The signals that were blocked on entry to this function */
8622   int status;      /* The return status of _gl_load_history() */
8623 /*
8624  * Check the arguments.
8625  */
8626   if(!gl || !filename || !comment) {
8627     if(gl)
8628       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8629     errno = EINVAL;
8630     return 1;
8631   };
8632 /*
8633  * Block all signals.
8634  */
8635   if(gl_mask_signals(gl, &oldset))
8636     return 1;
8637 /*
8638  * Execute the private body of the function while signals are blocked.
8639  */
8640   status = _gl_load_history(gl, filename, comment);
8641 /*
8642  * Restore the process signal mask.
8643  */
8644   gl_unmask_signals(gl, &oldset);
8645   return status;
8646 }
8647 
8648 /*.......................................................................
8649  * This is the private body of the gl_load_history() function. It
8650  * assumes that the caller has checked its arguments and blocked the
8651  * delivery of signals.
8652  */
_gl_load_history(GetLine * gl,const char * filename,const char * comment)8653 static int _gl_load_history(GetLine *gl, const char *filename,
8654 			    const char *comment)
8655 {
8656 /*
8657  * If filesystem access is to be excluded, then history files can't
8658  * be read.
8659  */
8660 #ifdef WITHOUT_FILE_SYSTEM
8661   _err_record_msg(gl->err, "Can't load history without filesystem access",
8662 		  END_ERR_MSG);
8663   errno = EINVAL;
8664   return 1;
8665 #else
8666   FileExpansion *expansion; /* The expansion of the filename */
8667 /*
8668  * Expand the filename.
8669  */
8670   expansion = ef_expand_file(gl->ef, filename, -1);
8671   if(!expansion) {
8672     gl_print_info(gl, "Unable to expand ", filename, " (",
8673 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8674     return 1;
8675   };
8676 /*
8677  * Attempt to load from the specified file.
8678  */
8679   if(_glh_load_history(gl->glh, expansion->files[0], comment,
8680 		       gl->cutbuf, gl->linelen+1)) {
8681     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8682     gl->cutbuf[0] = '\0';
8683     return 1;
8684   };
8685   gl->cutbuf[0] = '\0';
8686   return 0;
8687 #endif
8688 }
8689 
8690 /*.......................................................................
8691  * Where possible, register a function and associated data to be called
8692  * whenever a specified event is seen on a file descriptor.
8693  *
8694  * Input:
8695  *  gl            GetLine *  The resource object of the command-line input
8696  *                           module.
8697  *  fd                int    The file descriptor to watch.
8698  *  event       GlFdEvent    The type of activity to watch for.
8699  *  callback  GlFdEventFn *  The function to call when the specified
8700  *                           event occurs. Setting this to 0 removes
8701  *                           any existing callback.
8702  *  data             void *  A pointer to arbitrary data to pass to the
8703  *                           callback function.
8704  * Output:
8705  *  return            int    0 - OK.
8706  *                           1 - Either gl==NULL, or this facility isn't
8707  *                               available on the the host system
8708  *                               (ie. select() isn't available). No
8709  *                               error message is generated in the latter
8710  *                               case.
8711  */
gl_watch_fd(GetLine * gl,int fd,GlFdEvent event,GlFdEventFn * callback,void * data)8712 int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8713 		GlFdEventFn *callback, void *data)
8714 {
8715   sigset_t oldset; /* The signals that were blocked on entry to this function */
8716   int status;      /* The return status of _gl_watch_fd() */
8717 /*
8718  * Check the arguments.
8719  */
8720   if(!gl) {
8721     errno = EINVAL;
8722     return 1;
8723   };
8724   if(fd < 0) {
8725     _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG);
8726     errno = EINVAL;
8727     return 1;
8728   };
8729 /*
8730  * Block all signals.
8731  */
8732   if(gl_mask_signals(gl, &oldset))
8733     return 1;
8734 /*
8735  * Execute the private body of the function while signals are blocked.
8736  */
8737   status = _gl_watch_fd(gl, fd, event, callback, data);
8738 /*
8739  * Restore the process signal mask.
8740  */
8741   gl_unmask_signals(gl, &oldset);
8742   return status;
8743 }
8744 
8745 /*.......................................................................
8746  * This is the private body of the gl_watch_fd() function. It
8747  * assumes that the caller has checked its arguments and blocked the
8748  * delivery of signals.
8749  */
_gl_watch_fd(GetLine * gl,int fd,GlFdEvent event,GlFdEventFn * callback,void * data)8750 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8751 			GlFdEventFn *callback, void *data)
8752 #if !defined(HAVE_SELECT)
8753 {return 1;}               /* The facility isn't supported on this system */
8754 #else
8755 {
8756   GlFdNode *prev;  /* The node that precedes 'node' in gl->fd_nodes */
8757   GlFdNode *node;  /* The file-descriptor node being checked */
8758 /*
8759  * Search the list of already registered fd activity nodes for the specified
8760  * file descriptor.
8761  */
8762   for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd;
8763       prev=node, node=node->next)
8764     ;
8765 /*
8766  * Hasn't a node been allocated for this fd yet?
8767  */
8768   if(!node) {
8769 /*
8770  * If there is no callback to record, just ignore the call.
8771  */
8772     if(!callback)
8773       return 0;
8774 /*
8775  * Allocate the new node.
8776  */
8777     node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem);
8778     if(!node) {
8779       errno = ENOMEM;
8780       _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG);
8781       return 1;
8782     };
8783 /*
8784  * Prepend the node to the list.
8785  */
8786     node->next = gl->fd_nodes;
8787     gl->fd_nodes = node;
8788 /*
8789  * Initialize the node.
8790  */
8791     node->fd = fd;
8792     node->rd.fn = 0;
8793     node->rd.data = NULL;
8794     node->ur = node->wr = node->rd;
8795   };
8796 /*
8797  * Record the new callback.
8798  */
8799   switch(event) {
8800   case GLFD_READ:
8801     node->rd.fn = callback;
8802     node->rd.data = data;
8803     if(callback)
8804       FD_SET(fd, &gl->rfds);
8805     else
8806       FD_CLR(fd, &gl->rfds);
8807     break;
8808   case GLFD_WRITE:
8809     node->wr.fn = callback;
8810     node->wr.data = data;
8811     if(callback)
8812       FD_SET(fd, &gl->wfds);
8813     else
8814       FD_CLR(fd, &gl->wfds);
8815     break;
8816   case GLFD_URGENT:
8817     node->ur.fn = callback;
8818     node->ur.data = data;
8819     if(callback)
8820       FD_SET(fd, &gl->ufds);
8821     else
8822       FD_CLR(fd, &gl->ufds);
8823     break;
8824   };
8825 /*
8826  * Keep a record of the largest file descriptor being watched.
8827  */
8828   if(fd > gl->max_fd)
8829     gl->max_fd = fd;
8830 /*
8831  * If we are deleting an existing callback, also delete the parent
8832  * activity node if no callbacks are registered to the fd anymore.
8833  */
8834   if(!callback) {
8835     if(!node->rd.fn && !node->wr.fn && !node->ur.fn) {
8836       if(prev)
8837 	prev->next = node->next;
8838       else
8839 	gl->fd_nodes = node->next;
8840       node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node);
8841     };
8842   };
8843   return 0;
8844 }
8845 #endif
8846 
8847 /*.......................................................................
8848  * On systems with the select() system call, the gl_inactivity_timeout()
8849  * function provides the option of setting (or cancelling) an
8850  * inactivity timeout. Inactivity, in this case, refers both to
8851  * terminal input received from the user, and to I/O on any file
8852  * descriptors registered by calls to gl_watch_fd(). If at any time,
8853  * no activity is seen for the requested time period, the specified
8854  * timeout callback function is called. On returning, this callback
8855  * returns a code which tells gl_get_line() what to do next. Note that
8856  * each call to gl_inactivity_timeout() replaces any previously installed
8857  * timeout callback, and that specifying a callback of 0, turns off
8858  * inactivity timing.
8859  *
8860  * Beware that although the timeout argument includes a nano-second
8861  * component, few computer clocks presently have resolutions finer
8862  * than a few milliseconds, so asking for less than a few milliseconds
8863  * is equivalent to zero on a lot of systems.
8864  *
8865  * Input:
8866  *  gl            GetLine *  The resource object of the command-line input
8867  *                           module.
8868  *  callback  GlTimeoutFn *  The function to call when the inactivity
8869  *                           timeout is exceeded. To turn off
8870  *                           inactivity timeouts altogether, send 0.
8871  *  data             void *  A pointer to arbitrary data to pass to the
8872  *                           callback function.
8873  *  sec     unsigned long    The number of whole seconds in the timeout.
8874  *  nsec    unsigned long    The fractional number of seconds in the
8875  *                           timeout, expressed in nano-seconds (see
8876  *                           the caveat above).
8877  * Output:
8878  *  return            int    0 - OK.
8879  *                           1 - Either gl==NULL, or this facility isn't
8880  *                               available on the the host system
8881  *                               (ie. select() isn't available). No
8882  *                               error message is generated in the latter
8883  *                               case.
8884  */
gl_inactivity_timeout(GetLine * gl,GlTimeoutFn * timeout_fn,void * data,unsigned long sec,unsigned long nsec)8885 int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data,
8886 		   unsigned long sec, unsigned long nsec)
8887 #if !defined(HAVE_SELECT)
8888 {return 1;}               /* The facility isn't supported on this system */
8889 #else
8890 {
8891   sigset_t oldset; /* The signals that were blocked on entry to this function */
8892 /*
8893  * Check the arguments.
8894  */
8895   if(!gl) {
8896     errno = EINVAL;
8897     return 1;
8898   };
8899 /*
8900  * Block all signals.
8901  */
8902   if(gl_mask_signals(gl, &oldset))
8903     return 1;
8904 /*
8905  * Install a new timeout?
8906  */
8907   if(timeout_fn) {
8908     gl->timer.dt.tv_sec = sec;
8909     gl->timer.dt.tv_usec = nsec / 1000;
8910     gl->timer.fn = timeout_fn;
8911     gl->timer.data = data;
8912   } else {
8913     gl->timer.fn = 0;
8914     gl->timer.data = NULL;
8915   };
8916 /*
8917  * Restore the process signal mask.
8918  */
8919   gl_unmask_signals(gl, &oldset);
8920   return 0;
8921 }
8922 #endif
8923 
8924 /*.......................................................................
8925  * When select() is available, this is a private function of
8926  * gl_read_input() which responds to file-descriptor events registered by
8927  * the caller. Note that it assumes that it is being called from within
8928  * gl_read_input()'s sigsetjump() clause.
8929  *
8930  * Input:
8931  *  gl    GetLine *  The resource object of this module.
8932  *  fd        int    The file descriptor to be watched for user input.
8933  * Output:
8934  *  return    int    0 - OK.
8935  *                   1 - An error occurred.
8936  */
gl_event_handler(GetLine * gl,int fd)8937 static int gl_event_handler(GetLine *gl, int fd)
8938 {
8939 #if !defined(HAVE_SELECT)
8940   return 0;
8941 #else
8942 /*
8943  * Set up a zero-second timeout.
8944  */
8945   struct timeval zero;
8946   zero.tv_sec = zero.tv_usec = 0;
8947 /*
8948  * If at any time no external callbacks remain, quit the loop return,
8949  * so that we can simply wait in read(). This is designed as an
8950  * optimization for when no callbacks have been registered on entry to
8951  * this function, but since callbacks can delete themselves, it can
8952  * also help later.
8953  */
8954   while(gl->fd_nodes || gl->timer.fn) {
8955     int nready;   /* The number of file descriptors that are ready for I/O */
8956 /*
8957  * Get the set of descriptors to be watched.
8958  */
8959     fd_set rfds = gl->rfds;
8960     fd_set wfds = gl->wfds;
8961     fd_set ufds = gl->ufds;
8962 /*
8963  * Get the appropriate timeout.
8964  */
8965     struct timeval dt = gl->timer.fn ? gl->timer.dt : zero;
8966 /*
8967  * Add the specified user-input file descriptor tot he set that is to
8968  * be watched.
8969  */
8970     FD_SET(fd, &rfds);
8971 /*
8972  * Unblock the signals that we are watching, while select is blocked
8973  * waiting for I/O.
8974  */
8975     gl_catch_signals(gl);
8976 /*
8977  * Wait for activity on any of the file descriptors.
8978  */
8979     nready = select(gl->max_fd+1, &rfds, &wfds, &ufds,
8980 	    (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL);
8981 /*
8982  * We don't want to do a longjmp in the middle of a callback that
8983  * might be modifying global or heap data, so block all the signals
8984  * that we are trapping before executing callback functions. Note that
8985  * the caller will unblock them again when it needs to, so there is
8986  * no need to undo this before returning.
8987  */
8988     gl_mask_signals(gl, NULL);
8989 /*
8990  * If select() returns but none of the file descriptors are reported
8991  * to have activity, then select() timed out.
8992  */
8993     if(nready == 0) {
8994 /*
8995  * Note that in non-blocking server mode, the inactivity timer is used
8996  * to allow I/O to block for a specified amount of time, so in this
8997  * mode we return the postponed blocked status when an abort is
8998  * requested.
8999  */
9000       if(gl_call_timeout_handler(gl)) {
9001 	return 1;
9002       } else if(gl->io_mode == GL_SERVER_MODE) {
9003 	gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
9004 	return 1;
9005       };
9006 /*
9007  * If nready < 0, this means an error occurred.
9008  */
9009     } else if(nready < 0) {
9010       if(errno != EINTR) {
9011 	gl_record_status(gl, GLR_ERROR, errno);
9012 	return 1;
9013       };
9014 /*
9015  * If the user-input file descriptor has data available, return.
9016  */
9017     } else if(FD_ISSET(fd, &rfds)) {
9018       return 0;
9019 /*
9020  * Check for activity on any of the file descriptors registered by the
9021  * calling application, and call the associated callback functions.
9022  */
9023     } else {
9024       GlFdNode *node;   /* The fd event node being checked */
9025 /*
9026  * Search the list for the file descriptor that caused select() to return.
9027  */
9028       for(node=gl->fd_nodes; node; node=node->next) {
9029 /*
9030  * Is there urgent out of band data waiting to be read on fd?
9031  */
9032 	if(node->ur.fn && FD_ISSET(node->fd, &ufds)) {
9033 	  if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT))
9034 	    return 1;
9035 	  break;  /* The callback may have changed the list of nodes */
9036 /*
9037  * Is the fd readable?
9038  */
9039 	} else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) {
9040 	  if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ))
9041 	    return 1;
9042 	  break;  /* The callback may have changed the list of nodes */
9043 /*
9044  * Is the fd writable?
9045  */
9046 	} else if(node->wr.fn && FD_ISSET(node->fd, &wfds)) {
9047 	  if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE))
9048 	    return 1;
9049 	  break;  /* The callback may have changed the list of nodes */
9050 	};
9051       };
9052     };
9053 /*
9054  * Just in case the above event handlers asked for the input line to
9055  * be redrawn, flush any pending output.
9056  */
9057     if(gl_flush_output(gl))
9058       return 1;
9059   };
9060   return 0;
9061 }
9062 #endif
9063 
9064 #if defined(HAVE_SELECT)
9065 /*.......................................................................
9066  * This is a private function of gl_event_handler(), used to call a
9067  * file-descriptor callback.
9068  *
9069  * Input:
9070  *  gl       GetLine *  The resource object of gl_get_line().
9071  *  gfh  GlFdHandler *  The I/O handler.
9072  *  fd           int    The file-descriptor being reported.
9073  *  event  GlFdEvent    The I/O event being reported.
9074  * Output:
9075  *  return       int    0 - OK.
9076  *                      1 - Error.
9077  */
9078 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
9079 			      GlFdEvent event)
9080 {
9081   Termios attr;       /* The terminal attributes */
9082   int waserr = 0;     /* True after any error */
9083 /*
9084  * Re-enable conversion of newline characters to carriage-return/linefeed,
9085  * so that the callback can write to the terminal without having to do
9086  * anything special.
9087  */
9088   if(tcgetattr(gl->input_fd, &attr)) {
9089     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9090     return 1;
9091   };
9092   attr.c_oflag |= OPOST;
9093   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9094     if(errno != EINTR) {
9095       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9096       return 1;
9097     };
9098   };
9099 /*
9100  * Invoke the application's callback function.
9101  */
9102   switch(gfh->fn(gl, gfh->data, fd, event)) {
9103   default:
9104   case GLFD_ABORT:
9105     gl_record_status(gl, GLR_FDABORT, 0);
9106     waserr = 1;
9107     break;
9108   case GLFD_REFRESH:
9109     gl_queue_redisplay(gl);
9110     break;
9111   case GLFD_CONTINUE:
9112     break;
9113   };
9114 /*
9115  * Disable conversion of newline characters to carriage-return/linefeed.
9116  */
9117   attr.c_oflag &= ~(OPOST);
9118   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9119     if(errno != EINTR) {
9120       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9121       return 1;
9122     };
9123   };
9124   return waserr;
9125 }
9126 
9127 /*.......................................................................
9128  * This is a private function of gl_event_handler(), used to call a
9129  * inactivity timer callbacks.
9130  *
9131  * Input:
9132  *  gl       GetLine *  The resource object of gl_get_line().
9133  * Output:
9134  *  return       int    0 - OK.
9135  *                      1 - Error.
9136  */
9137 static int gl_call_timeout_handler(GetLine *gl)
9138 {
9139   Termios attr;       /* The terminal attributes */
9140   int waserr = 0;     /* True after any error */
9141 /*
9142  * Make sure that there is an inactivity timeout callback.
9143  */
9144   if(!gl->timer.fn)
9145     return 0;
9146 /*
9147  * Re-enable conversion of newline characters to carriage-return/linefeed,
9148  * so that the callback can write to the terminal without having to do
9149  * anything special.
9150  */
9151   if(tcgetattr(gl->input_fd, &attr)) {
9152     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9153     return 1;
9154   };
9155   attr.c_oflag |= OPOST;
9156   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9157     if(errno != EINTR) {
9158       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9159       return 1;
9160     };
9161   };
9162 /*
9163  * Invoke the application's callback function.
9164  */
9165   switch(gl->timer.fn(gl, gl->timer.data)) {
9166   default:
9167   case GLTO_ABORT:
9168     gl_record_status(gl, GLR_TIMEOUT, 0);
9169     waserr = 1;
9170     break;
9171   case GLTO_REFRESH:
9172     gl_queue_redisplay(gl);
9173     break;
9174   case GLTO_CONTINUE:
9175     break;
9176   };
9177 /*
9178  * Disable conversion of newline characters to carriage-return/linefeed.
9179  */
9180   attr.c_oflag &= ~(OPOST);
9181   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9182     if(errno != EINTR) {
9183       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9184       return 1;
9185     };
9186   };
9187   return waserr;
9188 }
9189 #endif  /* HAVE_SELECT */
9190 
9191 /*.......................................................................
9192  * Switch history groups. History groups represent separate history
9193  * lists recorded within a single history buffer. Different groups
9194  * are distinguished by integer identifiers chosen by the calling
9195  * appplicaton. Initially new_GetLine() sets the group identifier to
9196  * 0. Whenever a new line is appended to the history list, the current
9197  * group identifier is recorded with it, and history lookups only
9198  * consider lines marked with the current group identifier.
9199  *
9200  * Input:
9201  *  gl      GetLine *  The resource object of gl_get_line().
9202  *  id     unsigned    The new history group identifier.
9203  * Output:
9204  *  return      int    0 - OK.
9205  *                     1 - Error.
9206  */
9207 int gl_group_history(GetLine *gl, unsigned id)
9208 {
9209   sigset_t oldset; /* The signals that were blocked on entry to this function */
9210   int status;      /* The return status of this function */
9211 /*
9212  * Check the arguments.
9213  */
9214   if(!gl) {
9215     errno = EINVAL;
9216     return 1;
9217   };
9218 /*
9219  * Block all signals while we install the new configuration.
9220  */
9221   if(gl_mask_signals(gl, &oldset))
9222     return 1;
9223 /*
9224  * If the group isn't being changed, do nothing.
9225  */
9226   if(_glh_get_group(gl->glh) == id) {
9227     status = 0;
9228 /*
9229  * Establish the new group.
9230  */
9231   } else if(_glh_set_group(gl->glh, id)) {
9232     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9233     status = 1;
9234 /*
9235  * Prevent history information from the previous group being
9236  * inappropriately used by the next call to gl_get_line().
9237  */
9238   } else {
9239     gl->preload_history = 0;
9240     gl->last_search = -1;
9241     status = 0;
9242   };
9243 /*
9244  * Restore the process signal mask.
9245  */
9246   gl_unmask_signals(gl, &oldset);
9247   return status;
9248 }
9249 
9250 /*.......................................................................
9251  * Display the contents of the history list.
9252  *
9253  * Input:
9254  *  gl      GetLine *  The resource object of gl_get_line().
9255  *  fp         FILE *  The stdio output stream to write to.
9256  *  fmt  const char *  A format string. This containing characters to be
9257  *                     written verbatim, plus any of the following
9258  *                     format directives:
9259  *                       %D  -  The date, formatted like 2001-11-20
9260  *                       %T  -  The time of day, formatted like 23:59:59
9261  *                       %N  -  The sequential entry number of the
9262  *                              line in the history buffer.
9263  *                       %G  -  The number of the history group that
9264  *                              the line belongs to.
9265  *                       %%  -  A literal % character.
9266  *                       %H  -  The history line itself.
9267  *                     Note that a '\n' newline character is not
9268  *                     appended by default.
9269  *  all_groups  int    If true, display history lines from all
9270  *                     history groups. Otherwise only display
9271  *                     those of the current history group.
9272  *  max_lines   int    If max_lines is < 0, all available lines
9273  *                     are displayed. Otherwise only the most
9274  *                     recent max_lines lines will be displayed.
9275  * Output:
9276  *  return      int    0 - OK.
9277  *                     1 - Error.
9278  */
9279 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups,
9280 		    int max_lines)
9281 {
9282   sigset_t oldset; /* The signals that were blocked on entry to this function */
9283   int status;      /* The return status of this function */
9284 /*
9285  * Check the arguments.
9286  */
9287   if(!gl || !fp || !fmt) {
9288     if(gl)
9289       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
9290     errno = EINVAL;
9291     return 1;
9292   };
9293 /*
9294  * Block all signals.
9295  */
9296   if(gl_mask_signals(gl, &oldset))
9297     return 1;
9298 /*
9299  * Display the specified history group(s) while signals are blocked.
9300  */
9301   status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups,
9302 			     max_lines) || fflush(fp)==EOF;
9303   if(!status)
9304     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9305 /*
9306  * Restore the process signal mask.
9307  */
9308   gl_unmask_signals(gl, &oldset);
9309   return status;
9310 }
9311 
9312 /*.......................................................................
9313  * Update if necessary, and return the current size of the terminal.
9314  *
9315  * Input:
9316  *  gl            GetLine *  The resource object of gl_get_line().
9317  *  def_ncolumn       int    If the number of columns in the terminal
9318  *                           can't be determined, substitute this number.
9319  *  def_nline         int    If the number of lines in the terminal can't
9320  *                           be determined, substitute this number.
9321  * Output:
9322  *  return GlTerminalSize    The current terminal size.
9323  */
9324 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline)
9325 {
9326   GlTerminalSize size;  /* The object to be returned */
9327   sigset_t oldset;      /* The signals that were blocked on entry */
9328                         /*  to this function */
9329 /*
9330  * Block all signals while accessing gl.
9331  */
9332   gl_mask_signals(gl, &oldset);
9333 /*
9334  * Lookup/configure the terminal size.
9335  */
9336   _gl_terminal_size(gl, def_ncolumn, def_nline, &size);
9337 /*
9338  * Restore the process signal mask before returning.
9339  */
9340   gl_unmask_signals(gl, &oldset);
9341   return size;
9342 }
9343 
9344 /*.......................................................................
9345  * This is the private body of the gl_terminal_size() function. It
9346  * assumes that the caller has checked its arguments and blocked the
9347  * delivery of signals.
9348  */
9349 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
9350 			      GlTerminalSize *size)
9351 {
9352   const char *env;      /* The value of an environment variable */
9353   int n;                /* A number read from env[] */
9354 /*
9355  * Set the number of lines and columns to non-sensical values so that
9356  * we know later if they have been set.
9357  */
9358   gl->nline = 0;
9359   gl->ncolumn = 0;
9360 /*
9361  * Are we reading from a terminal?
9362  */
9363   if(gl->is_term) {
9364 /*
9365  * Ask the terminal directly if possible.
9366  */
9367     (void) _gl_update_size(gl);
9368 /*
9369  * If gl_update_size() couldn't ask the terminal, it will have
9370  * left gl->nrow and gl->ncolumn unchanged. If these values haven't
9371  * been changed from their initial values of zero, we need to find
9372  * a different method to get the terminal size.
9373  *
9374  * If the number of lines isn't known yet, first see if the
9375  * LINES environment ariable exists and specifies a believable number.
9376  * If this doesn't work, look up the default size in the terminal
9377  * information database.
9378  */
9379     if(gl->nline < 1) {
9380       if((env = getenv("LINES")) && (n=atoi(env)) > 0)
9381 	gl->nline = n;
9382 #ifdef USE_TERMINFO
9383       else
9384 	gl->nline = tigetnum((char *)"lines");
9385 #elif defined(USE_TERMCAP)
9386       else
9387         gl->nline = tgetnum("li");
9388 #endif
9389     };
9390 /*
9391  * If the number of lines isn't known yet, first see if the COLUMNS
9392  * environment ariable exists and specifies a believable number.  If
9393  * this doesn't work, look up the default size in the terminal
9394  * information database.
9395  */
9396     if(gl->ncolumn < 1) {
9397       if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0)
9398 	gl->ncolumn = n;
9399 #ifdef USE_TERMINFO
9400       else
9401 	gl->ncolumn = tigetnum((char *)"cols");
9402 #elif defined(USE_TERMCAP)
9403       else
9404 	gl->ncolumn = tgetnum("co");
9405 #endif
9406     };
9407   };
9408 /*
9409  * If we still haven't been able to acquire reasonable values, substitute
9410  * the default values specified by the caller.
9411  */
9412   if(gl->nline <= 0)
9413     gl->nline = def_nline;
9414   if(gl->ncolumn <= 0)
9415     gl->ncolumn = def_ncolumn;
9416 /*
9417  * Copy the new size into the return value.
9418  */
9419   if(size) {
9420     size->nline = gl->nline;
9421     size->ncolumn = gl->ncolumn;
9422   };
9423   return;
9424 }
9425 
9426 /*.......................................................................
9427  * Resize or delete the history buffer.
9428  *
9429  * Input:
9430  *  gl      GetLine *  The resource object of gl_get_line().
9431  *  bufsize  size_t    The number of bytes in the history buffer, or 0
9432  *                     to delete the buffer completely.
9433  * Output:
9434  *  return      int    0 - OK.
9435  *                     1 - Insufficient memory (the previous buffer
9436  *                         will have been retained). No error message
9437  *                         will be displayed.
9438  */
9439 int gl_resize_history(GetLine *gl, size_t bufsize)
9440 {
9441   sigset_t oldset; /* The signals that were blocked on entry to this function */
9442   int status;      /* The return status of this function */
9443 /*
9444  * Check the arguments.
9445  */
9446   if(!gl)
9447     return 1;
9448 /*
9449  * Block all signals while modifying the contents of gl.
9450  */
9451   if(gl_mask_signals(gl, &oldset))
9452     return 1;
9453 /*
9454  * Perform the resize while signals are blocked.
9455  */
9456   status = _glh_resize_history(gl->glh, bufsize);
9457   if(status)
9458     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9459 /*
9460  * Restore the process signal mask before returning.
9461  */
9462   gl_unmask_signals(gl, &oldset);
9463   return status;
9464 }
9465 
9466 /*.......................................................................
9467  * Set an upper limit to the number of lines that can be recorded in the
9468  * history list, or remove a previously specified limit.
9469  *
9470  * Input:
9471  *  gl      GetLine *  The resource object of gl_get_line().
9472  *  max_lines   int    The maximum number of lines to allow, or -1 to
9473  *                     cancel a previous limit and allow as many lines
9474  *                     as will fit in the current history buffer size.
9475  */
9476 void gl_limit_history(GetLine *gl, int max_lines)
9477 {
9478   if(gl) {
9479     sigset_t oldset; /* The signals that were blocked on entry to this block */
9480 /*
9481  * Temporarily block all signals.
9482  */
9483     gl_mask_signals(gl, &oldset);
9484 /*
9485  * Apply the limit while signals are blocked.
9486  */
9487     _glh_limit_history(gl->glh, max_lines);
9488 /*
9489  * Restore the process signal mask before returning.
9490  */
9491     gl_unmask_signals(gl, &oldset);
9492   };
9493 }
9494 
9495 /*.......................................................................
9496  * Discard either all historical lines, or just those associated with the
9497  * current history group.
9498  *
9499  * Input:
9500  *  gl      GetLine *  The resource object of gl_get_line().
9501  *  all_groups  int    If true, clear all of the history. If false,
9502  *                     clear only the stored lines associated with the
9503  *                     currently selected history group.
9504  */
9505 void gl_clear_history(GetLine *gl, int all_groups)
9506 {
9507   if(gl) {
9508     sigset_t oldset; /* The signals that were blocked on entry to this block */
9509 /*
9510  * Temporarily block all signals.
9511  */
9512     gl_mask_signals(gl, &oldset);
9513 /*
9514  * Clear the history buffer while signals are blocked.
9515  */
9516     _glh_clear_history(gl->glh, all_groups);
9517 /*
9518  * Restore the process signal mask before returning.
9519  */
9520     gl_unmask_signals(gl, &oldset);
9521   };
9522 }
9523 
9524 /*.......................................................................
9525  * Temporarily enable or disable the gl_get_line() history mechanism.
9526  *
9527  * Input:
9528  *  gl      GetLine *  The resource object of gl_get_line().
9529  *  enable      int    If true, turn on the history mechanism. If
9530  *                     false, disable it.
9531  */
9532 void gl_toggle_history(GetLine *gl, int enable)
9533 {
9534   if(gl) {
9535     sigset_t oldset; /* The signals that were blocked on entry to this block */
9536 /*
9537  * Temporarily block all signals.
9538  */
9539     gl_mask_signals(gl, &oldset);
9540 /*
9541  * Change the history recording mode while signals are blocked.
9542  */
9543     _glh_toggle_history(gl->glh, enable);
9544 /*
9545  * Restore the process signal mask before returning.
9546  */
9547     gl_unmask_signals(gl, &oldset);
9548   };
9549 }
9550 
9551 /*.......................................................................
9552  * Lookup a history line by its sequential number of entry in the
9553  * history buffer.
9554  *
9555  * Input:
9556  *  gl            GetLine *  The resource object of gl_get_line().
9557  *  id      unsigned long    The identification number of the line to
9558  *                           be returned, where 0 denotes the first line
9559  *                           that was entered in the history list, and
9560  *                           each subsequently added line has a number
9561  *                           one greater than the previous one. For
9562  *                           the range of lines currently in the list,
9563  *                           see the gl_range_of_history() function.
9564  * Input/Output:
9565  *  line    GlHistoryLine *  A pointer to the variable in which to
9566  *                           return the details of the line.
9567  * Output:
9568  *  return            int    0 - The line is no longer in the history
9569  *                               list, and *line has not been changed.
9570  *                           1 - The requested line can be found in
9571  *                               *line. Note that line->line is part
9572  *                               of the history buffer, so a
9573  *                               private copy should be made if you
9574  *                               wish to use it after subsequent calls
9575  *                               to any functions that take *gl as an
9576  *                               argument.
9577  */
9578 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line)
9579 {
9580   sigset_t oldset; /* The signals that were blocked on entry to this function */
9581   int status;      /* The return status of this function */
9582 /*
9583  * Check the arguments.
9584  */
9585   if(!gl)
9586     return 0;
9587 /*
9588  * Block all signals while modifying the contents of gl.
9589  */
9590   if(gl_mask_signals(gl, &oldset))
9591     return 1;
9592 /*
9593  * Perform the lookup while signals are blocked.
9594  */
9595   status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line,
9596 			       &line->group, &line->timestamp);
9597   if(status)
9598     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9599 /*
9600  * Restore the process signal mask before returning.
9601  */
9602   gl_unmask_signals(gl, &oldset);
9603   return status;
9604 }
9605 
9606 /*.......................................................................
9607  * Query the state of the history list. Note that any of the input/output
9608  * pointers can be specified as NULL.
9609  *
9610  * Input:
9611  *  gl            GetLine *  The resource object of gl_get_line().
9612  * Input/Output:
9613  *  state  GlHistoryState *  A pointer to the variable in which to record
9614  *                           the return values.
9615  */
9616 void gl_state_of_history(GetLine *gl, GlHistoryState *state)
9617 {
9618   if(gl && state) {
9619     sigset_t oldset; /* The signals that were blocked on entry to this block */
9620 /*
9621  * Temporarily block all signals.
9622  */
9623     gl_mask_signals(gl, &oldset);
9624 /*
9625  * Lookup the status while signals are blocked.
9626  */
9627     _glh_state_of_history(gl->glh, &state->enabled, &state->group,
9628 			  &state->max_lines);
9629 /*
9630  * Restore the process signal mask before returning.
9631  */
9632     gl_unmask_signals(gl, &oldset);
9633   };
9634 }
9635 
9636 /*.......................................................................
9637  * Query the number and range of lines in the history buffer.
9638  *
9639  * Input:
9640  *  gl            GetLine *  The resource object of gl_get_line().
9641  *  range  GlHistoryRange *  A pointer to the variable in which to record
9642  *                           the return values. If range->nline=0, the
9643  *                           range of lines will be given as 0-0.
9644  */
9645 void gl_range_of_history(GetLine *gl, GlHistoryRange *range)
9646 {
9647   if(gl && range) {
9648     sigset_t oldset; /* The signals that were blocked on entry to this block */
9649 /*
9650  * Temporarily block all signals.
9651  */
9652     gl_mask_signals(gl, &oldset);
9653 /*
9654  * Lookup the information while signals are blocked.
9655  */
9656     _glh_range_of_history(gl->glh, &range->oldest, &range->newest,
9657 			  &range->nlines);
9658 /*
9659  * Restore the process signal mask before returning.
9660  */
9661     gl_unmask_signals(gl, &oldset);
9662   };
9663 }
9664 
9665 /*.......................................................................
9666  * Return the size of the history buffer and the amount of the
9667  * buffer that is currently in use.
9668  *
9669  * Input:
9670  *  gl         GetLine *  The gl_get_line() resource object.
9671  * Input/Output:
9672  *  GlHistorySize size *  A pointer to the variable in which to return
9673  *                        the results.
9674  */
9675 void gl_size_of_history(GetLine *gl, GlHistorySize *size)
9676 {
9677   if(gl && size) {
9678     sigset_t oldset; /* The signals that were blocked on entry to this block */
9679 /*
9680  * Temporarily block all signals.
9681  */
9682     gl_mask_signals(gl, &oldset);
9683 /*
9684  * Lookup the information while signals are blocked.
9685  */
9686     _glh_size_of_history(gl->glh, &size->size, &size->used);
9687 /*
9688  * Restore the process signal mask before returning.
9689  */
9690     gl_unmask_signals(gl, &oldset);
9691   };
9692 }
9693 
9694 /*.......................................................................
9695  * This is the action function that lists the contents of the history
9696  * list.
9697  */
9698 static KT_KEY_FN(gl_list_history)
9699 {
9700 /*
9701  * Start a new line.
9702  */
9703   if(gl_start_newline(gl, 1))
9704     return 1;
9705 /*
9706  * List history lines that belong to the current group.
9707  */
9708   _glh_show_history(gl->glh, gl_write_fn, gl, "%N  %T   %H\r\n", 0,
9709 		    count<=1 ? -1 : count);
9710 /*
9711  * Arrange for the input line to be redisplayed.
9712  */
9713   gl_queue_redisplay(gl);
9714   return 0;
9715 }
9716 
9717 /*.......................................................................
9718  * Specify whether text that users type should be displayed or hidden.
9719  * In the latter case, only the prompt is displayed, and the final
9720  * input line is not archived in the history list.
9721  *
9722  * Input:
9723  *  gl         GetLine *  The gl_get_line() resource object.
9724  *  enable         int     0 - Disable echoing.
9725  *                         1 - Enable echoing.
9726  *                        -1 - Just query the mode without changing it.
9727  * Output:
9728  *  return         int    The echoing disposition that was in effect
9729  *                        before this function was called:
9730  *                         0 - Echoing was disabled.
9731  *                         1 - Echoing was enabled.
9732  */
9733 int gl_echo_mode(GetLine *gl, int enable)
9734 {
9735   if(gl) {
9736     sigset_t oldset; /* The signals that were blocked on entry to this block */
9737     int was_echoing; /* The echoing disposition on entry to this function */
9738 /*
9739  * Temporarily block all signals.
9740  */
9741     gl_mask_signals(gl, &oldset);
9742 /*
9743  * Install the new disposition while signals are blocked.
9744  */
9745     was_echoing = gl->echo;
9746     if(enable >= 0)
9747       gl->echo = enable;
9748 /*
9749  * Restore the process signal mask before returning.
9750  */
9751     gl_unmask_signals(gl, &oldset);
9752 /*
9753  * Return the original echoing disposition.
9754  */
9755     return was_echoing;
9756   };
9757   return 1;
9758 }
9759 
9760 /*.......................................................................
9761  * Display the prompt.
9762  *
9763  * Input:
9764  *  gl         GetLine *  The resource object of gl_get_line().
9765  * Output:
9766  *  return         int    0 - OK.
9767  *                        1 - Error.
9768  */
9769 static int gl_display_prompt(GetLine *gl)
9770 {
9771   const char *pptr;       /* A pointer into gl->prompt[] */
9772   unsigned old_attr=0;    /* The current text display attributes */
9773   unsigned new_attr=0;    /* The requested text display attributes */
9774 /*
9775  * Temporarily switch to echoing output characters.
9776  */
9777   int kept_echo = gl->echo;
9778   gl->echo = 1;
9779 /*
9780  * In case the screen got messed up, send a carriage return to
9781  * put the cursor at the beginning of the current terminal line.
9782  */
9783   if(gl_print_control_sequence(gl, 1, gl->bol))
9784     return 1;
9785 /*
9786  * Mark the line as partially displayed.
9787  */
9788   gl->displayed = 1;
9789 /*
9790  * Write the prompt, using the currently selected prompt style.
9791  */
9792   switch(gl->prompt_style) {
9793   case GL_LITERAL_PROMPT:
9794     if(gl_print_string(gl, gl->prompt, '\0'))
9795       return 1;
9796     break;
9797   case GL_FORMAT_PROMPT:
9798     for(pptr=gl->prompt; *pptr; pptr++) {
9799 /*
9800  * Does the latest character appear to be the start of a directive?
9801  */
9802       if(*pptr == '%') {
9803 /*
9804  * Check for and act on attribute changing directives.
9805  */
9806 	switch(pptr[1]) {
9807 /*
9808  * Add or remove a text attribute from the new set of attributes.
9809  */
9810 	case 'B': case 'U': case 'S': case 'P': case 'F': case 'V':
9811 	case 'b': case 'u': case 's': case 'p': case 'f': case 'v':
9812 	  switch(*++pptr) {
9813 	  case 'B':           /* Switch to a bold font */
9814 	    new_attr |= GL_TXT_BOLD;
9815 	    break;
9816 	  case 'b':           /* Switch to a non-bold font */
9817 	    new_attr &= ~GL_TXT_BOLD;
9818 	    break;
9819 	  case 'U':           /* Start underlining */
9820 	    new_attr |= GL_TXT_UNDERLINE;
9821 	    break;
9822 	  case 'u':           /* Stop underlining */
9823 	    new_attr &= ~GL_TXT_UNDERLINE;
9824 	    break;
9825 	  case 'S':           /* Start highlighting */
9826 	    new_attr |= GL_TXT_STANDOUT;
9827 	    break;
9828 	  case 's':           /* Stop highlighting */
9829 	    new_attr &= ~GL_TXT_STANDOUT;
9830 	    break;
9831 	  case 'P':           /* Switch to a pale font */
9832 	    new_attr |= GL_TXT_DIM;
9833 	    break;
9834 	  case 'p':           /* Switch to a non-pale font */
9835 	    new_attr &= ~GL_TXT_DIM;
9836 	    break;
9837 	  case 'F':           /* Switch to a flashing font */
9838 	    new_attr |= GL_TXT_BLINK;
9839 	    break;
9840 	  case 'f':           /* Switch to a steady font */
9841 	    new_attr &= ~GL_TXT_BLINK;
9842 	    break;
9843 	  case 'V':           /* Switch to reverse video */
9844 	    new_attr |= GL_TXT_REVERSE;
9845 	    break;
9846 	  case 'v':           /* Switch out of reverse video */
9847 	    new_attr &= ~GL_TXT_REVERSE;
9848 	    break;
9849 	  };
9850 	  continue;
9851 /*
9852  * A literal % is represented by %%. Skip the leading %.
9853  */
9854 	case '%':
9855 	  pptr++;
9856 	  break;
9857 	};
9858       };
9859 /*
9860  * Many terminals, when asked to turn off a single text attribute, turn
9861  * them all off, so the portable way to turn one off individually is to
9862  * explicitly turn them all off, then specify those that we want from
9863  * scratch.
9864  */
9865       if(old_attr & ~new_attr) {
9866 	if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9867 	  return 1;
9868 	old_attr = 0;
9869       };
9870 /*
9871  * Install new text attributes?
9872  */
9873       if(new_attr != old_attr) {
9874 	if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) &&
9875 	   gl_print_control_sequence(gl, 1, gl->bold))
9876 	  return 1;
9877 	if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) &&
9878 	   gl_print_control_sequence(gl, 1, gl->underline))
9879 	  return 1;
9880 	if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) &&
9881 	   gl_print_control_sequence(gl, 1, gl->standout))
9882 	  return 1;
9883 	if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) &&
9884 	   gl_print_control_sequence(gl, 1, gl->dim))
9885 	  return 1;
9886 	if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) &&
9887 	   gl_print_control_sequence(gl, 1, gl->reverse))
9888 	  return 1;
9889 	if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) &&
9890 	   gl_print_control_sequence(gl, 1, gl->blink))
9891 	  return 1;
9892 	old_attr = new_attr;
9893       };
9894 /*
9895  * Display the latest character.
9896  */
9897       if(gl_print_char(gl, *pptr, pptr[1]))
9898 	return 1;
9899     };
9900 /*
9901  * Turn off all text attributes now that we have finished drawing
9902  * the prompt.
9903  */
9904     if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9905       return 1;
9906     break;
9907   };
9908 /*
9909  * Restore the original echo mode.
9910  */
9911   gl->echo = kept_echo;
9912 /*
9913  * The prompt has now been displayed at least once.
9914  */
9915   gl->prompt_changed = 0;
9916   return 0;
9917 }
9918 
9919 /*.......................................................................
9920  * This function can be called from gl_get_line() callbacks to have
9921  * the prompt changed when they return. It has no effect if gl_get_line()
9922  * is not currently being invoked.
9923  *
9924  * Input:
9925  *  gl         GetLine *  The resource object of gl_get_line().
9926  *  prompt  const char *  The new prompt.
9927  */
9928 void gl_replace_prompt(GetLine *gl, const char *prompt)
9929 {
9930   if(gl) {
9931     sigset_t oldset; /* The signals that were blocked on entry to this block */
9932 /*
9933  * Temporarily block all signals.
9934  */
9935     gl_mask_signals(gl, &oldset);
9936 /*
9937  * Replace the prompt.
9938  */
9939     _gl_replace_prompt(gl, prompt);
9940 /*
9941  * Restore the process signal mask before returning.
9942  */
9943     gl_unmask_signals(gl, &oldset);
9944   };
9945 }
9946 
9947 /*.......................................................................
9948  * This is the private body of the gl_replace_prompt() function. It
9949  * assumes that the caller has checked its arguments and blocked the
9950  * delivery of signals.
9951  */
9952 static void _gl_replace_prompt(GetLine *gl, const char *prompt)
9953 {
9954   size_t size;
9955 
9956 /*
9957  * Substitute an empty prompt?
9958  */
9959   if(!prompt)
9960     prompt = "";
9961 /*
9962  * Gaurd against aliasing between prompt and gl->prompt.
9963  */
9964   if(gl->prompt != prompt) {
9965 /*
9966  * Get the length of the new prompt string.
9967  */
9968     size_t slen = strlen(prompt);
9969 /*
9970  * If needed, allocate a new buffer for the prompt string.
9971  */
9972     size = sizeof(char) * (slen + 1);
9973     if(!gl->prompt || slen > strlen(gl->prompt)) {
9974       char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size);
9975       if(!new_prompt)
9976 	return;
9977       gl->prompt = new_prompt;
9978     };
9979 /*
9980  * Make a copy of the new prompt.
9981  */
9982     strlcpy(gl->prompt, prompt, size);
9983   };
9984 /*
9985  * Record the statistics of the new prompt.
9986  */
9987   gl->prompt_len = gl_displayed_prompt_width(gl);
9988   gl->prompt_changed = 1;
9989   gl_queue_redisplay(gl);
9990   return;
9991 }
9992 
9993 /*.......................................................................
9994  * Work out the length of the current prompt on the terminal, according
9995  * to the current prompt formatting style.
9996  *
9997  * Input:
9998  *  gl       GetLine *  The resource object of this library.
9999  * Output:
10000  *  return       int    The number of displayed characters.
10001  */
10002 static int gl_displayed_prompt_width(GetLine *gl)
10003 {
10004   int slen=0;         /* The displayed number of characters */
10005   const char *pptr;   /* A pointer into prompt[] */
10006 /*
10007  * The length differs according to the prompt display style.
10008  */
10009   switch(gl->prompt_style) {
10010   case GL_LITERAL_PROMPT:
10011     return gl_displayed_string_width(gl, gl->prompt, -1, 0);
10012     break;
10013   case GL_FORMAT_PROMPT:
10014 /*
10015  * Add up the length of the displayed string, while filtering out
10016  * attribute directives.
10017  */
10018     for(pptr=gl->prompt; *pptr; pptr++) {
10019 /*
10020  * Does the latest character appear to be the start of a directive?
10021  */
10022       if(*pptr == '%') {
10023 /*
10024  * Check for and skip attribute changing directives.
10025  */
10026 	switch(pptr[1]) {
10027 	case 'B': case 'b': case 'U': case 'u': case 'S': case 's':
10028 	  pptr++;
10029 	  continue;
10030 /*
10031  * A literal % is represented by %%. Skip the leading %.
10032  */
10033 	case '%':
10034 	  pptr++;
10035 	  break;
10036 	};
10037       };
10038       slen += gl_displayed_char_width(gl, *pptr, slen);
10039     };
10040     break;
10041   };
10042   return slen;
10043 }
10044 
10045 /*.......................................................................
10046  * Specify whether to heed text attribute directives within prompt
10047  * strings.
10048  *
10049  * Input:
10050  *  gl           GetLine *  The resource object of gl_get_line().
10051  *  style  GlPromptStyle    The style of prompt (see the definition of
10052  *                          GlPromptStyle in libtecla.h for details).
10053  */
10054 void gl_prompt_style(GetLine *gl, GlPromptStyle style)
10055 {
10056   if(gl) {
10057     sigset_t oldset; /* The signals that were blocked on entry to this block */
10058 /*
10059  * Temporarily block all signals.
10060  */
10061     gl_mask_signals(gl, &oldset);
10062 /*
10063  * Install the new style in gl while signals are blocked.
10064  */
10065     if(style != gl->prompt_style) {
10066       gl->prompt_style = style;
10067       gl->prompt_len = gl_displayed_prompt_width(gl);
10068       gl->prompt_changed = 1;
10069       gl_queue_redisplay(gl);
10070     };
10071 /*
10072  * Restore the process signal mask before returning.
10073  */
10074     gl_unmask_signals(gl, &oldset);
10075   };
10076 }
10077 
10078 /*.......................................................................
10079  * Tell gl_get_line() how to respond to a given signal. This can be used
10080  * both to override the default responses to signals that gl_get_line()
10081  * normally catches and to add new signals to the list that are to be
10082  * caught.
10083  *
10084  * Input:
10085  *  gl           GetLine *  The resource object of gl_get_line().
10086  *  signo            int    The number of the signal to be caught.
10087  *  flags       unsigned    A bitwise union of GlSignalFlags enumerators.
10088  *  after  GlAfterSignal    What to do after the application's signal
10089  *                          handler has been called.
10090  *  errno_value      int    The value to set errno to.
10091  * Output:
10092  *  return           int    0 - OK.
10093  *                          1 - Error.
10094  */
10095 int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10096 		   GlAfterSignal after, int errno_value)
10097 {
10098   sigset_t oldset; /* The signals that were blocked on entry to this function */
10099   int status;      /* The return status of this function */
10100 /*
10101  * Check the arguments.
10102  */
10103   if(!gl) {
10104     errno = EINVAL;
10105     return 1;
10106   };
10107 /*
10108  * Block all signals while modifying the contents of gl.
10109  */
10110   if(gl_mask_signals(gl, &oldset))
10111     return 1;
10112 /*
10113  * Perform the modification while signals are blocked.
10114  */
10115   status = _gl_trap_signal(gl, signo, flags, after, errno_value);
10116 /*
10117  * Restore the process signal mask before returning.
10118  */
10119   gl_unmask_signals(gl, &oldset);
10120   return status;
10121 }
10122 
10123 /*.......................................................................
10124  * This is the private body of the gl_trap_signal() function. It
10125  * assumes that the caller has checked its arguments and blocked the
10126  * delivery of signals.
10127  */
10128 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10129 			   GlAfterSignal after, int errno_value)
10130 {
10131   GlSignalNode *sig;
10132 /*
10133  * Complain if an attempt is made to trap untrappable signals.
10134  * These would otherwise cause errors later in gl_mask_signals().
10135  */
10136   if(0
10137 #ifdef SIGKILL
10138      || signo==SIGKILL
10139 #endif
10140 #ifdef SIGBLOCK
10141      || signo==SIGBLOCK
10142 #endif
10143      ) {
10144     return 1;
10145   };
10146 /*
10147  * See if the signal has already been registered.
10148  */
10149   for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next)
10150     ;
10151 /*
10152  * If the signal hasn't already been registered, allocate a node for
10153  * it.
10154  */
10155   if(!sig) {
10156     sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem);
10157     if(!sig)
10158       return 1;
10159 /*
10160  * Add the new node to the head of the list.
10161  */
10162     sig->next = gl->sigs;
10163     gl->sigs = sig;
10164 /*
10165  * Record the signal number.
10166  */
10167     sig->signo = signo;
10168 /*
10169  * Create a signal set that includes just this signal.
10170  */
10171     sigemptyset(&sig->proc_mask);
10172     if(sigaddset(&sig->proc_mask, signo) == -1) {
10173       _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
10174       sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10175       return 1;
10176     };
10177 /*
10178  * Add the signal to the bit-mask of signals being trapped.
10179  */
10180     sigaddset(&gl->all_signal_set, signo);
10181   };
10182 /*
10183  * Record the new signal attributes.
10184  */
10185   sig->flags = flags;
10186   sig->after = after;
10187   sig->errno_value = errno_value;
10188   return 0;
10189 }
10190 
10191 /*.......................................................................
10192  * Remove a signal from the list of signals that gl_get_line() traps.
10193  *
10194  * Input:
10195  *  gl           GetLine *  The resource object of gl_get_line().
10196  *  signo            int    The number of the signal to be ignored.
10197  * Output:
10198  *  return           int    0 - OK.
10199  *                          1 - Error.
10200  */
10201 int gl_ignore_signal(GetLine *gl, int signo)
10202 {
10203   GlSignalNode *sig;  /* The gl->sigs list node of the specified signal */
10204   GlSignalNode *prev; /* The node that precedes sig in the list */
10205   sigset_t oldset;    /* The signals that were blocked on entry to this */
10206                       /*  function. */
10207 /*
10208  * Check the arguments.
10209  */
10210   if(!gl) {
10211     errno = EINVAL;
10212     return 1;
10213   };
10214 /*
10215  * Block all signals while modifying the contents of gl.
10216  */
10217   if(gl_mask_signals(gl, &oldset))
10218     return 1;
10219 /*
10220  * Find the node of the gl->sigs list which records the disposition
10221  * of the specified signal.
10222  */
10223   for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo;
10224       prev=sig,sig=sig->next)
10225     ;
10226   if(sig) {
10227 /*
10228  * Remove the node from the list.
10229  */
10230     if(prev)
10231       prev->next = sig->next;
10232     else
10233       gl->sigs = sig->next;
10234 /*
10235  * Return the node to the freelist.
10236  */
10237     sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10238 /*
10239  * Remove the signal from the bit-mask union of signals being trapped.
10240  */
10241     sigdelset(&gl->all_signal_set, signo);
10242   };
10243 /*
10244  * Restore the process signal mask before returning.
10245  */
10246   gl_unmask_signals(gl, &oldset);
10247   return 0;
10248 }
10249 
10250 /*.......................................................................
10251  * This function is called when an input line has been completed. It
10252  * appends the specified newline character, terminates the line,
10253  * records the line in the history buffer if appropriate, and positions
10254  * the terminal cursor at the start of the next line.
10255  *
10256  * Input:
10257  *  gl           GetLine *  The resource object of gl_get_line().
10258  *  newline_char     int    The newline character to add to the end
10259  *                          of the line.
10260  * Output:
10261  *  return           int    0 - OK.
10262  *                          1 - Error.
10263  */
10264 static int gl_line_ended(GetLine *gl, int newline_char)
10265 {
10266 /*
10267  * If the newline character is printable, display it at the end of
10268  * the line, and add it to the input line buffer.
10269  */
10270   if(isprint((int)(unsigned char) newline_char)) {
10271     if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char))
10272       return 1;
10273   } else {
10274 /*
10275  * Otherwise just append a newline character to the input line buffer.
10276  */
10277     newline_char = '\n';
10278     gl_buffer_char(gl, newline_char, gl->ntotal);
10279   };
10280 /*
10281  * Add the line to the history buffer if it was entered with a
10282  * newline character.
10283  */
10284   if(gl->echo && gl->automatic_history && newline_char=='\n')
10285     (void) _gl_append_history(gl, gl->line);
10286 /*
10287  * Except when depending on the system-provided line editing, start a new
10288  * line after the end of the line that has just been entered.
10289  */
10290   if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1))
10291     return 1;
10292 /*
10293  * Record the successful return status.
10294  */
10295   gl_record_status(gl, GLR_NEWLINE, 0);
10296 /*
10297  * Attempt to flush any pending output.
10298  */
10299   (void) gl_flush_output(gl);
10300 /*
10301  * The next call to gl_get_line() will write the prompt for a new line
10302  * (or continue the above flush if incomplete), so if we manage to
10303  * flush the terminal now, report that we are waiting to write to the
10304  * terminal.
10305  */
10306   gl->pending_io = GLP_WRITE;
10307   return 0;
10308 }
10309 
10310 /*.......................................................................
10311  * Return the last signal that was caught by the most recent call to
10312  * gl_get_line(), or -1 if no signals were caught. This is useful if
10313  * gl_get_line() returns errno=EINTR and you need to find out what signal
10314  * caused it to abort.
10315  *
10316  * Input:
10317  *  gl           GetLine *  The resource object of gl_get_line().
10318  * Output:
10319  *  return           int    The last signal caught by the most recent
10320  *                          call to gl_get_line(), or -1 if no signals
10321  *                          were caught.
10322  */
10323 int gl_last_signal(GetLine *gl)
10324 {
10325   int signo = -1;   /* The requested signal number */
10326   if(gl) {
10327     sigset_t oldset; /* The signals that were blocked on entry to this block */
10328 /*
10329  * Temporarily block all signals.
10330  */
10331     gl_mask_signals(gl, &oldset);
10332 /*
10333  * Access gl now that signals are blocked.
10334  */
10335     signo = gl->last_signal;
10336 /*
10337  * Restore the process signal mask before returning.
10338  */
10339     gl_unmask_signals(gl, &oldset);
10340   };
10341   return signo;
10342 }
10343 
10344 /*.......................................................................
10345  * Prepare to edit a new line.
10346  *
10347  * Input:
10348  *  gl         GetLine *  The resource object of this library.
10349  *  prompt        char *  The prompt to prefix the line with, or NULL to
10350  *                        use the same prompt that was used by the previous
10351  *                        line.
10352  *  start_line    char *  The initial contents of the input line, or NULL
10353  *                        if it should start out empty.
10354  *  start_pos      int    If start_line isn't NULL, this specifies the
10355  *                        index of the character over which the cursor
10356  *                        should initially be positioned within the line.
10357  *                        If you just want it to follow the last character
10358  *                        of the line, send -1.
10359  * Output:
10360  *  return    int    0 - OK.
10361  *                   1 - Error.
10362  */
10363 static int gl_present_line(GetLine *gl, const char *prompt,
10364 			   const char *start_line, int start_pos)
10365 {
10366 /*
10367  * Reset the properties of the line.
10368  */
10369   gl_reset_input_line(gl);
10370 /*
10371  * Record the new prompt and its displayed width.
10372  */
10373   if(prompt)
10374     _gl_replace_prompt(gl, prompt);
10375 /*
10376  * Reset the history search pointers.
10377  */
10378   if(_glh_cancel_search(gl->glh)) {
10379     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
10380     return 1;
10381   };
10382 /*
10383  * If the previous line was entered via the repeat-history action,
10384  * preload the specified history line.
10385  */
10386   if(gl->preload_history) {
10387     gl->preload_history = 0;
10388     if(gl->preload_id) {
10389       if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) {
10390 	gl_update_buffer(gl);          /* Compute gl->ntotal etc.. */
10391 	gl->buff_curpos = gl->ntotal;
10392       } else {
10393 	gl_truncate_buffer(gl, 0);
10394       };
10395       gl->preload_id = 0;
10396     };
10397 /*
10398  * Present a specified initial line?
10399  */
10400   } else if(start_line) {
10401     char *cptr;      /* A pointer into gl->line[] */
10402 /*
10403  * Measure the length of the starting line.
10404  */
10405     int start_len = strlen(start_line);
10406 /*
10407  * If the length of the line is greater than the available space,
10408  * truncate it.
10409  */
10410     if(start_len > gl->linelen)
10411       start_len = gl->linelen;
10412 /*
10413  * Load the line into the buffer.
10414  */
10415     if(start_line != gl->line)
10416       gl_buffer_string(gl, start_line, start_len, 0);
10417 /*
10418  * Strip off any trailing newline and carriage return characters.
10419  */
10420     for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line &&
10421 	(*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--)
10422       ;
10423     gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal);
10424 /*
10425  * Where should the cursor be placed within the line?
10426  */
10427     if(start_pos < 0 || start_pos > gl->ntotal) {
10428       if(gl_place_cursor(gl, gl->ntotal))
10429 	return 1;
10430     } else {
10431       if(gl_place_cursor(gl, start_pos))
10432 	return 1;
10433     };
10434 /*
10435  * Clear the input line?
10436  */
10437   } else {
10438     gl_truncate_buffer(gl, 0);
10439   };
10440 /*
10441  * Arrange for the line to be displayed by gl_flush_output().
10442  */
10443   gl_queue_redisplay(gl);
10444 /*
10445  * Update the display.
10446  */
10447   return gl_flush_output(gl);
10448 }
10449 
10450 /*.......................................................................
10451  * Reset all line input parameters for a new input line.
10452  *
10453  * Input:
10454  *  gl      GetLine *  The line editor resource object.
10455  */
10456 static void gl_reset_input_line(GetLine *gl)
10457 {
10458   gl->ntotal = 0;
10459   gl->line[0] = '\0';
10460   gl->buff_curpos = 0;
10461   gl->term_curpos = 0;
10462   gl->term_len = 0;
10463   gl->insert_curpos = 0;
10464   gl->number = -1;
10465   gl->displayed = 0;
10466   gl->endline = 0;
10467   gl->redisplay = 0;
10468   gl->postpone = 0;
10469   gl->nbuf = 0;
10470   gl->nread = 0;
10471   gl->vi.command = 0;
10472   gl->vi.undo.line[0] = '\0';
10473   gl->vi.undo.ntotal = 0;
10474   gl->vi.undo.buff_curpos = 0;
10475   gl->vi.repeat.action.fn = 0;
10476   gl->vi.repeat.action.data = 0;
10477   gl->last_signal = -1;
10478 }
10479 
10480 /*.......................................................................
10481  * Print an informational message to the terminal, after starting a new
10482  * line.
10483  *
10484  * Input:
10485  *  gl      GetLine *  The line editor resource object.
10486  *  ...  const char *  Zero or more strings to be printed.
10487  *  ...        void *  The last argument must always be GL_END_INFO.
10488  * Output:
10489  *  return      int    0 - OK.
10490  *                     1 - Error.
10491  */
10492 static int gl_print_info(GetLine *gl, ...)
10493 {
10494   va_list ap;     /* The variable argument list */
10495   const char *s;  /* The string being printed */
10496   int waserr = 0; /* True after an error */
10497 /*
10498  * Only display output when echoing is on.
10499  */
10500   if(gl->echo) {
10501 /*
10502  * Skip to the start of the next empty line before displaying the message.
10503  */
10504     if(gl_start_newline(gl, 1))
10505       return 1;
10506 /*
10507  * Display the list of provided messages.
10508  */
10509     va_start(ap, gl);
10510     while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO)
10511       waserr = gl_print_raw_string(gl, 1, s, -1);
10512     va_end(ap);
10513 /*
10514  * Start a newline.
10515  */
10516     waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1);
10517 /*
10518  * Arrange for the input line to be redrawn.
10519  */
10520     gl_queue_redisplay(gl);
10521   };
10522   return waserr;
10523 }
10524 
10525 /*.......................................................................
10526  * Go to the start of the next empty line, ready to output miscellaneous
10527  * text to the screen.
10528  *
10529  * Note that when async-signal safety is required, the 'buffered'
10530  * argument must be 0.
10531  *
10532  * Input:
10533  *  gl          GetLine *  The line editor resource object.
10534  *  buffered        int    If true, used buffered I/O when writing to
10535  *                         the terminal. Otherwise use async-signal-safe
10536  *                         unbuffered I/O.
10537  * Output:
10538  *  return          int    0 - OK.
10539  *                         1 - Error.
10540  */
10541 static int gl_start_newline(GetLine *gl, int buffered)
10542 {
10543   int waserr = 0;  /* True after any I/O error */
10544 /*
10545  * Move the cursor to the start of the terminal line that follows the
10546  * last line of the partially enterred line. In order that this
10547  * function remain async-signal safe when write_fn is signal safe, we
10548  * can't call our normal output functions, since they call tputs(),
10549  * who's signal saftey isn't defined. Fortunately, we can simply use
10550  * \r and \n to move the cursor to the right place.
10551  */
10552   if(gl->displayed) {   /* Is an input line currently displayed? */
10553 /*
10554  * On which terminal lines are the cursor and the last character of the
10555  * input line?
10556  */
10557     int curs_line = gl->term_curpos / gl->ncolumn;
10558     int last_line = gl->term_len / gl->ncolumn;
10559 /*
10560  * Move the cursor to the start of the line that follows the last
10561  * terminal line that is occupied by the input line.
10562  */
10563     for( ; curs_line < last_line + 1; curs_line++)
10564       waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1);
10565     waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1);
10566 /*
10567  * Mark the line as no longer displayed.
10568  */
10569     gl_line_erased(gl);
10570   };
10571   return waserr;
10572 }
10573 
10574 /*.......................................................................
10575  * The callback through which all terminal output is routed.
10576  * This simply appends characters to a queue buffer, which is
10577  * subsequently flushed to the output channel by gl_flush_output().
10578  *
10579  * Input:
10580  *  data     void *  The pointer to a GetLine line editor resource object
10581  *                   cast to (void *).
10582  *  s  const char *  The string to be written.
10583  *  n         int    The number of characters to write from s[].
10584  * Output:
10585  *  return    int    The number of characters written. This will always
10586  *                   be equal to 'n' unless an error occurs.
10587  */
10588 static GL_WRITE_FN(gl_write_fn)
10589 {
10590   GetLine *gl = (GetLine *) data;
10591   int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl);
10592   if(ndone != n)
10593     _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG);
10594   return ndone;
10595 }
10596 
10597 /*.......................................................................
10598  * Ask gl_get_line() what caused it to return.
10599  *
10600  * Input:
10601  *  gl             GetLine *  The line editor resource object.
10602  * Output:
10603  *  return  GlReturnStatus    The return status of the last call to
10604  *                            gl_get_line().
10605  */
10606 GlReturnStatus gl_return_status(GetLine *gl)
10607 {
10608   GlReturnStatus rtn_status = GLR_ERROR;   /* The requested status */
10609   if(gl) {
10610     sigset_t oldset; /* The signals that were blocked on entry to this block */
10611 /*
10612  * Temporarily block all signals.
10613  */
10614     gl_mask_signals(gl, &oldset);
10615 /*
10616  * Access gl while signals are blocked.
10617  */
10618     rtn_status = gl->rtn_status;
10619 /*
10620  * Restore the process signal mask before returning.
10621  */
10622     gl_unmask_signals(gl, &oldset);
10623   };
10624   return rtn_status;
10625 }
10626 
10627 /*.......................................................................
10628  * In non-blocking server-I/O mode, this function should be called
10629  * from the application's external event loop to see what type of
10630  * terminal I/O is being waited for by gl_get_line(), and thus what
10631  * direction of I/O to wait for with select() or poll().
10632  *
10633  * Input:
10634  *  gl          GetLine *  The resource object of gl_get_line().
10635  * Output:
10636  *  return  GlPendingIO    The type of pending I/O being waited for.
10637  */
10638 GlPendingIO gl_pending_io(GetLine *gl)
10639 {
10640   GlPendingIO pending_io = GLP_WRITE;   /* The requested information */
10641   if(gl) {
10642     sigset_t oldset; /* The signals that were blocked on entry to this block */
10643 /*
10644  * Temporarily block all signals.
10645  */
10646     gl_mask_signals(gl, &oldset);
10647 /*
10648  * Access gl while signals are blocked.
10649  */
10650     pending_io = gl->pending_io;
10651 /*
10652  * Restore the process signal mask before returning.
10653  */
10654     gl_unmask_signals(gl, &oldset);
10655   };
10656   return pending_io;
10657 }
10658 
10659 /*.......................................................................
10660  * In server mode, this function configures the terminal for non-blocking
10661  * raw terminal I/O. In normal I/O mode it does nothing.
10662  *
10663  * Callers of this function must be careful to trap all signals that
10664  * terminate or suspend the program, and call gl_normal_io()
10665  * from the corresponding signal handlers in order to restore the
10666  * terminal to its original settings before the program is terminated
10667  * or suspended. They should also trap the SIGCONT signal to detect
10668  * when the program resumes, and ensure that its signal handler
10669  * call gl_raw_io() to redisplay the line and resume editing.
10670  *
10671  * This function is async signal safe.
10672  *
10673  * Input:
10674  *  gl      GetLine *  The line editor resource object.
10675  * Output:
10676  *  return      int    0 - OK.
10677  *                     1 - Error.
10678  */
10679 int gl_raw_io(GetLine *gl)
10680 {
10681   sigset_t oldset; /* The signals that were blocked on entry to this function */
10682   int status;      /* The return status of _gl_raw_io() */
10683 /*
10684  * Check the arguments.
10685  */
10686   if(!gl) {
10687     errno = EINVAL;
10688     return 1;
10689   };
10690 /*
10691  * Block all signals.
10692  */
10693   if(gl_mask_signals(gl, &oldset))
10694     return 1;
10695 /*
10696  * Don't allow applications to switch into raw mode unless in server mode.
10697  */
10698   if(gl->io_mode != GL_SERVER_MODE) {
10699     _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode",
10700 		    END_ERR_MSG);
10701     errno = EPERM;
10702     status = 1;
10703   } else {
10704 /*
10705  * Execute the private body of the function while signals are blocked.
10706  */
10707     status = _gl_raw_io(gl, 1);
10708   };
10709 /*
10710  * Restore the process signal mask.
10711  */
10712   gl_unmask_signals(gl, &oldset);
10713   return status;
10714 }
10715 
10716 /*.......................................................................
10717  * This is the private body of the public function, gl_raw_io().
10718  * It assumes that the caller has checked its arguments and blocked the
10719  * delivery of signals.
10720  *
10721  * This function is async signal safe.
10722  */
10723 static int _gl_raw_io(GetLine *gl, int redisplay)
10724 {
10725 /*
10726  * If we are already in the correct mode, do nothing.
10727  */
10728   if(gl->raw_mode)
10729     return 0;
10730 /*
10731  * Switch the terminal to raw mode.
10732  */
10733   if(gl->is_term && gl_raw_terminal_mode(gl))
10734     return 1;
10735 /*
10736  * Switch to non-blocking I/O mode?
10737  */
10738   if(gl->io_mode==GL_SERVER_MODE &&
10739      (gl_nonblocking_io(gl, gl->input_fd) ||
10740       gl_nonblocking_io(gl, gl->output_fd) ||
10741       (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) {
10742     if(gl->is_term)
10743       gl_restore_terminal_attributes(gl);
10744     return 1;
10745   };
10746 /*
10747  * If an input line is being entered, arrange for it to be
10748  * displayed.
10749  */
10750   if(redisplay) {
10751     gl->postpone = 0;
10752     gl_queue_redisplay(gl);
10753   };
10754   return 0;
10755 }
10756 
10757 /*.......................................................................
10758  * Restore the terminal to the state that it had when
10759  * gl_raw_io() was last called. After calling
10760  * gl_raw_io(), this function must be called before
10761  * terminating or suspending the program, and before attempting other
10762  * uses of the terminal from within the program. See gl_raw_io()
10763  * for more details.
10764  *
10765  * Input:
10766  *  gl      GetLine *  The line editor resource object.
10767  * Output:
10768  *  return      int    0 - OK.
10769  *                     1 - Error.
10770  */
10771 int gl_normal_io(GetLine *gl)
10772 {
10773   sigset_t oldset; /* The signals that were blocked on entry to this function */
10774   int status;      /* The return status of _gl_normal_io() */
10775 /*
10776  * Check the arguments.
10777  */
10778   if(!gl) {
10779     errno = EINVAL;
10780     return 1;
10781   };
10782 /*
10783  * Block all signals.
10784  */
10785   if(gl_mask_signals(gl, &oldset))
10786     return 1;
10787 /*
10788  * Execute the private body of the function while signals are blocked.
10789  */
10790   status = _gl_normal_io(gl);
10791 /*
10792  * Restore the process signal mask.
10793  */
10794   gl_unmask_signals(gl, &oldset);
10795   return status;
10796 }
10797 
10798 /*.......................................................................
10799  * This is the private body of the public function, gl_normal_io().
10800  * It assumes that the caller has checked its arguments and blocked the
10801  * delivery of signals.
10802  */
10803 static int _gl_normal_io(GetLine *gl)
10804 {
10805 /*
10806  * If we are already in normal mode, do nothing.
10807  */
10808   if(!gl->raw_mode)
10809     return 0;
10810 /*
10811  * Postpone subsequent redisplays until after _gl_raw_io(gl, 1)
10812  * is next called.
10813  */
10814   gl->postpone = 1;
10815 /*
10816  * Switch back to blocking I/O. Note that this is essential to do
10817  * here, because when using non-blocking I/O, the terminal output
10818  * buffering code can't always make room for new output without calling
10819  * malloc(), and a call to malloc() would mean that this function
10820  * couldn't safely be called from signal handlers.
10821  */
10822   if(gl->io_mode==GL_SERVER_MODE &&
10823      (gl_blocking_io(gl, gl->input_fd) ||
10824       gl_blocking_io(gl, gl->output_fd) ||
10825       (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp)))))
10826     return 1;
10827 /*
10828  * Move the cursor to the next empty terminal line. Note that
10829  * unbuffered I/O is requested, to ensure that gl_start_newline() be
10830  * async-signal-safe.
10831  */
10832   if(gl->is_term && gl_start_newline(gl, 0))
10833     return 1;
10834 /*
10835  * Switch the terminal to normal mode.
10836  */
10837   if(gl->is_term && gl_restore_terminal_attributes(gl)) {
10838 /*
10839  * On error, revert to non-blocking I/O if needed, so that on failure
10840  * we remain in raw mode.
10841  */
10842     if(gl->io_mode==GL_SERVER_MODE) {
10843       gl_nonblocking_io(gl, gl->input_fd);
10844       gl_nonblocking_io(gl, gl->output_fd);
10845       if(gl->file_fp)
10846 	gl_nonblocking_io(gl, fileno(gl->file_fp));
10847     };
10848     return 1;
10849   };
10850   return 0;
10851 }
10852 
10853 /*.......................................................................
10854  * This function allows you to install an additional completion
10855  * action, or to change the completion function of an existing
10856  * one. This should be called before the first call to gl_get_line()
10857  * so that the name of the action be defined before the user's
10858  * configuration file is read.
10859  *
10860  * Input:
10861  *  gl            GetLine *  The resource object of the command-line input
10862  *                           module.
10863  *  data             void *  This is passed to match_fn() whenever it is
10864  *                           called. It could, for example, point to a
10865  *                           symbol table that match_fn() would look up
10866  *                           matches in.
10867  *  match_fn   CplMatchFn *  The function that will identify the prefix
10868  *                           to be completed from the input line, and
10869  *                           report matching symbols.
10870  *  list_only         int    If non-zero, install an action that only lists
10871  *                           possible completions, rather than attempting
10872  *                           to perform the completion.
10873  *  name       const char *  The name with which users can refer to the
10874  *                           binding in tecla configuration files.
10875  *  keyseq     const char *  Either NULL, or a key sequence with which
10876  *                           to invoke the binding. This should be
10877  *                           specified in the same manner as key-sequences
10878  *                           in tecla configuration files (eg. "M-^I").
10879  * Output:
10880  *  return            int    0 - OK.
10881  *                           1 - Error.
10882  */
10883 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10884 			 int list_only, const char *name, const char *keyseq)
10885 {
10886   sigset_t oldset; /* The signals that were blocked on entry to this function */
10887   int status;      /* The return status of _gl_completion_action() */
10888 /*
10889  * Check the arguments.
10890  */
10891   if(!gl || !name || !match_fn) {
10892     errno = EINVAL;
10893     return 1;
10894   };
10895 /*
10896  * Block all signals.
10897  */
10898   if(gl_mask_signals(gl, &oldset))
10899     return 1;
10900 /*
10901  * Install the new action while signals are blocked.
10902  */
10903   status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq);
10904 /*
10905  * Restore the process signal mask.
10906  */
10907   gl_unmask_signals(gl, &oldset);
10908   return status;
10909 }
10910 
10911 /*.......................................................................
10912  * This is the private body of the public function, gl_completion_action().
10913  * It assumes that the caller has checked its arguments and blocked the
10914  * delivery of signals.
10915  */
10916 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10917 				 int list_only, const char *name,
10918 				 const char *keyseq)
10919 {
10920   KtKeyFn *current_fn;      /* An existing action function */
10921   void *current_data;       /* The action-function callback data */
10922 /*
10923  * Which action function is desired?
10924  */
10925   KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word;
10926 /*
10927  * Is there already an action of the specified name?
10928  */
10929   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
10930 /*
10931  * If the action has the same type as the one being requested,
10932  * simply change the contents of its GlCplCallback callback data.
10933  */
10934     if(current_fn == action_fn) {
10935       GlCplCallback *cb = (GlCplCallback *) current_data;
10936       cb->fn = match_fn;
10937       cb->data = data;
10938     } else {
10939       errno = EINVAL;
10940       _err_record_msg(gl->err,
10941         "Illegal attempt to change the type of an existing completion action",
10942         END_ERR_MSG);
10943       return 1;
10944     };
10945 /*
10946  * No existing action has the specified name.
10947  */
10948   } else {
10949 /*
10950  * Allocate a new GlCplCallback callback object.
10951  */
10952     GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem);
10953     if(!cb) {
10954       errno = ENOMEM;
10955       _err_record_msg(gl->err, "Insufficient memory to add completion action",
10956 		      END_ERR_MSG);
10957       return 1;
10958     };
10959 /*
10960  * Record the completion callback data.
10961  */
10962     cb->fn = match_fn;
10963     cb->data = data;
10964 /*
10965  * Attempt to register the new action.
10966  */
10967     if(_kt_set_action(gl->bindings, name, action_fn, cb)) {
10968       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10969       _del_FreeListNode(gl->cpl_mem, (void *) cb);
10970       return 1;
10971     };
10972   };
10973 /*
10974  * Bind the action to a given key-sequence?
10975  */
10976   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
10977     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10978     return 1;
10979   };
10980   return 0;
10981 }
10982 
10983 /*.......................................................................
10984  * Register an application-provided function as an action function.
10985  * This should preferably be called before the first call to gl_get_line()
10986  * so that the name of the action becomes defined before the user's
10987  * configuration file is read.
10988  *
10989  * Input:
10990  *  gl            GetLine *  The resource object of the command-line input
10991  *                           module.
10992  *  data             void *  Arbitrary application-specific callback
10993  *                           data to be passed to the callback
10994  *                           function, fn().
10995  *  fn         GlActionFn *  The application-specific function that
10996  *                           implements the action. This will be invoked
10997  *                           whenever the user presses any
10998  *                           key-sequence which is bound to this action.
10999  *  name       const char *  The name with which users can refer to the
11000  *                           binding in tecla configuration files.
11001  *  keyseq     const char *  The key sequence with which to invoke
11002  *                           the binding. This should be specified in the
11003  *                           same manner as key-sequences in tecla
11004  *                           configuration files (eg. "M-^I").
11005  * Output:
11006  *  return            int    0 - OK.
11007  *                           1 - Error.
11008  */
11009 int gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11010                        const char *name, const char *keyseq)
11011 {
11012   sigset_t oldset; /* The signals that were blocked on entry to this function */
11013   int status;      /* The return status of _gl_register_action() */
11014 /*
11015  * Check the arguments.
11016  */
11017   if(!gl || !name || !fn) {
11018     errno = EINVAL;
11019     return 1;
11020   };
11021 /*
11022  * Block all signals.
11023  */
11024   if(gl_mask_signals(gl, &oldset))
11025     return 1;
11026 /*
11027  * Install the new action while signals are blocked.
11028  */
11029   status = _gl_register_action(gl, data, fn, name, keyseq);
11030 /*
11031  * Restore the process signal mask.
11032  */
11033   gl_unmask_signals(gl, &oldset);
11034   return status;
11035 }
11036 
11037 /*.......................................................................
11038  * This is the private body of the public function, gl_register_action().
11039  * It assumes that the caller has checked its arguments and blocked the
11040  * delivery of signals.
11041  */
11042 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11043 			       const char *name, const char *keyseq)
11044 {
11045   KtKeyFn *current_fn;      /* An existing action function */
11046   void *current_data;       /* The action-function callback data */
11047 /*
11048  * Get the action function which actually runs the application-provided
11049  * function.
11050  */
11051   KtKeyFn *action_fn = gl_run_external_action;
11052 /*
11053  * Is there already an action of the specified name?
11054  */
11055   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
11056 /*
11057  * If the action has the same type as the one being requested,
11058  * simply change the contents of its GlCplCallback callback data.
11059  */
11060     if(current_fn == action_fn) {
11061       GlExternalAction *a = (GlExternalAction *) current_data;
11062       a->fn = fn;
11063       a->data = data;
11064     } else {
11065       errno = EINVAL;
11066       _err_record_msg(gl->err,
11067         "Illegal attempt to change the type of an existing action",
11068 		      END_ERR_MSG);
11069       return 1;
11070     };
11071 /*
11072  * No existing action has the specified name.
11073  */
11074   } else {
11075 /*
11076  * Allocate a new GlCplCallback callback object.
11077  */
11078     GlExternalAction *a =
11079       (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem);
11080     if(!a) {
11081       errno = ENOMEM;
11082       _err_record_msg(gl->err, "Insufficient memory to add completion action",
11083 		      END_ERR_MSG);
11084       return 1;
11085     };
11086 /*
11087  * Record the completion callback data.
11088  */
11089     a->fn = fn;
11090     a->data = data;
11091 /*
11092  * Attempt to register the new action.
11093  */
11094     if(_kt_set_action(gl->bindings, name, action_fn, a)) {
11095       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11096       _del_FreeListNode(gl->cpl_mem, (void *) a);
11097       return 1;
11098     };
11099   };
11100 /*
11101  * Bind the action to a given key-sequence?
11102  */
11103   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
11104     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11105     return 1;
11106   };
11107   return 0;
11108 }
11109 
11110 /*.......................................................................
11111  * Invoke an action function previously registered by a call to
11112  * gl_register_action().
11113  */
11114 static KT_KEY_FN(gl_run_external_action)
11115 {
11116   GlAfterAction status;  /* The return value of the action function */
11117 /*
11118  * Get the container of the action function and associated callback data.
11119  */
11120   GlExternalAction *a = (GlExternalAction *) data;
11121 /*
11122  * Invoke the action function.
11123  */
11124   status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line);
11125 /*
11126  * If the callback took us out of raw (possibly non-blocking) input
11127  * mode, restore this mode, and queue a redisplay of the input line.
11128  */
11129   if(_gl_raw_io(gl, 1))
11130     return 1;
11131 /*
11132  * Finally, check to see what the action function wants us to do next.
11133  */
11134   switch(status) {
11135   default:
11136   case GLA_ABORT:
11137     gl_record_status(gl, GLR_ERROR, errno);
11138     return 1;
11139     break;
11140   case GLA_RETURN:
11141     return gl_newline(gl, 1, NULL);
11142     break;
11143   case GLA_CONTINUE:
11144     break;
11145   };
11146   return 0;
11147 }
11148 
11149 /*.......................................................................
11150  * In server-I/O mode the terminal is left in raw mode between calls
11151  * to gl_get_line(), so it is necessary for the application to install
11152  * terminal restoring signal handlers for signals that could terminate
11153  * or suspend the process, plus a terminal reconfiguration handler to
11154  * be called when a process resumption signal is received, and finally
11155  * a handler to be called when a terminal-resize signal is received.
11156  *
11157  * Since there are many signals that by default terminate or suspend
11158  * processes, and different systems support different sub-sets of
11159  * these signals, this function provides a convenient wrapper around
11160  * sigaction() for assigning the specified handlers to all appropriate
11161  * signals. It also arranges that when any one of these signals is
11162  * being handled, all other catchable signals are blocked. This is
11163  * necessary so that the specified signal handlers can safely call
11164  * gl_raw_io(), gl_normal_io() and gl_update_size() without
11165  * reentrancy issues.
11166  *
11167  * Input:
11168  *  term_handler  void (*)(int)  The signal handler to invoke when
11169  *                               a process terminating signal is
11170  *                               received.
11171  *  susp_handler  void (*)(int)  The signal handler to invoke when
11172  *                               a process suspending signal is
11173  *                               received.
11174  *  cont_handler  void (*)(int)  The signal handler to invoke when
11175  *                               a process resumption signal is
11176  *                               received (ie. SIGCONT).
11177  *  size_handler  void (*)(int)  The signal handler to invoke when
11178  *                               a terminal-resize signal (ie. SIGWINCH)
11179  *                               is received.
11180  * Output:
11181  *  return                  int  0 - OK.
11182  *                               1 - Error.
11183  */
11184 int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int),
11185 		   void (*cont_handler)(int), void (*size_handler)(int))
11186 {
11187   int i;
11188 /*
11189  * Search for signals of the specified classes, and assign the
11190  * associated signal handler to them.
11191  */
11192   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11193     const struct GlDefSignal *sig = gl_signal_list + i;
11194     if(sig->attr & GLSA_SUSP) {
11195       if(gl_set_tty_signal(sig->signo, term_handler))
11196 	return 1;
11197     } else if(sig->attr & GLSA_TERM) {
11198       if(gl_set_tty_signal(sig->signo, susp_handler))
11199 	return 1;
11200     } else if(sig->attr & GLSA_CONT) {
11201       if(gl_set_tty_signal(sig->signo, cont_handler))
11202 	return 1;
11203     } else if(sig->attr & GLSA_SIZE) {
11204       if(gl_set_tty_signal(sig->signo, size_handler))
11205 	return 1;
11206     };
11207   };
11208   return 0;
11209 }
11210 
11211 /*.......................................................................
11212  * This is a private function of gl_tty_signals(). It installs a given
11213  * signal handler, and arranges that when that signal handler is being
11214  * invoked other signals are blocked. The latter is important to allow
11215  * functions like gl_normal_io(), gl_raw_io() and gl_update_size()
11216  * to be called from signal handlers.
11217  *
11218  * Input:
11219  *  signo     int           The signal to be trapped.
11220  *  handler  void (*)(int)  The signal handler to assign to the signal.
11221  */
11222 static int gl_set_tty_signal(int signo, void (*handler)(int))
11223 {
11224   SigAction act;   /* The signal handler configuation */
11225 /*
11226  * Arrange to block all trappable signals except the one that is being
11227  * assigned (the trapped signal will be blocked automatically by the
11228  * system).
11229  */
11230   gl_list_trappable_signals(&act.sa_mask);
11231   sigdelset(&act.sa_mask, signo);
11232 /*
11233  * Assign the signal handler.
11234  */
11235   act.sa_handler = handler;
11236 /*
11237  * There is only one portable signal handling flag, and it isn't
11238  * relevant to us, so don't specify any flags.
11239  */
11240   act.sa_flags = 0;
11241 /*
11242  * Register the signal handler.
11243  */
11244   if(sigaction(signo, &act, NULL))
11245     return 1;
11246   return 0;
11247 }
11248 
11249 /*.......................................................................
11250  * Display a left-justified string over multiple terminal lines,
11251  * taking account of the current width of the terminal. Optional
11252  * indentation and an optional prefix string can be specified to be
11253  * displayed at the start of each new terminal line used. Similarly,
11254  * an optional suffix can be specified to be displayed at the end of
11255  * each terminal line.  If needed, a single paragraph can be broken
11256  * across multiple calls.  Note that literal newlines in the input
11257  * string can be used to force a newline at any point and that you
11258  * should use this feature to explicitly end all paragraphs, including
11259  * at the end of the last string that you write. Note that when a new
11260  * line is started between two words that are separated by spaces,
11261  * those spaces are not output, whereas when a new line is started
11262  * because a newline character was found in the string, only the
11263  * spaces before the newline character are discarded.
11264  *
11265  * Input:
11266  *  gl         GetLine *  The resource object of gl_get_line().
11267  *  indentation    int    The number of spaces of indentation to write
11268  *                        at the beginning of each new terminal line.
11269  *  prefix  const char *  An optional prefix string to write after the
11270  *                        indentation margin at the start of each new
11271  *                        terminal line. You can specify NULL if no
11272  *                        prefix is required.
11273  *  suffix  const char *  An optional suffix string to draw at the end
11274  *                        of the terminal line. Spaces will be added
11275  *                        where necessary to ensure that the suffix ends
11276  *                        in the last column of the terminal line. If
11277  *                        no suffix is desired, specify NULL.
11278  *  fill_char      int    The padding character to use when indenting
11279  *                        the line or padding up to the suffix.
11280  *  def_width      int    If the terminal width isn't known, such as when
11281  *                        writing to a pipe or redirecting to a file,
11282  *                        this number specifies what width to assume.
11283  *  start          int    The number of characters already written to
11284  *                        the start of the current terminal line. This
11285  *                        is primarily used to allow individual
11286  *                        paragraphs to be written over multiple calls
11287  *                        to this function, but can also be used to
11288  *                        allow you to start the first line of a
11289  *                        paragraph with a different prefix or
11290  *                        indentation than those specified above.
11291  *  string  const char *  The string to be written.
11292  * Output:
11293  *  return         int    On error -1 is returned. Otherwise the
11294  *                        return value is the terminal column index at
11295  *                        which the cursor was left after writing the
11296  *                        final word in the string. Successful return
11297  *                        values can thus be passed verbatim to the
11298  *                        'start' arguments of subsequent calls to
11299  *                        gl_display_text() to allow the printing of a
11300  *                        paragraph to be broken across multiple calls
11301  *                        to gl_display_text().
11302  */
11303 int gl_display_text(GetLine *gl, int indentation, const char *prefix,
11304 		    const char *suffix, int fill_char,
11305 		    int def_width, int start, const char *string)
11306 {
11307   sigset_t oldset; /* The signals that were blocked on entry to this function */
11308   int status;      /* The return status of _gl_completion_action() */
11309 /*
11310  * Check the arguments?
11311  */
11312   if(!gl || !string) {
11313     errno = EINVAL;
11314     return -1;
11315   };
11316 /*
11317  * Block all signals.
11318  */
11319   if(gl_mask_signals(gl, &oldset))
11320     return -1;
11321 /*
11322  * Display the text while signals are blocked.
11323  */
11324   status = _io_display_text(_io_write_stdio, gl->output_fp, indentation,
11325 			    prefix, suffix, fill_char,
11326 			    gl->ncolumn > 0 ? gl->ncolumn : def_width,
11327 			    start, string);
11328 /*
11329  * Restore the process signal mask.
11330  */
11331   gl_unmask_signals(gl, &oldset);
11332   return status;
11333 }
11334 
11335 /*.......................................................................
11336  * Block all of the signals that we are currently trapping.
11337  *
11338  * Input:
11339  *  gl       GetLine *   The resource object of gl_get_line().
11340  * Input/Output:
11341  *  oldset   sigset_t *   The superseded process signal mask
11342  *                        will be return in *oldset unless oldset is
11343  *                        NULL.
11344  * Output:
11345  *  return        int     0 - OK.
11346  *                        1 - Error.
11347  */
11348 static int gl_mask_signals(GetLine *gl, sigset_t *oldset)
11349 {
11350 /*
11351  * Block all signals in all_signal_set, along with any others that are
11352  * already blocked by the application.
11353  */
11354   if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) {
11355     gl->signals_masked = 1;
11356     return 0;
11357   };
11358 /*
11359  * On error attempt to query the current process signal mask, so
11360  * that oldset be the correct process signal mask to restore later
11361  * if the caller of this function ignores the error return value.
11362  */
11363   if(oldset)
11364     (void) sigprocmask(SIG_SETMASK, NULL, oldset);
11365   gl->signals_masked = 0;
11366   return 1;
11367 }
11368 
11369 /*.......................................................................
11370  * Restore a process signal mask that was previously returned via the
11371  * oldset argument of gl_mask_signals().
11372  *
11373  * Input:
11374  *  gl        GetLine *   The resource object of gl_get_line().
11375  * Input/Output:
11376  *  oldset   sigset_t *   The process signal mask to be restored.
11377  * Output:
11378  *  return        int     0 - OK.
11379  *                        1 - Error.
11380  */
11381 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset)
11382 {
11383   gl->signals_masked = 0;
11384   return sigprocmask(SIG_SETMASK, oldset, NULL) < 0;
11385 }
11386 
11387 /*.......................................................................
11388  * Arrange to temporarily catch the signals marked in gl->use_signal_set.
11389  *
11390  * Input:
11391  *  gl        GetLine *   The resource object of gl_get_line().
11392  * Output:
11393  *  return        int     0 - OK.
11394  *                        1 - Error.
11395  */
11396 static int gl_catch_signals(GetLine *gl)
11397 {
11398   return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0;
11399 }
11400 
11401 /*.......................................................................
11402  * Select the I/O mode to be used by gl_get_line().
11403  *
11404  * Input:
11405  *  gl         GetLine *  The resource object of gl_get_line().
11406  *  mode      GlIOMode    The I/O mode to establish.
11407  * Output:
11408  *  return         int    0 - OK.
11409  *                        1 - Error.
11410  */
11411 int gl_io_mode(GetLine *gl, GlIOMode mode)
11412 {
11413   sigset_t oldset; /* The signals that were blocked on entry to this function */
11414   int status;      /* The return status of _gl_io_mode() */
11415 /*
11416  * Check the arguments.
11417  */
11418   if(!gl) {
11419     errno = EINVAL;
11420     return 1;
11421   };
11422 /*
11423  * Check that the requested mode is known.
11424  */
11425   switch(mode) {
11426   case GL_NORMAL_MODE:
11427   case GL_SERVER_MODE:
11428     break;
11429   default:
11430     errno = EINVAL;
11431     _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.",
11432 		    END_ERR_MSG);
11433     return 1;
11434   };
11435 /*
11436  * Block all signals.
11437  */
11438   if(gl_mask_signals(gl, &oldset))
11439     return 1;
11440 /*
11441  * Invoke the private body of this function.
11442  */
11443   status = _gl_io_mode(gl, mode);
11444 /*
11445  * Restore the process signal mask.
11446  */
11447   gl_unmask_signals(gl, &oldset);
11448   return status;
11449 }
11450 
11451 /*.......................................................................
11452  * This is the private body of the public function, gl_io_mode().
11453  * It assumes that the caller has checked its arguments and blocked the
11454  * delivery of signals.
11455  */
11456 static int _gl_io_mode(GetLine *gl, GlIOMode mode)
11457 {
11458 /*
11459  * Are we already in the specified mode?
11460  */
11461   if(mode == gl->io_mode)
11462     return 0;
11463 /*
11464  * First revert to normal I/O in the current I/O mode.
11465  */
11466   _gl_normal_io(gl);
11467 /*
11468  * Record the new mode.
11469  */
11470   gl->io_mode = mode;
11471 /*
11472  * Perform any actions needed by the new mode.
11473  */
11474   if(mode==GL_SERVER_MODE) {
11475     if(_gl_raw_io(gl, 1))
11476       return 1;
11477   };
11478   return 0;
11479 }
11480 
11481 /*.......................................................................
11482  * Return extra information (ie. in addition to that provided by errno)
11483  * about the last error to occur in either gl_get_line() or its
11484  * associated public functions.
11485  *
11486  * Input:
11487  *  gl         GetLine *  The resource object of gl_get_line().
11488  * Input/Output:
11489  *  buff          char *  An optional output buffer. Note that if the
11490  *                        calling application calls any gl_*()
11491  *                        functions from signal handlers, it should
11492  *                        provide a buffer here, so that a copy of
11493  *                        the latest error message can safely be made
11494  *                        while signals are blocked.
11495  *  n           size_t    The allocated size of buff[].
11496  * Output:
11497  *  return  const char *  A pointer to the error message. This will
11498  *                        be the buff argument, unless buff==NULL, in
11499  *                        which case it will be a pointer to an
11500  *                        internal error buffer. In the latter case,
11501  *                        note that the contents of the returned buffer
11502  *                        will change on subsequent calls to any gl_*()
11503  *                        functions.
11504  */
11505 const char *gl_error_message(GetLine *gl, char *buff, size_t n)
11506 {
11507   if(!gl) {
11508     static const char *msg = "NULL GetLine argument";
11509     if(buff) {
11510       strncpy(buff, msg, n);
11511       buff[n-1] = '\0';
11512     } else {
11513       return msg;
11514     };
11515   } else if(buff) {
11516     sigset_t oldset; /* The signals that were blocked on entry to this block */
11517 /*
11518  * Temporarily block all signals.
11519  */
11520     gl_mask_signals(gl, &oldset);
11521 /*
11522  * Copy the error message into the specified buffer.
11523  */
11524     if(buff && n > 0) {
11525       strncpy(buff, _err_get_msg(gl->err), n);
11526       buff[n-1] = '\0';
11527     };
11528 /*
11529  * Restore the process signal mask before returning.
11530  */
11531     gl_unmask_signals(gl, &oldset);
11532   } else {
11533     return _err_get_msg(gl->err);
11534   };
11535   return buff;
11536 }
11537 
11538 /*.......................................................................
11539  * Return the signal mask used by gl_get_line(). This is the set of
11540  * signals that gl_get_line() is currently configured to trap.
11541  *
11542  * Input:
11543  *  gl         GetLine *  The resource object of gl_get_line().
11544  * Input/Output:
11545  *  set       sigset_t *  The set of signals will be returned in *set,
11546  *                        in the form of a signal process mask, as
11547  *                        used by sigaction(), sigprocmask(),
11548  *                        sigpending(), sigsuspend(), sigsetjmp() and
11549  *                        other standard POSIX signal-aware
11550  *                        functions.
11551  * Output:
11552  *  return         int    0 - OK.
11553  *                        1 - Error (examine errno for reason).
11554  */
11555 int gl_list_signals(GetLine *gl, sigset_t *set)
11556 {
11557 /*
11558  * Check the arguments.
11559  */
11560   if(!gl || !set) {
11561     if(gl)
11562       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
11563     errno = EINVAL;
11564     return 1;
11565   };
11566 /*
11567  * Copy the signal mask into *set.
11568  */
11569   memcpy(set, &gl->all_signal_set, sizeof(*set));
11570   return 0;
11571 }
11572 
11573 /*.......................................................................
11574  * By default, gl_get_line() doesn't trap signals that are blocked
11575  * when it is called. This default can be changed either on a
11576  * per-signal basis by calling gl_trap_signal(), or on a global basis
11577  * by calling this function. What this function does is add the
11578  * GLS_UNBLOCK_SIG flag to all signals that are currently configured
11579  * to be trapped by gl_get_line(), such that when subsequent calls to
11580  * gl_get_line() wait for I/O, these signals are temporarily
11581  * unblocked. This behavior is useful in non-blocking server-I/O mode,
11582  * where it is used to avoid race conditions related to handling these
11583  * signals externally to gl_get_line(). See the demonstration code in
11584  * demo3.c, or the gl_handle_signal() man page for further
11585  * information.
11586  *
11587  * Input:
11588  *  gl         GetLine *   The resource object of gl_get_line().
11589  */
11590 void gl_catch_blocked(GetLine *gl)
11591 {
11592   sigset_t oldset;    /* The process signal mask to restore */
11593   GlSignalNode *sig;  /* A signal node in gl->sigs */
11594 /*
11595  * Check the arguments.
11596  */
11597   if(!gl) {
11598     errno = EINVAL;
11599     return;
11600   };
11601 /*
11602  * Temporarily block all signals while we modify the contents of gl.
11603  */
11604   gl_mask_signals(gl, &oldset);
11605 /*
11606  * Add the GLS_UNBLOCK_SIG flag to all configured signals.
11607  */
11608   for(sig=gl->sigs; sig; sig=sig->next)
11609     sig->flags |= GLS_UNBLOCK_SIG;
11610 /*
11611  * Restore the process signal mask that was superseded by the call
11612  * to gl_mask_signals().
11613  */
11614   gl_unmask_signals(gl, &oldset);
11615   return;
11616 }
11617 
11618 /*.......................................................................
11619  * Respond to signals who's default effects have important
11620  * consequences to gl_get_line(). This is intended for use in
11621  * non-blocking server mode, where the external event loop is
11622  * responsible for catching signals. Signals that are handled include
11623  * those that by default terminate or suspend the process, and the
11624  * signal that indicates that the terminal size has changed. Note that
11625  * this function is not signal safe and should thus not be called from
11626  * a signal handler itself. See the gl_io_mode() man page for how it
11627  * should be used.
11628  *
11629  * In the case of signals that by default terminate or suspend
11630  * processes, command-line editing will be suspended, the terminal
11631  * returned to a usable state, then the default disposition of the
11632  * signal restored and the signal resent, in order to suspend or
11633  * terminate the process.  If the process subsequently resumes,
11634  * command-line editing is resumed.
11635  *
11636  * In the case of signals that indicate that the terminal has been
11637  * resized, the new size will be queried, and any input line that is
11638  * being edited will be redrawn to fit the new dimensions of the
11639  * terminal.
11640  *
11641  * Input:
11642  *  signo    int    The number of the signal to respond to.
11643  *  gl   GetLine *  The first element of an array of 'ngl' GetLine
11644  *                  objects.
11645  *  ngl      int    The number of elements in the gl[] array. Normally
11646  *                  this will be one.
11647  */
11648 void gl_handle_signal(int signo, GetLine *gl, int ngl)
11649 {
11650   int attr;             /* The attributes of the specified signal */
11651   sigset_t all_signals; /* The set of trappable signals */
11652   sigset_t oldset;      /* The process signal mask to restore */
11653   int i;
11654 /*
11655  * NULL operation?
11656  */
11657   if(ngl < 1 || !gl)
11658     return;
11659 /*
11660  * Look up the default attributes of the specified signal.
11661  */
11662   attr = gl_classify_signal(signo);
11663 /*
11664  * If the signal isn't known, we are done.
11665  */
11666   if(!attr)
11667     return;
11668 /*
11669  * Temporarily block all signals while we modify the gl objects.
11670  */
11671   gl_list_trappable_signals(&all_signals);
11672   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11673 /*
11674  * Suspend or terminate the process?
11675  */
11676   if(attr & (GLSA_SUSP | GLSA_TERM)) {
11677     gl_suspend_process(signo, gl, ngl);
11678 /*
11679  * Resize the terminal? Note that ioctl() isn't defined as being
11680  * signal safe, so we can't call gl_update_size() here. However,
11681  * gl_get_line() checks for resizes on each call, so simply arrange
11682  * for the application's event loop to call gl_get_line() as soon as
11683  * it becomes possible to write to the terminal. Note that if the
11684  * caller is calling select() or poll when this happens, these functions
11685  * get interrupted, since a signal has been caught.
11686  */
11687   } else if(attr & GLSA_SIZE) {
11688     for(i=0; i<ngl; i++)
11689       gl[i].pending_io = GLP_WRITE;
11690   };
11691 /*
11692  * Restore the process signal mask that was superseded by the call
11693  * to gl_mask_signals().
11694  */
11695   sigprocmask(SIG_SETMASK, &oldset, NULL);
11696   return;
11697 }
11698 
11699 /*.......................................................................
11700  * Respond to an externally caught process suspension or
11701  * termination signal.
11702  *
11703  * After restoring the terminal to a usable state, suspend or
11704  * terminate the calling process, using the original signal with its
11705  * default disposition restored to do so. If the process subsequently
11706  * resumes, resume editing any input lines that were being entered.
11707  *
11708  * Input:
11709  *  signo    int    The signal number to suspend the process with. Note
11710  *                  that the default disposition of this signal will be
11711  *                  restored before the signal is sent, so provided
11712  *                  that the default disposition of this signal is to
11713  *                  either suspend or terminate the application,
11714  *                  that is what wil happen, regardless of what signal
11715  *                  handler is currently assigned to this signal.
11716  *  gl   GetLine *  The first element of an array of 'ngl' GetLine objects
11717  *                  whose terminals should be restored to a sane state
11718  *                  while the application is suspended.
11719  *  ngl      int    The number of elements in the gl[] array.
11720  */
11721 static void gl_suspend_process(int signo, GetLine *gl, int ngl)
11722 {
11723   sigset_t only_signo;          /* A signal set containing just signo */
11724   sigset_t oldset;              /* The signal mask on entry to this function */
11725   sigset_t all_signals;         /* A signal set containing all signals */
11726   struct sigaction old_action;  /* The current signal handler */
11727   struct sigaction def_action;  /* The default signal handler */
11728   int i;
11729 /*
11730  * Create a signal mask containing the signal that was trapped.
11731  */
11732   sigemptyset(&only_signo);
11733   sigaddset(&only_signo, signo);
11734 /*
11735  * Temporarily block all signals.
11736  */
11737   gl_list_trappable_signals(&all_signals);
11738   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11739 /*
11740  * Restore the terminal to a usable state.
11741  */
11742   for(i=0; i<ngl; i++) {
11743     GetLine *obj = gl + i;
11744     if(obj->raw_mode) {
11745       _gl_normal_io(obj);
11746       if(!obj->raw_mode)        /* Check that gl_normal_io() succeded */
11747 	obj->raw_mode = -1;     /* Flag raw mode as needing to be restored */
11748     };
11749   };
11750 /*
11751  * Restore the system default disposition of the signal that we
11752  * caught.  Note that this signal is currently blocked. Note that we
11753  * don't use memcpy() to copy signal sets here, because the signal safety
11754  * of memcpy() is undefined.
11755  */
11756   def_action.sa_handler = SIG_DFL;
11757   {
11758     char *orig = (char *) &all_signals;
11759     char *dest = (char *) &def_action.sa_mask;
11760     for(i=0; i<sizeof(sigset_t); i++)
11761       *dest++ = *orig++;
11762   };
11763   sigaction(signo, &def_action, &old_action);
11764 /*
11765  * Resend the signal, and unblock it so that it gets delivered to
11766  * the application. This will invoke the default action of this signal.
11767  */
11768   raise(signo);
11769   sigprocmask(SIG_UNBLOCK, &only_signo, NULL);
11770 /*
11771  * If the process resumes again, it will resume here.
11772  * Block the signal again, then restore our signal handler.
11773  */
11774   sigprocmask(SIG_BLOCK, &only_signo, NULL);
11775   sigaction(signo, &old_action, NULL);
11776 /*
11777  * Resume command-line editing.
11778  */
11779   for(i=0; i<ngl; i++) {
11780     GetLine *obj = gl + i;
11781     if(obj->raw_mode == -1) { /* Did we flag the need to restore raw mode? */
11782       obj->raw_mode = 0;      /* gl_raw_io() does nothing unless raw_mode==0 */
11783       _gl_raw_io(obj, 1);
11784     };
11785   };
11786 /*
11787  * Restore the process signal mask to the way it was when this function
11788  * was called.
11789  */
11790   sigprocmask(SIG_SETMASK, &oldset, NULL);
11791   return;
11792 }
11793 
11794 /*.......................................................................
11795  * Return the information about the default attributes of a given signal.
11796  * The attributes that are returned are as defined by the standards that
11797  * created them, including POSIX, SVR4 and 4.3+BSD, and are taken from a
11798  * table in Richard Steven's book, "Advanced programming in the UNIX
11799  * environment".
11800  *
11801  * Input:
11802  *  signo        int   The signal to be characterized.
11803  * Output:
11804  *  return       int   A bitwise union of GlSigAttr enumerators, or 0
11805  *                     if the signal isn't known.
11806  */
11807 static int gl_classify_signal(int signo)
11808 {
11809   int i;
11810 /*
11811  * Search for the specified signal in the gl_signal_list[] table.
11812  */
11813   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11814     const struct GlDefSignal *sig = gl_signal_list + i;
11815     if(sig->signo == signo)
11816       return sig->attr;
11817   };
11818 /*
11819  * Signal not known.
11820  */
11821   return 0;
11822 }
11823 
11824 /*.......................................................................
11825  * When in non-blocking server mode, this function can be used to abandon
11826  * the current incompletely entered input line, and prepare to start
11827  * editing a new line on the next call to gl_get_line().
11828  *
11829  * Input:
11830  *  gl      GetLine *  The line editor resource object.
11831  */
11832 void gl_abandon_line(GetLine *gl)
11833 {
11834   sigset_t oldset;    /* The process signal mask to restore */
11835 /*
11836  * Check the arguments.
11837  */
11838   if(!gl) {
11839     errno = EINVAL;
11840     return;
11841   };
11842 /*
11843  * Temporarily block all signals while we modify the contents of gl.
11844  */
11845   gl_mask_signals(gl, &oldset);
11846 /*
11847  * Mark the input line as discarded.
11848  */
11849   _gl_abandon_line(gl);
11850 /*
11851  * Restore the process signal mask that was superseded by the call
11852  * to gl_mask_signals().
11853  */
11854   gl_unmask_signals(gl, &oldset);
11855   return;
11856 }
11857 
11858 /*.......................................................................
11859  * This is the private body of the gl_abandon_line() function. It
11860  * assumes that the caller has checked its arguments and blocked the
11861  * delivery of signals.
11862  */
11863 void _gl_abandon_line(GetLine *gl)
11864 {
11865   gl->endline = 1;
11866   gl->pending_io = GLP_WRITE;
11867 }
11868 
11869 /*.......................................................................
11870  * How many characters are needed to write a number as an octal string?
11871  *
11872  * Input:
11873  *  num   unsigned   The to be measured.
11874  * Output:
11875  *  return     int   The number of characters needed.
11876  */
11877 static int gl_octal_width(unsigned num)
11878 {
11879   int n;    /* The number of characters needed to render the number */
11880   for(n=1; num /= 8; n++)
11881     ;
11882   return n;
11883 }
11884 
11885 /*.......................................................................
11886  * Tell gl_get_line() the current terminal size. Note that this is only
11887  * necessary on systems where changes in terminal size aren't reported
11888  * via SIGWINCH.
11889  *
11890  * Input:
11891  *  gl            GetLine *  The resource object of gl_get_line().
11892  *  ncolumn           int    The number of columns in the terminal.
11893  *  nline             int    The number of lines in the terminal.
11894  * Output:
11895  *  return            int    0 - OK.
11896  *                           1 - Error.
11897  */
11898 int gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11899 {
11900   sigset_t oldset;      /* The signals that were blocked on entry */
11901                         /*  to this function */
11902   int status;           /* The return status */
11903 /*
11904  * Block all signals while accessing gl.
11905  */
11906   gl_mask_signals(gl, &oldset);
11907 /*
11908  * Install the new terminal size.
11909  */
11910   status = _gl_set_term_size(gl, ncolumn, nline);
11911 /*
11912  * Restore the process signal mask before returning.
11913  */
11914   gl_unmask_signals(gl, &oldset);
11915   return status;
11916 }
11917 
11918 /*.......................................................................
11919  * This is the private body of the gl_set_term_size() function. It
11920  * assumes that the caller has checked its arguments and blocked the
11921  * delivery of signals.
11922  */
11923 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11924 {
11925 /*
11926  * Check the arguments.
11927  */
11928   if(!gl) {
11929     errno = EINVAL;
11930     return 1;
11931   };
11932 /*
11933  * Reject non-sensical dimensions.
11934  */
11935   if(ncolumn <= 0 || nline <= 0) {
11936     _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG);
11937     errno = EINVAL;
11938     return 1;
11939   };
11940 /*
11941  * Install the new dimensions in the terminal driver if possible, so
11942  * that future calls to gl_query_size() get the new value.
11943  */
11944 #ifdef TIOCSWINSZ
11945   if(gl->is_term) {
11946     struct winsize size;
11947     size.ws_row = nline;
11948     size.ws_col = ncolumn;
11949     size.ws_xpixel = 0;
11950     size.ws_ypixel = 0;
11951     if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) {
11952       _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG);
11953       return 1;
11954     };
11955   };
11956 #endif
11957 /*
11958  * If an input line is in the process of being edited, redisplay it to
11959  * accomodate the new dimensions, and record the new dimensions in
11960  * gl->nline and gl->ncolumn.
11961  */
11962   return gl_handle_tty_resize(gl, ncolumn, nline);
11963 }
11964 
11965 /*.......................................................................
11966  * Record a character in the input line buffer at a given position.
11967  *
11968  * Input:
11969  *  gl    GetLine *   The resource object of gl_get_line().
11970  *  c        char     The character to be recorded.
11971  *  bufpos    int     The index in the buffer at which to record the
11972  *                    character.
11973  * Output:
11974  *  return    int     0 - OK.
11975  *                    1 - Insufficient room.
11976  */
11977 static int gl_buffer_char(GetLine *gl, char c, int bufpos)
11978 {
11979 /*
11980  * Guard against buffer overruns.
11981  */
11982   if(bufpos >= gl->linelen)
11983     return 1;
11984 /*
11985  * Record the new character.
11986  */
11987   gl->line[bufpos] = c;
11988 /*
11989  * If the new character was placed beyond the end of the current input
11990  * line, update gl->ntotal to reflect the increased number of characters
11991  * that are in gl->line, and terminate the string.
11992  */
11993   if(bufpos >= gl->ntotal) {
11994     gl->ntotal = bufpos+1;
11995     gl->line[gl->ntotal] = '\0';
11996   };
11997   return 0;
11998 }
11999 
12000 /*.......................................................................
12001  * Copy a given string into the input buffer, overwriting the current
12002  * contents.
12003  *
12004  * Input:
12005  *  gl    GetLine *   The resource object of gl_get_line().
12006  *  s  const char *   The string to be recorded.
12007  *  n         int     The number of characters to be copied from the
12008  *                    string.
12009  *  bufpos    int     The index in the buffer at which to place the
12010  *                    the first character of the string.
12011  * Output:
12012  *  return    int     0 - OK.
12013  *                    1 - String truncated to fit.
12014  */
12015 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos)
12016 {
12017   int nnew;  /* The number of characters actually recorded */
12018   int i;
12019 /*
12020  * How many of the characters will fit within the buffer?
12021  */
12022   nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos);
12023 /*
12024  * Record the first nnew characters of s[] in the buffer.
12025  */
12026   for(i=0; i<nnew; i++)
12027     gl_buffer_char(gl, s[i], bufpos + i);
12028 /*
12029  * Was the string truncated?
12030  */
12031   return nnew < n;
12032 }
12033 
12034 /*.......................................................................
12035  * Make room in the input buffer for a string to be inserted. This
12036  * involves moving the characters that follow a specified point, towards
12037  * the end of the buffer.
12038  *
12039  * Input:
12040  *  gl    GetLine *   The resource object of gl_get_line().
12041  *  start     int     The index of the first character to be moved.
12042  *  n         int     The width of the gap.
12043  * Output:
12044  *  return    int     0 - OK.
12045  *                    1 - Insufficient room.
12046  */
12047 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n)
12048 {
12049 /*
12050  * Ensure that the buffer has sufficient space.
12051  */
12052   if(gl->ntotal + n > gl->linelen)
12053     return 1;
12054 /*
12055  * Move everything including and beyond the character at 'start'
12056  * towards the end of the string.
12057  */
12058   memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1);
12059 /*
12060  * Update the recorded size of the line.
12061  */
12062   gl->ntotal += n;
12063   return 1;
12064 }
12065 
12066 /*.......................................................................
12067  * Remove a given number of characters from the input buffer. This
12068  * involves moving the characters that follow the removed characters to
12069  * where the removed sub-string started in the input buffer.
12070  *
12071  * Input:
12072  *  gl    GetLine *   The resource object of gl_get_line().
12073  *  start     int     The first character to be removed.
12074  *  n         int     The number of characters to remove.
12075  */
12076 static void gl_remove_from_buffer(GetLine *gl, int start, int n)
12077 {
12078   memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1);
12079 /*
12080  * Update the recorded size of the line.
12081  */
12082   gl->ntotal -= n;
12083 }
12084 
12085 /*.......................................................................
12086  * Truncate the string in the input line buffer after a given number of
12087  * characters.
12088  *
12089  * Input:
12090  *  gl       GetLine *   The resource object of gl_get_line().
12091  *  n            int     The new length of the line.
12092  * Output:
12093  *  return       int     0 - OK.
12094  *                       1 - n > gl->linelen.
12095  */
12096 static int gl_truncate_buffer(GetLine *gl, int n)
12097 {
12098   if(n > gl->linelen)
12099     return 1;
12100   gl->line[n] = '\0';
12101   gl->ntotal = n;
12102   return 0;
12103 }
12104 
12105 /*.......................................................................
12106  * When the contents of gl->line[] are changed without calling any of the
12107  * gl_ buffer manipulation functions, this function must be called to
12108  * compute the length of this string, and ancillary information.
12109  *
12110  * Input:
12111  *  gl      GetLine *   The resource object of gl_get_line().
12112  */
12113 static void gl_update_buffer(GetLine *gl)
12114 {
12115   int len;  /* The length of the line */
12116 /*
12117  * Measure the length of the input line.
12118  */
12119   for(len=0; len <= gl->linelen && gl->line[len]; len++)
12120     ;
12121 /*
12122  * Just in case the string wasn't correctly terminated, do so here.
12123  */
12124   gl->line[len] = '\0';
12125 /*
12126  * Record the number of characters that are now in gl->line[].
12127  */
12128   gl->ntotal = len;
12129 /*
12130  * Ensure that the cursor stays within the bounds of the modified
12131  * input line.
12132  */
12133   if(gl->buff_curpos > gl->ntotal)
12134     gl->buff_curpos = gl->ntotal;
12135 /*
12136  * Arrange for the input line to be redrawn.
12137  */
12138   gl_queue_redisplay(gl);
12139   return;
12140 }
12141 
12142 /*.......................................................................
12143  * Erase the displayed input line, including its prompt, and leave the
12144  * cursor where the erased line started. Note that to allow this
12145  * function to be used when responding to a terminal resize, this
12146  * function is designed to work even if the horizontal cursor position
12147  * doesn't match the internally recorded position.
12148  *
12149  * Input:
12150  *  gl      GetLine *   The resource object of gl_get_line().
12151  * Output:
12152  *  return      int     0 - OK.
12153  *                      1 - Error.
12154  */
12155 static int gl_erase_line(GetLine *gl)
12156 {
12157 /*
12158  * Is a line currently displayed?
12159  */
12160   if(gl->displayed) {
12161 /*
12162  * Relative the the start of the input line, which terminal line of
12163  * the current input line is the cursor currently on?
12164  */
12165     int cursor_line = gl->term_curpos / gl->ncolumn;
12166 /*
12167  * Move the cursor to the start of the line.
12168  */
12169     for( ; cursor_line > 0; cursor_line--) {
12170       if(gl_print_control_sequence(gl, 1, gl->up))
12171 	return 1;
12172     };
12173     if(gl_print_control_sequence(gl, 1, gl->bol))
12174       return 1;
12175 /*
12176  * Clear from the start of the line to the end of the terminal.
12177  */
12178     if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12179       return 1;
12180 /*
12181  * Mark the line as no longer displayed.
12182  */
12183     gl_line_erased(gl);
12184   };
12185   return 0;
12186 }
12187 
12188 /*.......................................................................
12189  * Arrange for the input line to be redisplayed by gl_flush_output(),
12190  * as soon as the output queue becomes empty.
12191  *
12192  * Input:
12193  *  gl          GetLine *   The resource object of gl_get_line().
12194  */
12195 static void gl_queue_redisplay(GetLine *gl)
12196 {
12197   gl->redisplay = 1;
12198   gl->pending_io = GLP_WRITE;
12199 }
12200 
12201 /*.......................................................................
12202  * Truncate the displayed input line starting from the current
12203  * terminal cursor position, and leave the cursor at the end of the
12204  * truncated line. The input-line buffer is not affected.
12205  *
12206  * Input:
12207  *  gl     GetLine *   The resource object of gl_get_line().
12208  * Output:
12209  *  return     int     0 - OK.
12210  *                     1 - Error.
12211  */
12212 static int gl_truncate_display(GetLine *gl)
12213 {
12214 /*
12215  * Keep a record of the current terminal cursor position.
12216  */
12217   int term_curpos = gl->term_curpos;
12218 /*
12219  * First clear from the cursor to the end of the current input line.
12220  */
12221   if(gl_print_control_sequence(gl, 1, gl->clear_eol))
12222     return 1;
12223 /*
12224  * If there is more than one line displayed, go to the start of the
12225  * next line and clear from there to the end of the display. Note that
12226  * we can't use clear_eod to do the whole job of clearing from the
12227  * current cursor position to the end of the terminal because
12228  * clear_eod is only defined when used at the start of a terminal line
12229  * (eg. with gnome terminals, clear_eod clears from the start of the
12230  * current terminal line, rather than from the current cursor
12231  * position).
12232  */
12233   if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) {
12234     if(gl_print_control_sequence(gl, 1, gl->down) ||
12235        gl_print_control_sequence(gl, 1, gl->bol) ||
12236        gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12237       return 1;
12238 /*
12239  * Where is the cursor now?
12240  */
12241     gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1);
12242 /*
12243  * Restore the cursor position.
12244  */
12245     gl_set_term_curpos(gl, term_curpos);
12246   };
12247 /*
12248  * Update the recorded position of the final character.
12249  */
12250   gl->term_len = gl->term_curpos;
12251   return 0;
12252 }
12253 
12254 /*.......................................................................
12255  * Return the set of all trappable signals.
12256  *
12257  * Input:
12258  *  signals   sigset_t *  The set of signals will be recorded in
12259  *                        *signals.
12260  */
12261 static void gl_list_trappable_signals(sigset_t *signals)
12262 {
12263 /*
12264  * Start with the set of all signals.
12265  */
12266   sigfillset(signals);
12267 /*
12268  * Remove un-trappable signals from this set.
12269  */
12270 #ifdef SIGKILL
12271   sigdelset(signals, SIGKILL);
12272 #endif
12273 #ifdef SIGSTOP
12274   sigdelset(signals, SIGSTOP);
12275 #endif
12276 }
12277 
12278 /*.......................................................................
12279  * Read an input line from a non-interactive input stream.
12280  *
12281  * Input:
12282  *  gl     GetLine *   The resource object of gl_get_line().
12283  * Output:
12284  *  return     int     0 - OK
12285  *                     1 - Error.
12286  */
12287 static int gl_read_stream_line(GetLine *gl)
12288 {
12289   char c = '\0'; /* The latest character read from fp */
12290 /*
12291  * Record the fact that we are about to read input.
12292  */
12293   gl->pending_io = GLP_READ;
12294 /*
12295  * If we are starting a new line, reset the line-input parameters.
12296  */
12297   if(gl->endline)
12298     gl_reset_input_line(gl);
12299 /*
12300  * Read one character at a time.
12301  */
12302   while(gl->ntotal < gl->linelen && c != '\n') {
12303 /*
12304  * Attempt to read one more character.
12305  */
12306     switch(gl_read_input(gl, &c)) {
12307     case GL_READ_OK:
12308       break;
12309     case GL_READ_EOF:        /* Reached end-of-file? */
12310 /*
12311  * If any characters were read before the end-of-file condition,
12312  * interpolate a newline character, so that the caller sees a
12313  * properly terminated line. Otherwise return an end-of-file
12314  * condition.
12315  */
12316       if(gl->ntotal > 0) {
12317 	c = '\n';
12318       } else {
12319 	gl_record_status(gl, GLR_EOF, 0);
12320 	return 1;
12321       };
12322       break;
12323     case GL_READ_BLOCKED:    /* Input blocked? */
12324       gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12325       return 1;
12326       break;
12327     case GL_READ_ERROR:     /* I/O error? */
12328       return 1;
12329       break;
12330     };
12331 /*
12332  * Append the character to the line buffer.
12333  */
12334     if(gl_buffer_char(gl, c, gl->ntotal))
12335       return 1;
12336   };
12337 /*
12338  * Was the end of the input line reached before running out of buffer space?
12339  */
12340   gl->endline = (c == '\n');
12341   return 0;
12342 }
12343 
12344 /*.......................................................................
12345  * Read a single character from a non-interactive input stream.
12346  *
12347  * Input:
12348  *  gl     GetLine *   The resource object of gl_get_line().
12349  * Output:
12350  *  return     int     The character, or EOF on error.
12351  */
12352 static int gl_read_stream_char(GetLine *gl)
12353 {
12354   char c = '\0';    /* The latest character read from fp */
12355   int retval = EOF; /* The return value of this function */
12356 /*
12357  * Arrange to discard any incomplete input line.
12358  */
12359   _gl_abandon_line(gl);
12360 /*
12361  * Record the fact that we are about to read input.
12362  */
12363   gl->pending_io = GLP_READ;
12364 /*
12365  * Attempt to read one more character.
12366  */
12367   switch(gl_read_input(gl, &c)) {
12368   case GL_READ_OK:      /* Success */
12369     retval = c;
12370     break;
12371   case GL_READ_BLOCKED: /* The read blocked */
12372     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12373     retval = EOF;  /* Failure */
12374     break;
12375   case GL_READ_EOF:     /* End of file reached */
12376     gl_record_status(gl, GLR_EOF, 0);
12377     retval = EOF;  /* Failure */
12378     break;
12379   case GL_READ_ERROR:
12380     retval = EOF;  /* Failure */
12381     break;
12382   };
12383   return retval;
12384 }
12385 
12386 /*.......................................................................
12387  * Bind a key sequence to a given action.
12388  *
12389  * Input:
12390  *  gl          GetLine *   The resource object of gl_get_line().
12391  *  origin  GlKeyOrigin     The originator of the key binding.
12392  *  key      const char *   The key-sequence to be bound (or unbound).
12393  *  action   const char *   The name of the action to bind the key to,
12394  *                          or either NULL or "" to unbind the
12395  *                          key-sequence.
12396  * Output:
12397  *  return          int     0 - OK
12398  *                          1 - Error.
12399  */
12400 int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq,
12401 		   const char *action)
12402 {
12403   KtBinder binder;  /* The private internal equivalent of 'origin' */
12404 /*
12405  * Check the arguments.
12406  */
12407   if(!gl || !keyseq) {
12408     errno = EINVAL;
12409     if(gl)
12410       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
12411     return 1;
12412   };
12413 /*
12414  * An empty action string requests that the key-sequence be unbound.
12415  * This is indicated to _kt_set_keybinding() by passing a NULL action
12416  * string, so convert an empty string to a NULL action pointer.
12417  */
12418   if(action && *action=='\0')
12419     action = NULL;
12420 /*
12421  * Translate the public originator enumeration to the private equivalent.
12422  */
12423   binder = origin==GL_USER_KEY ? KTB_USER : KTB_NORM;
12424 /*
12425  * Bind the action to a given key-sequence?
12426  */
12427   if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
12428     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
12429     return 1;
12430   };
12431   return 0;
12432 }
12433 
12434 /*.......................................................................
12435  * This is the public wrapper around the gl_clear_termina() function.
12436  * It clears the terminal and leaves the cursor at the home position.
12437  * In server I/O mode, the next call to gl_get_line() will also
12438  * redisplay the current input line.
12439  *
12440  * Input:
12441  *  gl          GetLine *   The resource object of gl_get_line().
12442  * Output:
12443  *  return          int     0 - OK.
12444  *                          1 - Error.
12445  */
12446 int gl_erase_terminal(GetLine *gl)
12447 {
12448   sigset_t oldset;      /* The signals that were blocked on entry */
12449                         /*  to this function */
12450   int status;           /* The return status */
12451 /*
12452  * Block all signals while accessing gl.
12453  */
12454   gl_mask_signals(gl, &oldset);
12455 /*
12456  * Clear the terminal.
12457  */
12458   status = gl_clear_screen(gl, 1, NULL);
12459 /*
12460  * Attempt to flush the clear-screen control codes to the terminal.
12461  * If this doesn't complete the job, the next call to gl_get_line()
12462  * will.
12463  */
12464   (void) gl_flush_output(gl);
12465 /*
12466  * Restore the process signal mask before returning.
12467  */
12468   gl_unmask_signals(gl, &oldset);
12469   return status;
12470 }
12471 
12472 /*.......................................................................
12473  * This function must be called by any function that erases the input
12474  * line.
12475  *
12476  * Input:
12477  *  gl          GetLine *   The resource object of gl_get_line().
12478  */
12479 static void gl_line_erased(GetLine *gl)
12480 {
12481   gl->displayed = 0;
12482   gl->term_curpos = 0;
12483   gl->term_len = 0;
12484 }
12485 
12486 /*.......................................................................
12487  * Append a specified line to the history list.
12488  *
12489  * Input:
12490  *  gl          GetLine *   The resource object of gl_get_line().
12491  *  line     const char *   The line to be added.
12492  * Output:
12493  *  return          int     0 - OK.
12494  *                          1 - Error.
12495  */
12496 int gl_append_history(GetLine *gl, const char *line)
12497 {
12498   sigset_t oldset;      /* The signals that were blocked on entry */
12499                         /*  to this function */
12500   int status;           /* The return status */
12501 /*
12502  * Check the arguments.
12503  */
12504   if(!gl || !line) {
12505     errno = EINVAL;
12506     return 1;
12507   };
12508 /*
12509  * Block all signals.
12510  */
12511   if(gl_mask_signals(gl, &oldset))
12512     return 1;
12513 /*
12514  * Execute the private body of the function while signals are blocked.
12515  */
12516   status = _gl_append_history(gl, line);
12517 /*
12518  * Restore the process signal mask.
12519  */
12520   gl_unmask_signals(gl, &oldset);
12521   return status;
12522 }
12523 
12524 /*.......................................................................
12525  * This is the private body of the public function, gl_append_history().
12526  * It assumes that the caller has checked its arguments and blocked the
12527  * delivery of signals.
12528  */
12529 static int _gl_append_history(GetLine *gl, const char *line)
12530 {
12531   int status =_glh_add_history(gl->glh, line, 0);
12532   if(status)
12533     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
12534   return status;
12535 }
12536 
12537 /*.......................................................................
12538  * Enable or disable the automatic addition of newly entered lines to the
12539  * history list.
12540  *
12541  * Input:
12542  *  gl          GetLine *   The resource object of gl_get_line().
12543  *  enable          int     If true, subsequently entered lines will
12544  *                          automatically be added to the history list
12545  *                          before they are returned to the caller of
12546  *                          gl_get_line(). If 0, the choice of how and
12547  *                          when to archive lines in the history list,
12548  *                          is left up to the calling application, which
12549  *                          can do so via calls to gl_append_history().
12550  * Output:
12551  *  return          int     0 - OK.
12552  *                          1 - Error.
12553  */
12554 int gl_automatic_history(GetLine *gl, int enable)
12555 {
12556   sigset_t oldset;      /* The signals that were blocked on entry */
12557                         /*  to this function */
12558 /*
12559  * Check the arguments.
12560  */
12561   if(!gl) {
12562     errno = EINVAL;
12563     return 1;
12564   };
12565 /*
12566  * Block all signals.
12567  */
12568   if(gl_mask_signals(gl, &oldset))
12569     return 1;
12570 /*
12571  * Execute the private body of the function while signals are blocked.
12572  */
12573   gl->automatic_history = enable;
12574 /*
12575  * Restore the process signal mask.
12576  */
12577   gl_unmask_signals(gl, &oldset);
12578   return 0;
12579 }
12580 
12581 /*.......................................................................
12582  * This is a public function that reads a single uninterpretted
12583  * character from the user, without displaying anything.
12584  *
12585  * Input:
12586  *  gl     GetLine *  A resource object previously returned by
12587  *                    new_GetLine().
12588  * Output:
12589  *  return     int    The character that was read, or EOF if the read
12590  *                    had to be aborted (in which case you can call
12591  *                    gl_return_status() to find out why).
12592  */
12593 int gl_read_char(GetLine *gl)
12594 {
12595   int retval;   /* The return value of _gl_read_char() */
12596 /*
12597  * This function can be called from application callback functions,
12598  * so check whether signals have already been masked, so that we don't
12599  * do it again, and overwrite gl->old_signal_set.
12600  */
12601   int was_masked = gl->signals_masked;
12602 /*
12603  * Check the arguments.
12604  */
12605   if(!gl) {
12606     errno = EINVAL;
12607     return EOF;
12608   };
12609 /*
12610  * Temporarily block all of the signals that we have been asked to trap.
12611  */
12612   if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set))
12613     return EOF;
12614 /*
12615  * Perform the character reading task.
12616  */
12617   retval = _gl_read_char(gl);
12618 /*
12619  * Restore the process signal mask to how it was when this function was
12620  * first called.
12621  */
12622   if(!was_masked)
12623     gl_unmask_signals(gl, &gl->old_signal_set);
12624   return retval;
12625 }
12626 
12627 /*.......................................................................
12628  * This is the main body of the public function gl_read_char().
12629  */
12630 static int _gl_read_char(GetLine *gl)
12631 {
12632   int retval = EOF;  /* The return value */
12633   int waserr = 0;    /* True if an error occurs */
12634   char c;            /* The character read */
12635 /*
12636  * This function can be called from application callback functions,
12637  * so check whether signals have already been overriden, so that we don't
12638  * overwrite the preserved signal handlers with gl_get_line()s. Also
12639  * record whether we are currently in raw I/O mode or not, so that this
12640  * can be left in the same state on leaving this function.
12641  */
12642   int was_overriden = gl->signals_overriden;
12643   int was_raw = gl->raw_mode;
12644 /*
12645  * Also keep a record of the direction of any I/O that gl_get_line()
12646  * is awaiting, so that we can restore this status on return.
12647  */
12648   GlPendingIO old_pending_io = gl->pending_io;
12649 /*
12650  * Assume that this call will successfully complete the input operation
12651  * until proven otherwise.
12652  */
12653   gl_clear_status(gl);
12654 /*
12655  * If this is the first call to this function or gl_get_line(),
12656  * since new_GetLine(), complete any postponed configuration.
12657  */
12658   if(!gl->configured) {
12659     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
12660     gl->configured = 1;
12661   };
12662 /*
12663  * Before installing our signal handler functions, record the fact
12664  * that there are no pending signals.
12665  */
12666   gl_pending_signal = -1;
12667 /*
12668  * Temporarily override the signal handlers of the calling program,
12669  * so that we can intercept signals that would leave the terminal
12670  * in a bad state.
12671  */
12672   if(!was_overriden)
12673     waserr = gl_override_signal_handlers(gl);
12674 /*
12675  * After recording the current terminal settings, switch the terminal
12676  * into raw input mode, without redisplaying any partially entered input
12677  * line.
12678  */
12679   if(!was_raw)
12680     waserr = waserr || _gl_raw_io(gl, 0);
12681 /*
12682  * Attempt to read the line. This will require more than one attempt if
12683  * either a current temporary input file is opened by gl_get_input_line()
12684  * or the end of a temporary input file is reached by gl_read_stream_line().
12685  */
12686   while(!waserr) {
12687 /*
12688  * Read a line from a non-interactive stream?
12689  */
12690     if(gl->file_fp || !gl->is_term) {
12691       retval = gl_read_stream_char(gl);
12692       if(retval != EOF) {            /* Success? */
12693 	break;
12694       } else if(gl->file_fp) {  /* End of temporary input file? */
12695 	gl_revert_input(gl);
12696 	gl_record_status(gl, GLR_NEWLINE, 0);
12697       } else {                  /* An error? */
12698 	waserr = 1;
12699 	break;
12700       };
12701     };
12702 /*
12703  * Read from the terminal? Note that the above if() block may have
12704  * changed gl->file_fp, so it is necessary to retest it here, rather
12705  * than using an else statement.
12706  */
12707     if(!gl->file_fp && gl->is_term) {
12708 /*
12709  * Flush any pending output to the terminal before waiting
12710  * for the user to type a character.
12711  */
12712       if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) {
12713 	retval = EOF;
12714 /*
12715  * Read one character. Don't append it to the key buffer, since
12716  * this would subseuqnely appear as bogus input to the line editor.
12717  */
12718       } else if(gl_read_terminal(gl, 0, &c) == 0) {
12719 /*
12720  * Record the character for return.
12721  */
12722 	retval = c;
12723 /*
12724  * In this mode, count each character as being a new key-sequence.
12725  */
12726 	gl->keyseq_count++;
12727 /*
12728  * Delete the character that was read, from the key-press buffer.
12729  */
12730 	gl_discard_chars(gl, 1);
12731       };
12732       if(retval==EOF)
12733 	waserr = 1;
12734       else
12735 	break;
12736     };
12737   };
12738 /*
12739  * If an error occurred, but gl->rtn_status is still set to
12740  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
12741  * leave it at whatever specific value was assigned by the function
12742  * that aborted input. This means that only functions that trap
12743  * non-generic errors have to remember to update gl->rtn_status
12744  * themselves.
12745  */
12746   if(waserr && gl->rtn_status == GLR_NEWLINE)
12747     gl_record_status(gl, GLR_ERROR, errno);
12748 /*
12749  * Restore terminal settings, if they were changed by this function.
12750  */
12751   if(!was_raw && gl->io_mode != GL_SERVER_MODE)
12752     _gl_normal_io(gl);
12753 /*
12754  * Restore the signal handlers, if they were overriden by this function.
12755  */
12756   if(!was_overriden)
12757     gl_restore_signal_handlers(gl);
12758 /*
12759  * If this function gets aborted early, the errno value associated
12760  * with the event that caused this to happen is recorded in
12761  * gl->rtn_errno. Since errno may have been overwritten by cleanup
12762  * functions after this, restore its value to the value that it had
12763  * when the error condition occured, so that the caller can examine it
12764  * to find out what happened.
12765  */
12766   errno = gl->rtn_errno;
12767 /*
12768  * Error conditions are signalled to the caller, by setting the returned
12769  * character to EOF.
12770  */
12771   if(gl->rtn_status != GLR_NEWLINE)
12772     retval = EOF;
12773 /*
12774  * Restore the indication of what direction of I/O gl_get_line()
12775  * was awaiting before this call.
12776  */
12777   gl->pending_io = old_pending_io;
12778 /*
12779  * Return the acquired character.
12780  */
12781   return retval;
12782 }
12783 
12784 /*.......................................................................
12785  * Reset the GetLine completion status. This function should be called
12786  * at the start of gl_get_line(), gl_read_char() and gl_query_char()
12787  * to discard the completion status and non-zero errno value of any
12788  * preceding calls to these functions.
12789  *
12790  * Input:
12791  *  gl       GetLine *  The resource object of this module.
12792  */
12793 static void gl_clear_status(GetLine *gl)
12794 {
12795   gl_record_status(gl, GLR_NEWLINE, 0);
12796 }
12797 
12798 /*.......................................................................
12799  * When an error or other event causes gl_get_line() to return, this
12800  * function should be called to record information about what
12801  * happened, including the value of errno and the value that
12802  * gl_return_status() should return.
12803  *
12804  * Input:
12805  *  gl                GetLine *  The resource object of this module.
12806  *  rtn_status GlReturnStatus    The completion status. To clear a
12807  *                               previous abnormal completion status,
12808  *                               specify GLR_NEWLINE (this is what
12809  *                               gl_clear_status() does).
12810  *  rtn_errno             int    The associated value of errno.
12811  */
12812 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
12813 			     int rtn_errno)
12814 {
12815 /*
12816  * If rtn_status==GLR_NEWLINE, then this resets the completion status, so we
12817  * should always heed this. Otherwise, only record the first abnormal
12818  * condition that occurs after such a reset.
12819  */
12820   if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) {
12821     gl->rtn_status = rtn_status;
12822     gl->rtn_errno = rtn_errno;
12823   };
12824 }
12825 
12826