xref: /titanic_50/usr/src/lib/libtecla/common/getline.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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   if(!term || setupterm((char *)term, gl->input_fd, NULL) == ERR) {
3543     bad_term = 1;
3544   } else {
3545     _clr_StringGroup(gl->capmem);
3546     gl->left = gl_tigetstr(gl, "cub1");
3547     gl->right = gl_tigetstr(gl, "cuf1");
3548     gl->up = gl_tigetstr(gl, "cuu1");
3549     gl->down = gl_tigetstr(gl, "cud1");
3550     gl->home = gl_tigetstr(gl, "home");
3551     gl->clear_eol = gl_tigetstr(gl, "el");
3552     gl->clear_eod = gl_tigetstr(gl, "ed");
3553     gl->u_arrow = gl_tigetstr(gl, "kcuu1");
3554     gl->d_arrow = gl_tigetstr(gl, "kcud1");
3555     gl->l_arrow = gl_tigetstr(gl, "kcub1");
3556     gl->r_arrow = gl_tigetstr(gl, "kcuf1");
3557     gl->left_n = gl_tigetstr(gl, "cub");
3558     gl->right_n = gl_tigetstr(gl, "cuf");
3559     gl->sound_bell = gl_tigetstr(gl, "bel");
3560     gl->bold = gl_tigetstr(gl, "bold");
3561     gl->underline = gl_tigetstr(gl, "smul");
3562     gl->standout = gl_tigetstr(gl, "smso");
3563     gl->dim = gl_tigetstr(gl, "dim");
3564     gl->reverse = gl_tigetstr(gl, "rev");
3565     gl->blink = gl_tigetstr(gl, "blink");
3566     gl->text_attr_off = gl_tigetstr(gl, "sgr0");
3567   };
3568 #elif defined(USE_TERMCAP)
3569   if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) {
3570     bad_term = 1;
3571   } else {
3572     char *tgetstr_buf_ptr = gl->tgetstr_buf;
3573     _clr_StringGroup(gl->capmem);
3574     gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr);
3575     gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr);
3576     gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr);
3577     gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr);
3578     gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr);
3579     gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr);
3580     gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr);
3581     gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr);
3582     gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr);
3583     gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr);
3584     gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr);
3585     gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr);
3586     gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr);
3587     gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr);
3588     gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr);
3589     gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr);
3590     gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr);
3591     gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr);
3592     gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr);
3593   };
3594 #endif
3595 /*
3596  * Report term being unusable.
3597  */
3598   if(bad_term) {
3599     gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)",
3600 		  "\". Will assume vt100.", GL_END_INFO);
3601   };
3602 /*
3603  * Fill in missing information with ANSI VT100 strings.
3604  */
3605   if(!gl->left)
3606     gl->left = "\b";    /* ^H */
3607   if(!gl->right)
3608     gl->right = GL_ESC_STR "[C";
3609   if(!gl->up)
3610     gl->up = GL_ESC_STR "[A";
3611   if(!gl->down)
3612     gl->down = "\n";
3613   if(!gl->home)
3614     gl->home = GL_ESC_STR "[H";
3615   if(!gl->bol)
3616     gl->bol = "\r";
3617   if(!gl->clear_eol)
3618     gl->clear_eol = GL_ESC_STR "[K";
3619   if(!gl->clear_eod)
3620     gl->clear_eod = GL_ESC_STR "[J";
3621   if(!gl->u_arrow)
3622     gl->u_arrow = GL_ESC_STR "[A";
3623   if(!gl->d_arrow)
3624     gl->d_arrow = GL_ESC_STR "[B";
3625   if(!gl->l_arrow)
3626     gl->l_arrow = GL_ESC_STR "[D";
3627   if(!gl->r_arrow)
3628     gl->r_arrow = GL_ESC_STR "[C";
3629   if(!gl->sound_bell)
3630     gl->sound_bell = "\a";
3631   if(!gl->bold)
3632     gl->bold = GL_ESC_STR "[1m";
3633   if(!gl->underline)
3634     gl->underline = GL_ESC_STR "[4m";
3635   if(!gl->standout)
3636     gl->standout = GL_ESC_STR "[1;7m";
3637   if(!gl->dim)
3638     gl->dim = "";  /* Not available */
3639   if(!gl->reverse)
3640     gl->reverse = GL_ESC_STR "[7m";
3641   if(!gl->blink)
3642     gl->blink = GL_ESC_STR "[5m";
3643   if(!gl->text_attr_off)
3644     gl->text_attr_off = GL_ESC_STR "[m";
3645 /*
3646  * Find out the current terminal size.
3647  */
3648   (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL);
3649   return 0;
3650 }
3651 
3652 #ifdef USE_TERMINFO
3653 /*.......................................................................
3654  * This is a private function of gl_control_strings() used to look up
3655  * a termninal capability string from the terminfo database and make
3656  * a private copy of it.
3657  *
3658  * Input:
3659  *  gl         GetLine *  The resource object of gl_get_line().
3660  *  name    const char *  The name of the terminfo string to look up.
3661  * Output:
3662  *  return  const char *  The local copy of the capability, or NULL
3663  *                        if not available.
3664  */
3665 static const char *gl_tigetstr(GetLine *gl, const char *name)
3666 {
3667   const char *value = tigetstr((char *)name);
3668   if(!value || value == (char *) -1)
3669     return NULL;
3670   return _sg_store_string(gl->capmem, value, 0);
3671 }
3672 #elif defined(USE_TERMCAP)
3673 /*.......................................................................
3674  * This is a private function of gl_control_strings() used to look up
3675  * a termninal capability string from the termcap database and make
3676  * a private copy of it. Note that some emulations of tgetstr(), such
3677  * as that used by Solaris, ignores the buffer pointer that is past to
3678  * it, so we can't assume that a private copy has been made that won't
3679  * be trashed by another call to gl_control_strings() by another
3680  * GetLine object. So we make what may be a redundant private copy
3681  * of the string in gl->capmem.
3682  *
3683  * Input:
3684  *  gl         GetLine *  The resource object of gl_get_line().
3685  *  name    const char *  The name of the terminfo string to look up.
3686  * Input/Output:
3687  *  bufptr        char ** On input *bufptr points to the location in
3688  *                        gl->tgetstr_buf at which to record the
3689  *                        capability string. On output *bufptr is
3690  *                        incremented over the stored string.
3691  * Output:
3692  *  return  const char *  The local copy of the capability, or NULL
3693  *                        on error.
3694  */
3695 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr)
3696 {
3697   const char *value = tgetstr((char *)name, bufptr);
3698   if(!value || value == (char *) -1)
3699     return NULL;
3700   return _sg_store_string(gl->capmem, value, 0);
3701 }
3702 #endif
3703 
3704 /*.......................................................................
3705  * This is an action function that implements a user interrupt (eg. ^C).
3706  */
3707 static KT_KEY_FN(gl_user_interrupt)
3708 {
3709   raise(SIGINT);
3710   return 1;
3711 }
3712 
3713 /*.......................................................................
3714  * This is an action function that implements the abort signal.
3715  */
3716 static KT_KEY_FN(gl_abort)
3717 {
3718   raise(SIGABRT);
3719   return 1;
3720 }
3721 
3722 /*.......................................................................
3723  * This is an action function that sends a suspend signal (eg. ^Z) to the
3724  * the parent process.
3725  */
3726 static KT_KEY_FN(gl_suspend)
3727 {
3728   raise(SIGTSTP);
3729   return 0;
3730 }
3731 
3732 /*.......................................................................
3733  * This is an action function that halts output to the terminal.
3734  */
3735 static KT_KEY_FN(gl_stop_output)
3736 {
3737   tcflow(gl->output_fd, TCOOFF);
3738   return 0;
3739 }
3740 
3741 /*.......................................................................
3742  * This is an action function that resumes halted terminal output.
3743  */
3744 static KT_KEY_FN(gl_start_output)
3745 {
3746   tcflow(gl->output_fd, TCOON);
3747   return 0;
3748 }
3749 
3750 /*.......................................................................
3751  * This is an action function that allows the next character to be accepted
3752  * without any interpretation as a special character.
3753  */
3754 static KT_KEY_FN(gl_literal_next)
3755 {
3756   char c;   /* The character to be added to the line */
3757   int i;
3758 /*
3759  * Get the character to be inserted literally.
3760  */
3761   if(gl_read_terminal(gl, 1, &c))
3762     return 1;
3763 /*
3764  * Add the character to the line 'count' times.
3765  */
3766   for(i=0; i<count; i++)
3767     gl_add_char_to_line(gl, c);
3768   return 0;
3769 }
3770 
3771 /*.......................................................................
3772  * Return the width of a tab character at a given position when
3773  * displayed at a given position on the terminal. This is needed
3774  * because the width of tab characters depends on where they are,
3775  * relative to the preceding tab stops.
3776  *
3777  * Input:
3778  *  gl       GetLine *  The resource object of this library.
3779  *  term_curpos  int    The destination terminal location of the character.
3780  * Output:
3781  *  return       int    The number of terminal charaters needed.
3782  */
3783 static int gl_displayed_tab_width(GetLine *gl, int term_curpos)
3784 {
3785   return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH);
3786 }
3787 
3788 /*.......................................................................
3789  * Return the number of characters needed to display a given character
3790  * on the screen. Tab characters require eight spaces, and control
3791  * characters are represented by a caret followed by the modified
3792  * character.
3793  *
3794  * Input:
3795  *  gl       GetLine *  The resource object of this library.
3796  *  c           char    The character to be displayed.
3797  *  term_curpos  int    The destination terminal location of the character.
3798  *                      This is needed because the width of tab characters
3799  *                      depends on where they are, relative to the
3800  *                      preceding tab stops.
3801  * Output:
3802  *  return       int    The number of terminal charaters needed.
3803  */
3804 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos)
3805 {
3806   if(c=='\t')
3807     return gl_displayed_tab_width(gl, term_curpos);
3808   if(IS_CTRL_CHAR(c))
3809     return 2;
3810   if(!isprint((int)(unsigned char) c))
3811     return gl_octal_width((int)(unsigned char)c) + 1;
3812   return 1;
3813 }
3814 
3815 
3816 /*.......................................................................
3817  * Work out the length of given string of characters on the terminal.
3818  *
3819  * Input:
3820  *  gl       GetLine *  The resource object of this library.
3821  *  string      char *  The string to be measured.
3822  *  nc           int    The number of characters to be measured, or -1
3823  *                      to measure the whole string.
3824  *  term_curpos  int    The destination terminal location of the character.
3825  *                      This is needed because the width of tab characters
3826  *                      depends on where they are, relative to the
3827  *                      preceding tab stops.
3828  * Output:
3829  *  return       int    The number of displayed characters.
3830  */
3831 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
3832 				     int term_curpos)
3833 {
3834   int slen = 0;   /* The displayed number of characters */
3835   int i;
3836 /*
3837  * How many characters are to be measured?
3838  */
3839   if(nc < 0)
3840     nc = strlen(string);
3841 /*
3842  * Add up the length of the displayed string.
3843  */
3844   for(i=0; i<nc; i++)
3845     slen += gl_displayed_char_width(gl, string[i], term_curpos + slen);
3846   return slen;
3847 }
3848 
3849 /*.......................................................................
3850  * Write a string verbatim to the current terminal or output stream.
3851  *
3852  * Note that when async-signal safety is required, the 'buffered'
3853  * argument must be 0, and n must not be -1.
3854  *
3855  * Input:
3856  *  gl         GetLine *  The resource object of the gl_get_line().
3857  *  buffered       int    If true, used buffered I/O when writing to
3858  *                        the terminal. Otherwise use async-signal-safe
3859  *                        unbuffered I/O.
3860  *  string  const char *  The string to be written (this need not be
3861  *                        '\0' terminated unless n<0).
3862  *  n              int    The number of characters to write from the
3863  *                        prefix of string[], or -1 to request that
3864  *                        gl_print_raw_string() use strlen() to figure
3865  *                        out the length.
3866  * Output:
3867  *  return         int    0 - OK.
3868  *                        1 - Error.
3869  */
3870 static int gl_print_raw_string(GetLine *gl, int buffered,
3871 			       const char *string, int n)
3872 {
3873   GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn;
3874 /*
3875  * Only display output when echoing is turned on.
3876  */
3877   if(gl->echo) {
3878     int ndone = 0;   /* The number of characters written so far */
3879 /*
3880  * When using un-buffered I/O, flush pending output first.
3881  */
3882     if(!buffered) {
3883       if(gl_flush_output(gl))
3884 	return 1;
3885     };
3886 /*
3887  * If no length has been provided, measure the length of the string.
3888  */
3889     if(n < 0)
3890       n = strlen(string);
3891 /*
3892  * Write the string.
3893  */
3894     if(write_fn(gl, string + ndone, n-ndone) != n)
3895       return 1;
3896   };
3897   return 0;
3898 }
3899 
3900 /*.......................................................................
3901  * Output a terminal control sequence. When using terminfo,
3902  * this must be a sequence returned by tgetstr() or tigetstr()
3903  * respectively.
3904  *
3905  * Input:
3906  *  gl     GetLine *   The resource object of this library.
3907  *  nline      int     The number of lines affected by the operation,
3908  *                     or 1 if not relevant.
3909  *  string    char *   The control sequence to be sent.
3910  * Output:
3911  *  return     int     0 - OK.
3912  *                     1 - Error.
3913  */
3914 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string)
3915 {
3916   int waserr = 0;   /* True if an error occurs */
3917 /*
3918  * Only write characters to the terminal when echoing is enabled.
3919  */
3920   if(gl->echo) {
3921 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3922     tputs_gl = gl;
3923     errno = 0;
3924     tputs((char *)string, nline, gl_tputs_putchar);
3925     waserr = errno != 0;
3926 #else
3927     waserr = gl_print_raw_string(gl, 1, string, -1);
3928 #endif
3929   };
3930   return waserr;
3931 }
3932 
3933 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3934 /*.......................................................................
3935  * The following callback function is called by tputs() to output a raw
3936  * control character to the terminal.
3937  */
3938 static TputsRetType gl_tputs_putchar(TputsArgType c)
3939 {
3940   char ch = c;
3941 #if TPUTS_RETURNS_VALUE
3942   return gl_print_raw_string(tputs_gl, 1, &ch, 1);
3943 #else
3944   (void) gl_print_raw_string(tputs_gl, 1, &ch, 1);
3945 #endif
3946 }
3947 #endif
3948 
3949 /*.......................................................................
3950  * Move the terminal cursor n characters to the left or right.
3951  *
3952  * Input:
3953  *  gl     GetLine *   The resource object of this program.
3954  *  n          int     number of positions to the right (> 0) or left (< 0).
3955  * Output:
3956  *  return     int     0 - OK.
3957  *                     1 - Error.
3958  */
3959 static int gl_terminal_move_cursor(GetLine *gl, int n)
3960 {
3961   int cur_row, cur_col; /* The current terminal row and column index of */
3962                         /*  the cursor wrt the start of the input line. */
3963   int new_row, new_col; /* The target terminal row and column index of */
3964                         /*  the cursor wrt the start of the input line. */
3965 /*
3966  * Do nothing if the input line isn't currently displayed. In this
3967  * case, the cursor will be moved to the right place when the line
3968  * is next redisplayed.
3969  */
3970   if(!gl->displayed)
3971     return 0;
3972 /*
3973  * How far can we move left?
3974  */
3975   if(gl->term_curpos + n < 0)
3976     n = gl->term_curpos;
3977 /*
3978  * Break down the current and target cursor locations into rows and columns.
3979  */
3980   cur_row = gl->term_curpos / gl->ncolumn;
3981   cur_col = gl->term_curpos % gl->ncolumn;
3982   new_row = (gl->term_curpos + n) / gl->ncolumn;
3983   new_col = (gl->term_curpos + n) % gl->ncolumn;
3984 /*
3985  * Move down to the next line.
3986  */
3987   for(; cur_row < new_row; cur_row++) {
3988     if(gl_print_control_sequence(gl, 1, gl->down))
3989       return 1;
3990   };
3991 /*
3992  * Move up to the previous line.
3993  */
3994   for(; cur_row > new_row; cur_row--) {
3995     if(gl_print_control_sequence(gl, 1, gl->up))
3996       return 1;
3997   };
3998 /*
3999  * Move to the right within the target line?
4000  */
4001   if(cur_col < new_col) {
4002 #ifdef USE_TERMINFO
4003 /*
4004  * Use a parameterized control sequence if it generates less control
4005  * characters (guess based on ANSI terminal termcap entry).
4006  */
4007     if(gl->right_n != NULL && new_col - cur_col > 1) {
4008       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n,
4009            (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4010 	return 1;
4011     } else
4012 #endif
4013     {
4014       for(; cur_col < new_col; cur_col++) {
4015         if(gl_print_control_sequence(gl, 1, gl->right))
4016           return 1;
4017       };
4018     };
4019 /*
4020  * Move to the left within the target line?
4021  */
4022   } else if(cur_col > new_col) {
4023 #ifdef USE_TERMINFO
4024 /*
4025  * Use a parameterized control sequence if it generates less control
4026  * characters (guess based on ANSI terminal termcap entry).
4027  */
4028     if(gl->left_n != NULL && cur_col - new_col > 3) {
4029       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n,
4030            (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4031 	return 1;
4032     } else
4033 #endif
4034     {
4035       for(; cur_col > new_col; cur_col--) {
4036         if(gl_print_control_sequence(gl, 1, gl->left))
4037           return 1;
4038       };
4039     };
4040   }
4041 /*
4042  * Update the recorded position of the terminal cursor.
4043  */
4044   gl->term_curpos += n;
4045   return 0;
4046 }
4047 
4048 /*.......................................................................
4049  * Write a character to the terminal after expanding tabs and control
4050  * characters to their multi-character representations.
4051  *
4052  * Input:
4053  *  gl    GetLine *   The resource object of this program.
4054  *  c        char     The character to be output.
4055  *  pad      char     Many terminals have the irritating feature that
4056  *                    when one writes a character in the last column of
4057  *                    of the terminal, the cursor isn't wrapped to the
4058  *                    start of the next line until one more character
4059  *                    is written. Some terminals don't do this, so
4060  *                    after such a write, we don't know where the
4061  *                    terminal is unless we output an extra character.
4062  *                    This argument specifies the character to write.
4063  *                    If at the end of the input line send '\0' or a
4064  *                    space, and a space will be written. Otherwise,
4065  *                    pass the next character in the input line
4066  *                    following the one being written.
4067  * Output:
4068  *  return    int     0 - OK.
4069  */
4070 static int gl_print_char(GetLine *gl, char c, char pad)
4071 {
4072   char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */
4073   int nchar;                  /* The number of terminal characters */
4074   int i;
4075 /*
4076  * Check for special characters.
4077  */
4078   if(c == '\t') {
4079 /*
4080  * How many spaces do we need to represent a tab at the current terminal
4081  * column?
4082  */
4083     nchar = gl_displayed_tab_width(gl, gl->term_curpos);
4084 /*
4085  * Compose the tab string.
4086  */
4087     for(i=0; i<nchar; i++)
4088       string[i] = ' ';
4089   } else if(IS_CTRL_CHAR(c)) {
4090     string[0] = '^';
4091     string[1] = CTRL_TO_CHAR(c);
4092     nchar = 2;
4093   } else if(!isprint((int)(unsigned char) c)) {
4094     snprintf(string, sizeof(string), "\\%o", (int)(unsigned char)c);
4095     nchar = strlen(string);
4096   } else {
4097     string[0] = c;
4098     nchar = 1;
4099   };
4100 /*
4101  * Terminate the string.
4102  */
4103   string[nchar] = '\0';
4104 /*
4105  * Write the string to the terminal.
4106  */
4107   if(gl_print_raw_string(gl, 1, string, -1))
4108     return 1;
4109 /*
4110  * Except for one exception to be described in a moment, the cursor should
4111  * now have been positioned after the character that was just output.
4112  */
4113   gl->term_curpos += nchar;
4114 /*
4115  * Keep a record of the number of characters in the terminal version
4116  * of the input line.
4117  */
4118   if(gl->term_curpos > gl->term_len)
4119     gl->term_len = gl->term_curpos;
4120 /*
4121  * If the new character ended exactly at the end of a line,
4122  * most terminals won't move the cursor onto the next line until we
4123  * have written a character on the next line, so append an extra
4124  * space then move the cursor back.
4125  */
4126   if(gl->term_curpos % gl->ncolumn == 0) {
4127     int term_curpos = gl->term_curpos;
4128     if(gl_print_char(gl, pad ? pad : ' ', ' ') ||
4129        gl_set_term_curpos(gl, term_curpos))
4130       return 1;
4131   };
4132   return 0;
4133 }
4134 
4135 /*.......................................................................
4136  * Write a string to the terminal after expanding tabs and control
4137  * characters to their multi-character representations.
4138  *
4139  * Input:
4140  *  gl    GetLine *   The resource object of this program.
4141  *  string   char *   The string to be output.
4142  *  pad      char     Many terminals have the irritating feature that
4143  *                    when one writes a character in the last column of
4144  *                    of the terminal, the cursor isn't wrapped to the
4145  *                    start of the next line until one more character
4146  *                    is written. Some terminals don't do this, so
4147  *                    after such a write, we don't know where the
4148  *                    terminal is unless we output an extra character.
4149  *                    This argument specifies the character to write.
4150  *                    If at the end of the input line send '\0' or a
4151  *                    space, and a space will be written. Otherwise,
4152  *                    pass the next character in the input line
4153  *                    following the one being written.
4154  * Output:
4155  *  return    int     0 - OK.
4156  */
4157 static int gl_print_string(GetLine *gl, const char *string, char pad)
4158 {
4159   const char *cptr;   /* A pointer into string[] */
4160   for(cptr=string; *cptr; cptr++) {
4161     char nextc = cptr[1];
4162     if(gl_print_char(gl, *cptr, nextc ? nextc : pad))
4163       return 1;
4164   };
4165   return 0;
4166 }
4167 
4168 /*.......................................................................
4169  * Move the terminal cursor position.
4170  *
4171  * Input:
4172  *  gl      GetLine *  The resource object of this library.
4173  *  term_curpos int    The destination terminal cursor position.
4174  * Output:
4175  *  return      int    0 - OK.
4176  *                     1 - Error.
4177  */
4178 static int gl_set_term_curpos(GetLine *gl, int term_curpos)
4179 {
4180   return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos);
4181 }
4182 
4183 /*.......................................................................
4184  * This is an action function that moves the buffer cursor one character
4185  * left, and updates the terminal cursor to match.
4186  */
4187 static KT_KEY_FN(gl_cursor_left)
4188 {
4189   return gl_place_cursor(gl, gl->buff_curpos - count);
4190 }
4191 
4192 /*.......................................................................
4193  * This is an action function that moves the buffer cursor one character
4194  * right, and updates the terminal cursor to match.
4195  */
4196 static KT_KEY_FN(gl_cursor_right)
4197 {
4198   return gl_place_cursor(gl, gl->buff_curpos + count);
4199 }
4200 
4201 /*.......................................................................
4202  * This is an action function that toggles between overwrite and insert
4203  * mode.
4204  */
4205 static KT_KEY_FN(gl_insert_mode)
4206 {
4207   gl->insert = !gl->insert;
4208   return 0;
4209 }
4210 
4211 /*.......................................................................
4212  * This is an action function which moves the cursor to the beginning of
4213  * the line.
4214  */
4215 static KT_KEY_FN(gl_beginning_of_line)
4216 {
4217   return gl_place_cursor(gl, 0);
4218 }
4219 
4220 /*.......................................................................
4221  * This is an action function which moves the cursor to the end of
4222  * the line.
4223  */
4224 static KT_KEY_FN(gl_end_of_line)
4225 {
4226   return gl_place_cursor(gl, gl->ntotal);
4227 }
4228 
4229 /*.......................................................................
4230  * This is an action function which deletes the entire contents of the
4231  * current line.
4232  */
4233 static KT_KEY_FN(gl_delete_line)
4234 {
4235 /*
4236  * If in vi command mode, preserve the current line for potential
4237  * use by vi-undo.
4238  */
4239   gl_save_for_undo(gl);
4240 /*
4241  * Copy the contents of the line to the cut buffer.
4242  */
4243   strlcpy(gl->cutbuf, gl->line, gl->linelen);
4244 /*
4245  * Clear the buffer.
4246  */
4247   gl_truncate_buffer(gl, 0);
4248 /*
4249  * Move the terminal cursor to just after the prompt.
4250  */
4251   if(gl_place_cursor(gl, 0))
4252     return 1;
4253 /*
4254  * Clear from the end of the prompt to the end of the terminal.
4255  */
4256   if(gl_truncate_display(gl))
4257     return 1;
4258   return 0;
4259 }
4260 
4261 /*.......................................................................
4262  * This is an action function which deletes all characters between the
4263  * current cursor position and the end of the line.
4264  */
4265 static KT_KEY_FN(gl_kill_line)
4266 {
4267 /*
4268  * If in vi command mode, preserve the current line for potential
4269  * use by vi-undo.
4270  */
4271   gl_save_for_undo(gl);
4272 /*
4273  * Copy the part of the line that is about to be deleted to the cut buffer.
4274  */
4275   strlcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->linelen);
4276 /*
4277  * Terminate the buffered line at the current cursor position.
4278  */
4279   gl_truncate_buffer(gl, gl->buff_curpos);
4280 /*
4281  * Clear the part of the line that follows the cursor.
4282  */
4283   if(gl_truncate_display(gl))
4284     return 1;
4285 /*
4286  * Explicitly reset the cursor position to allow vi command mode
4287  * constraints on its position to be set.
4288  */
4289   return gl_place_cursor(gl, gl->buff_curpos);
4290 }
4291 
4292 /*.......................................................................
4293  * This is an action function which deletes all characters between the
4294  * start of the line and the current cursor position.
4295  */
4296 static KT_KEY_FN(gl_backward_kill_line)
4297 {
4298 /*
4299  * How many characters are to be deleted from before the cursor?
4300  */
4301   int nc = gl->buff_curpos - gl->insert_curpos;
4302   if (!nc)
4303     return 0;
4304 /*
4305  * Move the cursor to the start of the line, or in vi input mode,
4306  * the start of the sub-line at which insertion started, and delete
4307  * up to the old cursor position.
4308  */
4309   return gl_place_cursor(gl, gl->insert_curpos) ||
4310          gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command);
4311 }
4312 
4313 /*.......................................................................
4314  * This is an action function which moves the cursor forward by a word.
4315  */
4316 static KT_KEY_FN(gl_forward_word)
4317 {
4318   return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) +
4319 			 (gl->editor==GL_EMACS_MODE));
4320 }
4321 
4322 /*.......................................................................
4323  * This is an action function which moves the cursor forward to the start
4324  * of the next word.
4325  */
4326 static KT_KEY_FN(gl_forward_to_word)
4327 {
4328   return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count));
4329 }
4330 
4331 /*.......................................................................
4332  * This is an action function which moves the cursor backward by a word.
4333  */
4334 static KT_KEY_FN(gl_backward_word)
4335 {
4336   return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count));
4337 }
4338 
4339 /*.......................................................................
4340  * Delete one or more characters, starting with the one under the cursor.
4341  *
4342  * Input:
4343  *  gl     GetLine *  The resource object of this library.
4344  *  nc         int    The number of characters to delete.
4345  *  cut        int    If true, copy the characters to the cut buffer.
4346  * Output:
4347  *  return     int    0 - OK.
4348  *                    1 - Error.
4349  */
4350 static int gl_delete_chars(GetLine *gl, int nc, int cut)
4351 {
4352 /*
4353  * If in vi command mode, preserve the current line for potential
4354  * use by vi-undo.
4355  */
4356   gl_save_for_undo(gl);
4357 /*
4358  * If there are fewer than nc characters following the cursor, limit
4359  * nc to the number available.
4360  */
4361   if(gl->buff_curpos + nc > gl->ntotal)
4362     nc = gl->ntotal - gl->buff_curpos;
4363 /*
4364  * Copy the about to be deleted region to the cut buffer.
4365  */
4366   if(cut) {
4367     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc);
4368     gl->cutbuf[nc] = '\0';
4369   }
4370 /*
4371  * Nothing to delete?
4372  */
4373   if(nc <= 0)
4374     return 0;
4375 /*
4376  * In vi overwrite mode, restore any previously overwritten characters
4377  * from the undo buffer.
4378  */
4379   if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) {
4380 /*
4381  * How many of the characters being deleted can be restored from the
4382  * undo buffer?
4383  */
4384     int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ?
4385       nc : gl->vi.undo.ntotal - gl->buff_curpos;
4386 /*
4387  * Restore any available characters.
4388  */
4389     if(nrestore > 0) {
4390       gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore,
4391 		       gl->buff_curpos);
4392     };
4393 /*
4394  * If their were insufficient characters in the undo buffer, then this
4395  * implies that we are deleting from the end of the line, so we need
4396  * to terminate the line either where the undo buffer ran out, or if
4397  * we are deleting from beyond the end of the undo buffer, at the current
4398  * cursor position.
4399  */
4400     if(nc != nrestore) {
4401       gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ?
4402 			 gl->vi.undo.ntotal : gl->buff_curpos);
4403     };
4404   } else {
4405 /*
4406  * Copy the remaining part of the line back over the deleted characters.
4407  */
4408     gl_remove_from_buffer(gl, gl->buff_curpos, nc);
4409   };
4410 /*
4411  * Redraw the remaining characters following the cursor.
4412  */
4413   if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0'))
4414     return 1;
4415 /*
4416  * Clear to the end of the terminal.
4417  */
4418   if(gl_truncate_display(gl))
4419     return 1;
4420 /*
4421  * Place the cursor at the start of where the deletion was performed.
4422  */
4423   return gl_place_cursor(gl, gl->buff_curpos);
4424 }
4425 
4426 /*.......................................................................
4427  * This is an action function which deletes character(s) under the
4428  * cursor without moving the cursor.
4429  */
4430 static KT_KEY_FN(gl_forward_delete_char)
4431 {
4432 /*
4433  * Delete 'count' characters.
4434  */
4435   return gl_delete_chars(gl, count, gl->vi.command);
4436 }
4437 
4438 /*.......................................................................
4439  * This is an action function which deletes character(s) under the
4440  * cursor and moves the cursor back one character.
4441  */
4442 static KT_KEY_FN(gl_backward_delete_char)
4443 {
4444 /*
4445  * Restrict the deletion count to the number of characters that
4446  * precede the insertion point.
4447  */
4448   if(count > gl->buff_curpos - gl->insert_curpos)
4449     count = gl->buff_curpos - gl->insert_curpos;
4450 /*
4451  * If in vi command mode, preserve the current line for potential
4452  * use by vi-undo.
4453  */
4454   gl_save_for_undo(gl);
4455   return gl_cursor_left(gl, count, NULL) ||
4456     gl_delete_chars(gl, count, gl->vi.command);
4457 }
4458 
4459 /*.......................................................................
4460  * Starting from the cursor position delete to the specified column.
4461  */
4462 static KT_KEY_FN(gl_delete_to_column)
4463 {
4464   if (--count >= gl->buff_curpos)
4465     return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL);
4466   else
4467     return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL);
4468 }
4469 
4470 /*.......................................................................
4471  * Starting from the cursor position delete characters to a matching
4472  * parenthesis.
4473  */
4474 static KT_KEY_FN(gl_delete_to_parenthesis)
4475 {
4476   int curpos = gl_index_of_matching_paren(gl);
4477   if(curpos >= 0) {
4478     gl_save_for_undo(gl);
4479     if(curpos >= gl->buff_curpos)
4480       return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL);
4481     else
4482       return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
4483   };
4484   return 0;
4485 }
4486 
4487 /*.......................................................................
4488  * This is an action function which deletes from the cursor to the end
4489  * of the word that the cursor is either in or precedes.
4490  */
4491 static KT_KEY_FN(gl_forward_delete_word)
4492 {
4493 /*
4494  * If in vi command mode, preserve the current line for potential
4495  * use by vi-undo.
4496  */
4497   gl_save_for_undo(gl);
4498 /*
4499  * In emacs mode delete to the end of the word. In vi mode delete to the
4500  * start of the net word.
4501  */
4502   if(gl->editor == GL_EMACS_MODE) {
4503     return gl_delete_chars(gl,
4504 		gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1);
4505   } else {
4506     return gl_delete_chars(gl,
4507 		gl_nth_word_start_forward(gl,count) - gl->buff_curpos,
4508 		gl->vi.command);
4509   };
4510 }
4511 
4512 /*.......................................................................
4513  * This is an action function which deletes the word that precedes the
4514  * cursor.
4515  */
4516 static KT_KEY_FN(gl_backward_delete_word)
4517 {
4518 /*
4519  * Keep a record of the current cursor position.
4520  */
4521   int buff_curpos = gl->buff_curpos;
4522 /*
4523  * If in vi command mode, preserve the current line for potential
4524  * use by vi-undo.
4525  */
4526   gl_save_for_undo(gl);
4527 /*
4528  * Move back 'count' words.
4529  */
4530   if(gl_backward_word(gl, count, NULL))
4531     return 1;
4532 /*
4533  * Delete from the new cursor position to the original one.
4534  */
4535   return gl_delete_chars(gl, buff_curpos - gl->buff_curpos,
4536   			 gl->editor == GL_EMACS_MODE || gl->vi.command);
4537 }
4538 
4539 /*.......................................................................
4540  * Searching in a given direction, delete to the count'th
4541  * instance of a specified or queried character, in the input line.
4542  *
4543  * Input:
4544  *  gl       GetLine *  The getline resource object.
4545  *  count        int    The number of times to search.
4546  *  c           char    The character to be searched for, or '\0' if
4547  *                      the character should be read from the user.
4548  *  forward      int    True if searching forward.
4549  *  onto         int    True if the search should end on top of the
4550  *                      character, false if the search should stop
4551  *                      one character before the character in the
4552  *                      specified search direction.
4553  *  change       int    If true, this function is being called upon
4554  *                      to do a vi change command, in which case the
4555  *                      user will be left in insert mode after the
4556  *                      deletion.
4557  * Output:
4558  *  return       int    0 - OK.
4559  *                      1 - Error.
4560  */
4561 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
4562 			  int onto, int change)
4563 {
4564 /*
4565  * Search for the character, and abort the deletion if not found.
4566  */
4567   int pos = gl_find_char(gl, count, forward, onto, c);
4568   if(pos < 0)
4569     return 0;
4570 /*
4571  * If in vi command mode, preserve the current line for potential
4572  * use by vi-undo.
4573  */
4574   gl_save_for_undo(gl);
4575 /*
4576  * Allow the cursor to be at the end of the line if this is a change
4577  * command.
4578  */
4579   if(change)
4580     gl->vi.command = 0;
4581 /*
4582  * Delete the appropriate span of characters.
4583  */
4584   if(forward) {
4585     if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1))
4586       return 1;
4587   } else {
4588     int buff_curpos = gl->buff_curpos;
4589     if(gl_place_cursor(gl, pos) ||
4590        gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1))
4591       return 1;
4592   };
4593 /*
4594  * If this is a change operation, switch the insert mode.
4595  */
4596   if(change && gl_vi_insert(gl, 0, NULL))
4597     return 1;
4598   return 0;
4599 }
4600 
4601 /*.......................................................................
4602  * This is an action function which deletes forward from the cursor up to and
4603  * including a specified character.
4604  */
4605 static KT_KEY_FN(gl_forward_delete_find)
4606 {
4607   return gl_delete_find(gl, count, '\0', 1, 1, 0);
4608 }
4609 
4610 /*.......................................................................
4611  * This is an action function which deletes backward from the cursor back to
4612  * and including a specified character.
4613  */
4614 static KT_KEY_FN(gl_backward_delete_find)
4615 {
4616   return gl_delete_find(gl, count, '\0', 0, 1, 0);
4617 }
4618 
4619 /*.......................................................................
4620  * This is an action function which deletes forward from the cursor up to but
4621  * not including a specified character.
4622  */
4623 static KT_KEY_FN(gl_forward_delete_to)
4624 {
4625   return gl_delete_find(gl, count, '\0', 1, 0, 0);
4626 }
4627 
4628 /*.......................................................................
4629  * This is an action function which deletes backward from the cursor back to
4630  * but not including a specified character.
4631  */
4632 static KT_KEY_FN(gl_backward_delete_to)
4633 {
4634   return gl_delete_find(gl, count, '\0', 0, 0, 0);
4635 }
4636 
4637 /*.......................................................................
4638  * This is an action function which deletes to a character specified by a
4639  * previous search.
4640  */
4641 static KT_KEY_FN(gl_delete_refind)
4642 {
4643   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
4644 			gl->vi.find_onto, 0);
4645 }
4646 
4647 /*.......................................................................
4648  * This is an action function which deletes to a character specified by a
4649  * previous search, but in the opposite direction.
4650  */
4651 static KT_KEY_FN(gl_delete_invert_refind)
4652 {
4653   return gl_delete_find(gl, count, gl->vi.find_char,
4654 			!gl->vi.find_forward, gl->vi.find_onto, 0);
4655 }
4656 
4657 /*.......................................................................
4658  * This is an action function which converts the characters in the word
4659  * following the cursor to upper case.
4660  */
4661 static KT_KEY_FN(gl_upcase_word)
4662 {
4663 /*
4664  * Locate the count'th word ending after the cursor.
4665  */
4666   int last = gl_nth_word_end_forward(gl, count);
4667 /*
4668  * If in vi command mode, preserve the current line for potential
4669  * use by vi-undo.
4670  */
4671   gl_save_for_undo(gl);
4672 /*
4673  * Upcase characters from the current cursor position to 'last'.
4674  */
4675   while(gl->buff_curpos <= last) {
4676     char *cptr = gl->line + gl->buff_curpos;
4677 /*
4678  * Convert the character to upper case?
4679  */
4680     if(islower((int)(unsigned char) *cptr))
4681       gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos);
4682     gl->buff_curpos++;
4683 /*
4684  * Write the possibly modified character back. Note that for non-modified
4685  * characters we want to do this as well, so as to advance the cursor.
4686  */
4687     if(gl_print_char(gl, *cptr, cptr[1]))
4688       return 1;
4689   };
4690   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4691 }
4692 
4693 /*.......................................................................
4694  * This is an action function which converts the characters in the word
4695  * following the cursor to lower case.
4696  */
4697 static KT_KEY_FN(gl_downcase_word)
4698 {
4699 /*
4700  * Locate the count'th word ending after the cursor.
4701  */
4702   int last = gl_nth_word_end_forward(gl, count);
4703 /*
4704  * If in vi command mode, preserve the current line for potential
4705  * use by vi-undo.
4706  */
4707   gl_save_for_undo(gl);
4708 /*
4709  * Upcase characters from the current cursor position to 'last'.
4710  */
4711   while(gl->buff_curpos <= last) {
4712     char *cptr = gl->line + gl->buff_curpos;
4713 /*
4714  * Convert the character to upper case?
4715  */
4716     if(isupper((int)(unsigned char) *cptr))
4717       gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos);
4718     gl->buff_curpos++;
4719 /*
4720  * Write the possibly modified character back. Note that for non-modified
4721  * characters we want to do this as well, so as to advance the cursor.
4722  */
4723     if(gl_print_char(gl, *cptr, cptr[1]))
4724       return 1;
4725   };
4726   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4727 }
4728 
4729 /*.......................................................................
4730  * This is an action function which converts the first character of the
4731  * following word to upper case, in order to capitalize the word, and
4732  * leaves the cursor at the end of the word.
4733  */
4734 static KT_KEY_FN(gl_capitalize_word)
4735 {
4736   char *cptr;   /* &gl->line[gl->buff_curpos] */
4737   int first;    /* True for the first letter of the word */
4738   int i;
4739 /*
4740  * Keep a record of the current insert mode and the cursor position.
4741  */
4742   int insert = gl->insert;
4743 /*
4744  * If in vi command mode, preserve the current line for potential
4745  * use by vi-undo.
4746  */
4747   gl_save_for_undo(gl);
4748 /*
4749  * We want to overwrite the modified word.
4750  */
4751   gl->insert = 0;
4752 /*
4753  * Capitalize 'count' words.
4754  */
4755   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
4756     int pos = gl->buff_curpos;
4757 /*
4758  * If we are not already within a word, skip to the start of the word.
4759  */
4760     for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr);
4761 	pos++, cptr++)
4762       ;
4763 /*
4764  * Move the cursor to the new position.
4765  */
4766     if(gl_place_cursor(gl, pos))
4767       return 1;
4768 /*
4769  * While searching for the end of the word, change lower case letters
4770  * to upper case.
4771  */
4772     for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr);
4773 	gl->buff_curpos++, cptr++) {
4774 /*
4775  * Convert the character to upper case?
4776  */
4777       if(first) {
4778 	if(islower((int)(unsigned char) *cptr))
4779 	  gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
4780       } else {
4781 	if(isupper((int)(unsigned char) *cptr))
4782 	  gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
4783       };
4784       first = 0;
4785 /*
4786  * Write the possibly modified character back. Note that for non-modified
4787  * characters we want to do this as well, so as to advance the cursor.
4788  */
4789       if(gl_print_char(gl, *cptr, cptr[1]))
4790 	return 1;
4791     };
4792   };
4793 /*
4794  * Restore the insertion mode.
4795  */
4796   gl->insert = insert;
4797   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4798 }
4799 
4800 /*.......................................................................
4801  * This is an action function which redraws the current line.
4802  */
4803 static KT_KEY_FN(gl_redisplay)
4804 {
4805 /*
4806  * Keep a record of the current cursor position.
4807  */
4808   int buff_curpos = gl->buff_curpos;
4809 /*
4810  * Do nothing if there is no line to be redisplayed.
4811  */
4812   if(gl->endline)
4813     return 0;
4814 /*
4815  * Erase the current input line.
4816  */
4817   if(gl_erase_line(gl))
4818     return 1;
4819 /*
4820  * Display the current prompt.
4821  */
4822   if(gl_display_prompt(gl))
4823     return 1;
4824 /*
4825  * Render the part of the line that the user has typed in so far.
4826  */
4827   if(gl_print_string(gl, gl->line, '\0'))
4828     return 1;
4829 /*
4830  * Restore the cursor position.
4831  */
4832   if(gl_place_cursor(gl, buff_curpos))
4833     return 1;
4834 /*
4835  * Mark the redisplay operation as having been completed.
4836  */
4837   gl->redisplay = 0;
4838 /*
4839  * Flush the redisplayed line to the terminal.
4840  */
4841   return gl_flush_output(gl);
4842 }
4843 
4844 /*.......................................................................
4845  * This is an action function which clears the display and redraws the
4846  * input line from the home position.
4847  */
4848 static KT_KEY_FN(gl_clear_screen)
4849 {
4850 /*
4851  * Home the cursor and clear from there to the end of the display.
4852  */
4853   if(gl_print_control_sequence(gl, gl->nline, gl->home) ||
4854      gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
4855     return 1;
4856 /*
4857  * The input line is no longer displayed.
4858  */
4859   gl_line_erased(gl);
4860 /*
4861  * Arrange for the input line to be redisplayed.
4862  */
4863   gl_queue_redisplay(gl);
4864   return 0;
4865 }
4866 
4867 /*.......................................................................
4868  * This is an action function which swaps the character under the cursor
4869  * with the character to the left of the cursor.
4870  */
4871 static KT_KEY_FN(gl_transpose_chars)
4872 {
4873   char from[3];     /* The original string of 2 characters */
4874   char swap[3];     /* The swapped string of two characters */
4875 /*
4876  * If we are at the beginning or end of the line, there aren't two
4877  * characters to swap.
4878  */
4879   if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal)
4880     return 0;
4881 /*
4882  * If in vi command mode, preserve the current line for potential
4883  * use by vi-undo.
4884  */
4885   gl_save_for_undo(gl);
4886 /*
4887  * Get the original and swapped strings of the two characters.
4888  */
4889   from[0] = gl->line[gl->buff_curpos - 1];
4890   from[1] = gl->line[gl->buff_curpos];
4891   from[2] = '\0';
4892   swap[0] = gl->line[gl->buff_curpos];
4893   swap[1] = gl->line[gl->buff_curpos - 1];
4894   swap[2] = '\0';
4895 /*
4896  * Move the cursor to the start of the two characters.
4897  */
4898   if(gl_place_cursor(gl, gl->buff_curpos-1))
4899     return 1;
4900 /*
4901  * Swap the two characters in the buffer.
4902  */
4903   gl_buffer_char(gl, swap[0], gl->buff_curpos);
4904   gl_buffer_char(gl, swap[1], gl->buff_curpos+1);
4905 /*
4906  * If the sum of the displayed width of the two characters
4907  * in their current and final positions is the same, swapping can
4908  * be done by just overwriting with the two swapped characters.
4909  */
4910   if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) ==
4911      gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) {
4912     int insert = gl->insert;
4913     gl->insert = 0;
4914     if(gl_print_char(gl, swap[0], swap[1]) ||
4915        gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2]))
4916       return 1;
4917     gl->insert = insert;
4918 /*
4919  * If the swapped substring has a different displayed size, we need to
4920  * redraw everything after the first of the characters.
4921  */
4922   } else {
4923     if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') ||
4924        gl_truncate_display(gl))
4925       return 1;
4926   };
4927 /*
4928  * Advance the cursor to the character after the swapped pair.
4929  */
4930   return gl_place_cursor(gl, gl->buff_curpos + 2);
4931 }
4932 
4933 /*.......................................................................
4934  * This is an action function which sets a mark at the current cursor
4935  * location.
4936  */
4937 static KT_KEY_FN(gl_set_mark)
4938 {
4939   gl->buff_mark = gl->buff_curpos;
4940   return 0;
4941 }
4942 
4943 /*.......................................................................
4944  * This is an action function which swaps the mark location for the
4945  * cursor location.
4946  */
4947 static KT_KEY_FN(gl_exchange_point_and_mark)
4948 {
4949 /*
4950  * Get the old mark position, and limit to the extent of the input
4951  * line.
4952  */
4953   int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal;
4954 /*
4955  * Make the current cursor position the new mark.
4956  */
4957   gl->buff_mark = gl->buff_curpos;
4958 /*
4959  * Move the cursor to the old mark position.
4960  */
4961   return gl_place_cursor(gl, old_mark);
4962 }
4963 
4964 /*.......................................................................
4965  * This is an action function which deletes the characters between the
4966  * mark and the cursor, recording them in gl->cutbuf for later pasting.
4967  */
4968 static KT_KEY_FN(gl_kill_region)
4969 {
4970 /*
4971  * If in vi command mode, preserve the current line for potential
4972  * use by vi-undo.
4973  */
4974   gl_save_for_undo(gl);
4975 /*
4976  * Limit the mark to be within the line.
4977  */
4978   if(gl->buff_mark > gl->ntotal)
4979     gl->buff_mark = gl->ntotal;
4980 /*
4981  * If there are no characters between the cursor and the mark, simply clear
4982  * the cut buffer.
4983  */
4984   if(gl->buff_mark == gl->buff_curpos) {
4985     gl->cutbuf[0] = '\0';
4986     return 0;
4987   };
4988 /*
4989  * If the mark is before the cursor, swap the cursor and the mark.
4990  */
4991   if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL))
4992     return 1;
4993 /*
4994  * Delete the characters.
4995  */
4996   if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1))
4997     return 1;
4998 /*
4999  * Make the mark the same as the cursor position.
5000  */
5001   gl->buff_mark = gl->buff_curpos;
5002   return 0;
5003 }
5004 
5005 /*.......................................................................
5006  * This is an action function which records the characters between the
5007  * mark and the cursor, in gl->cutbuf for later pasting.
5008  */
5009 static KT_KEY_FN(gl_copy_region_as_kill)
5010 {
5011   int ca, cb;  /* The indexes of the first and last characters in the region */
5012   int mark;    /* The position of the mark */
5013 /*
5014  * Get the position of the mark, limiting it to lie within the line.
5015  */
5016   mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark;
5017 /*
5018  * If there are no characters between the cursor and the mark, clear
5019  * the cut buffer.
5020  */
5021   if(mark == gl->buff_curpos) {
5022     gl->cutbuf[0] = '\0';
5023     return 0;
5024   };
5025 /*
5026  * Get the line indexes of the first and last characters in the region.
5027  */
5028   if(mark < gl->buff_curpos) {
5029     ca = mark;
5030     cb = gl->buff_curpos - 1;
5031   } else {
5032     ca = gl->buff_curpos;
5033     cb = mark - 1;
5034   };
5035 /*
5036  * Copy the region to the cut buffer.
5037  */
5038   memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca);
5039   gl->cutbuf[cb + 1 - ca] = '\0';
5040   return 0;
5041 }
5042 
5043 /*.......................................................................
5044  * This is an action function which inserts the contents of the cut
5045  * buffer at the current cursor location.
5046  */
5047 static KT_KEY_FN(gl_yank)
5048 {
5049   int i;
5050 /*
5051  * Set the mark at the current location.
5052  */
5053   gl->buff_mark = gl->buff_curpos;
5054 /*
5055  * Do nothing else if the cut buffer is empty.
5056  */
5057   if(gl->cutbuf[0] == '\0')
5058     return gl_ring_bell(gl, 1, NULL);
5059 /*
5060  * If in vi command mode, preserve the current line for potential
5061  * use by vi-undo.
5062  */
5063   gl_save_for_undo(gl);
5064 /*
5065  * Insert the string count times.
5066  */
5067   for(i=0; i<count; i++) {
5068     if(gl_add_string_to_line(gl, gl->cutbuf))
5069       return 1;
5070   };
5071 /*
5072  * gl_add_string_to_line() leaves the cursor after the last character that
5073  * was pasted, whereas vi leaves the cursor over the last character pasted.
5074  */
5075   if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL))
5076     return 1;
5077   return 0;
5078 }
5079 
5080 /*.......................................................................
5081  * This is an action function which inserts the contents of the cut
5082  * buffer one character beyond the current cursor location.
5083  */
5084 static KT_KEY_FN(gl_append_yank)
5085 {
5086   int was_command = gl->vi.command;
5087   int i;
5088 /*
5089  * If the cut buffer is empty, ring the terminal bell.
5090  */
5091   if(gl->cutbuf[0] == '\0')
5092     return gl_ring_bell(gl, 1, NULL);
5093 /*
5094  * Set the mark at the current location + 1.
5095  */
5096   gl->buff_mark = gl->buff_curpos + 1;
5097 /*
5098  * If in vi command mode, preserve the current line for potential
5099  * use by vi-undo.
5100  */
5101   gl_save_for_undo(gl);
5102 /*
5103  * Arrange to paste the text in insert mode after the current character.
5104  */
5105   if(gl_vi_append(gl, 0, NULL))
5106     return 1;
5107 /*
5108  * Insert the string count times.
5109  */
5110   for(i=0; i<count; i++) {
5111     if(gl_add_string_to_line(gl, gl->cutbuf))
5112       return 1;
5113   };
5114 /*
5115  * Switch back to command mode if necessary.
5116  */
5117   if(was_command)
5118     gl_vi_command_mode(gl);
5119   return 0;
5120 }
5121 
5122 /*.......................................................................
5123  * Attempt to ask the terminal for its current size. On systems that
5124  * don't support the TIOCWINSZ ioctl() for querying the terminal size,
5125  * the current values of gl->ncolumn and gl->nrow are returned.
5126  *
5127  * Input:
5128  *  gl     GetLine *  The resource object of gl_get_line().
5129  * Input/Output:
5130  *  ncolumn    int *  The number of columns will be assigned to *ncolumn.
5131  *  nline      int *  The number of lines will be assigned to *nline.
5132  */
5133 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline)
5134 {
5135 #ifdef TIOCGWINSZ
5136 /*
5137  * Query the new terminal window size. Ignore invalid responses.
5138  */
5139   struct winsize size;
5140   if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 &&
5141      size.ws_row > 0 && size.ws_col > 0) {
5142     *ncolumn = size.ws_col;
5143     *nline = size.ws_row;
5144     return;
5145   };
5146 #endif
5147 /*
5148  * Return the existing values.
5149  */
5150   *ncolumn = gl->ncolumn;
5151   *nline = gl->nline;
5152   return;
5153 }
5154 
5155 /*.......................................................................
5156  * Query the size of the terminal, and if it has changed, redraw the
5157  * current input line accordingly.
5158  *
5159  * Input:
5160  *  gl     GetLine *  The resource object of gl_get_line().
5161  * Output:
5162  *  return     int    0 - OK.
5163  *                    1 - Error.
5164  */
5165 static int _gl_update_size(GetLine *gl)
5166 {
5167   int ncolumn, nline;    /* The new size of the terminal */
5168 /*
5169  * Query the new terminal window size.
5170  */
5171   gl_query_size(gl, &ncolumn, &nline);
5172 /*
5173  * Update gl and the displayed line to fit the new dimensions.
5174  */
5175   return gl_handle_tty_resize(gl, ncolumn, nline);
5176 }
5177 
5178 /*.......................................................................
5179  * Redraw the current input line to account for a change in the terminal
5180  * size. Also install the new size in gl.
5181  *
5182  * Input:
5183  *  gl     GetLine *  The resource object of gl_get_line().
5184  *  ncolumn    int    The new number of columns.
5185  *  nline      int    The new number of lines.
5186  * Output:
5187  *  return     int    0 - OK.
5188  *                    1 - Error.
5189  */
5190 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline)
5191 {
5192 /*
5193  * If the input device isn't a terminal, just record the new size.
5194  */
5195   if(!gl->is_term) {
5196     gl->nline = nline;
5197     gl->ncolumn = ncolumn;
5198 /*
5199  * Has the size actually changed?
5200  */
5201   } else if(ncolumn != gl->ncolumn || nline != gl->nline) {
5202 /*
5203  * If we are currently editing a line, erase it.
5204  */
5205     if(gl_erase_line(gl))
5206       return 1;
5207 /*
5208  * Update the recorded window size.
5209  */
5210     gl->nline = nline;
5211     gl->ncolumn = ncolumn;
5212 /*
5213  * Arrange for the input line to be redrawn before the next character
5214  * is read from the terminal.
5215  */
5216     gl_queue_redisplay(gl);
5217   };
5218   return 0;
5219 }
5220 
5221 /*.......................................................................
5222  * This is the action function that recalls the previous line in the
5223  * history buffer.
5224  */
5225 static KT_KEY_FN(gl_up_history)
5226 {
5227 /*
5228  * In vi mode, switch to command mode, since the user is very
5229  * likely to want to move around newly recalled lines.
5230  */
5231   gl_vi_command_mode(gl);
5232 /*
5233  * Forget any previous recall session.
5234  */
5235   gl->preload_id = 0;
5236 /*
5237  * Record the key sequence number of this search action.
5238  */
5239   gl->last_search = gl->keyseq_count;
5240 /*
5241  * We don't want a search prefix for this function.
5242  */
5243   if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5244     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5245     return 1;
5246   };
5247 /*
5248  * Recall the count'th next older line in the history list. If the first one
5249  * fails we can return since nothing has changed, otherwise we must continue
5250  * and update the line state.
5251  */
5252   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5253     return 0;
5254   while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1))
5255     ;
5256 /*
5257  * Accomodate the new contents of gl->line[].
5258  */
5259   gl_update_buffer(gl);
5260 /*
5261  * Arrange to have the cursor placed at the end of the new line.
5262  */
5263   gl->buff_curpos = gl->ntotal;
5264 /*
5265  * Erase and display the new line.
5266  */
5267   gl_queue_redisplay(gl);
5268   return 0;
5269 }
5270 
5271 /*.......................................................................
5272  * This is the action function that recalls the next line in the
5273  * history buffer.
5274  */
5275 static KT_KEY_FN(gl_down_history)
5276 {
5277 /*
5278  * In vi mode, switch to command mode, since the user is very
5279  * likely to want to move around newly recalled lines.
5280  */
5281   gl_vi_command_mode(gl);
5282 /*
5283  * Record the key sequence number of this search action.
5284  */
5285   gl->last_search = gl->keyseq_count;
5286 /*
5287  * If no search is currently in progress continue a previous recall
5288  * session from a previous entered line if possible.
5289  */
5290   if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) {
5291     _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1);
5292     gl->preload_id = 0;
5293   } else {
5294 /*
5295  * We don't want a search prefix for this function.
5296  */
5297     if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5298       _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5299       return 1;
5300     };
5301 /*
5302  * Recall the count'th next newer line in the history list. If the first one
5303  * fails we can return since nothing has changed otherwise we must continue
5304  * and update the line state.
5305  */
5306     if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5307       return 0;
5308     while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1))
5309       ;
5310   };
5311 /*
5312  * Accomodate the new contents of gl->line[].
5313  */
5314   gl_update_buffer(gl);
5315 /*
5316  * Arrange to have the cursor placed at the end of the new line.
5317  */
5318   gl->buff_curpos = gl->ntotal;
5319 /*
5320  * Erase and display the new line.
5321  */
5322   gl_queue_redisplay(gl);
5323   return 0;
5324 }
5325 
5326 /*.......................................................................
5327  * This is the action function that recalls the previous line in the
5328  * history buffer whos prefix matches the characters that currently
5329  * precede the cursor. By setting count=-1, this can be used internally
5330  * to force searching for the prefix used in the last search.
5331  */
5332 static KT_KEY_FN(gl_history_search_backward)
5333 {
5334 /*
5335  * In vi mode, switch to command mode, since the user is very
5336  * likely to want to move around newly recalled lines.
5337  */
5338   gl_vi_command_mode(gl);
5339 /*
5340  * Forget any previous recall session.
5341  */
5342   gl->preload_id = 0;
5343 /*
5344  * Record the key sequence number of this search action.
5345  */
5346   gl->last_search = gl->keyseq_count;
5347 /*
5348  * If a prefix search isn't already in progress, replace the search
5349  * prefix to the string that precedes the cursor. In vi command mode
5350  * include the character that is under the cursor in the string.  If
5351  * count<0 keep the previous search prefix regardless, so as to force
5352  * a repeat search even if the last command wasn't a history command.
5353  */
5354   if(count >= 0 && !_glh_search_active(gl->glh) &&
5355      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5356 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5357     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5358     return 1;
5359   };
5360 /*
5361  * Search backwards for a match to the part of the line which precedes the
5362  * cursor.
5363  */
5364   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5365     return 0;
5366 /*
5367  * Accomodate the new contents of gl->line[].
5368  */
5369   gl_update_buffer(gl);
5370 /*
5371  * Arrange to have the cursor placed at the end of the new line.
5372  */
5373   gl->buff_curpos = gl->ntotal;
5374 /*
5375  * Erase and display the new line.
5376  */
5377   gl_queue_redisplay(gl);
5378   return 0;
5379 }
5380 
5381 /*.......................................................................
5382  * This is the action function that recalls the previous line in the
5383  * history buffer who's prefix matches that specified in an earlier call
5384  * to gl_history_search_backward() or gl_history_search_forward().
5385  */
5386 static KT_KEY_FN(gl_history_re_search_backward)
5387 {
5388   return gl_history_search_backward(gl, -1, NULL);
5389 }
5390 
5391 /*.......................................................................
5392  * This is the action function that recalls the next line in the
5393  * history buffer who's prefix matches that specified in the earlier call
5394  * to gl_history_search_backward) which started the history search.
5395  * By setting count=-1, this can be used internally to force searching
5396  * for the prefix used in the last search.
5397  */
5398 static KT_KEY_FN(gl_history_search_forward)
5399 {
5400 /*
5401  * In vi mode, switch to command mode, since the user is very
5402  * likely to want to move around newly recalled lines.
5403  */
5404   gl_vi_command_mode(gl);
5405 /*
5406  * Record the key sequence number of this search action.
5407  */
5408   gl->last_search = gl->keyseq_count;
5409 /*
5410  * If a prefix search isn't already in progress, replace the search
5411  * prefix to the string that precedes the cursor. In vi command mode
5412  * include the character that is under the cursor in the string.  If
5413  * count<0 keep the previous search prefix regardless, so as to force
5414  * a repeat search even if the last command wasn't a history command.
5415  */
5416   if(count >= 0 && !_glh_search_active(gl->glh) &&
5417      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5418 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5419     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5420     return 1;
5421   };
5422 /*
5423  * Search forwards for the next matching line.
5424  */
5425   if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5426     return 0;
5427 /*
5428  * Accomodate the new contents of gl->line[].
5429  */
5430   gl_update_buffer(gl);
5431 /*
5432  * Arrange for the cursor to be placed at the end of the new line.
5433  */
5434   gl->buff_curpos = gl->ntotal;
5435 /*
5436  * Erase and display the new line.
5437  */
5438   gl_queue_redisplay(gl);
5439   return 0;
5440 }
5441 
5442 /*.......................................................................
5443  * This is the action function that recalls the next line in the
5444  * history buffer who's prefix matches that specified in an earlier call
5445  * to gl_history_search_backward() or gl_history_search_forward().
5446  */
5447 static KT_KEY_FN(gl_history_re_search_forward)
5448 {
5449   return gl_history_search_forward(gl, -1, NULL);
5450 }
5451 
5452 #ifdef HIDE_FILE_SYSTEM
5453 /*.......................................................................
5454  * The following function is used as the default completion handler when
5455  * the filesystem is to be hidden. It simply reports no completions.
5456  */
5457 static CPL_MATCH_FN(gl_no_completions)
5458 {
5459   return 0;
5460 }
5461 #endif
5462 
5463 /*.......................................................................
5464  * This is the tab completion function that completes the filename that
5465  * precedes the cursor position. Its callback data argument must be a
5466  * pointer to a GlCplCallback containing the completion callback function
5467  * and its callback data, or NULL to use the builtin filename completer.
5468  */
5469 static KT_KEY_FN(gl_complete_word)
5470 {
5471   CplMatches *matches;    /* The possible completions */
5472   int suffix_len;         /* The length of the completion extension */
5473   int cont_len;           /* The length of any continuation suffix */
5474   int nextra;             /* The number of characters being added to the */
5475                           /*  total length of the line. */
5476   int buff_pos;           /* The buffer index at which the completion is */
5477                           /*  to be inserted. */
5478   int waserr = 0;         /* True after errors */
5479 /*
5480  * Get the container of the completion callback and its callback data.
5481  */
5482   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
5483 /*
5484  * In vi command mode, switch to append mode so that the character under
5485  * the cursor is included in the completion (otherwise people can't
5486  * complete at the end of the line).
5487  */
5488   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5489     return 1;
5490 /*
5491  * Get the cursor position at which the completion is to be inserted.
5492  */
5493   buff_pos = gl->buff_curpos;
5494 /*
5495  * Perform the completion.
5496  */
5497   matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data,
5498 			      cb->fn);
5499 /*
5500  * No matching completions?
5501  */
5502   if(!matches) {
5503     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
5504 /*
5505  * Are there any completions?
5506  */
5507   } else if(matches->nmatch >= 1) {
5508 /*
5509  * If there any ambiguous matches, report them, starting on a new line.
5510  */
5511     if(matches->nmatch > 1 && gl->echo) {
5512       if(_gl_normal_io(gl) ||
5513 	 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
5514 	waserr = 1;
5515     };
5516 /*
5517  * Get the length of the suffix and any continuation suffix to add to it.
5518  */
5519     suffix_len = strlen(matches->suffix);
5520     cont_len = strlen(matches->cont_suffix);
5521 /*
5522  * If there is an unambiguous match, and the continuation suffix ends in
5523  * a newline, strip that newline and arrange to have getline return
5524  * after this action function returns.
5525  */
5526     if(matches->nmatch==1 && cont_len > 0 &&
5527        matches->cont_suffix[cont_len - 1] == '\n') {
5528       cont_len--;
5529       if(gl_newline(gl, 1, NULL))
5530 	waserr = 1;
5531     };
5532 /*
5533  * Work out the number of characters that are to be added.
5534  */
5535     nextra = suffix_len + cont_len;
5536 /*
5537  * Is there anything to be added?
5538  */
5539     if(!waserr && nextra) {
5540 /*
5541  * Will there be space for the expansion in the line buffer?
5542  */
5543       if(gl->ntotal + nextra < gl->linelen) {
5544 /*
5545  * Make room to insert the filename extension.
5546  */
5547 	gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5548 /*
5549  * Insert the filename extension.
5550  */
5551 	gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos);
5552 /*
5553  * Add the terminating characters.
5554  */
5555 	gl_buffer_string(gl, matches->cont_suffix, cont_len,
5556 			 gl->buff_curpos + suffix_len);
5557 /*
5558  * Place the cursor position at the end of the completion.
5559  */
5560 	gl->buff_curpos += nextra;
5561 /*
5562  * If we don't have to redisplay the whole line, redisplay the part
5563  * of the line which follows the original cursor position, and place
5564  * the cursor at the end of the completion.
5565  */
5566 	if(gl->displayed) {
5567 	  if(gl_truncate_display(gl) ||
5568 	     gl_print_string(gl, gl->line + buff_pos, '\0') ||
5569 	     gl_place_cursor(gl, gl->buff_curpos))
5570 	    waserr = 1;
5571 	};
5572       } else {
5573 	(void) gl_print_info(gl,
5574 			     "Insufficient room in line for file completion.",
5575 			     GL_END_INFO);
5576 	waserr = 1;
5577       };
5578     };
5579   };
5580 /*
5581  * If any output had to be written to the terminal, then editing will
5582  * have been suspended, make sure that we are back in raw line editing
5583  * mode before returning.
5584  */
5585   if(_gl_raw_io(gl, 1))
5586     waserr = 1;
5587   return 0;
5588 }
5589 
5590 #ifndef HIDE_FILE_SYSTEM
5591 /*.......................................................................
5592  * This is the function that expands the filename that precedes the
5593  * cursor position. It expands ~user/ expressions, $envvar expressions,
5594  * and wildcards.
5595  */
5596 static KT_KEY_FN(gl_expand_filename)
5597 {
5598   char *start_path;      /* The pointer to the start of the pathname in */
5599                          /*  gl->line[]. */
5600   FileExpansion *result; /* The results of the filename expansion */
5601   int pathlen;           /* The length of the pathname being expanded */
5602   int length;            /* The number of characters needed to display the */
5603                          /*  expanded files. */
5604   int nextra;            /* The number of characters to be added */
5605   int i,j;
5606 /*
5607  * In vi command mode, switch to append mode so that the character under
5608  * the cursor is included in the completion (otherwise people can't
5609  * complete at the end of the line).
5610  */
5611   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5612     return 1;
5613 /*
5614  * Locate the start of the filename that precedes the cursor position.
5615  */
5616   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5617   if(!start_path)
5618     return 1;
5619 /*
5620  * Get the length of the string that is to be expanded.
5621  */
5622   pathlen = gl->buff_curpos - (start_path - gl->line);
5623 /*
5624  * Attempt to expand it.
5625  */
5626   result = ef_expand_file(gl->ef, start_path, pathlen);
5627 /*
5628  * If there was an error, report the error on a new line.
5629  */
5630   if(!result)
5631     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
5632 /*
5633  * If no files matched, report this as well.
5634  */
5635   if(result->nfile == 0 || !result->exists)
5636     return gl_print_info(gl, "No files match.", GL_END_INFO);
5637 /*
5638  * If in vi command mode, preserve the current line for potential use by
5639  * vi-undo.
5640  */
5641   gl_save_for_undo(gl);
5642 /*
5643  * Work out how much space we will need to display all of the matching
5644  * filenames, taking account of the space that we need to place between
5645  * them, and the number of additional '\' characters needed to escape
5646  * spaces, tabs and backslash characters in the individual filenames.
5647  */
5648   length = 0;
5649   for(i=0; i<result->nfile; i++) {
5650     char *file = result->files[i];
5651     while(*file) {
5652       int c = *file++;
5653       switch(c) {
5654       case ' ': case '\t': case '\\': case '*': case '?': case '[':
5655 	length++;  /* Count extra backslash characters */
5656       };
5657       length++;    /* Count the character itself */
5658     };
5659     length++;      /* Count the space that follows each filename */
5660   };
5661 /*
5662  * Work out the number of characters that are to be added.
5663  */
5664   nextra = length - pathlen;
5665 /*
5666  * Will there be space for the expansion in the line buffer?
5667  */
5668   if(gl->ntotal + nextra >= gl->linelen) {
5669     return gl_print_info(gl, "Insufficient room in line for file expansion.",
5670 			 GL_END_INFO);
5671   } else {
5672 /*
5673  * Do we need to move the part of the line that followed the unexpanded
5674  * filename?
5675  */
5676     if(nextra > 0) {
5677       gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5678     } else if(nextra < 0) {
5679       gl->buff_curpos += nextra;
5680       gl_remove_from_buffer(gl, gl->buff_curpos, -nextra);
5681     };
5682 /*
5683  * Insert the filenames, separated by spaces, and with internal spaces,
5684  * tabs and backslashes escaped with backslashes.
5685  */
5686     for(i=0,j=start_path - gl->line; i<result->nfile; i++) {
5687       char *file = result->files[i];
5688       while(*file) {
5689 	int c = *file++;
5690 	switch(c) {
5691 	case ' ': case '\t': case '\\': case '*': case '?': case '[':
5692 	  gl_buffer_char(gl, '\\', j++);
5693 	};
5694 	gl_buffer_char(gl, c, j++);
5695       };
5696       gl_buffer_char(gl, ' ', j++);
5697     };
5698   };
5699 /*
5700  * Redisplay the part of the line which follows the start of
5701  * the original filename.
5702  */
5703   if(gl_place_cursor(gl, start_path - gl->line) ||
5704      gl_truncate_display(gl) ||
5705      gl_print_string(gl, start_path, start_path[length]))
5706     return 1;
5707 /*
5708  * Move the cursor to the end of the expansion.
5709  */
5710   return gl_place_cursor(gl, (start_path - gl->line) + length);
5711 }
5712 #endif
5713 
5714 #ifndef HIDE_FILE_SYSTEM
5715 /*.......................................................................
5716  * This is the action function that lists glob expansions of the
5717  * filename that precedes the cursor position. It expands ~user/
5718  * expressions, $envvar expressions, and wildcards.
5719  */
5720 static KT_KEY_FN(gl_list_glob)
5721 {
5722   char *start_path;      /* The pointer to the start of the pathname in */
5723                          /*  gl->line[]. */
5724   FileExpansion *result; /* The results of the filename expansion */
5725   int pathlen;           /* The length of the pathname being expanded */
5726 /*
5727  * Locate the start of the filename that precedes the cursor position.
5728  */
5729   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5730   if(!start_path)
5731     return 1;
5732 /*
5733  * Get the length of the string that is to be expanded.
5734  */
5735   pathlen = gl->buff_curpos - (start_path - gl->line);
5736 /*
5737  * Attempt to expand it.
5738  */
5739   result = ef_expand_file(gl->ef, start_path, pathlen);
5740 /*
5741  * If there was an error, report it.
5742  */
5743   if(!result) {
5744     return gl_print_info(gl,  ef_last_error(gl->ef), GL_END_INFO);
5745 /*
5746  * If no files matched, report this as well.
5747  */
5748   } else if(result->nfile == 0 || !result->exists) {
5749     return gl_print_info(gl, "No files match.", GL_END_INFO);
5750 /*
5751  * List the matching expansions.
5752  */
5753   } else if(gl->echo) {
5754     if(gl_start_newline(gl, 1) ||
5755        _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn))
5756       return 1;
5757     gl_queue_redisplay(gl);
5758   };
5759   return 0;
5760 }
5761 #endif
5762 
5763 /*.......................................................................
5764  * Return non-zero if a character should be considered a part of a word.
5765  *
5766  * Input:
5767  *  c       int  The character to be tested.
5768  * Output:
5769  *  return  int  True if the character should be considered part of a word.
5770  */
5771 static int gl_is_word_char(int c)
5772 {
5773   return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL;
5774 }
5775 
5776 /*.......................................................................
5777  * Override the builtin file-completion callback that is bound to the
5778  * "complete_word" action function.
5779  *
5780  * Input:
5781  *  gl            GetLine *  The resource object of the command-line input
5782  *                           module.
5783  *  data             void *  This is passed to match_fn() whenever it is
5784  *                           called. It could, for example, point to a
5785  *                           symbol table where match_fn() could look
5786  *                           for possible completions.
5787  *  match_fn   CplMatchFn *  The function that will identify the prefix
5788  *                           to be completed from the input line, and
5789  *                           report matching symbols.
5790  * Output:
5791  *  return            int    0 - OK.
5792  *                           1 - Error.
5793  */
5794 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn)
5795 {
5796   sigset_t oldset; /* The signals that were blocked on entry to this function */
5797 /*
5798  * Check the arguments.
5799  */
5800   if(!gl || !match_fn) {
5801     if(gl)
5802       _err_record_msg(gl->err, "NULL argument", END_ERR_MSG);
5803     errno = EINVAL;
5804     return 1;
5805   };
5806 /*
5807  * Temporarily block all signals.
5808  */
5809   gl_mask_signals(gl, &oldset);
5810 /*
5811  * Record the new completion function and its callback data.
5812  */
5813   gl->cplfn.fn = match_fn;
5814   gl->cplfn.data = data;
5815 /*
5816  * Restore the process signal mask before returning.
5817  */
5818   gl_unmask_signals(gl, &oldset);
5819   return 0;
5820 }
5821 
5822 /*.......................................................................
5823  * Change the terminal (or stream) that getline interacts with.
5824  *
5825  * Input:
5826  *  gl            GetLine *  The resource object of the command-line input
5827  *                           module.
5828  *  input_fp         FILE *  The stdio stream to read from.
5829  *  output_fp        FILE *  The stdio stream to write to.
5830  *  term             char *  The terminal type. This can be NULL if
5831  *                           either or both of input_fp and output_fp don't
5832  *                           refer to a terminal. Otherwise it should refer
5833  *                           to an entry in the terminal information database.
5834  * Output:
5835  *  return            int    0 - OK.
5836  *                           1 - Error.
5837  */
5838 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5839 		       const char *term)
5840 {
5841   sigset_t oldset; /* The signals that were blocked on entry to this function */
5842   int status;      /* The return status of _gl_change_terminal() */
5843 /*
5844  * Check the arguments.
5845  */
5846   if(!gl) {
5847     errno = EINVAL;
5848     return 1;
5849   };
5850 /*
5851  * Block all signals.
5852  */
5853   if(gl_mask_signals(gl, &oldset))
5854     return 1;
5855 /*
5856  * Execute the private body of the function while signals are blocked.
5857  */
5858   status = _gl_change_terminal(gl, input_fp, output_fp, term);
5859 /*
5860  * Restore the process signal mask.
5861  */
5862   gl_unmask_signals(gl, &oldset);
5863   return status;
5864 }
5865 
5866 /*.......................................................................
5867  * This is the private body of the gl_change_terminal() function. It
5868  * assumes that the caller has checked its arguments and blocked the
5869  * delivery of signals.
5870  */
5871 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5872 			       const char *term)
5873 {
5874   int is_term = 0;   /* True if both input_fd and output_fd are associated */
5875                      /*  with a terminal. */
5876 /*
5877  * Require that input_fp and output_fp both be valid.
5878  */
5879   if(!input_fp || !output_fp) {
5880     gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).",
5881 		  GL_END_INFO);
5882     return 1;
5883   };
5884 /*
5885  * Are we displacing an existing terminal (as opposed to setting the
5886  * initial terminal)?
5887  */
5888   if(gl->input_fd >= 0) {
5889 /*
5890  * Make sure to leave the previous terminal in a usable state.
5891  */
5892     if(_gl_normal_io(gl))
5893       return 1;
5894 /*
5895  * Remove the displaced terminal from the list of fds to watch.
5896  */
5897 #ifdef HAVE_SELECT
5898     FD_CLR(gl->input_fd, &gl->rfds);
5899 #endif
5900   };
5901 /*
5902  * Record the file descriptors and streams.
5903  */
5904   gl->input_fp = input_fp;
5905   gl->input_fd = fileno(input_fp);
5906   gl->output_fp = output_fp;
5907   gl->output_fd = fileno(output_fp);
5908 /*
5909  * If needed, expand the record of the maximum file-descriptor that might
5910  * need to be monitored with select().
5911  */
5912 #ifdef HAVE_SELECT
5913   if(gl->input_fd > gl->max_fd)
5914     gl->max_fd = gl->input_fd;
5915 #endif
5916 /*
5917  * Disable terminal interaction until we have enough info to interact
5918  * with the terminal.
5919  */
5920   gl->is_term = 0;
5921 /*
5922  * For terminal editing, we need both output_fd and input_fd to refer to
5923  * a terminal. While we can't verify that they both point to the same
5924  * terminal, we can verify that they point to terminals.
5925  */
5926   is_term = isatty(gl->input_fd) && isatty(gl->output_fd);
5927 /*
5928  * If we are interacting with a terminal and no terminal type has been
5929  * specified, treat it as a generic ANSI terminal.
5930  */
5931   if(is_term && !term)
5932     term = "ansi";
5933 /*
5934  * Make a copy of the terminal type string.
5935  */
5936   if(term != gl->term) {
5937 /*
5938  * Delete any old terminal type string.
5939  */
5940     if(gl->term) {
5941       free(gl->term);
5942       gl->term = NULL;
5943     };
5944 /*
5945  * Make a copy of the new terminal-type string, if any.
5946  */
5947     if(term) {
5948       size_t termsz = strlen(term)+1;
5949 
5950       gl->term = (char *) malloc(termsz);
5951       if(gl->term)
5952 	strlcpy(gl->term, term, termsz);
5953     };
5954   };
5955 /*
5956  * Clear any terminal-specific key bindings that were taken from the
5957  * settings of the last terminal.
5958  */
5959   _kt_clear_bindings(gl->bindings, KTB_TERM);
5960 /*
5961  * If we have a terminal install new bindings for it.
5962  */
5963   if(is_term) {
5964 /*
5965  * Get the current settings of the terminal.
5966  */
5967     if(tcgetattr(gl->input_fd, &gl->oldattr)) {
5968       _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
5969       return 1;
5970     };
5971 /*
5972  * If we don't set this now, gl_control_strings() won't know
5973  * that it is talking to a terminal.
5974  */
5975     gl->is_term = 1;
5976 /*
5977  * Lookup the terminal control string and size information.
5978  */
5979     if(gl_control_strings(gl, term)) {
5980       gl->is_term = 0;
5981       return 1;
5982     };
5983 /*
5984  * Bind terminal-specific keys.
5985  */
5986     if(gl_bind_terminal_keys(gl))
5987       return 1;
5988   };
5989 /*
5990  * Assume that the caller has given us a terminal in a sane state.
5991  */
5992   gl->io_mode = GL_NORMAL_MODE;
5993 /*
5994  * Switch into the currently configured I/O mode.
5995  */
5996   if(_gl_io_mode(gl, gl->io_mode))
5997     return 1;
5998   return 0;
5999 }
6000 
6001 /*.......................................................................
6002  * Set up terminal-specific key bindings.
6003  *
6004  * Input:
6005  *  gl            GetLine *  The resource object of the command-line input
6006  *                           module.
6007  * Output:
6008  *  return            int    0 - OK.
6009  *                           1 - Error.
6010  */
6011 static int gl_bind_terminal_keys(GetLine *gl)
6012 {
6013 /*
6014  * Install key-bindings for the special terminal characters.
6015  */
6016   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR],
6017 			  "user-interrupt") ||
6018      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") ||
6019      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend"))
6020     return 1;
6021 /*
6022  * In vi-mode, arrange for the above characters to be seen in command
6023  * mode.
6024  */
6025   if(gl->editor == GL_VI_MODE) {
6026     if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]),
6027 			    "user-interrupt") ||
6028        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]),
6029 			    "abort") ||
6030        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]),
6031 			    "suspend"))
6032       return 1;
6033   };
6034 /*
6035  * Non-universal special keys.
6036  */
6037 #ifdef VLNEXT
6038   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT],
6039 			  "literal-next"))
6040     return 1;
6041 #else
6042   if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) {
6043     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6044     return 1;
6045   };
6046 #endif
6047 /*
6048  * Bind action functions to the terminal-specific arrow keys
6049  * looked up by gl_control_strings().
6050  */
6051   if(_gl_bind_arrow_keys(gl))
6052     return 1;
6053   return 0;
6054 }
6055 
6056 /*.......................................................................
6057  * This function is normally bound to control-D. When it is invoked within
6058  * a line it deletes the character which follows the cursor. When invoked
6059  * at the end of the line it lists possible file completions, and when
6060  * invoked on an empty line it causes gl_get_line() to return EOF. This
6061  * function emulates the one that is normally bound to control-D by tcsh.
6062  */
6063 static KT_KEY_FN(gl_del_char_or_list_or_eof)
6064 {
6065 /*
6066  * If we have an empty line arrange to return EOF.
6067  */
6068   if(gl->ntotal < 1) {
6069     gl_record_status(gl, GLR_EOF, 0);
6070     return 1;
6071 /*
6072  * If we are at the end of the line list possible completions.
6073  */
6074   } else if(gl->buff_curpos >= gl->ntotal) {
6075     return gl_list_completions(gl, 1, NULL);
6076 /*
6077  * Within the line delete the character that follows the cursor.
6078  */
6079   } else {
6080 /*
6081  * If in vi command mode, first preserve the current line for potential use
6082  * by vi-undo.
6083  */
6084     gl_save_for_undo(gl);
6085 /*
6086  * Delete 'count' characters.
6087  */
6088     return gl_forward_delete_char(gl, count, NULL);
6089   };
6090 }
6091 
6092 /*.......................................................................
6093  * This function is normally bound to control-D in vi mode. When it is
6094  * invoked within a line it lists possible file completions, and when
6095  * invoked on an empty line it causes gl_get_line() to return EOF. This
6096  * function emulates the one that is normally bound to control-D by tcsh.
6097  */
6098 static KT_KEY_FN(gl_list_or_eof)
6099 {
6100 /*
6101  * If we have an empty line arrange to return EOF.
6102  */
6103   if(gl->ntotal < 1) {
6104     gl_record_status(gl, GLR_EOF, 0);
6105     return 1;
6106 /*
6107  * Otherwise list possible completions.
6108  */
6109   } else {
6110     return gl_list_completions(gl, 1, NULL);
6111   };
6112 }
6113 
6114 /*.......................................................................
6115  * List possible completions of the word that precedes the cursor. The
6116  * callback data argument must either be NULL to select the default
6117  * file completion callback, or be a GlCplCallback object containing the
6118  * completion callback function to call.
6119  */
6120 static KT_KEY_FN(gl_list_completions)
6121 {
6122   int waserr = 0;   /* True after errors */
6123 /*
6124  * Get the container of the completion callback and its callback data.
6125  */
6126   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
6127 /*
6128  * Get the list of possible completions.
6129  */
6130   CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos,
6131 					  cb->data, cb->fn);
6132 /*
6133  * No matching completions?
6134  */
6135   if(!matches) {
6136     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
6137 /*
6138  * List the matches.
6139  */
6140   } else if(matches->nmatch > 0 && gl->echo) {
6141     if(_gl_normal_io(gl) ||
6142        _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
6143       waserr = 1;
6144   };
6145 /*
6146  * If any output had to be written to the terminal, then editing will
6147  * have been suspended, make sure that we are back in raw line editing
6148  * mode before returning.
6149  */
6150   if(_gl_raw_io(gl, 1))
6151     waserr = 1;
6152   return waserr;
6153 }
6154 
6155 /*.......................................................................
6156  * Where the user has used the symbolic arrow-key names to specify
6157  * arrow key bindings, bind the specified action functions to the default
6158  * and terminal specific arrow key sequences.
6159  *
6160  * Input:
6161  *  gl     GetLine *   The getline resource object.
6162  * Output:
6163  *  return     int     0 - OK.
6164  *                     1 - Error.
6165  */
6166 static int _gl_bind_arrow_keys(GetLine *gl)
6167 {
6168 /*
6169  * Process each of the arrow keys.
6170  */
6171   if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") ||
6172      _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") ||
6173      _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") ||
6174      _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC"))
6175     return 1;
6176   return 0;
6177 }
6178 
6179 /*.......................................................................
6180  * Lookup the action function of a symbolic arrow-key binding, and bind
6181  * it to the terminal-specific and default arrow-key sequences. Note that
6182  * we don't trust the terminal-specified key sequences to be correct.
6183  * The main reason for this is that on some machines the xterm terminfo
6184  * entry is for hardware X-terminals, rather than xterm terminal emulators
6185  * and the two terminal types emit different character sequences when the
6186  * their cursor keys are pressed. As a result we also supply a couple
6187  * of default key sequences.
6188  *
6189  * Input:
6190  *  gl          GetLine *   The resource object of gl_get_line().
6191  *  name           char *   The symbolic name of the arrow key.
6192  *  term_seq       char *   The terminal-specific arrow-key sequence.
6193  *  def_seq1       char *   The first default arrow-key sequence.
6194  *  def_seq2       char *   The second arrow-key sequence.
6195  * Output:
6196  *  return          int     0 - OK.
6197  *                          1 - Error.
6198  */
6199 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
6200 				const char *term_seq, const char *def_seq1,
6201 				const char *def_seq2)
6202 {
6203   KeySym *keysym;  /* The binding-table entry matching the arrow-key name */
6204   int nsym;        /* The number of ambiguous matches */
6205 /*
6206  * Lookup the key binding for the symbolic name of the arrow key. This
6207  * will either be the default action, or a user provided one.
6208  */
6209   if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym)
6210      == KT_EXACT_MATCH) {
6211 /*
6212  * Get the action function.
6213  */
6214     KtAction *action = keysym->actions + keysym->binder;
6215     KtKeyFn *fn = action->fn;
6216     void *data = action->data;
6217 /*
6218  * Bind this to each of the specified key sequences.
6219  */
6220     if((term_seq &&
6221 	_kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) ||
6222        (def_seq1 &&
6223 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) ||
6224        (def_seq2 &&
6225 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) {
6226       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6227       return 1;
6228     };
6229   };
6230   return 0;
6231 }
6232 
6233 /*.......................................................................
6234  * Read getline configuration information from a given file.
6235  *
6236  * Input:
6237  *  gl           GetLine *  The getline resource object.
6238  *  filename  const char *  The name of the file to read configuration
6239  *                          information from. The contents of this file
6240  *                          are as described in the gl_get_line(3) man
6241  *                          page for the default ~/.teclarc configuration
6242  *                          file.
6243  *  who         KtBinder    Who bindings are to be installed for.
6244  * Output:
6245  *  return           int    0 - OK.
6246  *                          1 - Irrecoverable error.
6247  */
6248 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who)
6249 {
6250 /*
6251  * If filesystem access is to be excluded, configuration files can't
6252  * be read.
6253  */
6254 #ifdef WITHOUT_FILE_SYSTEM
6255   _err_record_msg(gl->err,
6256 		  "Can't read configuration files without filesystem access",
6257 		  END_ERR_MSG);
6258   errno = EINVAL;
6259   return 1;
6260 #else
6261   FileExpansion *expansion; /* The expansion of the filename */
6262   FILE *fp;                 /* The opened file */
6263   int waserr = 0;           /* True if an error occurred while reading */
6264   int lineno = 1;           /* The line number being processed */
6265 /*
6266  * Check the arguments.
6267  */
6268   if(!gl || !filename) {
6269     if(gl)
6270       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6271     errno = EINVAL;
6272     return 1;
6273   };
6274 /*
6275  * Expand the filename.
6276  */
6277   expansion = ef_expand_file(gl->ef, filename, -1);
6278   if(!expansion) {
6279     gl_print_info(gl, "Unable to expand ", filename, " (",
6280 		  ef_last_error(gl->ef), ").", GL_END_INFO);
6281     return 1;
6282   };
6283 /*
6284  * Attempt to open the file.
6285  */
6286   fp = fopen(expansion->files[0], "r");
6287 /*
6288  * It isn't an error for there to be no configuration file.
6289  */
6290   if(!fp)
6291     return 0;
6292 /*
6293  * Parse the contents of the file.
6294  */
6295   while(!waserr && !feof(fp))
6296     waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who,
6297 				   &lineno);
6298 /*
6299  * Bind action functions to the terminal-specific arrow keys.
6300  */
6301   if(_gl_bind_arrow_keys(gl))
6302     return 1;
6303 /*
6304  * Clean up.
6305  */
6306   (void) fclose(fp);
6307   return waserr;
6308 #endif
6309 }
6310 
6311 /*.......................................................................
6312  * Read GetLine configuration information from a string. The contents of
6313  * the string are the same as those described in the gl_get_line(3)
6314  * man page for the contents of the ~/.teclarc configuration file.
6315  */
6316 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who)
6317 {
6318   const char *bptr;         /* A pointer into buffer[] */
6319   int waserr = 0;           /* True if an error occurred while reading */
6320   int lineno = 1;           /* The line number being processed */
6321 /*
6322  * Check the arguments.
6323  */
6324   if(!gl || !buffer) {
6325     if(gl)
6326       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6327     errno = EINVAL;
6328     return 1;
6329   };
6330 /*
6331  * Get a pointer to the start of the buffer.
6332  */
6333   bptr = buffer;
6334 /*
6335  * Parse the contents of the buffer.
6336  */
6337   while(!waserr && *bptr)
6338     waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno);
6339 /*
6340  * Bind action functions to the terminal-specific arrow keys.
6341  */
6342   if(_gl_bind_arrow_keys(gl))
6343     return 1;
6344   return waserr;
6345 }
6346 
6347 /*.......................................................................
6348  * Parse the next line of a getline configuration file.
6349  *
6350  * Input:
6351  *  gl         GetLine *  The getline resource object.
6352  *  stream        void *  The pointer representing the stream to be read
6353  *                        by getc_fn().
6354  *  getc_fn  GlcGetcFn *  A callback function which when called with
6355  *                       'stream' as its argument, returns the next
6356  *                        unread character from the stream.
6357  *  origin  const char *  The name of the entity being read (eg. a
6358  *                        file name).
6359  *  who       KtBinder    Who bindings are to be installed for.
6360  * Input/Output:
6361  *  lineno         int *  The line number being processed is to be
6362  *                        maintained in *lineno.
6363  * Output:
6364  *  return         int    0 - OK.
6365  *                        1 - Irrecoverable error.
6366  */
6367 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
6368 				 const char *origin, KtBinder who, int *lineno)
6369 {
6370   char buffer[GL_CONF_BUFLEN+1];  /* The input line buffer */
6371   char *argv[GL_CONF_MAXARG];     /* The argument list */
6372   int argc = 0;                   /* The number of arguments in argv[] */
6373   int c;                          /* A character from the file */
6374   int escaped = 0;                /* True if the next character is escaped */
6375   int i;
6376 /*
6377  * Skip spaces and tabs.
6378  */
6379   do c = getc_fn(stream); while(c==' ' || c=='\t');
6380 /*
6381  * Comments extend to the end of the line.
6382  */
6383   if(c=='#')
6384     do c = getc_fn(stream); while(c != '\n' && c != EOF);
6385 /*
6386  * Ignore empty lines.
6387  */
6388   if(c=='\n' || c==EOF) {
6389     (*lineno)++;
6390     return 0;
6391   };
6392 /*
6393  * Record the buffer location of the start of the first argument.
6394  */
6395   argv[argc] = buffer;
6396 /*
6397  * Read the rest of the line, stopping early if a comment is seen, or
6398  * the buffer overflows, and replacing sequences of spaces with a
6399  * '\0', and recording the thus terminated string as an argument.
6400  */
6401   i = 0;
6402   while(i<GL_CONF_BUFLEN) {
6403 /*
6404  * Did we hit the end of the latest argument?
6405  */
6406     if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) {
6407 /*
6408  * Terminate the argument.
6409  */
6410       buffer[i++] = '\0';
6411       argc++;
6412 /*
6413  * Skip spaces and tabs.
6414  */
6415       while(c==' ' || c=='\t')
6416 	c = getc_fn(stream);
6417 /*
6418  * If we hit the end of the line, or the start of a comment, exit the loop.
6419  */
6420       if(c==EOF || c=='\n' || c=='#')
6421 	break;
6422 /*
6423  * Start recording the next argument.
6424  */
6425       if(argc >= GL_CONF_MAXARG) {
6426 	gl_report_config_error(gl, origin, *lineno, "Too many arguments.");
6427 	do c = getc_fn(stream); while(c!='\n' && c!=EOF);  /* Skip past eol */
6428 	return 0;
6429       };
6430       argv[argc] = buffer + i;
6431 /*
6432  * The next character was preceded by spaces, so it isn't escaped.
6433  */
6434       escaped = 0;
6435     } else {
6436 /*
6437  * If we hit an unescaped backslash, this means that we should arrange
6438  * to treat the next character like a simple alphabetical character.
6439  */
6440       if(c=='\\' && !escaped) {
6441 	escaped = 1;
6442 /*
6443  * Splice lines where the newline is escaped.
6444  */
6445       } else if(c=='\n' && escaped) {
6446 	(*lineno)++;
6447 /*
6448  * Record a normal character, preserving any preceding backslash.
6449  */
6450       } else {
6451 	if(escaped)
6452 	  buffer[i++] = '\\';
6453 	if(i>=GL_CONF_BUFLEN)
6454 	  break;
6455 	escaped = 0;
6456 	buffer[i++] = c;
6457       };
6458 /*
6459  * Get the next character.
6460  */
6461       c = getc_fn(stream);
6462     };
6463   };
6464 /*
6465  * Did the buffer overflow?
6466  */
6467   if(i>=GL_CONF_BUFLEN) {
6468     gl_report_config_error(gl, origin, *lineno, "Line too long.");
6469     return 0;
6470   };
6471 /*
6472  * The first argument should be a command name.
6473  */
6474   if(strcmp(argv[0], "bind") == 0) {
6475     const char *action = NULL; /* A NULL action removes a keybinding */
6476     const char *keyseq = NULL;
6477     switch(argc) {
6478     case 3:
6479       action = argv[2];
6480     case 2:              /* Note the intentional fallthrough */
6481       keyseq = argv[1];
6482 /*
6483  * Attempt to record the new keybinding.
6484  */
6485       if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) {
6486 	gl_report_config_error(gl, origin, *lineno,
6487 			       _kt_last_error(gl->bindings));
6488       };
6489       break;
6490     default:
6491       gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments.");
6492     };
6493   } else if(strcmp(argv[0], "edit-mode") == 0) {
6494     if(argc == 2 && strcmp(argv[1], "emacs") == 0) {
6495       gl_change_editor(gl, GL_EMACS_MODE);
6496     } else if(argc == 2 && strcmp(argv[1], "vi") == 0) {
6497       gl_change_editor(gl, GL_VI_MODE);
6498     } else if(argc == 2 && strcmp(argv[1], "none") == 0) {
6499       gl_change_editor(gl, GL_NO_EDITOR);
6500     } else {
6501       gl_report_config_error(gl, origin, *lineno,
6502 			     "The argument of editor should be vi or emacs.");
6503     };
6504   } else if(strcmp(argv[0], "nobeep") == 0) {
6505     gl->silence_bell = 1;
6506   } else {
6507     gl_report_config_error(gl, origin, *lineno, "Unknown command name.");
6508   };
6509 /*
6510  * Skip any trailing comment.
6511  */
6512   while(c != '\n' && c != EOF)
6513     c = getc_fn(stream);
6514   (*lineno)++;
6515   return 0;
6516 }
6517 
6518 /*.......................................................................
6519  * This is a private function of _gl_parse_config_line() which prints
6520  * out an error message about the contents of the line, prefixed by the
6521  * name of the origin of the line and its line number.
6522  *
6523  * Input:
6524  *  gl         GetLine *  The resource object of gl_get_line().
6525  *  origin  const char *  The name of the entity being read (eg. a
6526  *                        file name).
6527  *  lineno         int    The line number at which the error occurred.
6528  *  errmsg  const char *  The error message.
6529  * Output:
6530  *  return         int    0 - OK.
6531  *                        1 - Error.
6532  */
6533 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
6534 				  const char *errmsg)
6535 {
6536   char lnum[20];   /* A buffer in which to render a single integer */
6537 /*
6538  * Convert the line number into a string.
6539  */
6540   snprintf(lnum, sizeof(lnum), "%d", lineno);
6541 /*
6542  * Have the string printed on the terminal.
6543  */
6544   return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO);
6545 }
6546 
6547 /*.......................................................................
6548  * This is the _gl_parse_config_line() callback function which reads the
6549  * next character from a configuration file.
6550  */
6551 static GLC_GETC_FN(glc_file_getc)
6552 {
6553   return fgetc((FILE *) stream);
6554 }
6555 
6556 /*.......................................................................
6557  * This is the _gl_parse_config_line() callback function which reads the
6558  * next character from a buffer. Its stream argument is a pointer to a
6559  * variable which is, in turn, a pointer into the buffer being read from.
6560  */
6561 static GLC_GETC_FN(glc_buff_getc)
6562 {
6563   const char **lptr = (char const **) stream;
6564   return **lptr ? *(*lptr)++ : EOF;
6565 }
6566 
6567 #ifndef HIDE_FILE_SYSTEM
6568 /*.......................................................................
6569  * When this action is triggered, it arranges to temporarily read command
6570  * lines from the regular file whos name precedes the cursor.
6571  * The current line is first discarded.
6572  */
6573 static KT_KEY_FN(gl_read_from_file)
6574 {
6575   char *start_path;       /* The pointer to the start of the pathname in */
6576                           /*  gl->line[]. */
6577   FileExpansion *result;  /* The results of the filename expansion */
6578   int pathlen;            /* The length of the pathname being expanded */
6579 /*
6580  * Locate the start of the filename that precedes the cursor position.
6581  */
6582   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
6583   if(!start_path)
6584     return 1;
6585 /*
6586  * Get the length of the pathname string.
6587  */
6588   pathlen = gl->buff_curpos - (start_path - gl->line);
6589 /*
6590  * Attempt to expand the pathname.
6591  */
6592   result = ef_expand_file(gl->ef, start_path, pathlen);
6593 /*
6594  * If there was an error, report the error on a new line.
6595  */
6596   if(!result) {
6597     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
6598 /*
6599  * If no files matched, report this as well.
6600  */
6601   } else if(result->nfile == 0 || !result->exists) {
6602     return gl_print_info(gl, "No files match.", GL_END_INFO);
6603 /*
6604  * Complain if more than one file matches.
6605  */
6606   } else if(result->nfile > 1) {
6607     return gl_print_info(gl, "More than one file matches.", GL_END_INFO);
6608 /*
6609  * Disallow input from anything but normal files. In principle we could
6610  * also support input from named pipes. Terminal files would be a problem
6611  * since we wouldn't know the terminal type, and other types of files
6612  * might cause the library to lock up.
6613  */
6614   } else if(!_pu_path_is_file(result->files[0])) {
6615     return gl_print_info(gl, "Not a normal file.", GL_END_INFO);
6616   } else {
6617 /*
6618  * Attempt to open and install the specified file for reading.
6619  */
6620     gl->file_fp = fopen(result->files[0], "r");
6621     if(!gl->file_fp) {
6622       return gl_print_info(gl, "Unable to open: ", result->files[0],
6623 			   GL_END_INFO);
6624     };
6625 /*
6626  * If needed, expand the record of the maximum file-descriptor that might
6627  * need to be monitored with select().
6628  */
6629 #ifdef HAVE_SELECT
6630     if(fileno(gl->file_fp) > gl->max_fd)
6631       gl->max_fd = fileno(gl->file_fp);
6632 #endif
6633 /*
6634  * Is non-blocking I/O needed?
6635  */
6636     if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE &&
6637        gl_nonblocking_io(gl, fileno(gl->file_fp))) {
6638       gl_revert_input(gl);
6639       return gl_print_info(gl, "Can't read file %s with non-blocking I/O",
6640 			   result->files[0]);
6641     };
6642 /*
6643  * Inform the user what is happening.
6644  */
6645     if(gl_print_info(gl, "<Taking input from ", result->files[0], ">",
6646 		     GL_END_INFO))
6647       return 1;
6648   };
6649   return 0;
6650 }
6651 #endif
6652 
6653 /*.......................................................................
6654  * Close any temporary file that is being used for input.
6655  *
6656  * Input:
6657  *  gl     GetLine *  The getline resource object.
6658  */
6659 static void gl_revert_input(GetLine *gl)
6660 {
6661   if(gl->file_fp)
6662     fclose(gl->file_fp);
6663   gl->file_fp = NULL;
6664   gl->endline = 1;
6665 }
6666 
6667 /*.......................................................................
6668  * This is the action function that recalls the oldest line in the
6669  * history buffer.
6670  */
6671 static KT_KEY_FN(gl_beginning_of_history)
6672 {
6673 /*
6674  * In vi mode, switch to command mode, since the user is very
6675  * likely to want to move around newly recalled lines.
6676  */
6677   gl_vi_command_mode(gl);
6678 /*
6679  * Forget any previous recall session.
6680  */
6681   gl->preload_id = 0;
6682 /*
6683  * Record the key sequence number of this search action.
6684  */
6685   gl->last_search = gl->keyseq_count;
6686 /*
6687  * Recall the next oldest line in the history list.
6688  */
6689   if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6690     return 0;
6691 /*
6692  * Accomodate the new contents of gl->line[].
6693  */
6694   gl_update_buffer(gl);
6695 /*
6696  * Arrange to have the cursor placed at the end of the new line.
6697  */
6698   gl->buff_curpos = gl->ntotal;
6699 /*
6700  * Erase and display the new line.
6701  */
6702   gl_queue_redisplay(gl);
6703   return 0;
6704 }
6705 
6706 /*.......................................................................
6707  * If a history session is currently in progress, this action function
6708  * recalls the line that was being edited when the session started. If
6709  * no history session is in progress, it does nothing.
6710  */
6711 static KT_KEY_FN(gl_end_of_history)
6712 {
6713 /*
6714  * In vi mode, switch to command mode, since the user is very
6715  * likely to want to move around newly recalled lines.
6716  */
6717   gl_vi_command_mode(gl);
6718 /*
6719  * Forget any previous recall session.
6720  */
6721   gl->preload_id = 0;
6722 /*
6723  * Record the key sequence number of this search action.
6724  */
6725   gl->last_search = gl->keyseq_count;
6726 /*
6727  * Recall the next oldest line in the history list.
6728  */
6729   if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6730     return 0;
6731 /*
6732  * Accomodate the new contents of gl->line[].
6733  */
6734   gl_update_buffer(gl);
6735 /*
6736  * Arrange to have the cursor placed at the end of the new line.
6737  */
6738   gl->buff_curpos = gl->ntotal;
6739 /*
6740  * Erase and display the new line.
6741  */
6742   gl_queue_redisplay(gl);
6743   return 0;
6744 }
6745 
6746 /*.......................................................................
6747  * This action function is treated specially, in that its count argument
6748  * is set to the end keystroke of the keysequence that activated it.
6749  * It accumulates a numeric argument, adding one digit on each call in
6750  * which the last keystroke was a numeric digit.
6751  */
6752 static KT_KEY_FN(gl_digit_argument)
6753 {
6754 /*
6755  * Was the last keystroke a digit?
6756  */
6757   int is_digit = isdigit((int)(unsigned char) count);
6758 /*
6759  * In vi command mode, a lone '0' means goto-start-of-line.
6760  */
6761   if(gl->vi.command && gl->number < 0 && count == '0')
6762     return gl_beginning_of_line(gl, count, NULL);
6763 /*
6764  * Are we starting to accumulate a new number?
6765  */
6766   if(gl->number < 0 || !is_digit)
6767     gl->number = 0;
6768 /*
6769  * Was the last keystroke a digit?
6770  */
6771   if(is_digit) {
6772 /*
6773  * Read the numeric value of the digit, without assuming ASCII.
6774  */
6775     int n;
6776     char s[2]; s[0] = count; s[1] = '\0';
6777     n = atoi(s);
6778 /*
6779  * Append the new digit.
6780  */
6781     gl->number = gl->number * 10 + n;
6782   };
6783   return 0;
6784 }
6785 
6786 /*.......................................................................
6787  * The newline action function sets gl->endline to tell
6788  * gl_get_input_line() that the line is now complete.
6789  */
6790 static KT_KEY_FN(gl_newline)
6791 {
6792   GlhLineID id;    /* The last history line recalled while entering this line */
6793 /*
6794  * Flag the line as ended.
6795  */
6796   gl->endline = 1;
6797 /*
6798  * Record the next position in the history buffer, for potential
6799  * recall by an action function on the next call to gl_get_line().
6800  */
6801   id = _glh_line_id(gl->glh, 1);
6802   if(id)
6803     gl->preload_id = id;
6804   return 0;
6805 }
6806 
6807 /*.......................................................................
6808  * The 'repeat' action function sets gl->endline to tell
6809  * gl_get_input_line() that the line is now complete, and records the
6810  * ID of the next history line in gl->preload_id so that the next call
6811  * to gl_get_input_line() will preload the line with that history line.
6812  */
6813 static KT_KEY_FN(gl_repeat_history)
6814 {
6815   gl->endline = 1;
6816   gl->preload_id = _glh_line_id(gl->glh, 1);
6817   gl->preload_history = 1;
6818   return 0;
6819 }
6820 
6821 /*.......................................................................
6822  * Flush unwritten characters to the terminal.
6823  *
6824  * Input:
6825  *  gl     GetLine *  The getline resource object.
6826  * Output:
6827  *  return     int    0 - OK.
6828  *                    1 - Either an error occured, or the output
6829  *                        blocked and non-blocking I/O is being used.
6830  *                        See gl->rtn_status for details.
6831  */
6832 static int gl_flush_output(GetLine *gl)
6833 {
6834 /*
6835  * Record the fact that we are about to write to the terminal.
6836  */
6837   gl->pending_io = GLP_WRITE;
6838 /*
6839  * Attempt to flush the output to the terminal.
6840  */
6841   errno = 0;
6842   switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) {
6843   case GLQ_FLUSH_DONE:
6844     return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL);
6845     break;
6846   case GLQ_FLUSH_AGAIN:      /* Output blocked */
6847     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
6848     return 1;
6849     break;
6850   default:                   /* Abort the line if an error occurs */
6851     gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno);
6852     return 1;
6853     break;
6854   };
6855 }
6856 
6857 /*.......................................................................
6858  * This is the callback which _glq_flush_queue() uses to write buffered
6859  * characters to the terminal.
6860  */
6861 static GL_WRITE_FN(gl_flush_terminal)
6862 {
6863   int ndone = 0;    /* The number of characters written so far */
6864 /*
6865  * Get the line-editor resource object.
6866  */
6867   GetLine *gl = (GetLine *) data;
6868 /*
6869  * Transfer the latest array of characters to stdio.
6870  */
6871   while(ndone < n) {
6872     int nnew = write(gl->output_fd, s, n-ndone);
6873 /*
6874  * If the write was successful, add to the recorded number of bytes
6875  * that have now been written.
6876  */
6877     if(nnew > 0) {
6878       ndone += nnew;
6879 /*
6880  * If a signal interrupted the call, restart the write(), since all of
6881  * the signals that gl_get_line() has been told to watch for are
6882  * currently blocked.
6883  */
6884     } else if(errno == EINTR) {
6885       continue;
6886 /*
6887  * If we managed to write something before an I/O error occurred, or
6888  * output blocked before anything was written, report the number of
6889  * bytes that were successfully written before this happened.
6890  */
6891     } else if(ndone > 0
6892 #if defined(EAGAIN)
6893 	      || errno==EAGAIN
6894 #endif
6895 #if defined(EWOULDBLOCK)
6896 	      || errno==EWOULDBLOCK
6897 #endif
6898 	      ) {
6899       return ndone;
6900 
6901 /*
6902  * To get here, an error must have occurred before anything new could
6903  * be written.
6904  */
6905     } else {
6906       return -1;
6907     };
6908   };
6909 /*
6910  * To get here, we must have successfully written the number of
6911  * bytes that was specified.
6912  */
6913   return n;
6914 }
6915 
6916 /*.......................................................................
6917  * Change the style of editing to emulate a given editor.
6918  *
6919  * Input:
6920  *  gl       GetLine *  The getline resource object.
6921  *  editor  GlEditor    The type of editor to emulate.
6922  * Output:
6923  *  return       int    0 - OK.
6924  *                      1 - Error.
6925  */
6926 static int gl_change_editor(GetLine *gl, GlEditor editor)
6927 {
6928 /*
6929  * Install the default key-bindings of the requested editor.
6930  */
6931   switch(editor) {
6932   case GL_EMACS_MODE:
6933     _kt_clear_bindings(gl->bindings, KTB_NORM);
6934     _kt_clear_bindings(gl->bindings, KTB_TERM);
6935     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings,
6936 		   sizeof(gl_emacs_bindings)/sizeof(gl_emacs_bindings[0]));
6937     break;
6938   case GL_VI_MODE:
6939     _kt_clear_bindings(gl->bindings, KTB_NORM);
6940     _kt_clear_bindings(gl->bindings, KTB_TERM);
6941     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings,
6942 			    sizeof(gl_vi_bindings)/sizeof(gl_vi_bindings[0]));
6943     break;
6944   case GL_NO_EDITOR:
6945     break;
6946   default:
6947     _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG);
6948     errno = EINVAL;
6949     return 1;
6950   };
6951 /*
6952  * Record the new editing mode.
6953  */
6954   gl->editor = editor;
6955   gl->vi.command = 0;     /* Start in input mode */
6956   gl->insert_curpos = 0;
6957 /*
6958  * Reinstate terminal-specific bindings.
6959  */
6960   if(gl->editor != GL_NO_EDITOR && gl->input_fp)
6961     (void) gl_bind_terminal_keys(gl);
6962   return 0;
6963 }
6964 
6965 /*.......................................................................
6966  * This is an action function that switches to editing using emacs bindings
6967  */
6968 static KT_KEY_FN(gl_emacs_editing_mode)
6969 {
6970   return gl_change_editor(gl, GL_EMACS_MODE);
6971 }
6972 
6973 /*.......................................................................
6974  * This is an action function that switches to editing using vi bindings
6975  */
6976 static KT_KEY_FN(gl_vi_editing_mode)
6977 {
6978   return gl_change_editor(gl, GL_VI_MODE);
6979 }
6980 
6981 /*.......................................................................
6982  * This is the action function that switches to insert mode.
6983  */
6984 static KT_KEY_FN(gl_vi_insert)
6985 {
6986 /*
6987  * If in vi command mode, preserve the current line for potential
6988  * use by vi-undo.
6989  */
6990   gl_save_for_undo(gl);
6991 /*
6992  * Switch to vi insert mode.
6993  */
6994   gl->insert = 1;
6995   gl->vi.command = 0;
6996   gl->insert_curpos = gl->buff_curpos;
6997   return 0;
6998 }
6999 
7000 /*.......................................................................
7001  * This is an action function that switches to overwrite mode.
7002  */
7003 static KT_KEY_FN(gl_vi_overwrite)
7004 {
7005 /*
7006  * If in vi command mode, preserve the current line for potential
7007  * use by vi-undo.
7008  */
7009   gl_save_for_undo(gl);
7010 /*
7011  * Switch to vi overwrite mode.
7012  */
7013   gl->insert = 0;
7014   gl->vi.command = 0;
7015   gl->insert_curpos = gl->buff_curpos;
7016   return 0;
7017 }
7018 
7019 /*.......................................................................
7020  * This action function toggles the case of the character under the
7021  * cursor.
7022  */
7023 static KT_KEY_FN(gl_change_case)
7024 {
7025   int i;
7026 /*
7027  * Keep a record of the current insert mode and the cursor position.
7028  */
7029   int insert = gl->insert;
7030 /*
7031  * If in vi command mode, preserve the current line for potential
7032  * use by vi-undo.
7033  */
7034   gl_save_for_undo(gl);
7035 /*
7036  * We want to overwrite the modified word.
7037  */
7038   gl->insert = 0;
7039 /*
7040  * Toggle the case of 'count' characters.
7041  */
7042   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
7043     char *cptr = gl->line + gl->buff_curpos++;
7044 /*
7045  * Convert the character to upper case?
7046  */
7047     if(islower((int)(unsigned char) *cptr))
7048       gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
7049     else if(isupper((int)(unsigned char) *cptr))
7050       gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
7051 /*
7052  * Write the possibly modified character back. Note that for non-modified
7053  * characters we want to do this as well, so as to advance the cursor.
7054  */
7055       if(gl_print_char(gl, *cptr, cptr[1]))
7056 	return 1;
7057   };
7058 /*
7059  * Restore the insertion mode.
7060  */
7061   gl->insert = insert;
7062   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7063 }
7064 
7065 /*.......................................................................
7066  * This is the action function which implements the vi-style action which
7067  * moves the cursor to the start of the line, then switches to insert mode.
7068  */
7069 static KT_KEY_FN(gl_vi_insert_at_bol)
7070 {
7071   gl_save_for_undo(gl);
7072   return gl_beginning_of_line(gl, 0, NULL) ||
7073          gl_vi_insert(gl, 0, NULL);
7074 
7075 }
7076 
7077 /*.......................................................................
7078  * This is the action function which implements the vi-style action which
7079  * moves the cursor to the end of the line, then switches to insert mode
7080  * to allow text to be appended to the line.
7081  */
7082 static KT_KEY_FN(gl_vi_append_at_eol)
7083 {
7084   gl_save_for_undo(gl);
7085   gl->vi.command = 0;	/* Allow cursor at EOL */
7086   return gl_end_of_line(gl, 0, NULL) ||
7087          gl_vi_insert(gl, 0, NULL);
7088 }
7089 
7090 /*.......................................................................
7091  * This is the action function which implements the vi-style action which
7092  * moves the cursor to right one then switches to insert mode, thus
7093  * allowing text to be appended after the next character.
7094  */
7095 static KT_KEY_FN(gl_vi_append)
7096 {
7097   gl_save_for_undo(gl);
7098   gl->vi.command = 0;	/* Allow cursor at EOL */
7099   return gl_cursor_right(gl, 1, NULL) ||
7100          gl_vi_insert(gl, 0, NULL);
7101 }
7102 
7103 /*.......................................................................
7104  * This action function moves the cursor to the column specified by the
7105  * numeric argument. Column indexes start at 1.
7106  */
7107 static KT_KEY_FN(gl_goto_column)
7108 {
7109   return gl_place_cursor(gl, count - 1);
7110 }
7111 
7112 /*.......................................................................
7113  * Starting with the character under the cursor, replace 'count'
7114  * characters with the next character that the user types.
7115  */
7116 static KT_KEY_FN(gl_vi_replace_char)
7117 {
7118   char c;  /* The replacement character */
7119   int i;
7120 /*
7121  * Keep a record of the current insert mode.
7122  */
7123   int insert = gl->insert;
7124 /*
7125  * Get the replacement character.
7126  */
7127   if(gl->vi.repeat.active) {
7128     c = gl->vi.repeat.input_char;
7129   } else {
7130     if(gl_read_terminal(gl, 1, &c))
7131       return 1;
7132     gl->vi.repeat.input_char = c;
7133   };
7134 /*
7135  * Are there 'count' characters to be replaced?
7136  */
7137   if(gl->ntotal - gl->buff_curpos >= count) {
7138 /*
7139  * If in vi command mode, preserve the current line for potential
7140  * use by vi-undo.
7141  */
7142     gl_save_for_undo(gl);
7143 /*
7144  * Temporarily switch to overwrite mode.
7145  */
7146     gl->insert = 0;
7147 /*
7148  * Overwrite the current character plus count-1 subsequent characters
7149  * with the replacement character.
7150  */
7151     for(i=0; i<count; i++)
7152       gl_add_char_to_line(gl, c);
7153 /*
7154  * Restore the original insert/overwrite mode.
7155  */
7156     gl->insert = insert;
7157   };
7158   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7159 }
7160 
7161 /*.......................................................................
7162  * This is an action function which changes all characters between the
7163  * current cursor position and the end of the line.
7164  */
7165 static KT_KEY_FN(gl_vi_change_rest_of_line)
7166 {
7167   gl_save_for_undo(gl);
7168   gl->vi.command = 0;	/* Allow cursor at EOL */
7169   return gl_kill_line(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7170 }
7171 
7172 /*.......................................................................
7173  * This is an action function which changes all characters between the
7174  * start of the line and the current cursor position.
7175  */
7176 static KT_KEY_FN(gl_vi_change_to_bol)
7177 {
7178   return gl_backward_kill_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7179 }
7180 
7181 /*.......................................................................
7182  * This is an action function which deletes the entire contents of the
7183  * current line and switches to insert mode.
7184  */
7185 static KT_KEY_FN(gl_vi_change_line)
7186 {
7187   return gl_delete_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7188 }
7189 
7190 /*.......................................................................
7191  * Starting from the cursor position and looking towards the end of the
7192  * line, copy 'count' characters to the cut buffer.
7193  */
7194 static KT_KEY_FN(gl_forward_copy_char)
7195 {
7196 /*
7197  * Limit the count to the number of characters available.
7198  */
7199   if(gl->buff_curpos + count >= gl->ntotal)
7200     count = gl->ntotal - gl->buff_curpos;
7201   if(count < 0)
7202     count = 0;
7203 /*
7204  * Copy the characters to the cut buffer.
7205  */
7206   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7207   gl->cutbuf[count] = '\0';
7208   return 0;
7209 }
7210 
7211 /*.......................................................................
7212  * Starting from the character before the cursor position and looking
7213  * backwards towards the start of the line, copy 'count' characters to
7214  * the cut buffer.
7215  */
7216 static KT_KEY_FN(gl_backward_copy_char)
7217 {
7218 /*
7219  * Limit the count to the number of characters available.
7220  */
7221   if(count > gl->buff_curpos)
7222     count = gl->buff_curpos;
7223   if(count < 0)
7224     count = 0;
7225   gl_place_cursor(gl, gl->buff_curpos - count);
7226 /*
7227  * Copy the characters to the cut buffer.
7228  */
7229   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7230   gl->cutbuf[count] = '\0';
7231   return 0;
7232 }
7233 
7234 /*.......................................................................
7235  * Starting from the cursor position copy to the specified column into the
7236  * cut buffer.
7237  */
7238 static KT_KEY_FN(gl_copy_to_column)
7239 {
7240   if (--count >= gl->buff_curpos)
7241     return gl_forward_copy_char(gl, count - gl->buff_curpos, NULL);
7242   else
7243     return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL);
7244 }
7245 
7246 /*.......................................................................
7247  * Starting from the cursor position copy characters up to a matching
7248  * parenthesis into the cut buffer.
7249  */
7250 static KT_KEY_FN(gl_copy_to_parenthesis)
7251 {
7252   int curpos = gl_index_of_matching_paren(gl);
7253   if(curpos >= 0) {
7254     gl_save_for_undo(gl);
7255     if(curpos >= gl->buff_curpos)
7256       return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1, NULL);
7257     else
7258       return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
7259   };
7260   return 0;
7261 }
7262 
7263 /*.......................................................................
7264  * Starting from the cursor position copy the rest of the line into the
7265  * cut buffer.
7266  */
7267 static KT_KEY_FN(gl_copy_rest_of_line)
7268 {
7269 /*
7270  * Copy the characters to the cut buffer.
7271  */
7272   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos);
7273   gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0';
7274   return 0;
7275 }
7276 
7277 /*.......................................................................
7278  * Copy from the beginning of the line to the cursor position into the
7279  * cut buffer.
7280  */
7281 static KT_KEY_FN(gl_copy_to_bol)
7282 {
7283 /*
7284  * Copy the characters to the cut buffer.
7285  */
7286   memcpy(gl->cutbuf, gl->line, gl->buff_curpos);
7287   gl->cutbuf[gl->buff_curpos] = '\0';
7288   gl_place_cursor(gl, 0);
7289   return 0;
7290 }
7291 
7292 /*.......................................................................
7293  * Copy the entire line into the cut buffer.
7294  */
7295 static KT_KEY_FN(gl_copy_line)
7296 {
7297 /*
7298  * Copy the characters to the cut buffer.
7299  */
7300   memcpy(gl->cutbuf, gl->line, gl->ntotal);
7301   gl->cutbuf[gl->ntotal] = '\0';
7302   return 0;
7303 }
7304 
7305 /*.......................................................................
7306  * Search forwards for the next character that the user enters.
7307  */
7308 static KT_KEY_FN(gl_forward_find_char)
7309 {
7310   int pos = gl_find_char(gl, count, 1, 1, '\0');
7311   return pos >= 0 && gl_place_cursor(gl, pos);
7312 }
7313 
7314 /*.......................................................................
7315  * Search backwards for the next character that the user enters.
7316  */
7317 static KT_KEY_FN(gl_backward_find_char)
7318 {
7319   int pos = gl_find_char(gl, count, 0, 1, '\0');
7320   return pos >= 0 && gl_place_cursor(gl, pos);
7321 }
7322 
7323 /*.......................................................................
7324  * Search forwards for the next character that the user enters. Move up to,
7325  * but not onto, the found character.
7326  */
7327 static KT_KEY_FN(gl_forward_to_char)
7328 {
7329   int pos = gl_find_char(gl, count, 1, 0, '\0');
7330   return pos >= 0 && gl_place_cursor(gl, pos);
7331 }
7332 
7333 /*.......................................................................
7334  * Search backwards for the next character that the user enters. Move back to,
7335  * but not onto, the found character.
7336  */
7337 static KT_KEY_FN(gl_backward_to_char)
7338 {
7339   int pos = gl_find_char(gl, count, 0, 0, '\0');
7340   return pos >= 0 && gl_place_cursor(gl, pos);
7341 }
7342 
7343 /*.......................................................................
7344  * Searching in a given direction, return the index of a given (or
7345  * read) character in the input line, or the character that precedes
7346  * it in the specified search direction. Return -1 if not found.
7347  *
7348  * Input:
7349  *  gl       GetLine *  The getline resource object.
7350  *  count        int    The number of times to search.
7351  *  forward      int    True if searching forward.
7352  *  onto         int    True if the search should end on top of the
7353  *                      character, false if the search should stop
7354  *                      one character before the character in the
7355  *                      specified search direction.
7356  *  c           char    The character to be sought, or '\0' if the
7357  *                      character should be read from the user.
7358  * Output:
7359  *  return       int    The index of the character in gl->line[], or
7360  *                      -1 if not found.
7361  */
7362 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c)
7363 {
7364   int pos;     /* The index reached in searching the input line */
7365   int i;
7366 /*
7367  * Get a character from the user?
7368  */
7369   if(!c) {
7370 /*
7371  * If we are in the process of repeating a previous change command, substitute
7372  * the last find character.
7373  */
7374     if(gl->vi.repeat.active) {
7375       c = gl->vi.find_char;
7376     } else {
7377       if(gl_read_terminal(gl, 1, &c))
7378 	return -1;
7379 /*
7380  * Record the details of the new search, for use by repeat finds.
7381  */
7382       gl->vi.find_forward = forward;
7383       gl->vi.find_onto = onto;
7384       gl->vi.find_char = c;
7385     };
7386   };
7387 /*
7388  * Which direction should we search?
7389  */
7390   if(forward) {
7391 /*
7392  * Search forwards 'count' times for the character, starting with the
7393  * character that follows the cursor.
7394  */
7395     for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) {
7396 /*
7397  * Advance past the last match (or past the current cursor position
7398  * on the first search).
7399  */
7400       pos++;
7401 /*
7402  * Search for the next instance of c.
7403  */
7404       for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++)
7405 	;
7406     };
7407 /*
7408  * If the character was found and we have been requested to return the
7409  * position of the character that precedes the desired character, then
7410  * we have gone one character too far.
7411  */
7412     if(!onto && pos<gl->ntotal)
7413       pos--;
7414   } else {
7415 /*
7416  * Search backwards 'count' times for the character, starting with the
7417  * character that precedes the cursor.
7418  */
7419     for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) {
7420 /*
7421  * Step back one from the last match (or from the current cursor
7422  * position on the first search).
7423  */
7424       pos--;
7425 /*
7426  * Search for the next instance of c.
7427  */
7428       for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--)
7429 	;
7430     };
7431 /*
7432  * If the character was found and we have been requested to return the
7433  * position of the character that precedes the desired character, then
7434  * we have gone one character too far.
7435  */
7436     if(!onto && pos>=gl->insert_curpos)
7437       pos++;
7438   };
7439 /*
7440  * If found, return the cursor position of the count'th match.
7441  * Otherwise ring the terminal bell.
7442  */
7443   if(pos >= gl->insert_curpos && pos < gl->ntotal) {
7444     return pos;
7445   } else {
7446     (void) gl_ring_bell(gl, 1, NULL);
7447     return -1;
7448   }
7449 }
7450 
7451 /*.......................................................................
7452  * Repeat the last character search in the same direction as the last
7453  * search.
7454  */
7455 static KT_KEY_FN(gl_repeat_find_char)
7456 {
7457   int pos = gl->vi.find_char ?
7458     gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto,
7459 		 gl->vi.find_char) : -1;
7460   return pos >= 0 && gl_place_cursor(gl, pos);
7461 }
7462 
7463 /*.......................................................................
7464  * Repeat the last character search in the opposite direction as the last
7465  * search.
7466  */
7467 static KT_KEY_FN(gl_invert_refind_char)
7468 {
7469   int pos = gl->vi.find_char ?
7470     gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto,
7471 		 gl->vi.find_char) : -1;
7472   return pos >= 0 && gl_place_cursor(gl, pos);
7473 }
7474 
7475 /*.......................................................................
7476  * Search forward from the current position of the cursor for 'count'
7477  * word endings, returning the index of the last one found, or the end of
7478  * the line if there were less than 'count' words.
7479  *
7480  * Input:
7481  *  gl       GetLine *  The getline resource object.
7482  *  n            int    The number of word boundaries to search for.
7483  * Output:
7484  *  return       int    The buffer index of the located position.
7485  */
7486 static int gl_nth_word_end_forward(GetLine *gl, int n)
7487 {
7488   int bufpos;   /* The buffer index being checked. */
7489   int i;
7490 /*
7491  * In order to guarantee forward motion to the next word ending,
7492  * we need to start from one position to the right of the cursor
7493  * position, since this may already be at the end of a word.
7494  */
7495   bufpos = gl->buff_curpos + 1;
7496 /*
7497  * If we are at the end of the line, return the index of the last
7498  * real character on the line. Note that this will be -1 if the line
7499  * is empty.
7500  */
7501   if(bufpos >= gl->ntotal)
7502     return gl->ntotal - 1;
7503 /*
7504  * Search 'n' times, unless the end of the input line is reached first.
7505  */
7506   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7507 /*
7508  * If we are not already within a word, skip to the start of the next word.
7509  */
7510     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7511 	bufpos++)
7512       ;
7513 /*
7514  * Find the end of the next word.
7515  */
7516     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7517 	bufpos++)
7518       ;
7519   };
7520 /*
7521  * We will have overshot.
7522  */
7523   return bufpos > 0 ? bufpos-1 : bufpos;
7524 }
7525 
7526 /*.......................................................................
7527  * Search forward from the current position of the cursor for 'count'
7528  * word starts, returning the index of the last one found, or the end of
7529  * the line if there were less than 'count' words.
7530  *
7531  * Input:
7532  *  gl       GetLine *  The getline resource object.
7533  *  n            int    The number of word boundaries to search for.
7534  * Output:
7535  *  return       int    The buffer index of the located position.
7536  */
7537 static int gl_nth_word_start_forward(GetLine *gl, int n)
7538 {
7539   int bufpos;   /* The buffer index being checked. */
7540   int i;
7541 /*
7542  * Get the current cursor position.
7543  */
7544   bufpos = gl->buff_curpos;
7545 /*
7546  * Search 'n' times, unless the end of the input line is reached first.
7547  */
7548   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7549 /*
7550  * Find the end of the current word.
7551  */
7552     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7553 	bufpos++)
7554       ;
7555 /*
7556  * Skip to the start of the next word.
7557  */
7558     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7559 	bufpos++)
7560       ;
7561   };
7562   return bufpos;
7563 }
7564 
7565 /*.......................................................................
7566  * Search backward from the current position of the cursor for 'count'
7567  * word starts, returning the index of the last one found, or the start
7568  * of the line if there were less than 'count' words.
7569  *
7570  * Input:
7571  *  gl       GetLine *  The getline resource object.
7572  *  n            int    The number of word boundaries to search for.
7573  * Output:
7574  *  return       int    The buffer index of the located position.
7575  */
7576 static int gl_nth_word_start_backward(GetLine *gl, int n)
7577 {
7578   int bufpos;   /* The buffer index being checked. */
7579   int i;
7580 /*
7581  * Get the current cursor position.
7582  */
7583   bufpos = gl->buff_curpos;
7584 /*
7585  * Search 'n' times, unless the beginning of the input line (or vi insertion
7586  * point) is reached first.
7587  */
7588   for(i=0; i<n && bufpos > gl->insert_curpos; i++) {
7589 /*
7590  * Starting one character back from the last search, so as not to keep
7591  * settling on the same word-start, search backwards until finding a
7592  * word character.
7593  */
7594     while(--bufpos >= gl->insert_curpos &&
7595           !gl_is_word_char((int)gl->line[bufpos]))
7596       ;
7597 /*
7598  * Find the start of the word.
7599  */
7600     while(--bufpos >= gl->insert_curpos &&
7601           gl_is_word_char((int)gl->line[bufpos]))
7602       ;
7603 /*
7604  * We will have gone one character too far.
7605  */
7606     bufpos++;
7607   };
7608   return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos;
7609 }
7610 
7611 /*.......................................................................
7612  * Copy one or more words into the cut buffer without moving the cursor
7613  * or deleting text.
7614  */
7615 static KT_KEY_FN(gl_forward_copy_word)
7616 {
7617 /*
7618  * Find the location of the count'th start or end of a word
7619  * after the cursor, depending on whether in emacs or vi mode.
7620  */
7621   int next = gl->editor == GL_EMACS_MODE ?
7622     gl_nth_word_end_forward(gl, count) :
7623     gl_nth_word_start_forward(gl, count);
7624 /*
7625  * How many characters are to be copied into the cut buffer?
7626  */
7627   int n = next - gl->buff_curpos;
7628 /*
7629  * Copy the specified segment and terminate the string.
7630  */
7631   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7632   gl->cutbuf[n] = '\0';
7633   return 0;
7634 }
7635 
7636 /*.......................................................................
7637  * Copy one or more words preceding the cursor into the cut buffer,
7638  * without moving the cursor or deleting text.
7639  */
7640 static KT_KEY_FN(gl_backward_copy_word)
7641 {
7642 /*
7643  * Find the location of the count'th start of word before the cursor.
7644  */
7645   int next = gl_nth_word_start_backward(gl, count);
7646 /*
7647  * How many characters are to be copied into the cut buffer?
7648  */
7649   int n = gl->buff_curpos - next;
7650   gl_place_cursor(gl, next);
7651 /*
7652  * Copy the specified segment and terminate the string.
7653  */
7654   memcpy(gl->cutbuf, gl->line + next, n);
7655   gl->cutbuf[n] = '\0';
7656   return 0;
7657 }
7658 
7659 /*.......................................................................
7660  * Copy the characters between the cursor and the count'th instance of
7661  * a specified character in the input line, into the cut buffer.
7662  *
7663  * Input:
7664  *  gl       GetLine *  The getline resource object.
7665  *  count        int    The number of times to search.
7666  *  c           char    The character to be searched for, or '\0' if
7667  *                      the character should be read from the user.
7668  *  forward      int    True if searching forward.
7669  *  onto         int    True if the search should end on top of the
7670  *                      character, false if the search should stop
7671  *                      one character before the character in the
7672  *                      specified search direction.
7673  * Output:
7674  *  return       int    0 - OK.
7675  *                      1 - Error.
7676  *
7677  */
7678 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto)
7679 {
7680   int n;  /* The number of characters in the cut buffer */
7681 /*
7682  * Search for the character, and abort the operation if not found.
7683  */
7684   int pos = gl_find_char(gl, count, forward, onto, c);
7685   if(pos < 0)
7686     return 0;
7687 /*
7688  * Copy the specified segment.
7689  */
7690   if(forward) {
7691     n = pos + 1 - gl->buff_curpos;
7692     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7693   } else {
7694     n = gl->buff_curpos - pos;
7695     memcpy(gl->cutbuf, gl->line + pos, n);
7696     if(gl->editor == GL_VI_MODE)
7697       gl_place_cursor(gl, pos);
7698   }
7699 /*
7700  * Terminate the copy.
7701  */
7702   gl->cutbuf[n] = '\0';
7703   return 0;
7704 }
7705 
7706 /*.......................................................................
7707  * Copy a section up to and including a specified character into the cut
7708  * buffer without moving the cursor or deleting text.
7709  */
7710 static KT_KEY_FN(gl_forward_copy_find)
7711 {
7712   return gl_copy_find(gl, count, '\0', 1, 1);
7713 }
7714 
7715 /*.......................................................................
7716  * Copy a section back to and including a specified character into the cut
7717  * buffer without moving the cursor or deleting text.
7718  */
7719 static KT_KEY_FN(gl_backward_copy_find)
7720 {
7721   return gl_copy_find(gl, count, '\0', 0, 1);
7722 }
7723 
7724 /*.......................................................................
7725  * Copy a section up to and not including a specified character into the cut
7726  * buffer without moving the cursor or deleting text.
7727  */
7728 static KT_KEY_FN(gl_forward_copy_to)
7729 {
7730   return gl_copy_find(gl, count, '\0', 1, 0);
7731 }
7732 
7733 /*.......................................................................
7734  * Copy a section back to and not including a specified character into the cut
7735  * buffer without moving the cursor or deleting text.
7736  */
7737 static KT_KEY_FN(gl_backward_copy_to)
7738 {
7739   return gl_copy_find(gl, count, '\0', 0, 0);
7740 }
7741 
7742 /*.......................................................................
7743  * Copy to a character specified in a previous search into the cut
7744  * buffer without moving the cursor or deleting text.
7745  */
7746 static KT_KEY_FN(gl_copy_refind)
7747 {
7748   return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7749 		      gl->vi.find_onto);
7750 }
7751 
7752 /*.......................................................................
7753  * Copy to a character specified in a previous search, but in the opposite
7754  * direction, into the cut buffer without moving the cursor or deleting text.
7755  */
7756 static KT_KEY_FN(gl_copy_invert_refind)
7757 {
7758   return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7759 		      gl->vi.find_onto);
7760 }
7761 
7762 /*.......................................................................
7763  * Set the position of the cursor in the line input buffer and the
7764  * terminal.
7765  *
7766  * Input:
7767  *  gl       GetLine *  The getline resource object.
7768  *  buff_curpos  int    The new buffer cursor position.
7769  * Output:
7770  *  return       int    0 - OK.
7771  *                      1 - Error.
7772  */
7773 static int gl_place_cursor(GetLine *gl, int buff_curpos)
7774 {
7775 /*
7776  * Don't allow the cursor position to go out of the bounds of the input
7777  * line.
7778  */
7779   if(buff_curpos >= gl->ntotal)
7780     buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal;
7781   if(buff_curpos < 0)
7782     buff_curpos = 0;
7783 /*
7784  * Record the new buffer position.
7785  */
7786   gl->buff_curpos = buff_curpos;
7787 /*
7788  * Move the terminal cursor to the corresponding character.
7789  */
7790   return gl_set_term_curpos(gl, gl->prompt_len +
7791     gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len));
7792 }
7793 
7794 /*.......................................................................
7795  * In vi command mode, this function saves the current line to the
7796  * historical buffer needed by the undo command. In emacs mode it does
7797  * nothing. In order to allow action functions to call other action
7798  * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before
7799  * invoking an action, and thereafter once any call to this function
7800  * has set it to 1, further calls are ignored.
7801  *
7802  * Input:
7803  *  gl       GetLine *  The getline resource object.
7804  */
7805 static void gl_save_for_undo(GetLine *gl)
7806 {
7807   if(gl->vi.command && !gl->vi.undo.saved) {
7808     strlcpy(gl->vi.undo.line, gl->line, gl->linelen);
7809     gl->vi.undo.buff_curpos = gl->buff_curpos;
7810     gl->vi.undo.ntotal = gl->ntotal;
7811     gl->vi.undo.saved = 1;
7812   };
7813   if(gl->vi.command && !gl->vi.repeat.saved &&
7814      gl->current_action.fn != gl_vi_repeat_change) {
7815     gl->vi.repeat.action = gl->current_action;
7816     gl->vi.repeat.count = gl->current_count;
7817     gl->vi.repeat.saved = 1;
7818   };
7819   return;
7820 }
7821 
7822 /*.......................................................................
7823  * In vi mode, restore the line to the way it was before the last command
7824  * mode operation, storing the current line in the buffer so that the
7825  * undo operation itself can subsequently be undone.
7826  */
7827 static KT_KEY_FN(gl_vi_undo)
7828 {
7829 /*
7830  * Get pointers into the two lines.
7831  */
7832   char *undo_ptr = gl->vi.undo.line;
7833   char *line_ptr = gl->line;
7834 /*
7835  * Swap the characters of the two buffers up to the length of the shortest
7836  * line.
7837  */
7838   while(*undo_ptr && *line_ptr) {
7839     char c = *undo_ptr;
7840     *undo_ptr++ = *line_ptr;
7841     *line_ptr++ = c;
7842   };
7843 /*
7844  * Copy the rest directly.
7845  */
7846   if(gl->ntotal > gl->vi.undo.ntotal) {
7847     strlcpy(undo_ptr, line_ptr, gl->linelen);
7848     *line_ptr = '\0';
7849   } else {
7850     strlcpy(line_ptr, undo_ptr, gl->linelen);
7851     *undo_ptr = '\0';
7852   };
7853 /*
7854  * Record the length of the stored string.
7855  */
7856   gl->vi.undo.ntotal = gl->ntotal;
7857 /*
7858  * Accomodate the new contents of gl->line[].
7859  */
7860   gl_update_buffer(gl);
7861 /*
7862  * Set both cursor positions to the leftmost of the saved and current
7863  * cursor positions to emulate what vi does.
7864  */
7865   if(gl->buff_curpos < gl->vi.undo.buff_curpos)
7866     gl->vi.undo.buff_curpos = gl->buff_curpos;
7867   else
7868     gl->buff_curpos = gl->vi.undo.buff_curpos;
7869 /*
7870  * Since we have bipassed calling gl_save_for_undo(), record repeat
7871  * information inline.
7872  */
7873   gl->vi.repeat.action.fn = gl_vi_undo;
7874   gl->vi.repeat.action.data = NULL;
7875   gl->vi.repeat.count = 1;
7876 /*
7877  * Display the restored line.
7878  */
7879   gl_queue_redisplay(gl);
7880   return 0;
7881 }
7882 
7883 /*.......................................................................
7884  * Delete the following word and leave the user in vi insert mode.
7885  */
7886 static KT_KEY_FN(gl_vi_forward_change_word)
7887 {
7888   gl_save_for_undo(gl);
7889   gl->vi.command = 0;	/* Allow cursor at EOL */
7890   return gl_forward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7891 }
7892 
7893 /*.......................................................................
7894  * Delete the preceding word and leave the user in vi insert mode.
7895  */
7896 static KT_KEY_FN(gl_vi_backward_change_word)
7897 {
7898   return gl_backward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7899 }
7900 
7901 /*.......................................................................
7902  * Delete the following section and leave the user in vi insert mode.
7903  */
7904 static KT_KEY_FN(gl_vi_forward_change_find)
7905 {
7906   return gl_delete_find(gl, count, '\0', 1, 1, 1);
7907 }
7908 
7909 /*.......................................................................
7910  * Delete the preceding section and leave the user in vi insert mode.
7911  */
7912 static KT_KEY_FN(gl_vi_backward_change_find)
7913 {
7914   return gl_delete_find(gl, count, '\0', 0, 1, 1);
7915 }
7916 
7917 /*.......................................................................
7918  * Delete the following section and leave the user in vi insert mode.
7919  */
7920 static KT_KEY_FN(gl_vi_forward_change_to)
7921 {
7922   return gl_delete_find(gl, count, '\0', 1, 0, 1);
7923 }
7924 
7925 /*.......................................................................
7926  * Delete the preceding section and leave the user in vi insert mode.
7927  */
7928 static KT_KEY_FN(gl_vi_backward_change_to)
7929 {
7930   return gl_delete_find(gl, count, '\0', 0, 0, 1);
7931 }
7932 
7933 /*.......................................................................
7934  * Delete to a character specified by a previous search and leave the user
7935  * in vi insert mode.
7936  */
7937 static KT_KEY_FN(gl_vi_change_refind)
7938 {
7939   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7940 			gl->vi.find_onto, 1);
7941 }
7942 
7943 /*.......................................................................
7944  * Delete to a character specified by a previous search, but in the opposite
7945  * direction, and leave the user in vi insert mode.
7946  */
7947 static KT_KEY_FN(gl_vi_change_invert_refind)
7948 {
7949   return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7950 			gl->vi.find_onto, 1);
7951 }
7952 
7953 /*.......................................................................
7954  * Delete the following character and leave the user in vi insert mode.
7955  */
7956 static KT_KEY_FN(gl_vi_forward_change_char)
7957 {
7958   gl_save_for_undo(gl);
7959   gl->vi.command = 0;	/* Allow cursor at EOL */
7960   return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0, NULL);
7961 }
7962 
7963 /*.......................................................................
7964  * Delete the preceding character and leave the user in vi insert mode.
7965  */
7966 static KT_KEY_FN(gl_vi_backward_change_char)
7967 {
7968   return gl_backward_delete_char(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7969 }
7970 
7971 /*.......................................................................
7972  * Starting from the cursor position change characters to the specified column.
7973  */
7974 static KT_KEY_FN(gl_vi_change_to_column)
7975 {
7976   if (--count >= gl->buff_curpos)
7977     return gl_vi_forward_change_char(gl, count - gl->buff_curpos, NULL);
7978   else
7979     return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL);
7980 }
7981 
7982 /*.......................................................................
7983  * Starting from the cursor position change characters to a matching
7984  * parenthesis.
7985  */
7986 static KT_KEY_FN(gl_vi_change_to_parenthesis)
7987 {
7988   int curpos = gl_index_of_matching_paren(gl);
7989   if(curpos >= 0) {
7990     gl_save_for_undo(gl);
7991     if(curpos >= gl->buff_curpos)
7992       return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1, NULL);
7993     else
7994       return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1,
7995 					NULL);
7996   };
7997   return 0;
7998 }
7999 
8000 /*.......................................................................
8001  * If in vi mode, switch to vi command mode.
8002  *
8003  * Input:
8004  *  gl       GetLine *  The getline resource object.
8005  */
8006 static void gl_vi_command_mode(GetLine *gl)
8007 {
8008   if(gl->editor == GL_VI_MODE && !gl->vi.command) {
8009     gl->insert = 1;
8010     gl->vi.command = 1;
8011     gl->vi.repeat.input_curpos = gl->insert_curpos;
8012     gl->vi.repeat.command_curpos = gl->buff_curpos;
8013     gl->insert_curpos = 0;	 /* unrestrict left motion boundary */
8014     gl_cursor_left(gl, 1, NULL); /* Vi moves 1 left on entering command mode */
8015   };
8016 }
8017 
8018 /*.......................................................................
8019  * This is an action function which rings the terminal bell.
8020  */
8021 static KT_KEY_FN(gl_ring_bell)
8022 {
8023   return gl->silence_bell ? 0 :
8024     gl_print_control_sequence(gl, 1, gl->sound_bell);
8025 }
8026 
8027 /*.......................................................................
8028  * This is the action function which implements the vi-repeat-change
8029  * action.
8030  */
8031 static KT_KEY_FN(gl_vi_repeat_change)
8032 {
8033   int status;   /* The return status of the repeated action function */
8034   int i;
8035 /*
8036  * Nothing to repeat?
8037  */
8038   if(!gl->vi.repeat.action.fn)
8039     return gl_ring_bell(gl, 1, NULL);
8040 /*
8041  * Provide a way for action functions to know whether they are being
8042  * called by us.
8043  */
8044   gl->vi.repeat.active = 1;
8045 /*
8046  * Re-run the recorded function.
8047  */
8048   status = gl->vi.repeat.action.fn(gl, gl->vi.repeat.count,
8049 				   gl->vi.repeat.action.data);
8050 /*
8051  * Mark the repeat as completed.
8052  */
8053   gl->vi.repeat.active = 0;
8054 /*
8055  * Is we are repeating a function that has just switched to input
8056  * mode to allow the user to type, re-enter the text that the user
8057  * previously entered.
8058  */
8059   if(status==0 && !gl->vi.command) {
8060 /*
8061  * Make sure that the current line has been saved.
8062  */
8063     gl_save_for_undo(gl);
8064 /*
8065  * Repeat a previous insertion or overwrite?
8066  */
8067     if(gl->vi.repeat.input_curpos >= 0 &&
8068        gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos &&
8069        gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) {
8070 /*
8071  * Using the current line which is saved in the undo buffer, plus
8072  * the range of characters therein, as recorded by gl_vi_command_mode(),
8073  * add the characters that the user previously entered, to the input
8074  * line.
8075  */
8076       for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) {
8077 	if(gl_add_char_to_line(gl, gl->vi.undo.line[i]))
8078 	  return 1;
8079       };
8080     };
8081 /*
8082  * Switch back to command mode, now that the insertion has been repeated.
8083  */
8084     gl_vi_command_mode(gl);
8085   };
8086   return status;
8087 }
8088 
8089 /*.......................................................................
8090  * If the cursor is currently over a parenthesis character, return the
8091  * index of its matching parenthesis. If not currently over a parenthesis
8092  * character, return the next close parenthesis character to the right of
8093  * the cursor. If the respective parenthesis character isn't found,
8094  * ring the terminal bell and return -1.
8095  *
8096  * Input:
8097  *  gl       GetLine *  The getline resource object.
8098  * Output:
8099  *  return       int    Either the index of the matching parenthesis,
8100  *                      or -1 if not found.
8101  */
8102 static int gl_index_of_matching_paren(GetLine *gl)
8103 {
8104   int i;
8105 /*
8106  * List the recognized parentheses, and their matches.
8107  */
8108   const char *o_paren = "([{";
8109   const char *c_paren = ")]}";
8110   const char *cptr;
8111 /*
8112  * Get the character that is currently under the cursor.
8113  */
8114   char c = gl->line[gl->buff_curpos];
8115 /*
8116  * If the character under the cursor is an open parenthesis, look forward
8117  * for the matching close parenthesis.
8118  */
8119   if((cptr=strchr(o_paren, c))) {
8120     char match = c_paren[cptr - o_paren];
8121     int matches_needed = 1;
8122     for(i=gl->buff_curpos+1; i<gl->ntotal; i++) {
8123       if(gl->line[i] == c)
8124 	matches_needed++;
8125       else if(gl->line[i] == match && --matches_needed==0)
8126 	return i;
8127     };
8128 /*
8129  * If the character under the cursor is an close parenthesis, look forward
8130  * for the matching open parenthesis.
8131  */
8132   } else if((cptr=strchr(c_paren, c))) {
8133     char match = o_paren[cptr - c_paren];
8134     int matches_needed = 1;
8135     for(i=gl->buff_curpos-1; i>=0; i--) {
8136       if(gl->line[i] == c)
8137 	matches_needed++;
8138       else if(gl->line[i] == match && --matches_needed==0)
8139 	return i;
8140     };
8141 /*
8142  * If not currently over a parenthesis character, search forwards for
8143  * the first close parenthesis (this is what the vi % binding does).
8144  */
8145   } else {
8146     for(i=gl->buff_curpos+1; i<gl->ntotal; i++)
8147       if(strchr(c_paren, gl->line[i]) != NULL)
8148 	return i;
8149   };
8150 /*
8151  * Not found.
8152  */
8153   (void) gl_ring_bell(gl, 1, NULL);
8154   return -1;
8155 }
8156 
8157 /*.......................................................................
8158  * If the cursor is currently over a parenthesis character, this action
8159  * function moves the cursor to its matching parenthesis.
8160  */
8161 static KT_KEY_FN(gl_find_parenthesis)
8162 {
8163   int curpos = gl_index_of_matching_paren(gl);
8164   if(curpos >= 0)
8165     return gl_place_cursor(gl, curpos);
8166   return 0;
8167 }
8168 
8169 /*.......................................................................
8170  * Handle the receipt of the potential start of a new key-sequence from
8171  * the user.
8172  *
8173  * Input:
8174  *  gl      GetLine *   The resource object of this library.
8175  *  first_char char     The first character of the sequence.
8176  * Output:
8177  *  return      int     0 - OK.
8178  *                      1 - Error.
8179  */
8180 static int gl_interpret_char(GetLine *gl, char first_char)
8181 {
8182   char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */
8183   int nkey=0;                /* The number of characters in the key sequence */
8184   int count;                 /* The repeat count of an action function */
8185   int ret;                   /* The return value of an action function */
8186   int i;
8187 /*
8188  * Get the first character.
8189  */
8190   char c = first_char;
8191 /*
8192  * If editing is disabled, just add newly entered characters to the
8193  * input line buffer, and watch for the end of the line.
8194  */
8195   if(gl->editor == GL_NO_EDITOR) {
8196     gl_discard_chars(gl, 1);
8197     if(gl->ntotal >= gl->linelen)
8198       return 0;
8199     if(c == '\n' || c == '\r')
8200       return gl_newline(gl, 1, NULL);
8201     gl_buffer_char(gl, c, gl->ntotal);
8202     return 0;
8203   };
8204 /*
8205  * If the user is in the process of specifying a repeat count and the
8206  * new character is a digit, increment the repeat count accordingly.
8207  */
8208   if(gl->number >= 0 && isdigit((int)(unsigned char) c)) {
8209     gl_discard_chars(gl, 1);
8210     return gl_digit_argument(gl, c, NULL);
8211 /*
8212  * In vi command mode, all key-sequences entered need to be
8213  * either implicitly or explicitly prefixed with an escape character.
8214  */
8215   } else if(gl->vi.command && c != GL_ESC_CHAR) {
8216     keyseq[nkey++] = GL_ESC_CHAR;
8217 /*
8218  * If the first character of the sequence is a printable character,
8219  * then to avoid confusion with the special "up", "down", "left"
8220  * or "right" cursor key bindings, we need to prefix the
8221  * printable character with a backslash escape before looking it up.
8222  */
8223   } else if(!IS_META_CHAR(c) && !IS_CTRL_CHAR(c)) {
8224     keyseq[nkey++] = '\\';
8225   };
8226 /*
8227  * Compose a potentially multiple key-sequence in gl->keyseq.
8228  */
8229   while(nkey < GL_KEY_MAX) {
8230     KtAction *action; /* An action function */
8231     KeySym *keysym;   /* The symbol-table entry of a key-sequence */
8232     int nsym;         /* The number of ambiguously matching key-sequences */
8233 /*
8234  * If the character is an unprintable meta character, split it
8235  * into two characters, an escape character and the character
8236  * that was modified by the meta key.
8237  */
8238     if(IS_META_CHAR(c)) {
8239       keyseq[nkey++] = GL_ESC_CHAR;
8240       c = META_TO_CHAR(c);
8241       continue;
8242     };
8243 /*
8244  * Append the latest character to the key sequence.
8245  */
8246     keyseq[nkey++] = c;
8247 /*
8248  * When doing vi-style editing, an escape at the beginning of any binding
8249  * switches to command mode.
8250  */
8251     if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command)
8252       gl_vi_command_mode(gl);
8253 /*
8254  * Lookup the key sequence.
8255  */
8256     switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &keysym, &nsym)) {
8257     case KT_EXACT_MATCH:
8258 /*
8259  * Get the matching action function.
8260  */
8261       action = keysym->actions + keysym->binder;
8262 /*
8263  * Get the repeat count, passing the last keystroke if executing the
8264  * digit-argument action.
8265  */
8266       if(action->fn == gl_digit_argument) {
8267 	count = c;
8268       } else {
8269 	count = gl->number >= 0 ? gl->number : 1;
8270       };
8271 /*
8272  * Record the function that is being invoked.
8273  */
8274       gl->current_action = *action;
8275       gl->current_count = count;
8276 /*
8277  * Mark the current line as not yet preserved for use by the vi undo command.
8278  */
8279       gl->vi.undo.saved = 0;
8280       gl->vi.repeat.saved = 0;
8281 /*
8282  * Execute the action function. Note the action function can tell
8283  * whether the provided repeat count was defaulted or specified
8284  * explicitly by looking at whether gl->number is -1 or not. If
8285  * it is negative, then no repeat count was specified by the user.
8286  */
8287       ret = action->fn(gl, count, action->data);
8288 /*
8289  * In server mode, the action will return immediately if it tries to
8290  * read input from the terminal, and no input is currently available.
8291  * If this happens, abort. Note that gl_get_input_line() will rewind
8292  * the read-ahead buffer to allow the next call to redo the function
8293  * from scratch.
8294  */
8295       if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ)
8296 	return 1;
8297 /*
8298  * Discard the now processed characters from the key sequence buffer.
8299  */
8300       gl_discard_chars(gl, gl->nread);
8301 /*
8302  * If the latest action function wasn't a history action, cancel any
8303  * current history search.
8304  */
8305       if(gl->last_search != gl->keyseq_count)
8306 	_glh_cancel_search(gl->glh);
8307 /*
8308  * Reset the repeat count after running action functions.
8309  */
8310       if(action->fn != gl_digit_argument)
8311 	gl->number = -1;
8312       return ret ? 1 : 0;
8313       break;
8314     case KT_AMBIG_MATCH:    /* Ambiguous match - so read the next character */
8315       if(gl_read_terminal(gl, 1, &c))
8316 	return 1;
8317       break;
8318     case KT_NO_MATCH:
8319 /*
8320  * If the first character looked like it might be a prefix of a key-sequence
8321  * but it turned out not to be, ring the bell to tell the user that it
8322  * wasn't recognised.
8323  */
8324       if(keyseq[0] != '\\' && keyseq[0] != '\t') {
8325 	gl_ring_bell(gl, 1, NULL);
8326       } else {
8327 /*
8328  * The user typed a single printable character that doesn't match
8329  * the start of any keysequence, so add it to the line in accordance
8330  * with the current repeat count.
8331  */
8332 	count = gl->number >= 0 ? gl->number : 1;
8333 	for(i=0; i<count; i++)
8334 	  gl_add_char_to_line(gl, first_char);
8335 	gl->number = -1;
8336       };
8337       gl_discard_chars(gl, 1);
8338       _glh_cancel_search(gl->glh);
8339       return 0;
8340       break;
8341     case KT_BAD_MATCH:
8342       gl_ring_bell(gl, 1, NULL);
8343       gl_discard_chars(gl, gl->nread);
8344       _glh_cancel_search(gl->glh);
8345       return 1;
8346       break;
8347     };
8348   };
8349 /*
8350  * If the key sequence was too long to match, ring the bell, then
8351  * discard the first character, so that the next attempt to match a
8352  * key-sequence continues with the next key press. In practice this
8353  * shouldn't happen, since one isn't allowed to bind action functions
8354  * to keysequences that are longer than GL_KEY_MAX.
8355  */
8356   gl_ring_bell(gl, 1, NULL);
8357   gl_discard_chars(gl, 1);
8358   return 0;
8359 }
8360 
8361 /*.......................................................................
8362  * Configure the application and/or user-specific behavior of
8363  * gl_get_line().
8364  *
8365  * Note that calling this function between calling new_GetLine() and
8366  * the first call to gl_get_line(), disables the otherwise automatic
8367  * reading of ~/.teclarc on the first call to gl_get_line().
8368  *
8369  * Input:
8370  *  gl             GetLine *  The resource object of this library.
8371  *  app_string  const char *  Either NULL, or a string containing one
8372  *                            or more .teclarc command lines, separated
8373  *                            by newline characters. This can be used to
8374  *                            establish an application-specific
8375  *                            configuration, without the need for an external
8376  *                            file. This is particularly useful in embedded
8377  *                            environments where there is no filesystem.
8378  *  app_file    const char *  Either NULL, or the pathname of an
8379  *                            application-specific .teclarc file. The
8380  *                            contents of this file, if provided, are
8381  *                            read after the contents of app_string[].
8382  *  user_file   const char *  Either NULL, or the pathname of a
8383  *                            user-specific .teclarc file. Except in
8384  *                            embedded applications, this should
8385  *                            usually be "~/.teclarc".
8386  * Output:
8387  *  return             int    0 - OK.
8388  *                            1 - Bad argument(s).
8389  */
8390 int gl_configure_getline(GetLine *gl, const char *app_string,
8391 			 const char *app_file, const char *user_file)
8392 {
8393   sigset_t oldset; /* The signals that were blocked on entry to this function */
8394   int status;      /* The return status of _gl_configure_getline() */
8395 /*
8396  * Check the arguments.
8397  */
8398   if(!gl) {
8399     errno = EINVAL;
8400     return 1;
8401   };
8402 /*
8403  * Block all signals.
8404  */
8405   if(gl_mask_signals(gl, &oldset))
8406     return 1;
8407 /*
8408  * Execute the private body of the function while signals are blocked.
8409  */
8410   status = _gl_configure_getline(gl, app_string, app_file, user_file);
8411 /*
8412  * Restore the process signal mask.
8413  */
8414   gl_unmask_signals(gl, &oldset);
8415   return status;
8416 }
8417 
8418 /*.......................................................................
8419  * This is the private body of the gl_configure_getline() function. It
8420  * assumes that the caller has checked its arguments and blocked the
8421  * delivery of signals.
8422  */
8423 static int _gl_configure_getline(GetLine *gl, const char *app_string,
8424 				 const char *app_file, const char *user_file)
8425 {
8426 /*
8427  * Mark getline as having been explicitly configured.
8428  */
8429   gl->configured = 1;
8430 /*
8431  * Start by parsing the configuration string, if provided.
8432  */
8433   if(app_string)
8434     (void) _gl_read_config_string(gl, app_string, KTB_NORM);
8435 /*
8436  * Now parse the application-specific configuration file, if provided.
8437  */
8438   if(app_file)
8439     (void) _gl_read_config_file(gl, app_file, KTB_NORM);
8440 /*
8441  * Finally, parse the user-specific configuration file, if provided.
8442  */
8443   if(user_file)
8444     (void) _gl_read_config_file(gl, user_file, KTB_USER);
8445 /*
8446  * Record the names of the configuration files to allow them to
8447  * be re-read if requested at a later time.
8448  */
8449   if(gl_record_string(&gl->app_file, app_file) ||
8450      gl_record_string(&gl->user_file, user_file)) {
8451     errno = ENOMEM;
8452     _err_record_msg(gl->err,
8453 	   "Insufficient memory to record tecla configuration file names",
8454 	   END_ERR_MSG);
8455     return 1;
8456   };
8457   return 0;
8458 }
8459 
8460 /*.......................................................................
8461  * Replace a malloc'd string (or NULL), with another malloc'd copy of
8462  * a string (or NULL).
8463  *
8464  * Input:
8465  *  sptr          char **  On input if *sptr!=NULL, *sptr will be
8466  *                         free'd and *sptr will be set to NULL. Then,
8467  *                         on output, if string!=NULL a malloc'd copy
8468  *                         of this string will be assigned to *sptr.
8469  *  string  const char *   The string to be copied, or NULL to simply
8470  *                         discard any existing string.
8471  * Output:
8472  *  return         int     0 - OK.
8473  *                         1 - Malloc failure (no error message is generated).
8474  */
8475 static int gl_record_string(char **sptr, const char *string)
8476 {
8477 /*
8478  * If the original string is the same string, don't do anything.
8479  */
8480   if(*sptr == string || (*sptr && string && strcmp(*sptr, string)==0))
8481     return 0;
8482 /*
8483  * Discard any existing cached string.
8484  */
8485   if(*sptr) {
8486     free(*sptr);
8487     *sptr = NULL;
8488   };
8489 /*
8490  * Allocate memory for a copy of the specified string.
8491  */
8492   if(string) {
8493     size_t ssz = strlen(string) + 1;
8494     *sptr = (char *) malloc(ssz);
8495     if(!*sptr)
8496       return 1;
8497 /*
8498  * Copy the string.
8499  */
8500     strlcpy(*sptr, string, ssz);
8501   };
8502   return 0;
8503 }
8504 
8505 #ifndef HIDE_FILE_SYSTEM
8506 /*.......................................................................
8507  * Re-read any application-specific and user-specific files previously
8508  * specified via the gl_configure_getline() function.
8509  */
8510 static KT_KEY_FN(gl_read_init_files)
8511 {
8512   return _gl_configure_getline(gl, NULL, gl->app_file, gl->user_file);
8513 }
8514 #endif
8515 
8516 /*.......................................................................
8517  * Save the contents of the history buffer to a given new file.
8518  *
8519  * Input:
8520  *  gl             GetLine *  The resource object of this library.
8521  *  filename    const char *  The name of the new file to write to.
8522  *  comment     const char *  Extra information such as timestamps will
8523  *                            be recorded on a line started with this
8524  *                            string, the idea being that the file can
8525  *                            double as a command file. Specify "" if
8526  *                            you don't care.
8527  *  max_lines          int    The maximum number of lines to save, or -1
8528  *                            to save all of the lines in the history
8529  *                            list.
8530  * Output:
8531  *  return             int     0 - OK.
8532  *                             1 - Error.
8533  */
8534 int gl_save_history(GetLine *gl, const char *filename, const char *comment,
8535 		    int max_lines)
8536 {
8537   sigset_t oldset; /* The signals that were blocked on entry to this function */
8538   int status;      /* The return status of _gl_save_history() */
8539 /*
8540  * Check the arguments.
8541  */
8542   if(!gl || !filename || !comment) {
8543     if(gl)
8544       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8545     errno = EINVAL;
8546     return 1;
8547   };
8548 /*
8549  * Block all signals.
8550  */
8551   if(gl_mask_signals(gl, &oldset))
8552     return 1;
8553 /*
8554  * Execute the private body of the function while signals are blocked.
8555  */
8556   status = _gl_save_history(gl, filename, comment, max_lines);
8557 /*
8558  * Restore the process signal mask.
8559  */
8560   gl_unmask_signals(gl, &oldset);
8561   return status;
8562 }
8563 
8564 /*.......................................................................
8565  * This is the private body of the gl_save_history() function. It
8566  * assumes that the caller has checked its arguments and blocked the
8567  * delivery of signals.
8568  */
8569 static int _gl_save_history(GetLine *gl, const char *filename,
8570 			    const char *comment, int max_lines)
8571 {
8572 /*
8573  * If filesystem access is to be excluded, then history files can't
8574  * be written.
8575  */
8576 #ifdef WITHOUT_FILE_SYSTEM
8577   _err_record_msg(gl->err, "Can't save history without filesystem access",
8578 		  END_ERR_MSG);
8579   errno = EINVAL;
8580   return 1;
8581 #else
8582   FileExpansion *expansion; /* The expansion of the filename */
8583 /*
8584  * Expand the filename.
8585  */
8586   expansion = ef_expand_file(gl->ef, filename, -1);
8587   if(!expansion) {
8588     gl_print_info(gl, "Unable to expand ", filename, " (",
8589 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8590     return 1;
8591   };
8592 /*
8593  * Attempt to save to the specified file.
8594  */
8595   if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) {
8596     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8597     return 1;
8598   };
8599   return 0;
8600 #endif
8601 }
8602 
8603 /*.......................................................................
8604  * Restore the contents of the history buffer from a given new file.
8605  *
8606  * Input:
8607  *  gl             GetLine *  The resource object of this library.
8608  *  filename    const char *  The name of the new file to write to.
8609  *  comment     const char *  This must be the same string that was
8610  *                            passed to gl_save_history() when the file
8611  *                            was written.
8612  * Output:
8613  *  return             int     0 - OK.
8614  *                             1 - Error.
8615  */
8616 int gl_load_history(GetLine *gl, const char *filename, const char *comment)
8617 {
8618   sigset_t oldset; /* The signals that were blocked on entry to this function */
8619   int status;      /* The return status of _gl_load_history() */
8620 /*
8621  * Check the arguments.
8622  */
8623   if(!gl || !filename || !comment) {
8624     if(gl)
8625       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8626     errno = EINVAL;
8627     return 1;
8628   };
8629 /*
8630  * Block all signals.
8631  */
8632   if(gl_mask_signals(gl, &oldset))
8633     return 1;
8634 /*
8635  * Execute the private body of the function while signals are blocked.
8636  */
8637   status = _gl_load_history(gl, filename, comment);
8638 /*
8639  * Restore the process signal mask.
8640  */
8641   gl_unmask_signals(gl, &oldset);
8642   return status;
8643 }
8644 
8645 /*.......................................................................
8646  * This is the private body of the gl_load_history() function. It
8647  * assumes that the caller has checked its arguments and blocked the
8648  * delivery of signals.
8649  */
8650 static int _gl_load_history(GetLine *gl, const char *filename,
8651 			    const char *comment)
8652 {
8653 /*
8654  * If filesystem access is to be excluded, then history files can't
8655  * be read.
8656  */
8657 #ifdef WITHOUT_FILE_SYSTEM
8658   _err_record_msg(gl->err, "Can't load history without filesystem access",
8659 		  END_ERR_MSG);
8660   errno = EINVAL;
8661   return 1;
8662 #else
8663   FileExpansion *expansion; /* The expansion of the filename */
8664 /*
8665  * Expand the filename.
8666  */
8667   expansion = ef_expand_file(gl->ef, filename, -1);
8668   if(!expansion) {
8669     gl_print_info(gl, "Unable to expand ", filename, " (",
8670 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8671     return 1;
8672   };
8673 /*
8674  * Attempt to load from the specified file.
8675  */
8676   if(_glh_load_history(gl->glh, expansion->files[0], comment,
8677 		       gl->cutbuf, gl->linelen+1)) {
8678     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8679     gl->cutbuf[0] = '\0';
8680     return 1;
8681   };
8682   gl->cutbuf[0] = '\0';
8683   return 0;
8684 #endif
8685 }
8686 
8687 /*.......................................................................
8688  * Where possible, register a function and associated data to be called
8689  * whenever a specified event is seen on a file descriptor.
8690  *
8691  * Input:
8692  *  gl            GetLine *  The resource object of the command-line input
8693  *                           module.
8694  *  fd                int    The file descriptor to watch.
8695  *  event       GlFdEvent    The type of activity to watch for.
8696  *  callback  GlFdEventFn *  The function to call when the specified
8697  *                           event occurs. Setting this to 0 removes
8698  *                           any existing callback.
8699  *  data             void *  A pointer to arbitrary data to pass to the
8700  *                           callback function.
8701  * Output:
8702  *  return            int    0 - OK.
8703  *                           1 - Either gl==NULL, or this facility isn't
8704  *                               available on the the host system
8705  *                               (ie. select() isn't available). No
8706  *                               error message is generated in the latter
8707  *                               case.
8708  */
8709 int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8710 		GlFdEventFn *callback, void *data)
8711 {
8712   sigset_t oldset; /* The signals that were blocked on entry to this function */
8713   int status;      /* The return status of _gl_watch_fd() */
8714 /*
8715  * Check the arguments.
8716  */
8717   if(!gl) {
8718     errno = EINVAL;
8719     return 1;
8720   };
8721   if(fd < 0) {
8722     _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG);
8723     errno = EINVAL;
8724     return 1;
8725   };
8726 /*
8727  * Block all signals.
8728  */
8729   if(gl_mask_signals(gl, &oldset))
8730     return 1;
8731 /*
8732  * Execute the private body of the function while signals are blocked.
8733  */
8734   status = _gl_watch_fd(gl, fd, event, callback, data);
8735 /*
8736  * Restore the process signal mask.
8737  */
8738   gl_unmask_signals(gl, &oldset);
8739   return status;
8740 }
8741 
8742 /*.......................................................................
8743  * This is the private body of the gl_watch_fd() function. It
8744  * assumes that the caller has checked its arguments and blocked the
8745  * delivery of signals.
8746  */
8747 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8748 			GlFdEventFn *callback, void *data)
8749 #if !defined(HAVE_SELECT)
8750 {return 1;}               /* The facility isn't supported on this system */
8751 #else
8752 {
8753   GlFdNode *prev;  /* The node that precedes 'node' in gl->fd_nodes */
8754   GlFdNode *node;  /* The file-descriptor node being checked */
8755 /*
8756  * Search the list of already registered fd activity nodes for the specified
8757  * file descriptor.
8758  */
8759   for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd;
8760       prev=node, node=node->next)
8761     ;
8762 /*
8763  * Hasn't a node been allocated for this fd yet?
8764  */
8765   if(!node) {
8766 /*
8767  * If there is no callback to record, just ignore the call.
8768  */
8769     if(!callback)
8770       return 0;
8771 /*
8772  * Allocate the new node.
8773  */
8774     node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem);
8775     if(!node) {
8776       errno = ENOMEM;
8777       _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG);
8778       return 1;
8779     };
8780 /*
8781  * Prepend the node to the list.
8782  */
8783     node->next = gl->fd_nodes;
8784     gl->fd_nodes = node;
8785 /*
8786  * Initialize the node.
8787  */
8788     node->fd = fd;
8789     node->rd.fn = 0;
8790     node->rd.data = NULL;
8791     node->ur = node->wr = node->rd;
8792   };
8793 /*
8794  * Record the new callback.
8795  */
8796   switch(event) {
8797   case GLFD_READ:
8798     node->rd.fn = callback;
8799     node->rd.data = data;
8800     if(callback)
8801       FD_SET(fd, &gl->rfds);
8802     else
8803       FD_CLR(fd, &gl->rfds);
8804     break;
8805   case GLFD_WRITE:
8806     node->wr.fn = callback;
8807     node->wr.data = data;
8808     if(callback)
8809       FD_SET(fd, &gl->wfds);
8810     else
8811       FD_CLR(fd, &gl->wfds);
8812     break;
8813   case GLFD_URGENT:
8814     node->ur.fn = callback;
8815     node->ur.data = data;
8816     if(callback)
8817       FD_SET(fd, &gl->ufds);
8818     else
8819       FD_CLR(fd, &gl->ufds);
8820     break;
8821   };
8822 /*
8823  * Keep a record of the largest file descriptor being watched.
8824  */
8825   if(fd > gl->max_fd)
8826     gl->max_fd = fd;
8827 /*
8828  * If we are deleting an existing callback, also delete the parent
8829  * activity node if no callbacks are registered to the fd anymore.
8830  */
8831   if(!callback) {
8832     if(!node->rd.fn && !node->wr.fn && !node->ur.fn) {
8833       if(prev)
8834 	prev->next = node->next;
8835       else
8836 	gl->fd_nodes = node->next;
8837       node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node);
8838     };
8839   };
8840   return 0;
8841 }
8842 #endif
8843 
8844 /*.......................................................................
8845  * On systems with the select() system call, the gl_inactivity_timeout()
8846  * function provides the option of setting (or cancelling) an
8847  * inactivity timeout. Inactivity, in this case, refers both to
8848  * terminal input received from the user, and to I/O on any file
8849  * descriptors registered by calls to gl_watch_fd(). If at any time,
8850  * no activity is seen for the requested time period, the specified
8851  * timeout callback function is called. On returning, this callback
8852  * returns a code which tells gl_get_line() what to do next. Note that
8853  * each call to gl_inactivity_timeout() replaces any previously installed
8854  * timeout callback, and that specifying a callback of 0, turns off
8855  * inactivity timing.
8856  *
8857  * Beware that although the timeout argument includes a nano-second
8858  * component, few computer clocks presently have resolutions finer
8859  * than a few milliseconds, so asking for less than a few milliseconds
8860  * is equivalent to zero on a lot of systems.
8861  *
8862  * Input:
8863  *  gl            GetLine *  The resource object of the command-line input
8864  *                           module.
8865  *  callback  GlTimeoutFn *  The function to call when the inactivity
8866  *                           timeout is exceeded. To turn off
8867  *                           inactivity timeouts altogether, send 0.
8868  *  data             void *  A pointer to arbitrary data to pass to the
8869  *                           callback function.
8870  *  sec     unsigned long    The number of whole seconds in the timeout.
8871  *  nsec    unsigned long    The fractional number of seconds in the
8872  *                           timeout, expressed in nano-seconds (see
8873  *                           the caveat above).
8874  * Output:
8875  *  return            int    0 - OK.
8876  *                           1 - Either gl==NULL, or this facility isn't
8877  *                               available on the the host system
8878  *                               (ie. select() isn't available). No
8879  *                               error message is generated in the latter
8880  *                               case.
8881  */
8882 int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data,
8883 		   unsigned long sec, unsigned long nsec)
8884 #if !defined(HAVE_SELECT)
8885 {return 1;}               /* The facility isn't supported on this system */
8886 #else
8887 {
8888   sigset_t oldset; /* The signals that were blocked on entry to this function */
8889 /*
8890  * Check the arguments.
8891  */
8892   if(!gl) {
8893     errno = EINVAL;
8894     return 1;
8895   };
8896 /*
8897  * Block all signals.
8898  */
8899   if(gl_mask_signals(gl, &oldset))
8900     return 1;
8901 /*
8902  * Install a new timeout?
8903  */
8904   if(timeout_fn) {
8905     gl->timer.dt.tv_sec = sec;
8906     gl->timer.dt.tv_usec = nsec / 1000;
8907     gl->timer.fn = timeout_fn;
8908     gl->timer.data = data;
8909   } else {
8910     gl->timer.fn = 0;
8911     gl->timer.data = NULL;
8912   };
8913 /*
8914  * Restore the process signal mask.
8915  */
8916   gl_unmask_signals(gl, &oldset);
8917   return 0;
8918 }
8919 #endif
8920 
8921 /*.......................................................................
8922  * When select() is available, this is a private function of
8923  * gl_read_input() which responds to file-descriptor events registered by
8924  * the caller. Note that it assumes that it is being called from within
8925  * gl_read_input()'s sigsetjump() clause.
8926  *
8927  * Input:
8928  *  gl    GetLine *  The resource object of this module.
8929  *  fd        int    The file descriptor to be watched for user input.
8930  * Output:
8931  *  return    int    0 - OK.
8932  *                   1 - An error occurred.
8933  */
8934 static int gl_event_handler(GetLine *gl, int fd)
8935 {
8936 #if !defined(HAVE_SELECT)
8937   return 0;
8938 #else
8939 /*
8940  * Set up a zero-second timeout.
8941  */
8942   struct timeval zero;
8943   zero.tv_sec = zero.tv_usec = 0;
8944 /*
8945  * If at any time no external callbacks remain, quit the loop return,
8946  * so that we can simply wait in read(). This is designed as an
8947  * optimization for when no callbacks have been registered on entry to
8948  * this function, but since callbacks can delete themselves, it can
8949  * also help later.
8950  */
8951   while(gl->fd_nodes || gl->timer.fn) {
8952     int nready;   /* The number of file descriptors that are ready for I/O */
8953 /*
8954  * Get the set of descriptors to be watched.
8955  */
8956     fd_set rfds = gl->rfds;
8957     fd_set wfds = gl->wfds;
8958     fd_set ufds = gl->ufds;
8959 /*
8960  * Get the appropriate timeout.
8961  */
8962     struct timeval dt = gl->timer.fn ? gl->timer.dt : zero;
8963 /*
8964  * Add the specified user-input file descriptor tot he set that is to
8965  * be watched.
8966  */
8967     FD_SET(fd, &rfds);
8968 /*
8969  * Unblock the signals that we are watching, while select is blocked
8970  * waiting for I/O.
8971  */
8972     gl_catch_signals(gl);
8973 /*
8974  * Wait for activity on any of the file descriptors.
8975  */
8976     nready = select(gl->max_fd+1, &rfds, &wfds, &ufds,
8977 	    (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL);
8978 /*
8979  * We don't want to do a longjmp in the middle of a callback that
8980  * might be modifying global or heap data, so block all the signals
8981  * that we are trapping before executing callback functions. Note that
8982  * the caller will unblock them again when it needs to, so there is
8983  * no need to undo this before returning.
8984  */
8985     gl_mask_signals(gl, NULL);
8986 /*
8987  * If select() returns but none of the file descriptors are reported
8988  * to have activity, then select() timed out.
8989  */
8990     if(nready == 0) {
8991 /*
8992  * Note that in non-blocking server mode, the inactivity timer is used
8993  * to allow I/O to block for a specified amount of time, so in this
8994  * mode we return the postponed blocked status when an abort is
8995  * requested.
8996  */
8997       if(gl_call_timeout_handler(gl)) {
8998 	return 1;
8999       } else if(gl->io_mode == GL_SERVER_MODE) {
9000 	gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
9001 	return 1;
9002       };
9003 /*
9004  * If nready < 0, this means an error occurred.
9005  */
9006     } else if(nready < 0) {
9007       if(errno != EINTR) {
9008 	gl_record_status(gl, GLR_ERROR, errno);
9009 	return 1;
9010       };
9011 /*
9012  * If the user-input file descriptor has data available, return.
9013  */
9014     } else if(FD_ISSET(fd, &rfds)) {
9015       return 0;
9016 /*
9017  * Check for activity on any of the file descriptors registered by the
9018  * calling application, and call the associated callback functions.
9019  */
9020     } else {
9021       GlFdNode *node;   /* The fd event node being checked */
9022 /*
9023  * Search the list for the file descriptor that caused select() to return.
9024  */
9025       for(node=gl->fd_nodes; node; node=node->next) {
9026 /*
9027  * Is there urgent out of band data waiting to be read on fd?
9028  */
9029 	if(node->ur.fn && FD_ISSET(node->fd, &ufds)) {
9030 	  if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT))
9031 	    return 1;
9032 	  break;  /* The callback may have changed the list of nodes */
9033 /*
9034  * Is the fd readable?
9035  */
9036 	} else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) {
9037 	  if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ))
9038 	    return 1;
9039 	  break;  /* The callback may have changed the list of nodes */
9040 /*
9041  * Is the fd writable?
9042  */
9043 	} else if(node->wr.fn && FD_ISSET(node->fd, &wfds)) {
9044 	  if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE))
9045 	    return 1;
9046 	  break;  /* The callback may have changed the list of nodes */
9047 	};
9048       };
9049     };
9050 /*
9051  * Just in case the above event handlers asked for the input line to
9052  * be redrawn, flush any pending output.
9053  */
9054     if(gl_flush_output(gl))
9055       return 1;
9056   };
9057   return 0;
9058 }
9059 #endif
9060 
9061 #if defined(HAVE_SELECT)
9062 /*.......................................................................
9063  * This is a private function of gl_event_handler(), used to call a
9064  * file-descriptor callback.
9065  *
9066  * Input:
9067  *  gl       GetLine *  The resource object of gl_get_line().
9068  *  gfh  GlFdHandler *  The I/O handler.
9069  *  fd           int    The file-descriptor being reported.
9070  *  event  GlFdEvent    The I/O event being reported.
9071  * Output:
9072  *  return       int    0 - OK.
9073  *                      1 - Error.
9074  */
9075 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
9076 			      GlFdEvent event)
9077 {
9078   Termios attr;       /* The terminal attributes */
9079   int waserr = 0;     /* True after any error */
9080 /*
9081  * Re-enable conversion of newline characters to carriage-return/linefeed,
9082  * so that the callback can write to the terminal without having to do
9083  * anything special.
9084  */
9085   if(tcgetattr(gl->input_fd, &attr)) {
9086     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9087     return 1;
9088   };
9089   attr.c_oflag |= OPOST;
9090   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9091     if(errno != EINTR) {
9092       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9093       return 1;
9094     };
9095   };
9096 /*
9097  * Invoke the application's callback function.
9098  */
9099   switch(gfh->fn(gl, gfh->data, fd, event)) {
9100   default:
9101   case GLFD_ABORT:
9102     gl_record_status(gl, GLR_FDABORT, 0);
9103     waserr = 1;
9104     break;
9105   case GLFD_REFRESH:
9106     gl_queue_redisplay(gl);
9107     break;
9108   case GLFD_CONTINUE:
9109     break;
9110   };
9111 /*
9112  * Disable conversion of newline characters to carriage-return/linefeed.
9113  */
9114   attr.c_oflag &= ~(OPOST);
9115   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9116     if(errno != EINTR) {
9117       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9118       return 1;
9119     };
9120   };
9121   return waserr;
9122 }
9123 
9124 /*.......................................................................
9125  * This is a private function of gl_event_handler(), used to call a
9126  * inactivity timer callbacks.
9127  *
9128  * Input:
9129  *  gl       GetLine *  The resource object of gl_get_line().
9130  * Output:
9131  *  return       int    0 - OK.
9132  *                      1 - Error.
9133  */
9134 static int gl_call_timeout_handler(GetLine *gl)
9135 {
9136   Termios attr;       /* The terminal attributes */
9137   int waserr = 0;     /* True after any error */
9138 /*
9139  * Make sure that there is an inactivity timeout callback.
9140  */
9141   if(!gl->timer.fn)
9142     return 0;
9143 /*
9144  * Re-enable conversion of newline characters to carriage-return/linefeed,
9145  * so that the callback can write to the terminal without having to do
9146  * anything special.
9147  */
9148   if(tcgetattr(gl->input_fd, &attr)) {
9149     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9150     return 1;
9151   };
9152   attr.c_oflag |= OPOST;
9153   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9154     if(errno != EINTR) {
9155       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9156       return 1;
9157     };
9158   };
9159 /*
9160  * Invoke the application's callback function.
9161  */
9162   switch(gl->timer.fn(gl, gl->timer.data)) {
9163   default:
9164   case GLTO_ABORT:
9165     gl_record_status(gl, GLR_TIMEOUT, 0);
9166     waserr = 1;
9167     break;
9168   case GLTO_REFRESH:
9169     gl_queue_redisplay(gl);
9170     break;
9171   case GLTO_CONTINUE:
9172     break;
9173   };
9174 /*
9175  * Disable conversion of newline characters to carriage-return/linefeed.
9176  */
9177   attr.c_oflag &= ~(OPOST);
9178   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9179     if(errno != EINTR) {
9180       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9181       return 1;
9182     };
9183   };
9184   return waserr;
9185 }
9186 #endif  /* HAVE_SELECT */
9187 
9188 /*.......................................................................
9189  * Switch history groups. History groups represent separate history
9190  * lists recorded within a single history buffer. Different groups
9191  * are distinguished by integer identifiers chosen by the calling
9192  * appplicaton. Initially new_GetLine() sets the group identifier to
9193  * 0. Whenever a new line is appended to the history list, the current
9194  * group identifier is recorded with it, and history lookups only
9195  * consider lines marked with the current group identifier.
9196  *
9197  * Input:
9198  *  gl      GetLine *  The resource object of gl_get_line().
9199  *  id     unsigned    The new history group identifier.
9200  * Output:
9201  *  return      int    0 - OK.
9202  *                     1 - Error.
9203  */
9204 int gl_group_history(GetLine *gl, unsigned id)
9205 {
9206   sigset_t oldset; /* The signals that were blocked on entry to this function */
9207   int status;      /* The return status of this function */
9208 /*
9209  * Check the arguments.
9210  */
9211   if(!gl) {
9212     errno = EINVAL;
9213     return 1;
9214   };
9215 /*
9216  * Block all signals while we install the new configuration.
9217  */
9218   if(gl_mask_signals(gl, &oldset))
9219     return 1;
9220 /*
9221  * If the group isn't being changed, do nothing.
9222  */
9223   if(_glh_get_group(gl->glh) == id) {
9224     status = 0;
9225 /*
9226  * Establish the new group.
9227  */
9228   } else if(_glh_set_group(gl->glh, id)) {
9229     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9230     status = 1;
9231 /*
9232  * Prevent history information from the previous group being
9233  * inappropriately used by the next call to gl_get_line().
9234  */
9235   } else {
9236     gl->preload_history = 0;
9237     gl->last_search = -1;
9238     status = 0;
9239   };
9240 /*
9241  * Restore the process signal mask.
9242  */
9243   gl_unmask_signals(gl, &oldset);
9244   return status;
9245 }
9246 
9247 /*.......................................................................
9248  * Display the contents of the history list.
9249  *
9250  * Input:
9251  *  gl      GetLine *  The resource object of gl_get_line().
9252  *  fp         FILE *  The stdio output stream to write to.
9253  *  fmt  const char *  A format string. This containing characters to be
9254  *                     written verbatim, plus any of the following
9255  *                     format directives:
9256  *                       %D  -  The date, formatted like 2001-11-20
9257  *                       %T  -  The time of day, formatted like 23:59:59
9258  *                       %N  -  The sequential entry number of the
9259  *                              line in the history buffer.
9260  *                       %G  -  The number of the history group that
9261  *                              the line belongs to.
9262  *                       %%  -  A literal % character.
9263  *                       %H  -  The history line itself.
9264  *                     Note that a '\n' newline character is not
9265  *                     appended by default.
9266  *  all_groups  int    If true, display history lines from all
9267  *                     history groups. Otherwise only display
9268  *                     those of the current history group.
9269  *  max_lines   int    If max_lines is < 0, all available lines
9270  *                     are displayed. Otherwise only the most
9271  *                     recent max_lines lines will be displayed.
9272  * Output:
9273  *  return      int    0 - OK.
9274  *                     1 - Error.
9275  */
9276 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups,
9277 		    int max_lines)
9278 {
9279   sigset_t oldset; /* The signals that were blocked on entry to this function */
9280   int status;      /* The return status of this function */
9281 /*
9282  * Check the arguments.
9283  */
9284   if(!gl || !fp || !fmt) {
9285     if(gl)
9286       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
9287     errno = EINVAL;
9288     return 1;
9289   };
9290 /*
9291  * Block all signals.
9292  */
9293   if(gl_mask_signals(gl, &oldset))
9294     return 1;
9295 /*
9296  * Display the specified history group(s) while signals are blocked.
9297  */
9298   status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups,
9299 			     max_lines) || fflush(fp)==EOF;
9300   if(!status)
9301     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9302 /*
9303  * Restore the process signal mask.
9304  */
9305   gl_unmask_signals(gl, &oldset);
9306   return status;
9307 }
9308 
9309 /*.......................................................................
9310  * Update if necessary, and return the current size of the terminal.
9311  *
9312  * Input:
9313  *  gl            GetLine *  The resource object of gl_get_line().
9314  *  def_ncolumn       int    If the number of columns in the terminal
9315  *                           can't be determined, substitute this number.
9316  *  def_nline         int    If the number of lines in the terminal can't
9317  *                           be determined, substitute this number.
9318  * Output:
9319  *  return GlTerminalSize    The current terminal size.
9320  */
9321 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline)
9322 {
9323   GlTerminalSize size;  /* The object to be returned */
9324   sigset_t oldset;      /* The signals that were blocked on entry */
9325                         /*  to this function */
9326 /*
9327  * Block all signals while accessing gl.
9328  */
9329   gl_mask_signals(gl, &oldset);
9330 /*
9331  * Lookup/configure the terminal size.
9332  */
9333   _gl_terminal_size(gl, def_ncolumn, def_nline, &size);
9334 /*
9335  * Restore the process signal mask before returning.
9336  */
9337   gl_unmask_signals(gl, &oldset);
9338   return size;
9339 }
9340 
9341 /*.......................................................................
9342  * This is the private body of the gl_terminal_size() function. It
9343  * assumes that the caller has checked its arguments and blocked the
9344  * delivery of signals.
9345  */
9346 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
9347 			      GlTerminalSize *size)
9348 {
9349   const char *env;      /* The value of an environment variable */
9350   int n;                /* A number read from env[] */
9351 /*
9352  * Set the number of lines and columns to non-sensical values so that
9353  * we know later if they have been set.
9354  */
9355   gl->nline = 0;
9356   gl->ncolumn = 0;
9357 /*
9358  * Are we reading from a terminal?
9359  */
9360   if(gl->is_term) {
9361 /*
9362  * Ask the terminal directly if possible.
9363  */
9364     (void) _gl_update_size(gl);
9365 /*
9366  * If gl_update_size() couldn't ask the terminal, it will have
9367  * left gl->nrow and gl->ncolumn unchanged. If these values haven't
9368  * been changed from their initial values of zero, we need to find
9369  * a different method to get the terminal size.
9370  *
9371  * If the number of lines isn't known yet, first see if the
9372  * LINES environment ariable exists and specifies a believable number.
9373  * If this doesn't work, look up the default size in the terminal
9374  * information database.
9375  */
9376     if(gl->nline < 1) {
9377       if((env = getenv("LINES")) && (n=atoi(env)) > 0)
9378 	gl->nline = n;
9379 #ifdef USE_TERMINFO
9380       else
9381 	gl->nline = tigetnum((char *)"lines");
9382 #elif defined(USE_TERMCAP)
9383       else
9384         gl->nline = tgetnum("li");
9385 #endif
9386     };
9387 /*
9388  * If the number of lines isn't known yet, first see if the COLUMNS
9389  * environment ariable exists and specifies a believable number.  If
9390  * this doesn't work, look up the default size in the terminal
9391  * information database.
9392  */
9393     if(gl->ncolumn < 1) {
9394       if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0)
9395 	gl->ncolumn = n;
9396 #ifdef USE_TERMINFO
9397       else
9398 	gl->ncolumn = tigetnum((char *)"cols");
9399 #elif defined(USE_TERMCAP)
9400       else
9401 	gl->ncolumn = tgetnum("co");
9402 #endif
9403     };
9404   };
9405 /*
9406  * If we still haven't been able to acquire reasonable values, substitute
9407  * the default values specified by the caller.
9408  */
9409   if(gl->nline <= 0)
9410     gl->nline = def_nline;
9411   if(gl->ncolumn <= 0)
9412     gl->ncolumn = def_ncolumn;
9413 /*
9414  * Copy the new size into the return value.
9415  */
9416   if(size) {
9417     size->nline = gl->nline;
9418     size->ncolumn = gl->ncolumn;
9419   };
9420   return;
9421 }
9422 
9423 /*.......................................................................
9424  * Resize or delete the history buffer.
9425  *
9426  * Input:
9427  *  gl      GetLine *  The resource object of gl_get_line().
9428  *  bufsize  size_t    The number of bytes in the history buffer, or 0
9429  *                     to delete the buffer completely.
9430  * Output:
9431  *  return      int    0 - OK.
9432  *                     1 - Insufficient memory (the previous buffer
9433  *                         will have been retained). No error message
9434  *                         will be displayed.
9435  */
9436 int gl_resize_history(GetLine *gl, size_t bufsize)
9437 {
9438   sigset_t oldset; /* The signals that were blocked on entry to this function */
9439   int status;      /* The return status of this function */
9440 /*
9441  * Check the arguments.
9442  */
9443   if(!gl)
9444     return 1;
9445 /*
9446  * Block all signals while modifying the contents of gl.
9447  */
9448   if(gl_mask_signals(gl, &oldset))
9449     return 1;
9450 /*
9451  * Perform the resize while signals are blocked.
9452  */
9453   status = _glh_resize_history(gl->glh, bufsize);
9454   if(status)
9455     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9456 /*
9457  * Restore the process signal mask before returning.
9458  */
9459   gl_unmask_signals(gl, &oldset);
9460   return status;
9461 }
9462 
9463 /*.......................................................................
9464  * Set an upper limit to the number of lines that can be recorded in the
9465  * history list, or remove a previously specified limit.
9466  *
9467  * Input:
9468  *  gl      GetLine *  The resource object of gl_get_line().
9469  *  max_lines   int    The maximum number of lines to allow, or -1 to
9470  *                     cancel a previous limit and allow as many lines
9471  *                     as will fit in the current history buffer size.
9472  */
9473 void gl_limit_history(GetLine *gl, int max_lines)
9474 {
9475   if(gl) {
9476     sigset_t oldset; /* The signals that were blocked on entry to this block */
9477 /*
9478  * Temporarily block all signals.
9479  */
9480     gl_mask_signals(gl, &oldset);
9481 /*
9482  * Apply the limit while signals are blocked.
9483  */
9484     _glh_limit_history(gl->glh, max_lines);
9485 /*
9486  * Restore the process signal mask before returning.
9487  */
9488     gl_unmask_signals(gl, &oldset);
9489   };
9490 }
9491 
9492 /*.......................................................................
9493  * Discard either all historical lines, or just those associated with the
9494  * current history group.
9495  *
9496  * Input:
9497  *  gl      GetLine *  The resource object of gl_get_line().
9498  *  all_groups  int    If true, clear all of the history. If false,
9499  *                     clear only the stored lines associated with the
9500  *                     currently selected history group.
9501  */
9502 void gl_clear_history(GetLine *gl, int all_groups)
9503 {
9504   if(gl) {
9505     sigset_t oldset; /* The signals that were blocked on entry to this block */
9506 /*
9507  * Temporarily block all signals.
9508  */
9509     gl_mask_signals(gl, &oldset);
9510 /*
9511  * Clear the history buffer while signals are blocked.
9512  */
9513     _glh_clear_history(gl->glh, all_groups);
9514 /*
9515  * Restore the process signal mask before returning.
9516  */
9517     gl_unmask_signals(gl, &oldset);
9518   };
9519 }
9520 
9521 /*.......................................................................
9522  * Temporarily enable or disable the gl_get_line() history mechanism.
9523  *
9524  * Input:
9525  *  gl      GetLine *  The resource object of gl_get_line().
9526  *  enable      int    If true, turn on the history mechanism. If
9527  *                     false, disable it.
9528  */
9529 void gl_toggle_history(GetLine *gl, int enable)
9530 {
9531   if(gl) {
9532     sigset_t oldset; /* The signals that were blocked on entry to this block */
9533 /*
9534  * Temporarily block all signals.
9535  */
9536     gl_mask_signals(gl, &oldset);
9537 /*
9538  * Change the history recording mode while signals are blocked.
9539  */
9540     _glh_toggle_history(gl->glh, enable);
9541 /*
9542  * Restore the process signal mask before returning.
9543  */
9544     gl_unmask_signals(gl, &oldset);
9545   };
9546 }
9547 
9548 /*.......................................................................
9549  * Lookup a history line by its sequential number of entry in the
9550  * history buffer.
9551  *
9552  * Input:
9553  *  gl            GetLine *  The resource object of gl_get_line().
9554  *  id      unsigned long    The identification number of the line to
9555  *                           be returned, where 0 denotes the first line
9556  *                           that was entered in the history list, and
9557  *                           each subsequently added line has a number
9558  *                           one greater than the previous one. For
9559  *                           the range of lines currently in the list,
9560  *                           see the gl_range_of_history() function.
9561  * Input/Output:
9562  *  line    GlHistoryLine *  A pointer to the variable in which to
9563  *                           return the details of the line.
9564  * Output:
9565  *  return            int    0 - The line is no longer in the history
9566  *                               list, and *line has not been changed.
9567  *                           1 - The requested line can be found in
9568  *                               *line. Note that line->line is part
9569  *                               of the history buffer, so a
9570  *                               private copy should be made if you
9571  *                               wish to use it after subsequent calls
9572  *                               to any functions that take *gl as an
9573  *                               argument.
9574  */
9575 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line)
9576 {
9577   sigset_t oldset; /* The signals that were blocked on entry to this function */
9578   int status;      /* The return status of this function */
9579 /*
9580  * Check the arguments.
9581  */
9582   if(!gl)
9583     return 0;
9584 /*
9585  * Block all signals while modifying the contents of gl.
9586  */
9587   if(gl_mask_signals(gl, &oldset))
9588     return 1;
9589 /*
9590  * Perform the lookup while signals are blocked.
9591  */
9592   status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line,
9593 			       &line->group, &line->timestamp);
9594   if(status)
9595     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9596 /*
9597  * Restore the process signal mask before returning.
9598  */
9599   gl_unmask_signals(gl, &oldset);
9600   return status;
9601 }
9602 
9603 /*.......................................................................
9604  * Query the state of the history list. Note that any of the input/output
9605  * pointers can be specified as NULL.
9606  *
9607  * Input:
9608  *  gl            GetLine *  The resource object of gl_get_line().
9609  * Input/Output:
9610  *  state  GlHistoryState *  A pointer to the variable in which to record
9611  *                           the return values.
9612  */
9613 void gl_state_of_history(GetLine *gl, GlHistoryState *state)
9614 {
9615   if(gl && state) {
9616     sigset_t oldset; /* The signals that were blocked on entry to this block */
9617 /*
9618  * Temporarily block all signals.
9619  */
9620     gl_mask_signals(gl, &oldset);
9621 /*
9622  * Lookup the status while signals are blocked.
9623  */
9624     _glh_state_of_history(gl->glh, &state->enabled, &state->group,
9625 			  &state->max_lines);
9626 /*
9627  * Restore the process signal mask before returning.
9628  */
9629     gl_unmask_signals(gl, &oldset);
9630   };
9631 }
9632 
9633 /*.......................................................................
9634  * Query the number and range of lines in the history buffer.
9635  *
9636  * Input:
9637  *  gl            GetLine *  The resource object of gl_get_line().
9638  *  range  GlHistoryRange *  A pointer to the variable in which to record
9639  *                           the return values. If range->nline=0, the
9640  *                           range of lines will be given as 0-0.
9641  */
9642 void gl_range_of_history(GetLine *gl, GlHistoryRange *range)
9643 {
9644   if(gl && range) {
9645     sigset_t oldset; /* The signals that were blocked on entry to this block */
9646 /*
9647  * Temporarily block all signals.
9648  */
9649     gl_mask_signals(gl, &oldset);
9650 /*
9651  * Lookup the information while signals are blocked.
9652  */
9653     _glh_range_of_history(gl->glh, &range->oldest, &range->newest,
9654 			  &range->nlines);
9655 /*
9656  * Restore the process signal mask before returning.
9657  */
9658     gl_unmask_signals(gl, &oldset);
9659   };
9660 }
9661 
9662 /*.......................................................................
9663  * Return the size of the history buffer and the amount of the
9664  * buffer that is currently in use.
9665  *
9666  * Input:
9667  *  gl         GetLine *  The gl_get_line() resource object.
9668  * Input/Output:
9669  *  GlHistorySize size *  A pointer to the variable in which to return
9670  *                        the results.
9671  */
9672 void gl_size_of_history(GetLine *gl, GlHistorySize *size)
9673 {
9674   if(gl && size) {
9675     sigset_t oldset; /* The signals that were blocked on entry to this block */
9676 /*
9677  * Temporarily block all signals.
9678  */
9679     gl_mask_signals(gl, &oldset);
9680 /*
9681  * Lookup the information while signals are blocked.
9682  */
9683     _glh_size_of_history(gl->glh, &size->size, &size->used);
9684 /*
9685  * Restore the process signal mask before returning.
9686  */
9687     gl_unmask_signals(gl, &oldset);
9688   };
9689 }
9690 
9691 /*.......................................................................
9692  * This is the action function that lists the contents of the history
9693  * list.
9694  */
9695 static KT_KEY_FN(gl_list_history)
9696 {
9697 /*
9698  * Start a new line.
9699  */
9700   if(gl_start_newline(gl, 1))
9701     return 1;
9702 /*
9703  * List history lines that belong to the current group.
9704  */
9705   _glh_show_history(gl->glh, gl_write_fn, gl, "%N  %T   %H\r\n", 0,
9706 		    count<=1 ? -1 : count);
9707 /*
9708  * Arrange for the input line to be redisplayed.
9709  */
9710   gl_queue_redisplay(gl);
9711   return 0;
9712 }
9713 
9714 /*.......................................................................
9715  * Specify whether text that users type should be displayed or hidden.
9716  * In the latter case, only the prompt is displayed, and the final
9717  * input line is not archived in the history list.
9718  *
9719  * Input:
9720  *  gl         GetLine *  The gl_get_line() resource object.
9721  *  enable         int     0 - Disable echoing.
9722  *                         1 - Enable echoing.
9723  *                        -1 - Just query the mode without changing it.
9724  * Output:
9725  *  return         int    The echoing disposition that was in effect
9726  *                        before this function was called:
9727  *                         0 - Echoing was disabled.
9728  *                         1 - Echoing was enabled.
9729  */
9730 int gl_echo_mode(GetLine *gl, int enable)
9731 {
9732   if(gl) {
9733     sigset_t oldset; /* The signals that were blocked on entry to this block */
9734     int was_echoing; /* The echoing disposition on entry to this function */
9735 /*
9736  * Temporarily block all signals.
9737  */
9738     gl_mask_signals(gl, &oldset);
9739 /*
9740  * Install the new disposition while signals are blocked.
9741  */
9742     was_echoing = gl->echo;
9743     if(enable >= 0)
9744       gl->echo = enable;
9745 /*
9746  * Restore the process signal mask before returning.
9747  */
9748     gl_unmask_signals(gl, &oldset);
9749 /*
9750  * Return the original echoing disposition.
9751  */
9752     return was_echoing;
9753   };
9754   return 1;
9755 }
9756 
9757 /*.......................................................................
9758  * Display the prompt.
9759  *
9760  * Input:
9761  *  gl         GetLine *  The resource object of gl_get_line().
9762  * Output:
9763  *  return         int    0 - OK.
9764  *                        1 - Error.
9765  */
9766 static int gl_display_prompt(GetLine *gl)
9767 {
9768   const char *pptr;       /* A pointer into gl->prompt[] */
9769   unsigned old_attr=0;    /* The current text display attributes */
9770   unsigned new_attr=0;    /* The requested text display attributes */
9771 /*
9772  * Temporarily switch to echoing output characters.
9773  */
9774   int kept_echo = gl->echo;
9775   gl->echo = 1;
9776 /*
9777  * In case the screen got messed up, send a carriage return to
9778  * put the cursor at the beginning of the current terminal line.
9779  */
9780   if(gl_print_control_sequence(gl, 1, gl->bol))
9781     return 1;
9782 /*
9783  * Mark the line as partially displayed.
9784  */
9785   gl->displayed = 1;
9786 /*
9787  * Write the prompt, using the currently selected prompt style.
9788  */
9789   switch(gl->prompt_style) {
9790   case GL_LITERAL_PROMPT:
9791     if(gl_print_string(gl, gl->prompt, '\0'))
9792       return 1;
9793     break;
9794   case GL_FORMAT_PROMPT:
9795     for(pptr=gl->prompt; *pptr; pptr++) {
9796 /*
9797  * Does the latest character appear to be the start of a directive?
9798  */
9799       if(*pptr == '%') {
9800 /*
9801  * Check for and act on attribute changing directives.
9802  */
9803 	switch(pptr[1]) {
9804 /*
9805  * Add or remove a text attribute from the new set of attributes.
9806  */
9807 	case 'B': case 'U': case 'S': case 'P': case 'F': case 'V':
9808 	case 'b': case 'u': case 's': case 'p': case 'f': case 'v':
9809 	  switch(*++pptr) {
9810 	  case 'B':           /* Switch to a bold font */
9811 	    new_attr |= GL_TXT_BOLD;
9812 	    break;
9813 	  case 'b':           /* Switch to a non-bold font */
9814 	    new_attr &= ~GL_TXT_BOLD;
9815 	    break;
9816 	  case 'U':           /* Start underlining */
9817 	    new_attr |= GL_TXT_UNDERLINE;
9818 	    break;
9819 	  case 'u':           /* Stop underlining */
9820 	    new_attr &= ~GL_TXT_UNDERLINE;
9821 	    break;
9822 	  case 'S':           /* Start highlighting */
9823 	    new_attr |= GL_TXT_STANDOUT;
9824 	    break;
9825 	  case 's':           /* Stop highlighting */
9826 	    new_attr &= ~GL_TXT_STANDOUT;
9827 	    break;
9828 	  case 'P':           /* Switch to a pale font */
9829 	    new_attr |= GL_TXT_DIM;
9830 	    break;
9831 	  case 'p':           /* Switch to a non-pale font */
9832 	    new_attr &= ~GL_TXT_DIM;
9833 	    break;
9834 	  case 'F':           /* Switch to a flashing font */
9835 	    new_attr |= GL_TXT_BLINK;
9836 	    break;
9837 	  case 'f':           /* Switch to a steady font */
9838 	    new_attr &= ~GL_TXT_BLINK;
9839 	    break;
9840 	  case 'V':           /* Switch to reverse video */
9841 	    new_attr |= GL_TXT_REVERSE;
9842 	    break;
9843 	  case 'v':           /* Switch out of reverse video */
9844 	    new_attr &= ~GL_TXT_REVERSE;
9845 	    break;
9846 	  };
9847 	  continue;
9848 /*
9849  * A literal % is represented by %%. Skip the leading %.
9850  */
9851 	case '%':
9852 	  pptr++;
9853 	  break;
9854 	};
9855       };
9856 /*
9857  * Many terminals, when asked to turn off a single text attribute, turn
9858  * them all off, so the portable way to turn one off individually is to
9859  * explicitly turn them all off, then specify those that we want from
9860  * scratch.
9861  */
9862       if(old_attr & ~new_attr) {
9863 	if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9864 	  return 1;
9865 	old_attr = 0;
9866       };
9867 /*
9868  * Install new text attributes?
9869  */
9870       if(new_attr != old_attr) {
9871 	if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) &&
9872 	   gl_print_control_sequence(gl, 1, gl->bold))
9873 	  return 1;
9874 	if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) &&
9875 	   gl_print_control_sequence(gl, 1, gl->underline))
9876 	  return 1;
9877 	if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) &&
9878 	   gl_print_control_sequence(gl, 1, gl->standout))
9879 	  return 1;
9880 	if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) &&
9881 	   gl_print_control_sequence(gl, 1, gl->dim))
9882 	  return 1;
9883 	if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) &&
9884 	   gl_print_control_sequence(gl, 1, gl->reverse))
9885 	  return 1;
9886 	if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) &&
9887 	   gl_print_control_sequence(gl, 1, gl->blink))
9888 	  return 1;
9889 	old_attr = new_attr;
9890       };
9891 /*
9892  * Display the latest character.
9893  */
9894       if(gl_print_char(gl, *pptr, pptr[1]))
9895 	return 1;
9896     };
9897 /*
9898  * Turn off all text attributes now that we have finished drawing
9899  * the prompt.
9900  */
9901     if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9902       return 1;
9903     break;
9904   };
9905 /*
9906  * Restore the original echo mode.
9907  */
9908   gl->echo = kept_echo;
9909 /*
9910  * The prompt has now been displayed at least once.
9911  */
9912   gl->prompt_changed = 0;
9913   return 0;
9914 }
9915 
9916 /*.......................................................................
9917  * This function can be called from gl_get_line() callbacks to have
9918  * the prompt changed when they return. It has no effect if gl_get_line()
9919  * is not currently being invoked.
9920  *
9921  * Input:
9922  *  gl         GetLine *  The resource object of gl_get_line().
9923  *  prompt  const char *  The new prompt.
9924  */
9925 void gl_replace_prompt(GetLine *gl, const char *prompt)
9926 {
9927   if(gl) {
9928     sigset_t oldset; /* The signals that were blocked on entry to this block */
9929 /*
9930  * Temporarily block all signals.
9931  */
9932     gl_mask_signals(gl, &oldset);
9933 /*
9934  * Replace the prompt.
9935  */
9936     _gl_replace_prompt(gl, prompt);
9937 /*
9938  * Restore the process signal mask before returning.
9939  */
9940     gl_unmask_signals(gl, &oldset);
9941   };
9942 }
9943 
9944 /*.......................................................................
9945  * This is the private body of the gl_replace_prompt() function. It
9946  * assumes that the caller has checked its arguments and blocked the
9947  * delivery of signals.
9948  */
9949 static void _gl_replace_prompt(GetLine *gl, const char *prompt)
9950 {
9951   size_t size;
9952 
9953 /*
9954  * Substitute an empty prompt?
9955  */
9956   if(!prompt)
9957     prompt = "";
9958 /*
9959  * Gaurd against aliasing between prompt and gl->prompt.
9960  */
9961   if(gl->prompt != prompt) {
9962 /*
9963  * Get the length of the new prompt string.
9964  */
9965     size_t slen = strlen(prompt);
9966 /*
9967  * If needed, allocate a new buffer for the prompt string.
9968  */
9969     size = sizeof(char) * (slen + 1);
9970     if(!gl->prompt || slen > strlen(gl->prompt)) {
9971       char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size);
9972       if(!new_prompt)
9973 	return;
9974       gl->prompt = new_prompt;
9975     };
9976 /*
9977  * Make a copy of the new prompt.
9978  */
9979     strlcpy(gl->prompt, prompt, size);
9980   };
9981 /*
9982  * Record the statistics of the new prompt.
9983  */
9984   gl->prompt_len = gl_displayed_prompt_width(gl);
9985   gl->prompt_changed = 1;
9986   gl_queue_redisplay(gl);
9987   return;
9988 }
9989 
9990 /*.......................................................................
9991  * Work out the length of the current prompt on the terminal, according
9992  * to the current prompt formatting style.
9993  *
9994  * Input:
9995  *  gl       GetLine *  The resource object of this library.
9996  * Output:
9997  *  return       int    The number of displayed characters.
9998  */
9999 static int gl_displayed_prompt_width(GetLine *gl)
10000 {
10001   int slen=0;         /* The displayed number of characters */
10002   const char *pptr;   /* A pointer into prompt[] */
10003 /*
10004  * The length differs according to the prompt display style.
10005  */
10006   switch(gl->prompt_style) {
10007   case GL_LITERAL_PROMPT:
10008     return gl_displayed_string_width(gl, gl->prompt, -1, 0);
10009     break;
10010   case GL_FORMAT_PROMPT:
10011 /*
10012  * Add up the length of the displayed string, while filtering out
10013  * attribute directives.
10014  */
10015     for(pptr=gl->prompt; *pptr; pptr++) {
10016 /*
10017  * Does the latest character appear to be the start of a directive?
10018  */
10019       if(*pptr == '%') {
10020 /*
10021  * Check for and skip attribute changing directives.
10022  */
10023 	switch(pptr[1]) {
10024 	case 'B': case 'b': case 'U': case 'u': case 'S': case 's':
10025 	  pptr++;
10026 	  continue;
10027 /*
10028  * A literal % is represented by %%. Skip the leading %.
10029  */
10030 	case '%':
10031 	  pptr++;
10032 	  break;
10033 	};
10034       };
10035       slen += gl_displayed_char_width(gl, *pptr, slen);
10036     };
10037     break;
10038   };
10039   return slen;
10040 }
10041 
10042 /*.......................................................................
10043  * Specify whether to heed text attribute directives within prompt
10044  * strings.
10045  *
10046  * Input:
10047  *  gl           GetLine *  The resource object of gl_get_line().
10048  *  style  GlPromptStyle    The style of prompt (see the definition of
10049  *                          GlPromptStyle in libtecla.h for details).
10050  */
10051 void gl_prompt_style(GetLine *gl, GlPromptStyle style)
10052 {
10053   if(gl) {
10054     sigset_t oldset; /* The signals that were blocked on entry to this block */
10055 /*
10056  * Temporarily block all signals.
10057  */
10058     gl_mask_signals(gl, &oldset);
10059 /*
10060  * Install the new style in gl while signals are blocked.
10061  */
10062     if(style != gl->prompt_style) {
10063       gl->prompt_style = style;
10064       gl->prompt_len = gl_displayed_prompt_width(gl);
10065       gl->prompt_changed = 1;
10066       gl_queue_redisplay(gl);
10067     };
10068 /*
10069  * Restore the process signal mask before returning.
10070  */
10071     gl_unmask_signals(gl, &oldset);
10072   };
10073 }
10074 
10075 /*.......................................................................
10076  * Tell gl_get_line() how to respond to a given signal. This can be used
10077  * both to override the default responses to signals that gl_get_line()
10078  * normally catches and to add new signals to the list that are to be
10079  * caught.
10080  *
10081  * Input:
10082  *  gl           GetLine *  The resource object of gl_get_line().
10083  *  signo            int    The number of the signal to be caught.
10084  *  flags       unsigned    A bitwise union of GlSignalFlags enumerators.
10085  *  after  GlAfterSignal    What to do after the application's signal
10086  *                          handler has been called.
10087  *  errno_value      int    The value to set errno to.
10088  * Output:
10089  *  return           int    0 - OK.
10090  *                          1 - Error.
10091  */
10092 int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10093 		   GlAfterSignal after, int errno_value)
10094 {
10095   sigset_t oldset; /* The signals that were blocked on entry to this function */
10096   int status;      /* The return status of this function */
10097 /*
10098  * Check the arguments.
10099  */
10100   if(!gl) {
10101     errno = EINVAL;
10102     return 1;
10103   };
10104 /*
10105  * Block all signals while modifying the contents of gl.
10106  */
10107   if(gl_mask_signals(gl, &oldset))
10108     return 1;
10109 /*
10110  * Perform the modification while signals are blocked.
10111  */
10112   status = _gl_trap_signal(gl, signo, flags, after, errno_value);
10113 /*
10114  * Restore the process signal mask before returning.
10115  */
10116   gl_unmask_signals(gl, &oldset);
10117   return status;
10118 }
10119 
10120 /*.......................................................................
10121  * This is the private body of the gl_trap_signal() function. It
10122  * assumes that the caller has checked its arguments and blocked the
10123  * delivery of signals.
10124  */
10125 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10126 			   GlAfterSignal after, int errno_value)
10127 {
10128   GlSignalNode *sig;
10129 /*
10130  * Complain if an attempt is made to trap untrappable signals.
10131  * These would otherwise cause errors later in gl_mask_signals().
10132  */
10133   if(0
10134 #ifdef SIGKILL
10135      || signo==SIGKILL
10136 #endif
10137 #ifdef SIGBLOCK
10138      || signo==SIGBLOCK
10139 #endif
10140      ) {
10141     return 1;
10142   };
10143 /*
10144  * See if the signal has already been registered.
10145  */
10146   for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next)
10147     ;
10148 /*
10149  * If the signal hasn't already been registered, allocate a node for
10150  * it.
10151  */
10152   if(!sig) {
10153     sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem);
10154     if(!sig)
10155       return 1;
10156 /*
10157  * Add the new node to the head of the list.
10158  */
10159     sig->next = gl->sigs;
10160     gl->sigs = sig;
10161 /*
10162  * Record the signal number.
10163  */
10164     sig->signo = signo;
10165 /*
10166  * Create a signal set that includes just this signal.
10167  */
10168     sigemptyset(&sig->proc_mask);
10169     if(sigaddset(&sig->proc_mask, signo) == -1) {
10170       _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
10171       sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10172       return 1;
10173     };
10174 /*
10175  * Add the signal to the bit-mask of signals being trapped.
10176  */
10177     sigaddset(&gl->all_signal_set, signo);
10178   };
10179 /*
10180  * Record the new signal attributes.
10181  */
10182   sig->flags = flags;
10183   sig->after = after;
10184   sig->errno_value = errno_value;
10185   return 0;
10186 }
10187 
10188 /*.......................................................................
10189  * Remove a signal from the list of signals that gl_get_line() traps.
10190  *
10191  * Input:
10192  *  gl           GetLine *  The resource object of gl_get_line().
10193  *  signo            int    The number of the signal to be ignored.
10194  * Output:
10195  *  return           int    0 - OK.
10196  *                          1 - Error.
10197  */
10198 int gl_ignore_signal(GetLine *gl, int signo)
10199 {
10200   GlSignalNode *sig;  /* The gl->sigs list node of the specified signal */
10201   GlSignalNode *prev; /* The node that precedes sig in the list */
10202   sigset_t oldset;    /* The signals that were blocked on entry to this */
10203                       /*  function. */
10204 /*
10205  * Check the arguments.
10206  */
10207   if(!gl) {
10208     errno = EINVAL;
10209     return 1;
10210   };
10211 /*
10212  * Block all signals while modifying the contents of gl.
10213  */
10214   if(gl_mask_signals(gl, &oldset))
10215     return 1;
10216 /*
10217  * Find the node of the gl->sigs list which records the disposition
10218  * of the specified signal.
10219  */
10220   for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo;
10221       prev=sig,sig=sig->next)
10222     ;
10223   if(sig) {
10224 /*
10225  * Remove the node from the list.
10226  */
10227     if(prev)
10228       prev->next = sig->next;
10229     else
10230       gl->sigs = sig->next;
10231 /*
10232  * Return the node to the freelist.
10233  */
10234     sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10235 /*
10236  * Remove the signal from the bit-mask union of signals being trapped.
10237  */
10238     sigdelset(&gl->all_signal_set, signo);
10239   };
10240 /*
10241  * Restore the process signal mask before returning.
10242  */
10243   gl_unmask_signals(gl, &oldset);
10244   return 0;
10245 }
10246 
10247 /*.......................................................................
10248  * This function is called when an input line has been completed. It
10249  * appends the specified newline character, terminates the line,
10250  * records the line in the history buffer if appropriate, and positions
10251  * the terminal cursor at the start of the next line.
10252  *
10253  * Input:
10254  *  gl           GetLine *  The resource object of gl_get_line().
10255  *  newline_char     int    The newline character to add to the end
10256  *                          of the line.
10257  * Output:
10258  *  return           int    0 - OK.
10259  *                          1 - Error.
10260  */
10261 static int gl_line_ended(GetLine *gl, int newline_char)
10262 {
10263 /*
10264  * If the newline character is printable, display it at the end of
10265  * the line, and add it to the input line buffer.
10266  */
10267   if(isprint((int)(unsigned char) newline_char)) {
10268     if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char))
10269       return 1;
10270   } else {
10271 /*
10272  * Otherwise just append a newline character to the input line buffer.
10273  */
10274     newline_char = '\n';
10275     gl_buffer_char(gl, newline_char, gl->ntotal);
10276   };
10277 /*
10278  * Add the line to the history buffer if it was entered with a
10279  * newline character.
10280  */
10281   if(gl->echo && gl->automatic_history && newline_char=='\n')
10282     (void) _gl_append_history(gl, gl->line);
10283 /*
10284  * Except when depending on the system-provided line editing, start a new
10285  * line after the end of the line that has just been entered.
10286  */
10287   if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1))
10288     return 1;
10289 /*
10290  * Record the successful return status.
10291  */
10292   gl_record_status(gl, GLR_NEWLINE, 0);
10293 /*
10294  * Attempt to flush any pending output.
10295  */
10296   (void) gl_flush_output(gl);
10297 /*
10298  * The next call to gl_get_line() will write the prompt for a new line
10299  * (or continue the above flush if incomplete), so if we manage to
10300  * flush the terminal now, report that we are waiting to write to the
10301  * terminal.
10302  */
10303   gl->pending_io = GLP_WRITE;
10304   return 0;
10305 }
10306 
10307 /*.......................................................................
10308  * Return the last signal that was caught by the most recent call to
10309  * gl_get_line(), or -1 if no signals were caught. This is useful if
10310  * gl_get_line() returns errno=EINTR and you need to find out what signal
10311  * caused it to abort.
10312  *
10313  * Input:
10314  *  gl           GetLine *  The resource object of gl_get_line().
10315  * Output:
10316  *  return           int    The last signal caught by the most recent
10317  *                          call to gl_get_line(), or -1 if no signals
10318  *                          were caught.
10319  */
10320 int gl_last_signal(GetLine *gl)
10321 {
10322   int signo = -1;   /* The requested signal number */
10323   if(gl) {
10324     sigset_t oldset; /* The signals that were blocked on entry to this block */
10325 /*
10326  * Temporarily block all signals.
10327  */
10328     gl_mask_signals(gl, &oldset);
10329 /*
10330  * Access gl now that signals are blocked.
10331  */
10332     signo = gl->last_signal;
10333 /*
10334  * Restore the process signal mask before returning.
10335  */
10336     gl_unmask_signals(gl, &oldset);
10337   };
10338   return signo;
10339 }
10340 
10341 /*.......................................................................
10342  * Prepare to edit a new line.
10343  *
10344  * Input:
10345  *  gl         GetLine *  The resource object of this library.
10346  *  prompt        char *  The prompt to prefix the line with, or NULL to
10347  *                        use the same prompt that was used by the previous
10348  *                        line.
10349  *  start_line    char *  The initial contents of the input line, or NULL
10350  *                        if it should start out empty.
10351  *  start_pos      int    If start_line isn't NULL, this specifies the
10352  *                        index of the character over which the cursor
10353  *                        should initially be positioned within the line.
10354  *                        If you just want it to follow the last character
10355  *                        of the line, send -1.
10356  * Output:
10357  *  return    int    0 - OK.
10358  *                   1 - Error.
10359  */
10360 static int gl_present_line(GetLine *gl, const char *prompt,
10361 			   const char *start_line, int start_pos)
10362 {
10363 /*
10364  * Reset the properties of the line.
10365  */
10366   gl_reset_input_line(gl);
10367 /*
10368  * Record the new prompt and its displayed width.
10369  */
10370   if(prompt)
10371     _gl_replace_prompt(gl, prompt);
10372 /*
10373  * Reset the history search pointers.
10374  */
10375   if(_glh_cancel_search(gl->glh)) {
10376     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
10377     return 1;
10378   };
10379 /*
10380  * If the previous line was entered via the repeat-history action,
10381  * preload the specified history line.
10382  */
10383   if(gl->preload_history) {
10384     gl->preload_history = 0;
10385     if(gl->preload_id) {
10386       if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) {
10387 	gl_update_buffer(gl);          /* Compute gl->ntotal etc.. */
10388 	gl->buff_curpos = gl->ntotal;
10389       } else {
10390 	gl_truncate_buffer(gl, 0);
10391       };
10392       gl->preload_id = 0;
10393     };
10394 /*
10395  * Present a specified initial line?
10396  */
10397   } else if(start_line) {
10398     char *cptr;      /* A pointer into gl->line[] */
10399 /*
10400  * Measure the length of the starting line.
10401  */
10402     int start_len = strlen(start_line);
10403 /*
10404  * If the length of the line is greater than the available space,
10405  * truncate it.
10406  */
10407     if(start_len > gl->linelen)
10408       start_len = gl->linelen;
10409 /*
10410  * Load the line into the buffer.
10411  */
10412     if(start_line != gl->line)
10413       gl_buffer_string(gl, start_line, start_len, 0);
10414 /*
10415  * Strip off any trailing newline and carriage return characters.
10416  */
10417     for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line &&
10418 	(*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--)
10419       ;
10420     gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal);
10421 /*
10422  * Where should the cursor be placed within the line?
10423  */
10424     if(start_pos < 0 || start_pos > gl->ntotal) {
10425       if(gl_place_cursor(gl, gl->ntotal))
10426 	return 1;
10427     } else {
10428       if(gl_place_cursor(gl, start_pos))
10429 	return 1;
10430     };
10431 /*
10432  * Clear the input line?
10433  */
10434   } else {
10435     gl_truncate_buffer(gl, 0);
10436   };
10437 /*
10438  * Arrange for the line to be displayed by gl_flush_output().
10439  */
10440   gl_queue_redisplay(gl);
10441 /*
10442  * Update the display.
10443  */
10444   return gl_flush_output(gl);
10445 }
10446 
10447 /*.......................................................................
10448  * Reset all line input parameters for a new input line.
10449  *
10450  * Input:
10451  *  gl      GetLine *  The line editor resource object.
10452  */
10453 static void gl_reset_input_line(GetLine *gl)
10454 {
10455   gl->ntotal = 0;
10456   gl->line[0] = '\0';
10457   gl->buff_curpos = 0;
10458   gl->term_curpos = 0;
10459   gl->term_len = 0;
10460   gl->insert_curpos = 0;
10461   gl->number = -1;
10462   gl->displayed = 0;
10463   gl->endline = 0;
10464   gl->redisplay = 0;
10465   gl->postpone = 0;
10466   gl->nbuf = 0;
10467   gl->nread = 0;
10468   gl->vi.command = 0;
10469   gl->vi.undo.line[0] = '\0';
10470   gl->vi.undo.ntotal = 0;
10471   gl->vi.undo.buff_curpos = 0;
10472   gl->vi.repeat.action.fn = 0;
10473   gl->vi.repeat.action.data = 0;
10474   gl->last_signal = -1;
10475 }
10476 
10477 /*.......................................................................
10478  * Print an informational message to the terminal, after starting a new
10479  * line.
10480  *
10481  * Input:
10482  *  gl      GetLine *  The line editor resource object.
10483  *  ...  const char *  Zero or more strings to be printed.
10484  *  ...        void *  The last argument must always be GL_END_INFO.
10485  * Output:
10486  *  return      int    0 - OK.
10487  *                     1 - Error.
10488  */
10489 static int gl_print_info(GetLine *gl, ...)
10490 {
10491   va_list ap;     /* The variable argument list */
10492   const char *s;  /* The string being printed */
10493   int waserr = 0; /* True after an error */
10494 /*
10495  * Only display output when echoing is on.
10496  */
10497   if(gl->echo) {
10498 /*
10499  * Skip to the start of the next empty line before displaying the message.
10500  */
10501     if(gl_start_newline(gl, 1))
10502       return 1;
10503 /*
10504  * Display the list of provided messages.
10505  */
10506     va_start(ap, gl);
10507     while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO)
10508       waserr = gl_print_raw_string(gl, 1, s, -1);
10509     va_end(ap);
10510 /*
10511  * Start a newline.
10512  */
10513     waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1);
10514 /*
10515  * Arrange for the input line to be redrawn.
10516  */
10517     gl_queue_redisplay(gl);
10518   };
10519   return waserr;
10520 }
10521 
10522 /*.......................................................................
10523  * Go to the start of the next empty line, ready to output miscellaneous
10524  * text to the screen.
10525  *
10526  * Note that when async-signal safety is required, the 'buffered'
10527  * argument must be 0.
10528  *
10529  * Input:
10530  *  gl          GetLine *  The line editor resource object.
10531  *  buffered        int    If true, used buffered I/O when writing to
10532  *                         the terminal. Otherwise use async-signal-safe
10533  *                         unbuffered I/O.
10534  * Output:
10535  *  return          int    0 - OK.
10536  *                         1 - Error.
10537  */
10538 static int gl_start_newline(GetLine *gl, int buffered)
10539 {
10540   int waserr = 0;  /* True after any I/O error */
10541 /*
10542  * Move the cursor to the start of the terminal line that follows the
10543  * last line of the partially enterred line. In order that this
10544  * function remain async-signal safe when write_fn is signal safe, we
10545  * can't call our normal output functions, since they call tputs(),
10546  * who's signal saftey isn't defined. Fortunately, we can simply use
10547  * \r and \n to move the cursor to the right place.
10548  */
10549   if(gl->displayed) {   /* Is an input line currently displayed? */
10550 /*
10551  * On which terminal lines are the cursor and the last character of the
10552  * input line?
10553  */
10554     int curs_line = gl->term_curpos / gl->ncolumn;
10555     int last_line = gl->term_len / gl->ncolumn;
10556 /*
10557  * Move the cursor to the start of the line that follows the last
10558  * terminal line that is occupied by the input line.
10559  */
10560     for( ; curs_line < last_line + 1; curs_line++)
10561       waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1);
10562     waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1);
10563 /*
10564  * Mark the line as no longer displayed.
10565  */
10566     gl_line_erased(gl);
10567   };
10568   return waserr;
10569 }
10570 
10571 /*.......................................................................
10572  * The callback through which all terminal output is routed.
10573  * This simply appends characters to a queue buffer, which is
10574  * subsequently flushed to the output channel by gl_flush_output().
10575  *
10576  * Input:
10577  *  data     void *  The pointer to a GetLine line editor resource object
10578  *                   cast to (void *).
10579  *  s  const char *  The string to be written.
10580  *  n         int    The number of characters to write from s[].
10581  * Output:
10582  *  return    int    The number of characters written. This will always
10583  *                   be equal to 'n' unless an error occurs.
10584  */
10585 static GL_WRITE_FN(gl_write_fn)
10586 {
10587   GetLine *gl = (GetLine *) data;
10588   int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl);
10589   if(ndone != n)
10590     _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG);
10591   return ndone;
10592 }
10593 
10594 /*.......................................................................
10595  * Ask gl_get_line() what caused it to return.
10596  *
10597  * Input:
10598  *  gl             GetLine *  The line editor resource object.
10599  * Output:
10600  *  return  GlReturnStatus    The return status of the last call to
10601  *                            gl_get_line().
10602  */
10603 GlReturnStatus gl_return_status(GetLine *gl)
10604 {
10605   GlReturnStatus rtn_status = GLR_ERROR;   /* The requested status */
10606   if(gl) {
10607     sigset_t oldset; /* The signals that were blocked on entry to this block */
10608 /*
10609  * Temporarily block all signals.
10610  */
10611     gl_mask_signals(gl, &oldset);
10612 /*
10613  * Access gl while signals are blocked.
10614  */
10615     rtn_status = gl->rtn_status;
10616 /*
10617  * Restore the process signal mask before returning.
10618  */
10619     gl_unmask_signals(gl, &oldset);
10620   };
10621   return rtn_status;
10622 }
10623 
10624 /*.......................................................................
10625  * In non-blocking server-I/O mode, this function should be called
10626  * from the application's external event loop to see what type of
10627  * terminal I/O is being waited for by gl_get_line(), and thus what
10628  * direction of I/O to wait for with select() or poll().
10629  *
10630  * Input:
10631  *  gl          GetLine *  The resource object of gl_get_line().
10632  * Output:
10633  *  return  GlPendingIO    The type of pending I/O being waited for.
10634  */
10635 GlPendingIO gl_pending_io(GetLine *gl)
10636 {
10637   GlPendingIO pending_io = GLP_WRITE;   /* The requested information */
10638   if(gl) {
10639     sigset_t oldset; /* The signals that were blocked on entry to this block */
10640 /*
10641  * Temporarily block all signals.
10642  */
10643     gl_mask_signals(gl, &oldset);
10644 /*
10645  * Access gl while signals are blocked.
10646  */
10647     pending_io = gl->pending_io;
10648 /*
10649  * Restore the process signal mask before returning.
10650  */
10651     gl_unmask_signals(gl, &oldset);
10652   };
10653   return pending_io;
10654 }
10655 
10656 /*.......................................................................
10657  * In server mode, this function configures the terminal for non-blocking
10658  * raw terminal I/O. In normal I/O mode it does nothing.
10659  *
10660  * Callers of this function must be careful to trap all signals that
10661  * terminate or suspend the program, and call gl_normal_io()
10662  * from the corresponding signal handlers in order to restore the
10663  * terminal to its original settings before the program is terminated
10664  * or suspended. They should also trap the SIGCONT signal to detect
10665  * when the program resumes, and ensure that its signal handler
10666  * call gl_raw_io() to redisplay the line and resume editing.
10667  *
10668  * This function is async signal safe.
10669  *
10670  * Input:
10671  *  gl      GetLine *  The line editor resource object.
10672  * Output:
10673  *  return      int    0 - OK.
10674  *                     1 - Error.
10675  */
10676 int gl_raw_io(GetLine *gl)
10677 {
10678   sigset_t oldset; /* The signals that were blocked on entry to this function */
10679   int status;      /* The return status of _gl_raw_io() */
10680 /*
10681  * Check the arguments.
10682  */
10683   if(!gl) {
10684     errno = EINVAL;
10685     return 1;
10686   };
10687 /*
10688  * Block all signals.
10689  */
10690   if(gl_mask_signals(gl, &oldset))
10691     return 1;
10692 /*
10693  * Don't allow applications to switch into raw mode unless in server mode.
10694  */
10695   if(gl->io_mode != GL_SERVER_MODE) {
10696     _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode",
10697 		    END_ERR_MSG);
10698     errno = EPERM;
10699     status = 1;
10700   } else {
10701 /*
10702  * Execute the private body of the function while signals are blocked.
10703  */
10704     status = _gl_raw_io(gl, 1);
10705   };
10706 /*
10707  * Restore the process signal mask.
10708  */
10709   gl_unmask_signals(gl, &oldset);
10710   return status;
10711 }
10712 
10713 /*.......................................................................
10714  * This is the private body of the public function, gl_raw_io().
10715  * It assumes that the caller has checked its arguments and blocked the
10716  * delivery of signals.
10717  *
10718  * This function is async signal safe.
10719  */
10720 static int _gl_raw_io(GetLine *gl, int redisplay)
10721 {
10722 /*
10723  * If we are already in the correct mode, do nothing.
10724  */
10725   if(gl->raw_mode)
10726     return 0;
10727 /*
10728  * Switch the terminal to raw mode.
10729  */
10730   if(gl->is_term && gl_raw_terminal_mode(gl))
10731     return 1;
10732 /*
10733  * Switch to non-blocking I/O mode?
10734  */
10735   if(gl->io_mode==GL_SERVER_MODE &&
10736      (gl_nonblocking_io(gl, gl->input_fd) ||
10737       gl_nonblocking_io(gl, gl->output_fd) ||
10738       (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) {
10739     if(gl->is_term)
10740       gl_restore_terminal_attributes(gl);
10741     return 1;
10742   };
10743 /*
10744  * If an input line is being entered, arrange for it to be
10745  * displayed.
10746  */
10747   if(redisplay) {
10748     gl->postpone = 0;
10749     gl_queue_redisplay(gl);
10750   };
10751   return 0;
10752 }
10753 
10754 /*.......................................................................
10755  * Restore the terminal to the state that it had when
10756  * gl_raw_io() was last called. After calling
10757  * gl_raw_io(), this function must be called before
10758  * terminating or suspending the program, and before attempting other
10759  * uses of the terminal from within the program. See gl_raw_io()
10760  * for more details.
10761  *
10762  * Input:
10763  *  gl      GetLine *  The line editor resource object.
10764  * Output:
10765  *  return      int    0 - OK.
10766  *                     1 - Error.
10767  */
10768 int gl_normal_io(GetLine *gl)
10769 {
10770   sigset_t oldset; /* The signals that were blocked on entry to this function */
10771   int status;      /* The return status of _gl_normal_io() */
10772 /*
10773  * Check the arguments.
10774  */
10775   if(!gl) {
10776     errno = EINVAL;
10777     return 1;
10778   };
10779 /*
10780  * Block all signals.
10781  */
10782   if(gl_mask_signals(gl, &oldset))
10783     return 1;
10784 /*
10785  * Execute the private body of the function while signals are blocked.
10786  */
10787   status = _gl_normal_io(gl);
10788 /*
10789  * Restore the process signal mask.
10790  */
10791   gl_unmask_signals(gl, &oldset);
10792   return status;
10793 }
10794 
10795 /*.......................................................................
10796  * This is the private body of the public function, gl_normal_io().
10797  * It assumes that the caller has checked its arguments and blocked the
10798  * delivery of signals.
10799  */
10800 static int _gl_normal_io(GetLine *gl)
10801 {
10802 /*
10803  * If we are already in normal mode, do nothing.
10804  */
10805   if(!gl->raw_mode)
10806     return 0;
10807 /*
10808  * Postpone subsequent redisplays until after _gl_raw_io(gl, 1)
10809  * is next called.
10810  */
10811   gl->postpone = 1;
10812 /*
10813  * Switch back to blocking I/O. Note that this is essential to do
10814  * here, because when using non-blocking I/O, the terminal output
10815  * buffering code can't always make room for new output without calling
10816  * malloc(), and a call to malloc() would mean that this function
10817  * couldn't safely be called from signal handlers.
10818  */
10819   if(gl->io_mode==GL_SERVER_MODE &&
10820      (gl_blocking_io(gl, gl->input_fd) ||
10821       gl_blocking_io(gl, gl->output_fd) ||
10822       (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp)))))
10823     return 1;
10824 /*
10825  * Move the cursor to the next empty terminal line. Note that
10826  * unbuffered I/O is requested, to ensure that gl_start_newline() be
10827  * async-signal-safe.
10828  */
10829   if(gl->is_term && gl_start_newline(gl, 0))
10830     return 1;
10831 /*
10832  * Switch the terminal to normal mode.
10833  */
10834   if(gl->is_term && gl_restore_terminal_attributes(gl)) {
10835 /*
10836  * On error, revert to non-blocking I/O if needed, so that on failure
10837  * we remain in raw mode.
10838  */
10839     if(gl->io_mode==GL_SERVER_MODE) {
10840       gl_nonblocking_io(gl, gl->input_fd);
10841       gl_nonblocking_io(gl, gl->output_fd);
10842       if(gl->file_fp)
10843 	gl_nonblocking_io(gl, fileno(gl->file_fp));
10844     };
10845     return 1;
10846   };
10847   return 0;
10848 }
10849 
10850 /*.......................................................................
10851  * This function allows you to install an additional completion
10852  * action, or to change the completion function of an existing
10853  * one. This should be called before the first call to gl_get_line()
10854  * so that the name of the action be defined before the user's
10855  * configuration file is read.
10856  *
10857  * Input:
10858  *  gl            GetLine *  The resource object of the command-line input
10859  *                           module.
10860  *  data             void *  This is passed to match_fn() whenever it is
10861  *                           called. It could, for example, point to a
10862  *                           symbol table that match_fn() would look up
10863  *                           matches in.
10864  *  match_fn   CplMatchFn *  The function that will identify the prefix
10865  *                           to be completed from the input line, and
10866  *                           report matching symbols.
10867  *  list_only         int    If non-zero, install an action that only lists
10868  *                           possible completions, rather than attempting
10869  *                           to perform the completion.
10870  *  name       const char *  The name with which users can refer to the
10871  *                           binding in tecla configuration files.
10872  *  keyseq     const char *  Either NULL, or a key sequence with which
10873  *                           to invoke the binding. This should be
10874  *                           specified in the same manner as key-sequences
10875  *                           in tecla configuration files (eg. "M-^I").
10876  * Output:
10877  *  return            int    0 - OK.
10878  *                           1 - Error.
10879  */
10880 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10881 			 int list_only, const char *name, const char *keyseq)
10882 {
10883   sigset_t oldset; /* The signals that were blocked on entry to this function */
10884   int status;      /* The return status of _gl_completion_action() */
10885 /*
10886  * Check the arguments.
10887  */
10888   if(!gl || !name || !match_fn) {
10889     errno = EINVAL;
10890     return 1;
10891   };
10892 /*
10893  * Block all signals.
10894  */
10895   if(gl_mask_signals(gl, &oldset))
10896     return 1;
10897 /*
10898  * Install the new action while signals are blocked.
10899  */
10900   status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq);
10901 /*
10902  * Restore the process signal mask.
10903  */
10904   gl_unmask_signals(gl, &oldset);
10905   return status;
10906 }
10907 
10908 /*.......................................................................
10909  * This is the private body of the public function, gl_completion_action().
10910  * It assumes that the caller has checked its arguments and blocked the
10911  * delivery of signals.
10912  */
10913 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10914 				 int list_only, const char *name,
10915 				 const char *keyseq)
10916 {
10917   KtKeyFn *current_fn;      /* An existing action function */
10918   void *current_data;       /* The action-function callback data */
10919 /*
10920  * Which action function is desired?
10921  */
10922   KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word;
10923 /*
10924  * Is there already an action of the specified name?
10925  */
10926   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
10927 /*
10928  * If the action has the same type as the one being requested,
10929  * simply change the contents of its GlCplCallback callback data.
10930  */
10931     if(current_fn == action_fn) {
10932       GlCplCallback *cb = (GlCplCallback *) current_data;
10933       cb->fn = match_fn;
10934       cb->data = data;
10935     } else {
10936       errno = EINVAL;
10937       _err_record_msg(gl->err,
10938         "Illegal attempt to change the type of an existing completion action",
10939         END_ERR_MSG);
10940       return 1;
10941     };
10942 /*
10943  * No existing action has the specified name.
10944  */
10945   } else {
10946 /*
10947  * Allocate a new GlCplCallback callback object.
10948  */
10949     GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem);
10950     if(!cb) {
10951       errno = ENOMEM;
10952       _err_record_msg(gl->err, "Insufficient memory to add completion action",
10953 		      END_ERR_MSG);
10954       return 1;
10955     };
10956 /*
10957  * Record the completion callback data.
10958  */
10959     cb->fn = match_fn;
10960     cb->data = data;
10961 /*
10962  * Attempt to register the new action.
10963  */
10964     if(_kt_set_action(gl->bindings, name, action_fn, cb)) {
10965       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10966       _del_FreeListNode(gl->cpl_mem, (void *) cb);
10967       return 1;
10968     };
10969   };
10970 /*
10971  * Bind the action to a given key-sequence?
10972  */
10973   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
10974     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10975     return 1;
10976   };
10977   return 0;
10978 }
10979 
10980 /*.......................................................................
10981  * Register an application-provided function as an action function.
10982  * This should preferably be called before the first call to gl_get_line()
10983  * so that the name of the action becomes defined before the user's
10984  * configuration file is read.
10985  *
10986  * Input:
10987  *  gl            GetLine *  The resource object of the command-line input
10988  *                           module.
10989  *  data             void *  Arbitrary application-specific callback
10990  *                           data to be passed to the callback
10991  *                           function, fn().
10992  *  fn         GlActionFn *  The application-specific function that
10993  *                           implements the action. This will be invoked
10994  *                           whenever the user presses any
10995  *                           key-sequence which is bound to this action.
10996  *  name       const char *  The name with which users can refer to the
10997  *                           binding in tecla configuration files.
10998  *  keyseq     const char *  The key sequence with which to invoke
10999  *                           the binding. This should be specified in the
11000  *                           same manner as key-sequences in tecla
11001  *                           configuration files (eg. "M-^I").
11002  * Output:
11003  *  return            int    0 - OK.
11004  *                           1 - Error.
11005  */
11006 int gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11007                        const char *name, const char *keyseq)
11008 {
11009   sigset_t oldset; /* The signals that were blocked on entry to this function */
11010   int status;      /* The return status of _gl_register_action() */
11011 /*
11012  * Check the arguments.
11013  */
11014   if(!gl || !name || !fn) {
11015     errno = EINVAL;
11016     return 1;
11017   };
11018 /*
11019  * Block all signals.
11020  */
11021   if(gl_mask_signals(gl, &oldset))
11022     return 1;
11023 /*
11024  * Install the new action while signals are blocked.
11025  */
11026   status = _gl_register_action(gl, data, fn, name, keyseq);
11027 /*
11028  * Restore the process signal mask.
11029  */
11030   gl_unmask_signals(gl, &oldset);
11031   return status;
11032 }
11033 
11034 /*.......................................................................
11035  * This is the private body of the public function, gl_register_action().
11036  * It assumes that the caller has checked its arguments and blocked the
11037  * delivery of signals.
11038  */
11039 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11040 			       const char *name, const char *keyseq)
11041 {
11042   KtKeyFn *current_fn;      /* An existing action function */
11043   void *current_data;       /* The action-function callback data */
11044 /*
11045  * Get the action function which actually runs the application-provided
11046  * function.
11047  */
11048   KtKeyFn *action_fn = gl_run_external_action;
11049 /*
11050  * Is there already an action of the specified name?
11051  */
11052   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
11053 /*
11054  * If the action has the same type as the one being requested,
11055  * simply change the contents of its GlCplCallback callback data.
11056  */
11057     if(current_fn == action_fn) {
11058       GlExternalAction *a = (GlExternalAction *) current_data;
11059       a->fn = fn;
11060       a->data = data;
11061     } else {
11062       errno = EINVAL;
11063       _err_record_msg(gl->err,
11064         "Illegal attempt to change the type of an existing action",
11065 		      END_ERR_MSG);
11066       return 1;
11067     };
11068 /*
11069  * No existing action has the specified name.
11070  */
11071   } else {
11072 /*
11073  * Allocate a new GlCplCallback callback object.
11074  */
11075     GlExternalAction *a =
11076       (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem);
11077     if(!a) {
11078       errno = ENOMEM;
11079       _err_record_msg(gl->err, "Insufficient memory to add completion action",
11080 		      END_ERR_MSG);
11081       return 1;
11082     };
11083 /*
11084  * Record the completion callback data.
11085  */
11086     a->fn = fn;
11087     a->data = data;
11088 /*
11089  * Attempt to register the new action.
11090  */
11091     if(_kt_set_action(gl->bindings, name, action_fn, a)) {
11092       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11093       _del_FreeListNode(gl->cpl_mem, (void *) a);
11094       return 1;
11095     };
11096   };
11097 /*
11098  * Bind the action to a given key-sequence?
11099  */
11100   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
11101     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11102     return 1;
11103   };
11104   return 0;
11105 }
11106 
11107 /*.......................................................................
11108  * Invoke an action function previously registered by a call to
11109  * gl_register_action().
11110  */
11111 static KT_KEY_FN(gl_run_external_action)
11112 {
11113   GlAfterAction status;  /* The return value of the action function */
11114 /*
11115  * Get the container of the action function and associated callback data.
11116  */
11117   GlExternalAction *a = (GlExternalAction *) data;
11118 /*
11119  * Invoke the action function.
11120  */
11121   status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line);
11122 /*
11123  * If the callback took us out of raw (possibly non-blocking) input
11124  * mode, restore this mode, and queue a redisplay of the input line.
11125  */
11126   if(_gl_raw_io(gl, 1))
11127     return 1;
11128 /*
11129  * Finally, check to see what the action function wants us to do next.
11130  */
11131   switch(status) {
11132   default:
11133   case GLA_ABORT:
11134     gl_record_status(gl, GLR_ERROR, errno);
11135     return 1;
11136     break;
11137   case GLA_RETURN:
11138     return gl_newline(gl, 1, NULL);
11139     break;
11140   case GLA_CONTINUE:
11141     break;
11142   };
11143   return 0;
11144 }
11145 
11146 /*.......................................................................
11147  * In server-I/O mode the terminal is left in raw mode between calls
11148  * to gl_get_line(), so it is necessary for the application to install
11149  * terminal restoring signal handlers for signals that could terminate
11150  * or suspend the process, plus a terminal reconfiguration handler to
11151  * be called when a process resumption signal is received, and finally
11152  * a handler to be called when a terminal-resize signal is received.
11153  *
11154  * Since there are many signals that by default terminate or suspend
11155  * processes, and different systems support different sub-sets of
11156  * these signals, this function provides a convenient wrapper around
11157  * sigaction() for assigning the specified handlers to all appropriate
11158  * signals. It also arranges that when any one of these signals is
11159  * being handled, all other catchable signals are blocked. This is
11160  * necessary so that the specified signal handlers can safely call
11161  * gl_raw_io(), gl_normal_io() and gl_update_size() without
11162  * reentrancy issues.
11163  *
11164  * Input:
11165  *  term_handler  void (*)(int)  The signal handler to invoke when
11166  *                               a process terminating signal is
11167  *                               received.
11168  *  susp_handler  void (*)(int)  The signal handler to invoke when
11169  *                               a process suspending signal is
11170  *                               received.
11171  *  cont_handler  void (*)(int)  The signal handler to invoke when
11172  *                               a process resumption signal is
11173  *                               received (ie. SIGCONT).
11174  *  size_handler  void (*)(int)  The signal handler to invoke when
11175  *                               a terminal-resize signal (ie. SIGWINCH)
11176  *                               is received.
11177  * Output:
11178  *  return                  int  0 - OK.
11179  *                               1 - Error.
11180  */
11181 int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int),
11182 		   void (*cont_handler)(int), void (*size_handler)(int))
11183 {
11184   int i;
11185 /*
11186  * Search for signals of the specified classes, and assign the
11187  * associated signal handler to them.
11188  */
11189   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11190     const struct GlDefSignal *sig = gl_signal_list + i;
11191     if(sig->attr & GLSA_SUSP) {
11192       if(gl_set_tty_signal(sig->signo, term_handler))
11193 	return 1;
11194     } else if(sig->attr & GLSA_TERM) {
11195       if(gl_set_tty_signal(sig->signo, susp_handler))
11196 	return 1;
11197     } else if(sig->attr & GLSA_CONT) {
11198       if(gl_set_tty_signal(sig->signo, cont_handler))
11199 	return 1;
11200     } else if(sig->attr & GLSA_SIZE) {
11201       if(gl_set_tty_signal(sig->signo, size_handler))
11202 	return 1;
11203     };
11204   };
11205   return 0;
11206 }
11207 
11208 /*.......................................................................
11209  * This is a private function of gl_tty_signals(). It installs a given
11210  * signal handler, and arranges that when that signal handler is being
11211  * invoked other signals are blocked. The latter is important to allow
11212  * functions like gl_normal_io(), gl_raw_io() and gl_update_size()
11213  * to be called from signal handlers.
11214  *
11215  * Input:
11216  *  signo     int           The signal to be trapped.
11217  *  handler  void (*)(int)  The signal handler to assign to the signal.
11218  */
11219 static int gl_set_tty_signal(int signo, void (*handler)(int))
11220 {
11221   SigAction act;   /* The signal handler configuation */
11222 /*
11223  * Arrange to block all trappable signals except the one that is being
11224  * assigned (the trapped signal will be blocked automatically by the
11225  * system).
11226  */
11227   gl_list_trappable_signals(&act.sa_mask);
11228   sigdelset(&act.sa_mask, signo);
11229 /*
11230  * Assign the signal handler.
11231  */
11232   act.sa_handler = handler;
11233 /*
11234  * There is only one portable signal handling flag, and it isn't
11235  * relevant to us, so don't specify any flags.
11236  */
11237   act.sa_flags = 0;
11238 /*
11239  * Register the signal handler.
11240  */
11241   if(sigaction(signo, &act, NULL))
11242     return 1;
11243   return 0;
11244 }
11245 
11246 /*.......................................................................
11247  * Display a left-justified string over multiple terminal lines,
11248  * taking account of the current width of the terminal. Optional
11249  * indentation and an optional prefix string can be specified to be
11250  * displayed at the start of each new terminal line used. Similarly,
11251  * an optional suffix can be specified to be displayed at the end of
11252  * each terminal line.  If needed, a single paragraph can be broken
11253  * across multiple calls.  Note that literal newlines in the input
11254  * string can be used to force a newline at any point and that you
11255  * should use this feature to explicitly end all paragraphs, including
11256  * at the end of the last string that you write. Note that when a new
11257  * line is started between two words that are separated by spaces,
11258  * those spaces are not output, whereas when a new line is started
11259  * because a newline character was found in the string, only the
11260  * spaces before the newline character are discarded.
11261  *
11262  * Input:
11263  *  gl         GetLine *  The resource object of gl_get_line().
11264  *  indentation    int    The number of spaces of indentation to write
11265  *                        at the beginning of each new terminal line.
11266  *  prefix  const char *  An optional prefix string to write after the
11267  *                        indentation margin at the start of each new
11268  *                        terminal line. You can specify NULL if no
11269  *                        prefix is required.
11270  *  suffix  const char *  An optional suffix string to draw at the end
11271  *                        of the terminal line. Spaces will be added
11272  *                        where necessary to ensure that the suffix ends
11273  *                        in the last column of the terminal line. If
11274  *                        no suffix is desired, specify NULL.
11275  *  fill_char      int    The padding character to use when indenting
11276  *                        the line or padding up to the suffix.
11277  *  def_width      int    If the terminal width isn't known, such as when
11278  *                        writing to a pipe or redirecting to a file,
11279  *                        this number specifies what width to assume.
11280  *  start          int    The number of characters already written to
11281  *                        the start of the current terminal line. This
11282  *                        is primarily used to allow individual
11283  *                        paragraphs to be written over multiple calls
11284  *                        to this function, but can also be used to
11285  *                        allow you to start the first line of a
11286  *                        paragraph with a different prefix or
11287  *                        indentation than those specified above.
11288  *  string  const char *  The string to be written.
11289  * Output:
11290  *  return         int    On error -1 is returned. Otherwise the
11291  *                        return value is the terminal column index at
11292  *                        which the cursor was left after writing the
11293  *                        final word in the string. Successful return
11294  *                        values can thus be passed verbatim to the
11295  *                        'start' arguments of subsequent calls to
11296  *                        gl_display_text() to allow the printing of a
11297  *                        paragraph to be broken across multiple calls
11298  *                        to gl_display_text().
11299  */
11300 int gl_display_text(GetLine *gl, int indentation, const char *prefix,
11301 		    const char *suffix, int fill_char,
11302 		    int def_width, int start, const char *string)
11303 {
11304   sigset_t oldset; /* The signals that were blocked on entry to this function */
11305   int status;      /* The return status of _gl_completion_action() */
11306 /*
11307  * Check the arguments?
11308  */
11309   if(!gl || !string) {
11310     errno = EINVAL;
11311     return -1;
11312   };
11313 /*
11314  * Block all signals.
11315  */
11316   if(gl_mask_signals(gl, &oldset))
11317     return -1;
11318 /*
11319  * Display the text while signals are blocked.
11320  */
11321   status = _io_display_text(_io_write_stdio, gl->output_fp, indentation,
11322 			    prefix, suffix, fill_char,
11323 			    gl->ncolumn > 0 ? gl->ncolumn : def_width,
11324 			    start, string);
11325 /*
11326  * Restore the process signal mask.
11327  */
11328   gl_unmask_signals(gl, &oldset);
11329   return status;
11330 }
11331 
11332 /*.......................................................................
11333  * Block all of the signals that we are currently trapping.
11334  *
11335  * Input:
11336  *  gl       GetLine *   The resource object of gl_get_line().
11337  * Input/Output:
11338  *  oldset   sigset_t *   The superseded process signal mask
11339  *                        will be return in *oldset unless oldset is
11340  *                        NULL.
11341  * Output:
11342  *  return        int     0 - OK.
11343  *                        1 - Error.
11344  */
11345 static int gl_mask_signals(GetLine *gl, sigset_t *oldset)
11346 {
11347 /*
11348  * Block all signals in all_signal_set, along with any others that are
11349  * already blocked by the application.
11350  */
11351   if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) {
11352     gl->signals_masked = 1;
11353     return 0;
11354   };
11355 /*
11356  * On error attempt to query the current process signal mask, so
11357  * that oldset be the correct process signal mask to restore later
11358  * if the caller of this function ignores the error return value.
11359  */
11360   if(oldset)
11361     (void) sigprocmask(SIG_SETMASK, NULL, oldset);
11362   gl->signals_masked = 0;
11363   return 1;
11364 }
11365 
11366 /*.......................................................................
11367  * Restore a process signal mask that was previously returned via the
11368  * oldset argument of gl_mask_signals().
11369  *
11370  * Input:
11371  *  gl        GetLine *   The resource object of gl_get_line().
11372  * Input/Output:
11373  *  oldset   sigset_t *   The process signal mask to be restored.
11374  * Output:
11375  *  return        int     0 - OK.
11376  *                        1 - Error.
11377  */
11378 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset)
11379 {
11380   gl->signals_masked = 0;
11381   return sigprocmask(SIG_SETMASK, oldset, NULL) < 0;
11382 }
11383 
11384 /*.......................................................................
11385  * Arrange to temporarily catch the signals marked in gl->use_signal_set.
11386  *
11387  * Input:
11388  *  gl        GetLine *   The resource object of gl_get_line().
11389  * Output:
11390  *  return        int     0 - OK.
11391  *                        1 - Error.
11392  */
11393 static int gl_catch_signals(GetLine *gl)
11394 {
11395   return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0;
11396 }
11397 
11398 /*.......................................................................
11399  * Select the I/O mode to be used by gl_get_line().
11400  *
11401  * Input:
11402  *  gl         GetLine *  The resource object of gl_get_line().
11403  *  mode      GlIOMode    The I/O mode to establish.
11404  * Output:
11405  *  return         int    0 - OK.
11406  *                        1 - Error.
11407  */
11408 int gl_io_mode(GetLine *gl, GlIOMode mode)
11409 {
11410   sigset_t oldset; /* The signals that were blocked on entry to this function */
11411   int status;      /* The return status of _gl_io_mode() */
11412 /*
11413  * Check the arguments.
11414  */
11415   if(!gl) {
11416     errno = EINVAL;
11417     return 1;
11418   };
11419 /*
11420  * Check that the requested mode is known.
11421  */
11422   switch(mode) {
11423   case GL_NORMAL_MODE:
11424   case GL_SERVER_MODE:
11425     break;
11426   default:
11427     errno = EINVAL;
11428     _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.",
11429 		    END_ERR_MSG);
11430     return 1;
11431   };
11432 /*
11433  * Block all signals.
11434  */
11435   if(gl_mask_signals(gl, &oldset))
11436     return 1;
11437 /*
11438  * Invoke the private body of this function.
11439  */
11440   status = _gl_io_mode(gl, mode);
11441 /*
11442  * Restore the process signal mask.
11443  */
11444   gl_unmask_signals(gl, &oldset);
11445   return status;
11446 }
11447 
11448 /*.......................................................................
11449  * This is the private body of the public function, gl_io_mode().
11450  * It assumes that the caller has checked its arguments and blocked the
11451  * delivery of signals.
11452  */
11453 static int _gl_io_mode(GetLine *gl, GlIOMode mode)
11454 {
11455 /*
11456  * Are we already in the specified mode?
11457  */
11458   if(mode == gl->io_mode)
11459     return 0;
11460 /*
11461  * First revert to normal I/O in the current I/O mode.
11462  */
11463   _gl_normal_io(gl);
11464 /*
11465  * Record the new mode.
11466  */
11467   gl->io_mode = mode;
11468 /*
11469  * Perform any actions needed by the new mode.
11470  */
11471   if(mode==GL_SERVER_MODE) {
11472     if(_gl_raw_io(gl, 1))
11473       return 1;
11474   };
11475   return 0;
11476 }
11477 
11478 /*.......................................................................
11479  * Return extra information (ie. in addition to that provided by errno)
11480  * about the last error to occur in either gl_get_line() or its
11481  * associated public functions.
11482  *
11483  * Input:
11484  *  gl         GetLine *  The resource object of gl_get_line().
11485  * Input/Output:
11486  *  buff          char *  An optional output buffer. Note that if the
11487  *                        calling application calls any gl_*()
11488  *                        functions from signal handlers, it should
11489  *                        provide a buffer here, so that a copy of
11490  *                        the latest error message can safely be made
11491  *                        while signals are blocked.
11492  *  n           size_t    The allocated size of buff[].
11493  * Output:
11494  *  return  const char *  A pointer to the error message. This will
11495  *                        be the buff argument, unless buff==NULL, in
11496  *                        which case it will be a pointer to an
11497  *                        internal error buffer. In the latter case,
11498  *                        note that the contents of the returned buffer
11499  *                        will change on subsequent calls to any gl_*()
11500  *                        functions.
11501  */
11502 const char *gl_error_message(GetLine *gl, char *buff, size_t n)
11503 {
11504   if(!gl) {
11505     static const char *msg = "NULL GetLine argument";
11506     if(buff) {
11507       strncpy(buff, msg, n);
11508       buff[n-1] = '\0';
11509     } else {
11510       return msg;
11511     };
11512   } else if(buff) {
11513     sigset_t oldset; /* The signals that were blocked on entry to this block */
11514 /*
11515  * Temporarily block all signals.
11516  */
11517     gl_mask_signals(gl, &oldset);
11518 /*
11519  * Copy the error message into the specified buffer.
11520  */
11521     if(buff && n > 0) {
11522       strncpy(buff, _err_get_msg(gl->err), n);
11523       buff[n-1] = '\0';
11524     };
11525 /*
11526  * Restore the process signal mask before returning.
11527  */
11528     gl_unmask_signals(gl, &oldset);
11529   } else {
11530     return _err_get_msg(gl->err);
11531   };
11532   return buff;
11533 }
11534 
11535 /*.......................................................................
11536  * Return the signal mask used by gl_get_line(). This is the set of
11537  * signals that gl_get_line() is currently configured to trap.
11538  *
11539  * Input:
11540  *  gl         GetLine *  The resource object of gl_get_line().
11541  * Input/Output:
11542  *  set       sigset_t *  The set of signals will be returned in *set,
11543  *                        in the form of a signal process mask, as
11544  *                        used by sigaction(), sigprocmask(),
11545  *                        sigpending(), sigsuspend(), sigsetjmp() and
11546  *                        other standard POSIX signal-aware
11547  *                        functions.
11548  * Output:
11549  *  return         int    0 - OK.
11550  *                        1 - Error (examine errno for reason).
11551  */
11552 int gl_list_signals(GetLine *gl, sigset_t *set)
11553 {
11554 /*
11555  * Check the arguments.
11556  */
11557   if(!gl || !set) {
11558     if(gl)
11559       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
11560     errno = EINVAL;
11561     return 1;
11562   };
11563 /*
11564  * Copy the signal mask into *set.
11565  */
11566   memcpy(set, &gl->all_signal_set, sizeof(*set));
11567   return 0;
11568 }
11569 
11570 /*.......................................................................
11571  * By default, gl_get_line() doesn't trap signals that are blocked
11572  * when it is called. This default can be changed either on a
11573  * per-signal basis by calling gl_trap_signal(), or on a global basis
11574  * by calling this function. What this function does is add the
11575  * GLS_UNBLOCK_SIG flag to all signals that are currently configured
11576  * to be trapped by gl_get_line(), such that when subsequent calls to
11577  * gl_get_line() wait for I/O, these signals are temporarily
11578  * unblocked. This behavior is useful in non-blocking server-I/O mode,
11579  * where it is used to avoid race conditions related to handling these
11580  * signals externally to gl_get_line(). See the demonstration code in
11581  * demo3.c, or the gl_handle_signal() man page for further
11582  * information.
11583  *
11584  * Input:
11585  *  gl         GetLine *   The resource object of gl_get_line().
11586  */
11587 void gl_catch_blocked(GetLine *gl)
11588 {
11589   sigset_t oldset;    /* The process signal mask to restore */
11590   GlSignalNode *sig;  /* A signal node in gl->sigs */
11591 /*
11592  * Check the arguments.
11593  */
11594   if(!gl) {
11595     errno = EINVAL;
11596     return;
11597   };
11598 /*
11599  * Temporarily block all signals while we modify the contents of gl.
11600  */
11601   gl_mask_signals(gl, &oldset);
11602 /*
11603  * Add the GLS_UNBLOCK_SIG flag to all configured signals.
11604  */
11605   for(sig=gl->sigs; sig; sig=sig->next)
11606     sig->flags |= GLS_UNBLOCK_SIG;
11607 /*
11608  * Restore the process signal mask that was superseded by the call
11609  * to gl_mask_signals().
11610  */
11611   gl_unmask_signals(gl, &oldset);
11612   return;
11613 }
11614 
11615 /*.......................................................................
11616  * Respond to signals who's default effects have important
11617  * consequences to gl_get_line(). This is intended for use in
11618  * non-blocking server mode, where the external event loop is
11619  * responsible for catching signals. Signals that are handled include
11620  * those that by default terminate or suspend the process, and the
11621  * signal that indicates that the terminal size has changed. Note that
11622  * this function is not signal safe and should thus not be called from
11623  * a signal handler itself. See the gl_io_mode() man page for how it
11624  * should be used.
11625  *
11626  * In the case of signals that by default terminate or suspend
11627  * processes, command-line editing will be suspended, the terminal
11628  * returned to a usable state, then the default disposition of the
11629  * signal restored and the signal resent, in order to suspend or
11630  * terminate the process.  If the process subsequently resumes,
11631  * command-line editing is resumed.
11632  *
11633  * In the case of signals that indicate that the terminal has been
11634  * resized, the new size will be queried, and any input line that is
11635  * being edited will be redrawn to fit the new dimensions of the
11636  * terminal.
11637  *
11638  * Input:
11639  *  signo    int    The number of the signal to respond to.
11640  *  gl   GetLine *  The first element of an array of 'ngl' GetLine
11641  *                  objects.
11642  *  ngl      int    The number of elements in the gl[] array. Normally
11643  *                  this will be one.
11644  */
11645 void gl_handle_signal(int signo, GetLine *gl, int ngl)
11646 {
11647   int attr;             /* The attributes of the specified signal */
11648   sigset_t all_signals; /* The set of trappable signals */
11649   sigset_t oldset;      /* The process signal mask to restore */
11650   int i;
11651 /*
11652  * NULL operation?
11653  */
11654   if(ngl < 1 || !gl)
11655     return;
11656 /*
11657  * Look up the default attributes of the specified signal.
11658  */
11659   attr = gl_classify_signal(signo);
11660 /*
11661  * If the signal isn't known, we are done.
11662  */
11663   if(!attr)
11664     return;
11665 /*
11666  * Temporarily block all signals while we modify the gl objects.
11667  */
11668   gl_list_trappable_signals(&all_signals);
11669   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11670 /*
11671  * Suspend or terminate the process?
11672  */
11673   if(attr & (GLSA_SUSP | GLSA_TERM)) {
11674     gl_suspend_process(signo, gl, ngl);
11675 /*
11676  * Resize the terminal? Note that ioctl() isn't defined as being
11677  * signal safe, so we can't call gl_update_size() here. However,
11678  * gl_get_line() checks for resizes on each call, so simply arrange
11679  * for the application's event loop to call gl_get_line() as soon as
11680  * it becomes possible to write to the terminal. Note that if the
11681  * caller is calling select() or poll when this happens, these functions
11682  * get interrupted, since a signal has been caught.
11683  */
11684   } else if(attr & GLSA_SIZE) {
11685     for(i=0; i<ngl; i++)
11686       gl[i].pending_io = GLP_WRITE;
11687   };
11688 /*
11689  * Restore the process signal mask that was superseded by the call
11690  * to gl_mask_signals().
11691  */
11692   sigprocmask(SIG_SETMASK, &oldset, NULL);
11693   return;
11694 }
11695 
11696 /*.......................................................................
11697  * Respond to an externally caught process suspension or
11698  * termination signal.
11699  *
11700  * After restoring the terminal to a usable state, suspend or
11701  * terminate the calling process, using the original signal with its
11702  * default disposition restored to do so. If the process subsequently
11703  * resumes, resume editing any input lines that were being entered.
11704  *
11705  * Input:
11706  *  signo    int    The signal number to suspend the process with. Note
11707  *                  that the default disposition of this signal will be
11708  *                  restored before the signal is sent, so provided
11709  *                  that the default disposition of this signal is to
11710  *                  either suspend or terminate the application,
11711  *                  that is what wil happen, regardless of what signal
11712  *                  handler is currently assigned to this signal.
11713  *  gl   GetLine *  The first element of an array of 'ngl' GetLine objects
11714  *                  whose terminals should be restored to a sane state
11715  *                  while the application is suspended.
11716  *  ngl      int    The number of elements in the gl[] array.
11717  */
11718 static void gl_suspend_process(int signo, GetLine *gl, int ngl)
11719 {
11720   sigset_t only_signo;          /* A signal set containing just signo */
11721   sigset_t oldset;              /* The signal mask on entry to this function */
11722   sigset_t all_signals;         /* A signal set containing all signals */
11723   struct sigaction old_action;  /* The current signal handler */
11724   struct sigaction def_action;  /* The default signal handler */
11725   int i;
11726 /*
11727  * Create a signal mask containing the signal that was trapped.
11728  */
11729   sigemptyset(&only_signo);
11730   sigaddset(&only_signo, signo);
11731 /*
11732  * Temporarily block all signals.
11733  */
11734   gl_list_trappable_signals(&all_signals);
11735   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11736 /*
11737  * Restore the terminal to a usable state.
11738  */
11739   for(i=0; i<ngl; i++) {
11740     GetLine *obj = gl + i;
11741     if(obj->raw_mode) {
11742       _gl_normal_io(obj);
11743       if(!obj->raw_mode)        /* Check that gl_normal_io() succeded */
11744 	obj->raw_mode = -1;     /* Flag raw mode as needing to be restored */
11745     };
11746   };
11747 /*
11748  * Restore the system default disposition of the signal that we
11749  * caught.  Note that this signal is currently blocked. Note that we
11750  * don't use memcpy() to copy signal sets here, because the signal safety
11751  * of memcpy() is undefined.
11752  */
11753   def_action.sa_handler = SIG_DFL;
11754   {
11755     char *orig = (char *) &all_signals;
11756     char *dest = (char *) &def_action.sa_mask;
11757     for(i=0; i<sizeof(sigset_t); i++)
11758       *dest++ = *orig++;
11759   };
11760   sigaction(signo, &def_action, &old_action);
11761 /*
11762  * Resend the signal, and unblock it so that it gets delivered to
11763  * the application. This will invoke the default action of this signal.
11764  */
11765   raise(signo);
11766   sigprocmask(SIG_UNBLOCK, &only_signo, NULL);
11767 /*
11768  * If the process resumes again, it will resume here.
11769  * Block the signal again, then restore our signal handler.
11770  */
11771   sigprocmask(SIG_BLOCK, &only_signo, NULL);
11772   sigaction(signo, &old_action, NULL);
11773 /*
11774  * Resume command-line editing.
11775  */
11776   for(i=0; i<ngl; i++) {
11777     GetLine *obj = gl + i;
11778     if(obj->raw_mode == -1) { /* Did we flag the need to restore raw mode? */
11779       obj->raw_mode = 0;      /* gl_raw_io() does nothing unless raw_mode==0 */
11780       _gl_raw_io(obj, 1);
11781     };
11782   };
11783 /*
11784  * Restore the process signal mask to the way it was when this function
11785  * was called.
11786  */
11787   sigprocmask(SIG_SETMASK, &oldset, NULL);
11788   return;
11789 }
11790 
11791 /*.......................................................................
11792  * Return the information about the default attributes of a given signal.
11793  * The attributes that are returned are as defined by the standards that
11794  * created them, including POSIX, SVR4 and 4.3+BSD, and are taken from a
11795  * table in Richard Steven's book, "Advanced programming in the UNIX
11796  * environment".
11797  *
11798  * Input:
11799  *  signo        int   The signal to be characterized.
11800  * Output:
11801  *  return       int   A bitwise union of GlSigAttr enumerators, or 0
11802  *                     if the signal isn't known.
11803  */
11804 static int gl_classify_signal(int signo)
11805 {
11806   int i;
11807 /*
11808  * Search for the specified signal in the gl_signal_list[] table.
11809  */
11810   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11811     const struct GlDefSignal *sig = gl_signal_list + i;
11812     if(sig->signo == signo)
11813       return sig->attr;
11814   };
11815 /*
11816  * Signal not known.
11817  */
11818   return 0;
11819 }
11820 
11821 /*.......................................................................
11822  * When in non-blocking server mode, this function can be used to abandon
11823  * the current incompletely entered input line, and prepare to start
11824  * editing a new line on the next call to gl_get_line().
11825  *
11826  * Input:
11827  *  gl      GetLine *  The line editor resource object.
11828  */
11829 void gl_abandon_line(GetLine *gl)
11830 {
11831   sigset_t oldset;    /* The process signal mask to restore */
11832 /*
11833  * Check the arguments.
11834  */
11835   if(!gl) {
11836     errno = EINVAL;
11837     return;
11838   };
11839 /*
11840  * Temporarily block all signals while we modify the contents of gl.
11841  */
11842   gl_mask_signals(gl, &oldset);
11843 /*
11844  * Mark the input line as discarded.
11845  */
11846   _gl_abandon_line(gl);
11847 /*
11848  * Restore the process signal mask that was superseded by the call
11849  * to gl_mask_signals().
11850  */
11851   gl_unmask_signals(gl, &oldset);
11852   return;
11853 }
11854 
11855 /*.......................................................................
11856  * This is the private body of the gl_abandon_line() function. It
11857  * assumes that the caller has checked its arguments and blocked the
11858  * delivery of signals.
11859  */
11860 void _gl_abandon_line(GetLine *gl)
11861 {
11862   gl->endline = 1;
11863   gl->pending_io = GLP_WRITE;
11864 }
11865 
11866 /*.......................................................................
11867  * How many characters are needed to write a number as an octal string?
11868  *
11869  * Input:
11870  *  num   unsigned   The to be measured.
11871  * Output:
11872  *  return     int   The number of characters needed.
11873  */
11874 static int gl_octal_width(unsigned num)
11875 {
11876   int n;    /* The number of characters needed to render the number */
11877   for(n=1; num /= 8; n++)
11878     ;
11879   return n;
11880 }
11881 
11882 /*.......................................................................
11883  * Tell gl_get_line() the current terminal size. Note that this is only
11884  * necessary on systems where changes in terminal size aren't reported
11885  * via SIGWINCH.
11886  *
11887  * Input:
11888  *  gl            GetLine *  The resource object of gl_get_line().
11889  *  ncolumn           int    The number of columns in the terminal.
11890  *  nline             int    The number of lines in the terminal.
11891  * Output:
11892  *  return            int    0 - OK.
11893  *                           1 - Error.
11894  */
11895 int gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11896 {
11897   sigset_t oldset;      /* The signals that were blocked on entry */
11898                         /*  to this function */
11899   int status;           /* The return status */
11900 /*
11901  * Block all signals while accessing gl.
11902  */
11903   gl_mask_signals(gl, &oldset);
11904 /*
11905  * Install the new terminal size.
11906  */
11907   status = _gl_set_term_size(gl, ncolumn, nline);
11908 /*
11909  * Restore the process signal mask before returning.
11910  */
11911   gl_unmask_signals(gl, &oldset);
11912   return status;
11913 }
11914 
11915 /*.......................................................................
11916  * This is the private body of the gl_set_term_size() function. It
11917  * assumes that the caller has checked its arguments and blocked the
11918  * delivery of signals.
11919  */
11920 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11921 {
11922 /*
11923  * Check the arguments.
11924  */
11925   if(!gl) {
11926     errno = EINVAL;
11927     return 1;
11928   };
11929 /*
11930  * Reject non-sensical dimensions.
11931  */
11932   if(ncolumn <= 0 || nline <= 0) {
11933     _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG);
11934     errno = EINVAL;
11935     return 1;
11936   };
11937 /*
11938  * Install the new dimensions in the terminal driver if possible, so
11939  * that future calls to gl_query_size() get the new value.
11940  */
11941 #ifdef TIOCSWINSZ
11942   if(gl->is_term) {
11943     struct winsize size;
11944     size.ws_row = nline;
11945     size.ws_col = ncolumn;
11946     size.ws_xpixel = 0;
11947     size.ws_ypixel = 0;
11948     if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) {
11949       _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG);
11950       return 1;
11951     };
11952   };
11953 #endif
11954 /*
11955  * If an input line is in the process of being edited, redisplay it to
11956  * accomodate the new dimensions, and record the new dimensions in
11957  * gl->nline and gl->ncolumn.
11958  */
11959   return gl_handle_tty_resize(gl, ncolumn, nline);
11960 }
11961 
11962 /*.......................................................................
11963  * Record a character in the input line buffer at a given position.
11964  *
11965  * Input:
11966  *  gl    GetLine *   The resource object of gl_get_line().
11967  *  c        char     The character to be recorded.
11968  *  bufpos    int     The index in the buffer at which to record the
11969  *                    character.
11970  * Output:
11971  *  return    int     0 - OK.
11972  *                    1 - Insufficient room.
11973  */
11974 static int gl_buffer_char(GetLine *gl, char c, int bufpos)
11975 {
11976 /*
11977  * Guard against buffer overruns.
11978  */
11979   if(bufpos >= gl->linelen)
11980     return 1;
11981 /*
11982  * Record the new character.
11983  */
11984   gl->line[bufpos] = c;
11985 /*
11986  * If the new character was placed beyond the end of the current input
11987  * line, update gl->ntotal to reflect the increased number of characters
11988  * that are in gl->line, and terminate the string.
11989  */
11990   if(bufpos >= gl->ntotal) {
11991     gl->ntotal = bufpos+1;
11992     gl->line[gl->ntotal] = '\0';
11993   };
11994   return 0;
11995 }
11996 
11997 /*.......................................................................
11998  * Copy a given string into the input buffer, overwriting the current
11999  * contents.
12000  *
12001  * Input:
12002  *  gl    GetLine *   The resource object of gl_get_line().
12003  *  s  const char *   The string to be recorded.
12004  *  n         int     The number of characters to be copied from the
12005  *                    string.
12006  *  bufpos    int     The index in the buffer at which to place the
12007  *                    the first character of the string.
12008  * Output:
12009  *  return    int     0 - OK.
12010  *                    1 - String truncated to fit.
12011  */
12012 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos)
12013 {
12014   int nnew;  /* The number of characters actually recorded */
12015   int i;
12016 /*
12017  * How many of the characters will fit within the buffer?
12018  */
12019   nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos);
12020 /*
12021  * Record the first nnew characters of s[] in the buffer.
12022  */
12023   for(i=0; i<nnew; i++)
12024     gl_buffer_char(gl, s[i], bufpos + i);
12025 /*
12026  * Was the string truncated?
12027  */
12028   return nnew < n;
12029 }
12030 
12031 /*.......................................................................
12032  * Make room in the input buffer for a string to be inserted. This
12033  * involves moving the characters that follow a specified point, towards
12034  * the end of the buffer.
12035  *
12036  * Input:
12037  *  gl    GetLine *   The resource object of gl_get_line().
12038  *  start     int     The index of the first character to be moved.
12039  *  n         int     The width of the gap.
12040  * Output:
12041  *  return    int     0 - OK.
12042  *                    1 - Insufficient room.
12043  */
12044 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n)
12045 {
12046 /*
12047  * Ensure that the buffer has sufficient space.
12048  */
12049   if(gl->ntotal + n > gl->linelen)
12050     return 1;
12051 /*
12052  * Move everything including and beyond the character at 'start'
12053  * towards the end of the string.
12054  */
12055   memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1);
12056 /*
12057  * Update the recorded size of the line.
12058  */
12059   gl->ntotal += n;
12060   return 1;
12061 }
12062 
12063 /*.......................................................................
12064  * Remove a given number of characters from the input buffer. This
12065  * involves moving the characters that follow the removed characters to
12066  * where the removed sub-string started in the input buffer.
12067  *
12068  * Input:
12069  *  gl    GetLine *   The resource object of gl_get_line().
12070  *  start     int     The first character to be removed.
12071  *  n         int     The number of characters to remove.
12072  */
12073 static void gl_remove_from_buffer(GetLine *gl, int start, int n)
12074 {
12075   memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1);
12076 /*
12077  * Update the recorded size of the line.
12078  */
12079   gl->ntotal -= n;
12080 }
12081 
12082 /*.......................................................................
12083  * Truncate the string in the input line buffer after a given number of
12084  * characters.
12085  *
12086  * Input:
12087  *  gl       GetLine *   The resource object of gl_get_line().
12088  *  n            int     The new length of the line.
12089  * Output:
12090  *  return       int     0 - OK.
12091  *                       1 - n > gl->linelen.
12092  */
12093 static int gl_truncate_buffer(GetLine *gl, int n)
12094 {
12095   if(n > gl->linelen)
12096     return 1;
12097   gl->line[n] = '\0';
12098   gl->ntotal = n;
12099   return 0;
12100 }
12101 
12102 /*.......................................................................
12103  * When the contents of gl->line[] are changed without calling any of the
12104  * gl_ buffer manipulation functions, this function must be called to
12105  * compute the length of this string, and ancillary information.
12106  *
12107  * Input:
12108  *  gl      GetLine *   The resource object of gl_get_line().
12109  */
12110 static void gl_update_buffer(GetLine *gl)
12111 {
12112   int len;  /* The length of the line */
12113 /*
12114  * Measure the length of the input line.
12115  */
12116   for(len=0; len <= gl->linelen && gl->line[len]; len++)
12117     ;
12118 /*
12119  * Just in case the string wasn't correctly terminated, do so here.
12120  */
12121   gl->line[len] = '\0';
12122 /*
12123  * Record the number of characters that are now in gl->line[].
12124  */
12125   gl->ntotal = len;
12126 /*
12127  * Ensure that the cursor stays within the bounds of the modified
12128  * input line.
12129  */
12130   if(gl->buff_curpos > gl->ntotal)
12131     gl->buff_curpos = gl->ntotal;
12132 /*
12133  * Arrange for the input line to be redrawn.
12134  */
12135   gl_queue_redisplay(gl);
12136   return;
12137 }
12138 
12139 /*.......................................................................
12140  * Erase the displayed input line, including its prompt, and leave the
12141  * cursor where the erased line started. Note that to allow this
12142  * function to be used when responding to a terminal resize, this
12143  * function is designed to work even if the horizontal cursor position
12144  * doesn't match the internally recorded position.
12145  *
12146  * Input:
12147  *  gl      GetLine *   The resource object of gl_get_line().
12148  * Output:
12149  *  return      int     0 - OK.
12150  *                      1 - Error.
12151  */
12152 static int gl_erase_line(GetLine *gl)
12153 {
12154 /*
12155  * Is a line currently displayed?
12156  */
12157   if(gl->displayed) {
12158 /*
12159  * Relative the the start of the input line, which terminal line of
12160  * the current input line is the cursor currently on?
12161  */
12162     int cursor_line = gl->term_curpos / gl->ncolumn;
12163 /*
12164  * Move the cursor to the start of the line.
12165  */
12166     for( ; cursor_line > 0; cursor_line--) {
12167       if(gl_print_control_sequence(gl, 1, gl->up))
12168 	return 1;
12169     };
12170     if(gl_print_control_sequence(gl, 1, gl->bol))
12171       return 1;
12172 /*
12173  * Clear from the start of the line to the end of the terminal.
12174  */
12175     if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12176       return 1;
12177 /*
12178  * Mark the line as no longer displayed.
12179  */
12180     gl_line_erased(gl);
12181   };
12182   return 0;
12183 }
12184 
12185 /*.......................................................................
12186  * Arrange for the input line to be redisplayed by gl_flush_output(),
12187  * as soon as the output queue becomes empty.
12188  *
12189  * Input:
12190  *  gl          GetLine *   The resource object of gl_get_line().
12191  */
12192 static void gl_queue_redisplay(GetLine *gl)
12193 {
12194   gl->redisplay = 1;
12195   gl->pending_io = GLP_WRITE;
12196 }
12197 
12198 /*.......................................................................
12199  * Truncate the displayed input line starting from the current
12200  * terminal cursor position, and leave the cursor at the end of the
12201  * truncated line. The input-line buffer is not affected.
12202  *
12203  * Input:
12204  *  gl     GetLine *   The resource object of gl_get_line().
12205  * Output:
12206  *  return     int     0 - OK.
12207  *                     1 - Error.
12208  */
12209 static int gl_truncate_display(GetLine *gl)
12210 {
12211 /*
12212  * Keep a record of the current terminal cursor position.
12213  */
12214   int term_curpos = gl->term_curpos;
12215 /*
12216  * First clear from the cursor to the end of the current input line.
12217  */
12218   if(gl_print_control_sequence(gl, 1, gl->clear_eol))
12219     return 1;
12220 /*
12221  * If there is more than one line displayed, go to the start of the
12222  * next line and clear from there to the end of the display. Note that
12223  * we can't use clear_eod to do the whole job of clearing from the
12224  * current cursor position to the end of the terminal because
12225  * clear_eod is only defined when used at the start of a terminal line
12226  * (eg. with gnome terminals, clear_eod clears from the start of the
12227  * current terminal line, rather than from the current cursor
12228  * position).
12229  */
12230   if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) {
12231     if(gl_print_control_sequence(gl, 1, gl->down) ||
12232        gl_print_control_sequence(gl, 1, gl->bol) ||
12233        gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12234       return 1;
12235 /*
12236  * Where is the cursor now?
12237  */
12238     gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1);
12239 /*
12240  * Restore the cursor position.
12241  */
12242     gl_set_term_curpos(gl, term_curpos);
12243   };
12244 /*
12245  * Update the recorded position of the final character.
12246  */
12247   gl->term_len = gl->term_curpos;
12248   return 0;
12249 }
12250 
12251 /*.......................................................................
12252  * Return the set of all trappable signals.
12253  *
12254  * Input:
12255  *  signals   sigset_t *  The set of signals will be recorded in
12256  *                        *signals.
12257  */
12258 static void gl_list_trappable_signals(sigset_t *signals)
12259 {
12260 /*
12261  * Start with the set of all signals.
12262  */
12263   sigfillset(signals);
12264 /*
12265  * Remove un-trappable signals from this set.
12266  */
12267 #ifdef SIGKILL
12268   sigdelset(signals, SIGKILL);
12269 #endif
12270 #ifdef SIGSTOP
12271   sigdelset(signals, SIGSTOP);
12272 #endif
12273 }
12274 
12275 /*.......................................................................
12276  * Read an input line from a non-interactive input stream.
12277  *
12278  * Input:
12279  *  gl     GetLine *   The resource object of gl_get_line().
12280  * Output:
12281  *  return     int     0 - OK
12282  *                     1 - Error.
12283  */
12284 static int gl_read_stream_line(GetLine *gl)
12285 {
12286   char c = '\0'; /* The latest character read from fp */
12287 /*
12288  * Record the fact that we are about to read input.
12289  */
12290   gl->pending_io = GLP_READ;
12291 /*
12292  * If we are starting a new line, reset the line-input parameters.
12293  */
12294   if(gl->endline)
12295     gl_reset_input_line(gl);
12296 /*
12297  * Read one character at a time.
12298  */
12299   while(gl->ntotal < gl->linelen && c != '\n') {
12300 /*
12301  * Attempt to read one more character.
12302  */
12303     switch(gl_read_input(gl, &c)) {
12304     case GL_READ_OK:
12305       break;
12306     case GL_READ_EOF:        /* Reached end-of-file? */
12307 /*
12308  * If any characters were read before the end-of-file condition,
12309  * interpolate a newline character, so that the caller sees a
12310  * properly terminated line. Otherwise return an end-of-file
12311  * condition.
12312  */
12313       if(gl->ntotal > 0) {
12314 	c = '\n';
12315       } else {
12316 	gl_record_status(gl, GLR_EOF, 0);
12317 	return 1;
12318       };
12319       break;
12320     case GL_READ_BLOCKED:    /* Input blocked? */
12321       gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12322       return 1;
12323       break;
12324     case GL_READ_ERROR:     /* I/O error? */
12325       return 1;
12326       break;
12327     };
12328 /*
12329  * Append the character to the line buffer.
12330  */
12331     if(gl_buffer_char(gl, c, gl->ntotal))
12332       return 1;
12333   };
12334 /*
12335  * Was the end of the input line reached before running out of buffer space?
12336  */
12337   gl->endline = (c == '\n');
12338   return 0;
12339 }
12340 
12341 /*.......................................................................
12342  * Read a single character from a non-interactive input stream.
12343  *
12344  * Input:
12345  *  gl     GetLine *   The resource object of gl_get_line().
12346  * Output:
12347  *  return     int     The character, or EOF on error.
12348  */
12349 static int gl_read_stream_char(GetLine *gl)
12350 {
12351   char c = '\0';    /* The latest character read from fp */
12352   int retval = EOF; /* The return value of this function */
12353 /*
12354  * Arrange to discard any incomplete input line.
12355  */
12356   _gl_abandon_line(gl);
12357 /*
12358  * Record the fact that we are about to read input.
12359  */
12360   gl->pending_io = GLP_READ;
12361 /*
12362  * Attempt to read one more character.
12363  */
12364   switch(gl_read_input(gl, &c)) {
12365   case GL_READ_OK:      /* Success */
12366     retval = c;
12367     break;
12368   case GL_READ_BLOCKED: /* The read blocked */
12369     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12370     retval = EOF;  /* Failure */
12371     break;
12372   case GL_READ_EOF:     /* End of file reached */
12373     gl_record_status(gl, GLR_EOF, 0);
12374     retval = EOF;  /* Failure */
12375     break;
12376   case GL_READ_ERROR:
12377     retval = EOF;  /* Failure */
12378     break;
12379   };
12380   return retval;
12381 }
12382 
12383 /*.......................................................................
12384  * Bind a key sequence to a given action.
12385  *
12386  * Input:
12387  *  gl          GetLine *   The resource object of gl_get_line().
12388  *  origin  GlKeyOrigin     The originator of the key binding.
12389  *  key      const char *   The key-sequence to be bound (or unbound).
12390  *  action   const char *   The name of the action to bind the key to,
12391  *                          or either NULL or "" to unbind the
12392  *                          key-sequence.
12393  * Output:
12394  *  return          int     0 - OK
12395  *                          1 - Error.
12396  */
12397 int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq,
12398 		   const char *action)
12399 {
12400   KtBinder binder;  /* The private internal equivalent of 'origin' */
12401 /*
12402  * Check the arguments.
12403  */
12404   if(!gl || !keyseq) {
12405     errno = EINVAL;
12406     if(gl)
12407       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
12408     return 1;
12409   };
12410 /*
12411  * An empty action string requests that the key-sequence be unbound.
12412  * This is indicated to _kt_set_keybinding() by passing a NULL action
12413  * string, so convert an empty string to a NULL action pointer.
12414  */
12415   if(action && *action=='\0')
12416     action = NULL;
12417 /*
12418  * Translate the public originator enumeration to the private equivalent.
12419  */
12420   binder = origin==GL_USER_KEY ? KTB_USER : KTB_NORM;
12421 /*
12422  * Bind the action to a given key-sequence?
12423  */
12424   if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
12425     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
12426     return 1;
12427   };
12428   return 0;
12429 }
12430 
12431 /*.......................................................................
12432  * This is the public wrapper around the gl_clear_termina() function.
12433  * It clears the terminal and leaves the cursor at the home position.
12434  * In server I/O mode, the next call to gl_get_line() will also
12435  * redisplay the current input line.
12436  *
12437  * Input:
12438  *  gl          GetLine *   The resource object of gl_get_line().
12439  * Output:
12440  *  return          int     0 - OK.
12441  *                          1 - Error.
12442  */
12443 int gl_erase_terminal(GetLine *gl)
12444 {
12445   sigset_t oldset;      /* The signals that were blocked on entry */
12446                         /*  to this function */
12447   int status;           /* The return status */
12448 /*
12449  * Block all signals while accessing gl.
12450  */
12451   gl_mask_signals(gl, &oldset);
12452 /*
12453  * Clear the terminal.
12454  */
12455   status = gl_clear_screen(gl, 1, NULL);
12456 /*
12457  * Attempt to flush the clear-screen control codes to the terminal.
12458  * If this doesn't complete the job, the next call to gl_get_line()
12459  * will.
12460  */
12461   (void) gl_flush_output(gl);
12462 /*
12463  * Restore the process signal mask before returning.
12464  */
12465   gl_unmask_signals(gl, &oldset);
12466   return status;
12467 }
12468 
12469 /*.......................................................................
12470  * This function must be called by any function that erases the input
12471  * line.
12472  *
12473  * Input:
12474  *  gl          GetLine *   The resource object of gl_get_line().
12475  */
12476 static void gl_line_erased(GetLine *gl)
12477 {
12478   gl->displayed = 0;
12479   gl->term_curpos = 0;
12480   gl->term_len = 0;
12481 }
12482 
12483 /*.......................................................................
12484  * Append a specified line to the history list.
12485  *
12486  * Input:
12487  *  gl          GetLine *   The resource object of gl_get_line().
12488  *  line     const char *   The line to be added.
12489  * Output:
12490  *  return          int     0 - OK.
12491  *                          1 - Error.
12492  */
12493 int gl_append_history(GetLine *gl, const char *line)
12494 {
12495   sigset_t oldset;      /* The signals that were blocked on entry */
12496                         /*  to this function */
12497   int status;           /* The return status */
12498 /*
12499  * Check the arguments.
12500  */
12501   if(!gl || !line) {
12502     errno = EINVAL;
12503     return 1;
12504   };
12505 /*
12506  * Block all signals.
12507  */
12508   if(gl_mask_signals(gl, &oldset))
12509     return 1;
12510 /*
12511  * Execute the private body of the function while signals are blocked.
12512  */
12513   status = _gl_append_history(gl, line);
12514 /*
12515  * Restore the process signal mask.
12516  */
12517   gl_unmask_signals(gl, &oldset);
12518   return status;
12519 }
12520 
12521 /*.......................................................................
12522  * This is the private body of the public function, gl_append_history().
12523  * It assumes that the caller has checked its arguments and blocked the
12524  * delivery of signals.
12525  */
12526 static int _gl_append_history(GetLine *gl, const char *line)
12527 {
12528   int status =_glh_add_history(gl->glh, line, 0);
12529   if(status)
12530     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
12531   return status;
12532 }
12533 
12534 /*.......................................................................
12535  * Enable or disable the automatic addition of newly entered lines to the
12536  * history list.
12537  *
12538  * Input:
12539  *  gl          GetLine *   The resource object of gl_get_line().
12540  *  enable          int     If true, subsequently entered lines will
12541  *                          automatically be added to the history list
12542  *                          before they are returned to the caller of
12543  *                          gl_get_line(). If 0, the choice of how and
12544  *                          when to archive lines in the history list,
12545  *                          is left up to the calling application, which
12546  *                          can do so via calls to gl_append_history().
12547  * Output:
12548  *  return          int     0 - OK.
12549  *                          1 - Error.
12550  */
12551 int gl_automatic_history(GetLine *gl, int enable)
12552 {
12553   sigset_t oldset;      /* The signals that were blocked on entry */
12554                         /*  to this function */
12555 /*
12556  * Check the arguments.
12557  */
12558   if(!gl) {
12559     errno = EINVAL;
12560     return 1;
12561   };
12562 /*
12563  * Block all signals.
12564  */
12565   if(gl_mask_signals(gl, &oldset))
12566     return 1;
12567 /*
12568  * Execute the private body of the function while signals are blocked.
12569  */
12570   gl->automatic_history = enable;
12571 /*
12572  * Restore the process signal mask.
12573  */
12574   gl_unmask_signals(gl, &oldset);
12575   return 0;
12576 }
12577 
12578 /*.......................................................................
12579  * This is a public function that reads a single uninterpretted
12580  * character from the user, without displaying anything.
12581  *
12582  * Input:
12583  *  gl     GetLine *  A resource object previously returned by
12584  *                    new_GetLine().
12585  * Output:
12586  *  return     int    The character that was read, or EOF if the read
12587  *                    had to be aborted (in which case you can call
12588  *                    gl_return_status() to find out why).
12589  */
12590 int gl_read_char(GetLine *gl)
12591 {
12592   int retval;   /* The return value of _gl_read_char() */
12593 /*
12594  * This function can be called from application callback functions,
12595  * so check whether signals have already been masked, so that we don't
12596  * do it again, and overwrite gl->old_signal_set.
12597  */
12598   int was_masked = gl->signals_masked;
12599 /*
12600  * Check the arguments.
12601  */
12602   if(!gl) {
12603     errno = EINVAL;
12604     return EOF;
12605   };
12606 /*
12607  * Temporarily block all of the signals that we have been asked to trap.
12608  */
12609   if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set))
12610     return EOF;
12611 /*
12612  * Perform the character reading task.
12613  */
12614   retval = _gl_read_char(gl);
12615 /*
12616  * Restore the process signal mask to how it was when this function was
12617  * first called.
12618  */
12619   if(!was_masked)
12620     gl_unmask_signals(gl, &gl->old_signal_set);
12621   return retval;
12622 }
12623 
12624 /*.......................................................................
12625  * This is the main body of the public function gl_read_char().
12626  */
12627 static int _gl_read_char(GetLine *gl)
12628 {
12629   int retval = EOF;  /* The return value */
12630   int waserr = 0;    /* True if an error occurs */
12631   char c;            /* The character read */
12632 /*
12633  * This function can be called from application callback functions,
12634  * so check whether signals have already been overriden, so that we don't
12635  * overwrite the preserved signal handlers with gl_get_line()s. Also
12636  * record whether we are currently in raw I/O mode or not, so that this
12637  * can be left in the same state on leaving this function.
12638  */
12639   int was_overriden = gl->signals_overriden;
12640   int was_raw = gl->raw_mode;
12641 /*
12642  * Also keep a record of the direction of any I/O that gl_get_line()
12643  * is awaiting, so that we can restore this status on return.
12644  */
12645   GlPendingIO old_pending_io = gl->pending_io;
12646 /*
12647  * Assume that this call will successfully complete the input operation
12648  * until proven otherwise.
12649  */
12650   gl_clear_status(gl);
12651 /*
12652  * If this is the first call to this function or gl_get_line(),
12653  * since new_GetLine(), complete any postponed configuration.
12654  */
12655   if(!gl->configured) {
12656     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
12657     gl->configured = 1;
12658   };
12659 /*
12660  * Before installing our signal handler functions, record the fact
12661  * that there are no pending signals.
12662  */
12663   gl_pending_signal = -1;
12664 /*
12665  * Temporarily override the signal handlers of the calling program,
12666  * so that we can intercept signals that would leave the terminal
12667  * in a bad state.
12668  */
12669   if(!was_overriden)
12670     waserr = gl_override_signal_handlers(gl);
12671 /*
12672  * After recording the current terminal settings, switch the terminal
12673  * into raw input mode, without redisplaying any partially entered input
12674  * line.
12675  */
12676   if(!was_raw)
12677     waserr = waserr || _gl_raw_io(gl, 0);
12678 /*
12679  * Attempt to read the line. This will require more than one attempt if
12680  * either a current temporary input file is opened by gl_get_input_line()
12681  * or the end of a temporary input file is reached by gl_read_stream_line().
12682  */
12683   while(!waserr) {
12684 /*
12685  * Read a line from a non-interactive stream?
12686  */
12687     if(gl->file_fp || !gl->is_term) {
12688       retval = gl_read_stream_char(gl);
12689       if(retval != EOF) {            /* Success? */
12690 	break;
12691       } else if(gl->file_fp) {  /* End of temporary input file? */
12692 	gl_revert_input(gl);
12693 	gl_record_status(gl, GLR_NEWLINE, 0);
12694       } else {                  /* An error? */
12695 	waserr = 1;
12696 	break;
12697       };
12698     };
12699 /*
12700  * Read from the terminal? Note that the above if() block may have
12701  * changed gl->file_fp, so it is necessary to retest it here, rather
12702  * than using an else statement.
12703  */
12704     if(!gl->file_fp && gl->is_term) {
12705 /*
12706  * Flush any pending output to the terminal before waiting
12707  * for the user to type a character.
12708  */
12709       if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) {
12710 	retval = EOF;
12711 /*
12712  * Read one character. Don't append it to the key buffer, since
12713  * this would subseuqnely appear as bogus input to the line editor.
12714  */
12715       } else if(gl_read_terminal(gl, 0, &c) == 0) {
12716 /*
12717  * Record the character for return.
12718  */
12719 	retval = c;
12720 /*
12721  * In this mode, count each character as being a new key-sequence.
12722  */
12723 	gl->keyseq_count++;
12724 /*
12725  * Delete the character that was read, from the key-press buffer.
12726  */
12727 	gl_discard_chars(gl, 1);
12728       };
12729       if(retval==EOF)
12730 	waserr = 1;
12731       else
12732 	break;
12733     };
12734   };
12735 /*
12736  * If an error occurred, but gl->rtn_status is still set to
12737  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
12738  * leave it at whatever specific value was assigned by the function
12739  * that aborted input. This means that only functions that trap
12740  * non-generic errors have to remember to update gl->rtn_status
12741  * themselves.
12742  */
12743   if(waserr && gl->rtn_status == GLR_NEWLINE)
12744     gl_record_status(gl, GLR_ERROR, errno);
12745 /*
12746  * Restore terminal settings, if they were changed by this function.
12747  */
12748   if(!was_raw && gl->io_mode != GL_SERVER_MODE)
12749     _gl_normal_io(gl);
12750 /*
12751  * Restore the signal handlers, if they were overriden by this function.
12752  */
12753   if(!was_overriden)
12754     gl_restore_signal_handlers(gl);
12755 /*
12756  * If this function gets aborted early, the errno value associated
12757  * with the event that caused this to happen is recorded in
12758  * gl->rtn_errno. Since errno may have been overwritten by cleanup
12759  * functions after this, restore its value to the value that it had
12760  * when the error condition occured, so that the caller can examine it
12761  * to find out what happened.
12762  */
12763   errno = gl->rtn_errno;
12764 /*
12765  * Error conditions are signalled to the caller, by setting the returned
12766  * character to EOF.
12767  */
12768   if(gl->rtn_status != GLR_NEWLINE)
12769     retval = EOF;
12770 /*
12771  * Restore the indication of what direction of I/O gl_get_line()
12772  * was awaiting before this call.
12773  */
12774   gl->pending_io = old_pending_io;
12775 /*
12776  * Return the acquired character.
12777  */
12778   return retval;
12779 }
12780 
12781 /*.......................................................................
12782  * Reset the GetLine completion status. This function should be called
12783  * at the start of gl_get_line(), gl_read_char() and gl_query_char()
12784  * to discard the completion status and non-zero errno value of any
12785  * preceding calls to these functions.
12786  *
12787  * Input:
12788  *  gl       GetLine *  The resource object of this module.
12789  */
12790 static void gl_clear_status(GetLine *gl)
12791 {
12792   gl_record_status(gl, GLR_NEWLINE, 0);
12793 }
12794 
12795 /*.......................................................................
12796  * When an error or other event causes gl_get_line() to return, this
12797  * function should be called to record information about what
12798  * happened, including the value of errno and the value that
12799  * gl_return_status() should return.
12800  *
12801  * Input:
12802  *  gl                GetLine *  The resource object of this module.
12803  *  rtn_status GlReturnStatus    The completion status. To clear a
12804  *                               previous abnormal completion status,
12805  *                               specify GLR_NEWLINE (this is what
12806  *                               gl_clear_status() does).
12807  *  rtn_errno             int    The associated value of errno.
12808  */
12809 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
12810 			     int rtn_errno)
12811 {
12812 /*
12813  * If rtn_status==GLR_NEWLINE, then this resets the completion status, so we
12814  * should always heed this. Otherwise, only record the first abnormal
12815  * condition that occurs after such a reset.
12816  */
12817   if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) {
12818     gl->rtn_status = rtn_status;
12819     gl->rtn_errno = rtn_errno;
12820   };
12821 }
12822 
12823